block的使用总结:如果有感觉任何遗漏的话,欢迎留言补充,Block的循环使用那部分,这里我只贴出了解决方案,注意点应该是没有问题的
Block的使用
int a = 10; NSLog(@"1-----------%d %p",a,&a); void(^block)(void) = ^{ NSLog(@"2-----------%d %p",a,&a); }; a = 20; block(); NSLog(@"3-----------%d %p",a,&a);
输出结果:
结论:
从输出结果可以看出block内和block外是两个作用域,内部的指针a和外部的指针a虽然名字一样但他们的内存地址已经不同了,这也就是我们可以内部修改局部变量的原因。在block内部会将局部变量的指正复制一份,这样内部和外部就不是一个指针了,就算你重新给内部指针赋值,也无法改变外部指针的指向,他们只是名字相同。
__block int a = 10; NSLog(@"1-----------%d %p",a,&a); void(^block)(void) = ^{ NSLog(@"2-----------%d %p",a,&a); }; a = 20; block(); NSLog(@"3-----------%d %p",a,&a);
输入结果
结论:
没有通过__block修饰则是将值传进去,而通过__block修饰之后是将变量的内存地址传进去,这样就可以修改变量的值。
static int a = 10; NSLog(@"1-----------%d %p",a,&a); void(^block)(void) = ^{ NSLog(@"2-----------%d %p",a,&a); a = 30; }; a = 20; block(); NSLog(@"3-----------%d %p",a,&a);
输入结果:
结论:静态变量的内存地址一致,所以可以修改变量的值
_a = 10; NSLog(@"1-----------%d %p",_a,&_a); void(^block)(void) = ^{ NSLog(@"2-----------%d %p",_a,&_a); }; _a = 20; block(); NSLog(@"3-----------%d %p",_a,&_a);
输出结果
结论:全局变量的内存地址一致,所以可以修改变量值
总结:1.如果block访问的外部变量是局部变量,那么就是值传递,外界改了,不会影响里面 2.如果block访问的外部变量是__block或者static修饰,或者全局变量,那么就是指针传递,block里面的值和外界属于同一变量,外界改变,里面也会改变
以上都是无返回值的Block,可以举例一个有返回值的block
// 先定一个block函数 int (^sumFunction)(int a, int b) = ^(int x, int y) { return (x + y); }; NSLog(@"--------------:%d",sumFunction(2, 3));//5
如果这个block经常用到,在可以外部定义一个block
typedef int(^sumFunction)(int a, int b);
在内部使用
// 先定一个block函数 sumFunction sum = ^(int x, int y) { return (x + y); }; NSLog(@"--------------:%d",sum(2, 3));//5
block在fun的使用
+(void)sumFunctionWithA:(int)a withB:(int)b withBlock:(void (^)(int sum))sumBlock{ int sum = a+b; sumBlock(sum); }
全局的block在fun的使用
定义:
typedef void(^SumBlock)(int sum);
+(void)sumFunctionWithA:(int)a withB:(int)b withBlock:(SumBlock)sumBlock{ int sum = a+b; sumBlock(sum); }
[ViewController sumFunctionWithA:2 withB:4 withBlock:^(int sum) { NSLog(@"---------------------------:%d",sum);//6 }];
外部调用
[ViewController sumFunctionWithA:2 withB:4 withBlock:^void(int sum) { NSLog(@"--------------------:%d",sum);//6 }];
Block作为一个属性进行传值,比方A跳转到B页面,B页面个A传值
在B页面设置Block的全局,在.h的属性方法里设置,这里只写了一个全局的,property一定要用copy,因为block的存在栈上,需要copy到堆上才能我们才能对block的内存进行管理
typedef void(^SumBlock)(int sum); @interface ViewController : UIViewController @property(nonatomic,copy)SumBlock sumBlock;
@end
在B页面需要传值的时间里面调用,一定要加if,不然可能会出现错误
在A页面跳转B页面的使用使用:这里的vc.sumBlock如果不写,B页面一定需要加if,不然报错
Block的注意事项
在block内部使用外部指针且会造成循环引用的的情况下,需要使用
__weak typeof(self)weakSelf = self;
如果在block内部调用了延迟函数如果还是用弱指针则会取不到指针,因为已经会销毁了,则需要使用强指针在引用一次
__strong typeof(self)strongSelf = weakSelf;