//bolck:一塊代碼.聲明block類型的指針是指向一塊代碼,而不是一個對象
//block:閉包和匿名函數(shù)在OC中的實現(xiàn)
創(chuàng)建類型有多種:
1.無返回值無參數(shù)
2.無返回值有參數(shù)
3.有返回值有參數(shù)(有返回值要接收)
創(chuàng)建方式有3種: ??格式:(變量名)(參數(shù))
1.聲明和創(chuàng)建分開 ?調(diào)用時必須有()
//第一種方式:聲明一個無參數(shù)無返回值類型的block指針
//1.1聲明和創(chuàng)建分開block
void(^block1)(void);
//創(chuàng)建一個block (無參數(shù)無返回值類型的block)
block1 = ^(void){
//block的創(chuàng)建就類似于方法,同樣只有調(diào)用才會執(zhí)行block塊中的代碼
NSLog(@"***我執(zhí)行了***");
};
//block調(diào)用----即沒有參數(shù)必須加()
block1();
//1.2聲明和創(chuàng)建一起
//注意:當我們的參數(shù)為void的時候,聲明可以忽略聲明中的void,創(chuàng)建時可以省略(void)
void(^block2)() = ^{
NSLog(@"---我是一個省略(void)參數(shù)的block");
};
block2();
//1.3:宏定義方式
MyBlock blocck3;
blocck3 = ^ {
NSLog(@"我是重定義的");
};
blocck3();
2.聲明和創(chuàng)建一起 (注意:當我們的參數(shù)為void的時候,聲明可以忽略聲明中的void,創(chuàng)建可以忽略(void))
//第二種方式:有一個參數(shù)無返回值類型的block指針
void(^block4)(int a,int b);//等價于void (^block4)(int ,int )
block4 = ^(int a,int b){
NSLog(@"%d + %d = %d",a,b,a+b);
};
block4(1,3);
//多個參數(shù)之間逗號隔開
Plus block5 = ^(int a,int b){
NSLog(@"從定義后的加法%d+%d=%d",a,b,a+b);
};
block5(3,4);
3.宏定義方式:在接口之前聲明
typedef void(^別名)(參數(shù),參數(shù))
//給數(shù)據(jù)類型起別名----定義一個新的數(shù)據(jù)類型
//1.寫像聲明一個變量的代碼
//2.將變量名改為你想要的別名
//3.語句前加上typedef
//給void(^)(void)類型的block指針起別名
typedef void (^MyBlock)(void);
別名block;
block = ^ {block code};
block (參數(shù));
//第三種方式:有返回值多個參數(shù)的block類型指針
NSString * (^block6)(int,NSString* name);
block6 = ^(intage,NSString* name){
return [NSString stringWithFormat:@"我叫%@,%d歲",name,age];
};
//有返回值定義要接收
NSString *info = block6(18,@"翠花");
NSLog(@"---%@----",info);
Info block7 = ^(intage,NSString* name){
return[NSString stringWithFormat:@"== my name is %@,%d age ==",name,age];
};
NSString *new = block7 (2,@"baby");
NSLog(@"%@",new);
block_cycle
- (void)viewDidLoad {
[super viewDidLoad];
self.objc= [[NSObject alloc] init];
void(^block)(void) = ^{
};
Block_copy(block);
Block_release(block);
block();
}
//block的聲明用copy:因為我們的block是聲明在棧上,如果用retain,那么block依舊在棧上,當方法結(jié)束執(zhí)行后,棧上就會被釋放.所以我們要copy到堆上,堆內(nèi)存有我們自己管理,不會被隨意釋放
//棧上copy到堆上手動管理不會被隨意釋放
@property (nonatomic,copy) MyBlockblock;
使用局部變量以防止出現(xiàn)循環(huán)引用
//**如果我們在block(用copy描述屬性的block)中用到self,會導致block對視圖控制器(self), --->retain會導致循環(huán)引用(我們當前的視圖控制器無法釋放)
//解決辦法:__block SecondViewController * vc = self;
__block SecondViewController *vc =self;
//為了防止循環(huán)引用聲明一個局部的視圖控制器 == self
//對于成員變量也可以聲明局部變量對其進行接收在對局部變量進行操作即可
//**如果我們在block(用copy描述屬性的block)中用到self,會導致block對視圖控制器(self), --->retain會導致循環(huán)引用(我們當前的視圖控制器無法釋放)
//解決辦法:__block NSObject * obc = _obje;
__blockNSObject* obc =_obje;
#pragma mark ==對非基本數(shù)據(jù)類型的影響
/*
block對于非基本數(shù)據(jù)類型的影響
對于沒有__block修飾的局部非基本數(shù)據(jù)類型的變量,block內(nèi)會對其進行淺copy,也就是說,block內(nèi)外的people對象不是同一個,無任何關(guān)系,而且block內(nèi)的people只能讀不能寫,但是我們可以修改對象的屬性
對于成員變量(全局變量,非基本數(shù)據(jù)類型)或者有)__block修飾的局部非基本數(shù)據(jù)類型的變量,block內(nèi)外是同一個值(訪問同同一塊內(nèi)存),而且可以對其值進行修改
*/
#pragma mark ==對基本數(shù)據(jù)類型的影響
/*
block對于基本數(shù)據(jù)類型的影響
對于沒有__block修飾的局部基本數(shù)據(jù)類型的變量,block內(nèi)會對其值進行copy(淺),也就是說,block內(nèi)外的count不是同一個,無任何關(guān)系,而且block內(nèi)的count只能讀,不能寫,
對于成員變量(全局,基本數(shù)據(jù)類型)或者有__block修飾的局部基本數(shù)據(jù)類型的變量,block內(nèi)外是同有個值(深copy ,訪問同一塊內(nèi)存),而且可以對其值進行修改
*/
自定義block塊回調(diào)
在要傳值的.h界面聲明一個typedef void ( ^方法名)(類 * 參數(shù)名)的block,并寫一個返回值類型為id的帶參數(shù)的自定義方法(不要*);然后在.m文件中實現(xiàn)這個方法,用block的方法名聲明一個block接收自定義方法的參數(shù) ,擴大作用域.在要回傳的方法中調(diào)用block塊,回調(diào)時()內(nèi)的參數(shù)就是要傳的值
在要接收值的界面,在聲明界面初始化的時候,調(diào)用自定義方法,在方法的block塊中接收值.