#import "AppDelegate.h"
#import "RootViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
RootViewController *rootVC = [[RootViewController alloc]init];
UINavigationController *naVC = [[UINavigationController alloc]initWithRootViewController:rootVC];
self.window.rootViewController = naVC;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#import "RootViewController.h"
#import "TwoViewController.h"
//typedef之後,該block的別名就是block的名稱
typedef void(^argBlock)();
typedef void(^senderBlock)(NSString *str);
@interface RootViewController ()
@property(nonatomic,copy)argBlock circleBlock;
@end
@implementation RootViewController
//將block作爲方法的參數,作爲方法參數的時候,必須使用typedef修飾
-(void)testBlockWithBlock:(argBlock)senderBlock name:(NSString *)name{
NSLog(@"name---%@",name);
//當block作爲參數的時候,和普通類型一樣的,普通類型是需要我們使用該參數,block類型是需要我們調用該參數block
senderBlock();
}
//帶參數的block作爲一個方法的參數
-(void)myBlockWithBlock:(senderBlock)sender{
//將一個字符串傳遞出去
sender(@"我是要傳遞出去的字符串");
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"Block學習";
//使用typedef的block
argBlock typeBlock = ^(){
NSLog(@"MLGBWC,我是typedef");
};
typeBlock();
//調用帶block參數的方法
[self testBlockWithBlock:^{
NSLog(@"參數block");
}name:@"name"];
//__block外部串值 //block方法傳遞參數
__block NSString *Vstr = nil;
[self myBlockWithBlock:^(NSString *str) {
Vstr = str;
NSLog(@"str---%@",str);
}];
NSLog(@"Vstr---%@",Vstr);
//Block的學習
//第一種: 無返回值無參數的block定義以及實現
//void(^)(void) 當前block的類型
//block的名稱爲 oneBlock,類似於C語言中的函數名
//賦值號左邊爲block聲明,右邊爲實現
void (^oneBlock)(void) = ^(){
NSLog(@"Hello World");
};
//調用block 不管有沒有參數,都需要書寫小括號
oneBlock();
//調用外部的block
//第二種: 有返回值無參數的block聲明及實現
//有返回值的block需要在實現體內 return返回值
int (^twoBlock)(void) = ^(){
return 1000;
};
//調用block
int b = twoBlock();
NSLog(@"b---%d",b);
//第三種: 無返回值有參數的block聲明及實現
void(^threeBlock)(NSString *name) = ^(NSString *bb){
NSLog(@"我是bb--%@",bb);
};
//調用block
threeBlock(@"aaaaaaa");
//第三種://兩個參數的block
void(^fourBlock)(NSString *name,NSString *sex) = ^(NSString *cc,NSString *dd){
NSLog(@"%@,%@",cc,dd);
//拼接
NSString *pinjie = [cc stringByAppendingString:dd];
NSLog(@"%@",pinjie);
//拼接.2方法,一般拼接文件路徑
NSString *pinjie2 = [cc stringByAppendingPathComponent:dd];
NSLog(@"%@",pinjie2);
};
//調用
fourBlock(@"Han",@"OBa");
//第四種: 有返回值有參數的block聲明及實現
NSString *(^fiveBlock)(NSString *name) = ^(NSString *name){
return name;
};
//調用
NSString *name = fiveBlock(@"口鼻");
NSLog(@"%@",name);
//在block實現體內 使用外部變量
//當我們需要在block實現體內 對外部的局部變量做更改的時候,需要在局部變量的聲明之前加雙下劃線block(__block).未添加__block修飾的局部變量,block並沒有持有該變量,所以block只能使用該變量,但是不能做更改。使用__block修飾的局部變量,在block實現體 使用的時候,block是真正持有該變量,所以可以做修改
//__block修飾的局部變量,實際上是將該變量的作用域範圍擴大了一些,不光能在ViewDidLoad方法中使用該變量,也可以在block函數的作用域中使用該變量
__block int k = 1000;
//聲明並實現一個block
void (^myBlock)(void) = ^(){
NSLog(@"k-----%d",++k);
};
myBlock();
NSLog(@"%d",k);
//block的循環引用,有可能會造成內存泄露
//當block是self的一個屬性的時候,我們在block實現體內需要使用到self得時候,有可能會造成循環引用,導致的結果爲self的引用計數有可能爲2,釋放不掉,造成內存泄露。所以我們需要使用__weak關鍵字來修飾self對象,讓該對象在block實現體內不需要內存管理,這個時候引用計數也就不會增加。
//在ARC下使用__weak,在MRC下使用__block修飾。
__weak RootViewController *my_self = self;
self.circleBlock = ^(){
my_self.navigationItem.title =@"AAA";
};
//右按鈕
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc]initWithTitle:@"跳轉" style:UIBarButtonItemStylePlain target:self action:@selector(rightAction:)];
self.navigationItem.rightBarButtonItem = rightButton;
}
/*
//在方法外部聲明並實現block (瞭解知道就ok)
void (^outBlock)(void) = ^(){
NSLog(@"外面的block");
};
*/
//右按鈕回調方法
-(void)rightAction:(UIBarButtonItem *)sender{
NSLog(@"跳轉到下個界面");
TwoViewController *twoVC = [[TwoViewController alloc]init];
//調用two頁面的block,接收block的參數值
twoVC.passSender = ^(NSString *str){
NSLog(@"title-----%@",str); //打印,用於查看是否將值傳遞過來了
self.navigationItem.title = str;
};
[self.navigationController pushViewController:twoVC animated:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
#import "TwoViewController.h"
@interface TwoViewController ()
@end
@implementation TwoViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"MLGBWC";
//左按鈕
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(leftAction:)];
self.navigationItem.leftBarButtonItem = leftButton;
}
//左按鈕的回調方法
-(void)leftAction:(UIBarButtonItem *)sender{
NSLog(@"返回上一個界面");
//使用block將該界面的值傳遞到上個界面
self.passSender(@"標題");
[self.navigationController popViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end