block聲明
// block聲明:返回值(^block變量名)(參數)
void(^block)();
block的定義方式(三種)
// block定義:三種方式 = ^(參數){};
// 第一種
void(^block1)() = ^{
NSLog(@"調用了block1");
};
// 第二種 如果沒有參數,參數可以隱藏,如果有參數,定義的時候,必須要寫參數,而且必須要有參數變量名
void(^block2)(int) = ^(int a){
};
// 第三種 block返回可以省略,不管有沒有返回值,都可以省略
int(^block3)() = ^int{
return 3;
};
// block快捷方式 inline
// <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
// <#statements#>
// };
block 調用
block1();
通過typedef聲明一個block的類型
//FinishBlock:Block的類型名
typedef int(^FinishBlock)(int a,NSString *s);
//定義
FinishBlock myBlock1 =^(int a,NSString *s){
NSLog(@"myBlock1被調用了");
return 101;
};
//(3)block的調用
myBlock1(21,@"Block1");
注意:block的調用順序:
1 block塊 第一次運行的時候,不執行block塊
2 block塊執行的時機:調用block函數
block 使用方式
- 1.在一個方法中定義,在另外一個方法調用(不推薦使用,完全可以用方法的形式代替)
- 2.在一個類中定義,在另外一個類中調用(推薦使用,block的作用就是保存一段代碼)
- 3.注意:在編寫程序時,不要一味著想用block而用block,關鍵是看是否用block編寫是否為最佳形式
block傳值
- 1.傳值的核心思想:只要能拿到對方(類或對象)就能傳值
- 2.傳值包括兩種:
- 順傳:給需要傳值的對象,直接定義屬性就能傳值
- 逆傳:用代理,block,就是利用block去代替代理
//簡單demo
#import "ViewController.h"
#import "ModalViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
ModalViewController *modalVc = [[ModalViewController alloc] init];
modalVc.view.backgroundColor = [UIColor brownColor];
modalVc.block = ^(NSString *value) {
NSLog(@"%@",value);
};
// 跳轉
[self presentViewController:modalVc animated:YES completion:nil];
}
#import <UIKit/UIKit.h>
@interface ModalViewController : UIViewController
//設置一個block屬性
@property (nonatomic, strong) void(^block)(NSString *value);
@end
#import "ModalViewController.h"
@interface ModalViewController ()
@end
@implementation ModalViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 傳值給ViewController
// @"123"
if (_block) {
_block(@"123");
}
block內存管理機制
block是不是一個對象?是一個對象
如何判斷當前文件是MRC,還是ARC
1.dealloc 能否調用super,只有MRC才能調用super
2.能否使用retain,release.如果能用就是MRC
ARC管理原則:只要一個對象沒有被強指針修飾就會被銷毀,默認局部變量對象都是強指針,存放到堆里面
MRC了解開發常識:1.MRC沒有strong,weak,局部變量對象就是相當于基本數據類型
MRC給成員屬性賦值,一定要使用set方法,不能直接訪問下劃線成員屬性賦值
總結:只要block沒有引用外部局部變量,block放在全局區
-
MRC:管理block
- 只要Block引用外部局部變量,block放在棧里面.
- block只能使用copy,不能使用retain,使用retain,block還是在棧里面,會被銷毀
- ARC:管理block
- 只要block引用外部局部變量,block放在堆里面
- block使用strong.最好不要使用copy
- 補充:NSString也是最好使用strong,最好不要使用copy
block變量傳遞
// 如果是局部變量,Block是值傳遞
// 如果是靜態變量,全局變量,__block修飾的變量,block都是指針傳遞
int a=3;
- (void)viewDidLoad {
[super viewDidLoad];
//__block int a = 3;
// int a = 3;
// static int a =3;
void(^block)() = ^{
NSLog(@"%d",a);
};
a = 5;
block();
}
block作為參數使用
- (void)viewDidLoad {
[super viewDidLoad];
// 創建計算器管理者
CacultorManager *mgr = [[CacultorManager alloc] init];
[mgr cacultor:^(NSInteger result){
result += 5;
result += 6;
result *= 2;
return result;
}];
NSLog(@"%ld",mgr.result);
}
#import <Foundation/Foundation.h>
@interface CacultorManager : NSObject
@property (nonatomic, assign) NSInteger result;
// 計算
- (void)cacultor:(NSInteger(^)(NSInteger result))cacultorBlock;
@end
#import "CacultorManager.h"
@implementation CacultorManager
- (void)cacultor:(NSInteger (^)(NSInteger))cacultorBlock
{
if (cacultorBlock) {
_result = cacultorBlock(_result);
}
}
@end
block作為返回值使用
- (void)viewDidLoad {
[super viewDidLoad];
/*
鏈式編程思想:把所有的語句用.號連接起來,好處:可讀性非常好
*/
CalculatorManager *mgr = [[CalculatorManager alloc] init];
mgr.add(5).add(5).add(5).add(5);
NSLog(@"%d",mgr.result);
#import <Foundation/Foundation.h>
@interface CalculatorManager : NSObject
@property (nonatomic, assign) int result;
- (CalculatorManager *(^)(int))add;
@end
}
#import "CalculatorManager.h"
@implementation CalculatorManager
- (CalculatorManager *(^)(int))add
{
return ^(int value){
_result += value;
return self;
};
}