美文网首页
【知识总结】block 中使用返回对象

【知识总结】block 中使用返回对象

作者: 小子爱搞事 | 来源:发表于2017-02-20 10:21 被阅读64次

    Person

    @interface Person : NSObject
    @property (nonatomic, assign) NSInteger age;
    @property (nonatomic, assign) NSString *name;
    @end
    

    方法生成一个 Person 对象,block 延时 3 秒后回调,模仿异步回调过程

    - (Person *)personConfige:(void(^)())complete{
        
        Person *person = [Person new];
        person.name = @"000";
        person.age = 1111;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            !complete?:complete();
        });
        
        return person;
    }
    
    测试一:
        Person *person = [self personConfige:^{
            NSLog(@"person : %@ ", person); // 为 nil
        }];
    
    运行结果:
        person : (null) 
    
    解析:

    person 为 nil,block 捕获的 person 即为 nil;
    personConfige 返回对象给 person 后,person 指向新生成的 对象,但是 block 中捕获的 person 依然指向原先的 nil,因此输出为:null

    测试二:
        Person *testP = [Person new];
        NSLog(@"testP : %@ ", testP);
        Person *person = [self personConfige:^{
            NSLog(@"person : %@ ", person); // 为 nil
            NSLog(@"block testP : %@ ", testP);  // 存在
            NSLog(@"block testP.age : %ld, name: %@", testP.age, testP.name);
        }];
        testP = person;
    
    运行结果:
        testP : <Person: 0x6000000345a0> 
        person : (null) 
        block testP : <Person: 0x6000000345a0> 
        block testP.age : 0, name: (null)
    
    解析:

    如下图,1,testP 指向新生成的对象,block 获取 testP,block_testP 的引用也指向 testP 引用的对象;
    2,personConfige 返回新生成的对象给 person,testP 的指针指向 person 引用的对象
    3,testP 的指针虽然发生变化了,但是 block_testP 的指针没有改变,还是引用原来的对象,因此 block 中打印的还是最初的 testP 对象

    Paste_Image.png
    因此,block 中如果想要获取到方法中返回的对象,有一下两种做法:
    原理:

    对 blockTestP 引用的地址进行操作

    方法一:
        Person *testP = [Person new];
        NSLog(@"testP : %@ ", testP);
        Person *person = [self personConfige:^{
            NSLog(@"person : %@ ", person); // 为 nil
            NSLog(@"block testP : %@ ", testP);  // 存在
            NSLog(@"block testP.age : %ld, name: %@", testP.age, testP.name);
        }];
        testP.age = person.age;
        testP.name = person.name;
    
    运行结果:
        testP : <Person: 0x608000029880> 
        person : (null) 
        block testP : <Person: 0x608000029880> 
        block testP.age : 1111, name: 000
    

    将 person 对象的属性一个一个赋值给 testP 对象

    方法二:
        NSMutableArray *arr = [NSMutableArray arrayWithObject:@-1];
        Person *person2 = [self personConfige:^{
            
            Person *blockPer = arr.firstObject;
            NSLog(@"blockPer: %@", blockPer);
            NSLog(@"name: %@, age : %ld", blockPer.name, blockPer.age);
        }];
        NSLog(@"person2: %@", person2);
        arr[0] = person2;
    
    运行结果:  
        person2: <Person: 0x618000036620>
        blockPer: <Person: 0x618000036620>
        name: 000, age : 1111
    
    图解:
    Paste_Image.png
    方法三:

    推荐做法:利用 __block

        __block Person *person1 = nil;
        person1 = [self personConfige:^{
            NSLog(@"person : %@ ", person1); // 为 nil
        }];
    
      /**
         __block Person *person1 = [self personConfige:^{
             NSLog(@"person : %@ ", person1); // 为 nil
         }];
       */
    

    结果:

    2017-06-05 11:17:09.818614 单利-继承关系[4504:2175415] person : <Person: 0x17002d800>
    
    分析:

    block 捕获 arr,通过 arr 获取第一个保存的对象。对 arr 中保存的对象进行修改,arr 指向的还是原来的地址,隐藏 block_arr 能够获取到修改的对象

    相关文章

      网友评论

          本文标题:【知识总结】block 中使用返回对象

          本文链接:https://www.haomeiwen.com/subject/xsblwttx.html