• Block的测试


    //输出10
    int x = 10;
        void(^function)(void)  = ^(void) {
            printf("-----> %d",x);
        };
        x = 12;
        function();
    //输出12
    int __block  x = 10;
        void(^function)(void)  = ^(void) {
            printf("-----> %d",x);
        };
        x = 12;
        function();

     上面两个换成NSString一样是这种情况,带__block才会输出后面配置的新值。

    //输出ab
    int __block x = 10;
        NSMutableString *y = [NSMutableString stringWithString:@"a"];
        void(^function)(void)  = ^(void) {
            printf("-----> %d
    ",x);
            printf("++++>%s",[y UTF8String]);
        };
        x = 12;
        [y appendString:@"b"];
        function();

    可变对象没有问题

    //正常输出
    const char * text = "hello";
        void(^function)(void)  = ^(void) {
            printf("-----> %d
    ",x);
            printf("++++>%s",[y UTF8String]);
            [items addObject:@(10)];
            printf("%c",text[2]);
        };
    //数组没有实现对数组的截获,无法在Block里面使用数组
    const char  text[] = "hello";
        void(^function)(void)  = ^(void) {
            printf("-----> %d
    ",x);
            printf("++++>%s",[y UTF8String]);
            [items addObject:@(10)];
            printf("%c",text[2]);
        };
    @interface YDTestObject : NSObject
    
    @property (nonatomic, strong) YDTestObject *otherObject;
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, copy) void (^saveBlock)(void);
    
    - (void)doBlock:(void(^)(void))block;
    - (void)doSaveBlock;
    
    @end
    
    @interface ViewController ()
    
    @property (nonatomic, strong) YDTestObject *testObject;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        YDTestObject *testObject = [YDTestObject new];
        testObject.name = @"test";
        YDTestObject *aObject = [YDTestObject new];
        aObject.name = @"a";
        YDTestObject *bObject = [YDTestObject new];
        bObject.name = @"b";
        testObject.otherObject = aObject;
        aObject.otherObject = bObject;
        [testObject setSaveBlock:^{
            [bObject doBlock:^{
                [aObject doBlock:^{
                    NSLog(@"xxxxxx");
                }];
            }];
        }];
        [testObject doSaveBlock];
        NSLog(@"测试开始");
    }
    
    
    @end
    
    
    @implementation YDTestObject
    
    - (void)doBlock:(void (^)(void))block {
        !block?:block();
    }
    
    - (void)dealloc {
        NSLog(@"dealloc: %@",self.name);
    }
    
    - (void)doSaveBlock {
        !self.saveBlock?:self.saveBlock();
    }
    
    @end
    2020-11-03 19:34:21.953942+0800 justTestUnknow[14796:83939] xxxxxx
    2020-11-03 19:34:21.954051+0800 justTestUnknow[14796:83939] 测试开始
    2020-11-03 19:34:21.954124+0800 justTestUnknow[14796:83939] dealloc: test
    2020-11-03 19:34:21.954185+0800 justTestUnknow[14796:83939] dealloc: a
    2020-11-03 19:34:21.954240+0800 justTestUnknow[14796:83939] dealloc: b

    上述调用修改为将无法正常释放,aObject和bObject位置互换也是一样无法释放

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        YDTestObject *testObject = [YDTestObject new];
        testObject.name = @"test";
        YDTestObject *aObject = [YDTestObject new];
        aObject.name = @"a";
        YDTestObject *bObject = [YDTestObject new];
        bObject.name = @"b";
        testObject.otherObject = aObject;
        aObject.otherObject = bObject;
        [bObject setSaveBlock:^{
            [aObject doBlock:^{
                [testObject doBlock:^{
                    NSLog(@"xxxxxx");
                }];
            }];
        }];
        [bObject doSaveBlock];
        NSLog(@"测试开始");
    }

     再修改为下面的样子,则是都可以释放

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.testObject = [YDTestObject new];
        self.testObject.name = @"test";
        YDTestObject *aObject = [YDTestObject new];
        aObject.name = @"a";
        YDTestObject *bObject = [YDTestObject new];
        bObject.name = @"b";
        self.testObject.otherObject = aObject;
        aObject.otherObject = bObject;
        [aObject setSaveBlock:^{
            [bObject doBlock:^{
                [self.testObject doBlock:^{
                    NSLog(@"xxxxxx");
                }];
            }];
        }];
        [aObject doSaveBlock];
        NSLog(@"测试开始");
        self.testObject = nil;
    }

    再把self改成rootObject那么又无法释放内存了

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        YDTestObject *rootObject = [YDTestObject new];
        rootObject.name = @"root";
        YDTestObject *testObject = [YDTestObject new];
        testObject.name = @"test";
        YDTestObject *aObject = [YDTestObject new];
        aObject.name = @"a";
        YDTestObject *bObject = [YDTestObject new];
        bObject.name = @"b";
        rootObject.otherObject = testObject;
        testObject.otherObject = aObject;
        aObject.otherObject = bObject;
        [aObject setSaveBlock:^{
            [bObject doBlock:^{
                [rootObject.otherObject doBlock:^{
                    NSLog(@"xxxxxx");
                }];
            }];
        }];
        [aObject doSaveBlock];
        NSLog(@"测试开始");
    }

     再修改一下,又可以正常释放内存了

    @interface ViewController ()
    
    @property (nonatomic, strong) YDTestObject *testObject;
    @property (nonatomic, strong) YDTestObject *checkObject;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.testObject = [YDTestObject new];
        self.testObject.name = @"test";
        self.checkObject = [YDTestObject new];
        self.checkObject.name = @"a";
        YDTestObject *bObject = [YDTestObject new];
        bObject.name = @"b";
        self.testObject.otherObject = self.checkObject;
        self.checkObject.otherObject = bObject;
        [self.checkObject setSaveBlock:^{
            [bObject doBlock:^{
                [self.testObject doBlock:^{
                    NSLog(@"xxxxxx");
                }];
            }];
        }];
        [self.checkObject doSaveBlock];
        NSLog(@"测试开始");
        self.checkObject = nil;
        self.testObject = nil;
    }
    
    
    @end

     如果上面的不写上

    self.checkObject = nil;

    那么就是只有testObject得到释放了

    再改进一下,test和a都释放了,但是b却无法释放

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        [self testFunction];
        [self.checkObject doBlock:^{
            NSLog(@"%@",self.checkObject);
        }];
        [self.checkObject setSaveBlock:^{
            [self.testObject doBlock:^{
                [self.checkObject.otherObject doBlock:^{
                    NSLog(@"xxxxxx");
                }];
            }];
        }];
        [self.checkObject doSaveBlock];
        NSLog(@"测试开始");
        self.checkObject = nil;
        self.testObject = nil;
    }
    
    - (void)testFunction {
        self.testObject = [YDTestObject new];
        self.testObject.name = @"test";
        self.checkObject = [YDTestObject new];
        self.checkObject.name = @"a";
        self.testObject.otherObject = self.checkObject;
        YDTestObject *bObject = [YDTestObject new];
        bObject.name = @"b";
        self.checkObject.otherObject = bObject;
        [self.checkObject setSaveBlock:^{
            NSLog(@"%@",self.checkObject);
        }];
        [bObject setSaveBlock:^{
            NSLog(@"%@",bObject);
        }];
    }

     参照上面引入rootObject,导致循环引用的情况,打破它的循环引用

    - (void)test2 {
        YDTestObject *rootObject = [YDTestObject new];
        rootObject.name = @"root";
        YDTestObject *testObject = [YDTestObject new];
        testObject.name = @"test";
        YDTestObject *aObject = [YDTestObject new];
        aObject.name = @"a";
        YDTestObject *bObject = [YDTestObject new];
        bObject.name = @"b";
        rootObject.otherObject = testObject;
        testObject.otherObject = aObject;
        aObject.otherObject = bObject;
        [aObject setSaveBlock:^{
            [bObject doBlock:^{
                [rootObject.otherObject doBlock:^{
                    NSLog(@"xxxxxx");
                }];
            }];
        }];
        [aObject doSaveBlock];
        NSLog(@"测试开始");
        //方案一
        rootObject.otherObject = nil;
        //方案二
    //    testObject.otherObject = nil;
      //方案三
    // aObject.saveBlock = nil; }

    解决办法:

    aObject引用了saveBlock,saveBlock引用了bObject和rootObject,rootObject引用了testObject

    循环引用链是 aObject、aObject.saveBlock、rootObject、testObject、aObject

    打破循环引用,断其中一个链接即可,对应上述三个方案

    对比与其最相似的self.testObject

    起初循环引用链为  aObject、aObject.saveBlock、self、self.testObject、aObject

    最后一句self.testObject = nil 相当与将 self 和 self.testObject关联打破,破除了循环引用

  • 相关阅读:
    select poll使用
    linux下tomcat shutdown后 java进程依然存在
    poj 1222 EXTENDED LIGHTS OUT(高斯消元)
    poj 2377 Bad Cowtractors
    C#:总结页面传值几种方法
    从 Racket 入门函数式编程
    程序猿接私活经验总结,来自csdn论坛语录
    什么是SEO?SEO干嘛的?怎么做SEO?
    Java设计模式-观察者模式
    非常特别的一个动态规划新手教程
  • 原文地址:https://www.cnblogs.com/yuxiaoyiyou/p/11214865.html
Copyright © 2020-2023  润新知