void (^mutiplayBlock)(NSString *) = ^(NSString *str) {
NSLog(@"st=%@", str);
};
void :block返回值类型;
^ :脱字符,块语法标记
^mutiplayBlock :脱字符将mutiplayBlock声明为一个块对象
NSString * : 参数类型
递归关系就是实体自己和自己建立关系。
__nullable表示对象可以是NULL或nil,而__nonnull表示对象不应该为空
具体常用的用法(可以添加参数跟返回值)
import <UIKit/UIKit.h>
typedef void(^MyFirstBlock)(NSString *str);
typedef void(^MySecondBlock)(NSString *str);
typedef void(^setColor)(UIColor *);
@interface ViewController : UIViewController
@property (nonatomic, copy) void (^MyBlock)(NSString *block);
@property (nonatomic, copy) setColor color;
- (void)creatBlock:(void (^)(NSDictionary *dic))success;
- (void)firstBlock:(MyFirstBlock)first
second:(MySecondBlock)second;
@end
ARC情况下
1.如果用copy修饰Block,该Block就会存储在堆空间。则会对Block的内部对象进行强引用,导致循环引用。内存无法释放。解决方法:新建一个指针(__weak typeof(Target) weakTarget = Target )指向Block代码块里的对象,然后用weakTarget进行操作。就可以解决循环引用问题。
2.如果用weak修饰Block,该Block就会存放在栈空间。不会出现循环引用问题。
MRC情况下用copy修饰后,如果要在Block内部使用对象,则需要进行(__block typeof(Target) blockTarget = Target )处理。在Block里面用blockTarget进行操作。
声明block的时候实际上是把当时的临时变量又复制了一份,在block里即使修改了这些复制的变量,也不影响外面的原始变量。即所谓的闭包。
但是当变量是一个指针的时候,block里只是复制了一份这个指针,两个指针指向同一个地址。所以,在block里面对指针指向内容做的修改,在block外面也一样生效。
__weak __typeof(&*self)weakSelf =self; 等同于
__weak UIViewController *weakSelf =self;
__strong typeof(self) strongSelf = weakSelf; 在块语法内部调用
为什么不用__block 是因为通过引用来访问self的实例变量 ,self被retain,block也是一个强引用,引起循环引用,用__week是弱引用,当self释放时,weakSelf已经等于nil。
__block 为了改变block代码块外部的变量。
__weak 是为了防止循环引用(memory cycle),引起内存泄露的问题。不会影响对象的释放, 对象在被释放的同时,指向它的弱引用会自动被置nil
strong所声明的变量将成为对象的持有者;引用计数+1
weak 所声明的变量将没有对象的所有权,对象可以自动赋值nil;引用计数不变
copy 所声明的变量是拷贝对象的持有者。引用计数+1