oc中block的知识

1.oc里 nsstring/ block是什么意思

block 的表现在内存中位置

全局区:如果block中没有使用任何全局变量

栈区:如果 block 中使用了外部变量

MRC 模式可以看到

ARC 模式,系统会自动将 Block 复制到堆中

堆区:将 block 设置给 copy 属性

注意:虽然目前 ARC 编译器在设置属性时,已经替程序员复制了 block,但是定义 block时,仍然建议使用 copy 属性

注意:

2.OC 中得block ^ 后面的返回值什么时候可以省略,什么时候不能省

NSInteger是可以省略的:NSInteger (^myBlock)() = ^() { return 2; };这样写没有问题。

实际上返回值的省略不是一个值得成为问题的问题,报错了你就不省略就是了- -。

关于__block,一般来说,在block内只能读取在同一个作用域的变量而且没有办法修改在block外定义的任何变量,此时若我们想要这些变量能够在block中被修改,就必须在前面挂上__block关键字。不过有一个限制就是传入的变量在内存中必须是一个占有固定长度内存的变量。

在拥有引用计数(reference-counted)的环境中,若我们在block中引用到Objective-C的对象,在一般的情况下它将会自动增加对象的引用计数,不过若以__block为修饰词的对象,引用计数则是不受影响。如果我们在Objective-C的方法中使用block时,以下几个和内存管理的事是需要额外注意的:l 若直接存取实例变量(instance variable),self的引用计数将被加1。

l 若透过变量存取实例变量的值,则只变量的引用计数将被加1。实际上在ARC中,你根本不用担心上面的引用计数增加的问题,因为ARC会知道对象在什么时候引用计数加1了,ARC会帮你在适当的地方release的。

3.看我怎么搞定OC的block和Swift的闭包

Object-c申明一个在函数中使用Block且不带参数和没返回值的block // ****1:在函数中使用Block不带参数和没返回值的block -(void)AFNetWork:(NSString *)name withComplated:(void(^)())complated { NSLog(@”—-函数中打印-%@”,name); if (complated) { complated(); } } // ********调用函数 [self AFNetWork:@”ZZ” withComplated:^{ NSLog(@”—-Block–打印”); }]; Swift 声明不带参数和没返回值的闭包 // 声明不带参数和没返回值的闭包 func HttpTools(names: Int ,complated:() -> ()) -> Int { let resInt = names + 10 print(“1:先执行函数”) complated() return resInt } // ********调用 HttpTools(15) { print(“2:在执行Block了”) } Object-C 声明带参数和有返回值的Block在函数名中 // ***2:声明带参数和有返回值的Block在函数名中 -(void)AFNetWork:(NSString *)name withComplatedRetunStr:(NSString *(^)(NSString * names,NSString * school))complated { NSLog(@”—-函数中打印带参数有返回值-%@”,name); if (complated) { complated(name,@”军事博物馆”); } } // ********调用 [self AFNetWork:@”中国” withComplatedRetunStr:^NSString *(NSString *names,NSString * school) { NSLog(@”—-Block函数中打印带参数有返回值-%@—–%@”,names,school); return names; }]; Swift 声明带参数和有返回值的闭包在函数名中 // 声明带参数和有返回值的闭包在函数名中 func ajaxTools(name:String ,complated:(runStr: String,isStop:Bool) -> String) -> String { let resStr = name + “覆水难收” complated(runStr: resStr, isStop: true) return resStr + ” – 内部函数返回” } // ********调用 let ajaxResult = ajaxTools(”洲洲哥”) { (runStr, isStop) -> String in print(“—–(runStr)”) return “” } **Object-C里子页面给父页面传值** 工程目录 OC-Block.png 在SecondViewController.h文件中 申明一个Block typedef void(^changUserName)(NSString * userNames); 把Block申明成属性 @property (nonatomic, copy) changUserName changText; // 还可把set方法抛出来(或者使用实例方法调用) -(void)setChangText:(changUserName)changText; 点击返回按钮的回调方法我们要这样写 -(void)playVideoBack { if (self.changText) { self.changText(self.inputFiled.text); } [self.navigationController :YES]; } **在跳转按钮的方法里我们这样写(两种方法,对不两种不同属性哦) -(void)ButtonClick { SecondViewController * sec = [[SecondViewController alloc] init]; /**防止循环引用*/ __weak typeof(self) WeakSelf = self; // 第一种写法 // sec.changText = ^(NSString * textStr) { // WeakSelf.userNames.text = textStr; // [WeakSelf AFNetWork:@”历史遗留痕迹” withComplated:^{ // NSLog(@”—-block—弱引用”); // }]; // }; // 第二种写法 [sec setChangText:^(NSString *userNames) { WeakSelf.userNames.text = userNames; [WeakSelf AFNetWork:@”历史遗留痕迹” withComplated:^{ NSLog(@”—-block—弱引用”); }]; }]; [self.navigationController pushViewController:sec animated:YES]; } **Swift里子页面给父页面传值** 工程目录 swift-闭包.png 在SecondViewController.swift文件中 申明一个闭包 typealias changUserName = (String) ->() 把闭包申明成属性 var changText: changUserName? // 或者使用实例方法调用(方法名字不固定,但参数是必须的) func setMyChangeName(tempClose: changUserName) { self.changText = tempClose } 点击返回按钮的回调方法我们要这样写 func pushClick() { changText!(self.changName.text!) self.navigationController?.(true) } **在跳转按钮的方法里我们这样写(两种方法,对不两种不同属性哦) func ClickAction() { let secondVC = SecondViewController() // 防止循环引用 weak var WeakSelf = self // 第一用方法 secondVC.changText = { (names) -> () in print(“——(names)”) WeakSelf!.userNames!.text = names } // 第二用方法 // secondVC.setMyChangeName { (names) in // print(“——(names)”) // WeakSelf!.userNames!.text = names // } self.navigationController?.pushViewController(secondVC, animated: true) }。

%title插图%num