Block

什么是block

block其实就是一个代码块,把你想要执行的代码封装在这个代码块里,

等到需要的时候再去调用。

那block是OC对象吗?答案是肯定的

代理:打电话

Block:小弟

block的定义

1.block属性或变量

格式:返回值类型(^block名称)(参数列表)

 /*定义属性,block属性可以用strong修饰,也可以用copy修饰
  有小伙伴留言说苹果官方建议用copy,笔者查了下文档,
  确实是这样的,不过笔者未测试出copy与strong的区别,大家喜欢啥就用啥吧*/
 @property (nonatomic, strong) void(^myBlock)();//无参无返回值
 @property (nonatomic, strong) void(^myBlock1)(NSString *);//带参数
 @property (nonatomic, strong) NSString *(^myBlock2)(NSString *);//带参数与返回值
 //定义变量
 void(^myBlock)() = nil;//无参无返回值
 void(^myBlock1)(NSString *) = nil;//带参数
 NSString *(^myBlock2)(NSString *) = nil;//带参数与返回值

2.block被当做方法的参数

格式:(block类型)参数名称

//Block接受外界传入的代码块,也就意味着怎么去操作是由外界调用者决定的

 - (void)test:(void(^)())testBlock//无参无返回值
 - (void)test1:(void(^)(NSString *))testBlock//带参数
 - (void)test2:(NSString *(^)(NSString *))testBlock//带参数与返回值

3.使用typedef定义block

 typedef void(^myBlock)(); //以后就可以使用myBlock定义无参无返回值的block
 typedef void(^myBlock1)(NSString *); //使用myBlock1定义参数类型为NSString的block
 typedef NSString *(^myBlock2)(NSString *); //使用myBlock2定义参数类型为NSString,返回值也为NSString的block
 //定义属性
 @property (nonatomic, strong) myBlock testBlock;
 //定义变量
 myBlock testBlock = nil;
 //当做参数
 - (void)test:(myBlock)testBlock;

block的赋值

格式:block = ^返回值类型(参数列表){}

1.没有参数没有返回值

myBlock testBlock = ^void(){
     NSLog(@"test");
 };
 //没有返回值,void可以省略
myBlock testBlock1 = ^(){
     NSLog(@"test1");
 };
 //没有参数,小括号也可以省略
 myBlock testBlock2 = ^{
     NSLog(@"test2");
 };

2.有参数没有返回值

myBlock1 testBlock = ^void(NSString *str) {
      NSLog(str);
}
//省略void
myBlock1 testBlock = ^(NSString *str) {
      NSLog(str);
}

3.有参数有返回值

myBlock2 testBlock = ^NSString *(NSString *str) {
     NSLog(str)
     return @"hi";
}
//有返回值时也可以省略返回值类型
 myBlock2 testBlock2 = ^(NSString *str) {
     NSLog(str)
     return @"hi";
}

使用block传递数据

1.在B控制器的.h文件中定义一个没有返回值,参数类型为Person的block属性

 @property (nonatomic, strong) void(^saveBlock)(Person *);

2.在B控制器“保存”按钮的点击方法中调用block

 - (IBAction)save:(id)sender {
     //使用事先定义好的类方法创建Person对象
  Person *person = [Person personWithName:_nameText.text phoneNumber:_phoneNumberText.text];
   /**调用block之前最好先判断block是否为空,不为空才调用,否则程序崩溃*/
   //装逼写法
 //!self.saveBlock? : self.saveBlock(person);
   //一般写法
   if (self.saveBlock) {
       self.saveBlock(person);
   }
  [self.navigationController popViewControllerAnimated:YES];
 }

3.在A控制器中,给B控制器的block属性进行赋值

   //“新建”按钮点击执行的方法
   - (void)newContact {
     AddContactViewController *addVC = [[AddContactViewController alloc] init];
     addVC.saveBlock = ^(Person *person){
          //这里就可以拿到B控制器传递过来的person对象,添加到数组然后刷新表格
      [self.contactList addObject:person];
      [self.tableView reloadData];
     };
     [self.navigationController pushViewController:addVC animated:YES];
    }

block常见雷区---循环引用

使用block有一个特别要注意的地方,循环引用,何为循环引用?你引用我,我引用你,谁也不释放谁,对象无法销毁,占用内存

举例:block对象赋值给了控制器的属性,因此控制器会对block有一个强引用,而block中又用到了self(控制器对象),block会对使用到的外部变量进行捕获,所以,block对B控制器也有一个强引用,最终造成循环引用,谁也无法释放

循环引用解决方法

__weak typeof(self) weakSelf = self;

使用weakSelf(名称随便取的)替代self,block将不再对self进行强引用 图中weak也可使用unsafe_unretained,区别就是weak修饰的指针,当对象销毁后,指针会被自动置为nil,而unsafe_unretained修饰的指针,当对象销毁后会变成野指针,为了安全,推荐使用__weak

results matching ""

    No results matching ""