iOS(閉包)block傳值詳解
在iOSAPP開發(fā)的過程中 我們會用到很多需要傳值的地方 傳值的方式也多種多樣 有:代理傳值、通知傳值、KVC、KVO、block、單例 等。其中block 因為其簡潔實用規(guī)范的代碼 無疑是大牛們傳值的不二選擇 但對于初學(xué)者來說要理解并能運用 起初確實有些難以理解 以下我將細細的介紹下block
首先我總結(jié)了一下block的公式:
- 步驟1.block 的聲明 返回值類型(^block 的名字)(參數(shù)列表);
- 步驟2.block 實現(xiàn) block的名字 = ^(參數(shù)列表)(){};
- 步驟3.block 的調(diào)用 block的名字();
下面是一個簡單的block
// 聲明
void(^blockName)(int num,NSString *string);
// 實現(xiàn)
blockName = ^(int num,NSString *string)
{
NSLog(@"%d,%@",num,string);
};
// 調(diào)用
blockName(520,@"phyone_");
}
由該例可以看出block的代碼執(zhí)行順序和其他的代碼執(zhí)行順序不一樣 它是先執(zhí)行聲明代碼 然后執(zhí)行調(diào)用代碼 最后才執(zhí)行實現(xiàn)代碼 由此我們利用block的回調(diào)性質(zhì) 達到我們傳值效果 當(dāng)然這只是在一個頁面的一段代碼 只是說明了它具有傳值的作用 下面我們來試試 多頁面之間的block反向傳值 由于是反向傳值 所以我們創(chuàng)建兩個ViewController (ViewController,Next_ViewController)先由ViewController跳到Next_ViewController里將里面的值反向傳給ViewController
以下是代碼
ViewController.m里面
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor purpleColor];
UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
lable.backgroundColor = [UIColor brownColor];
[self.view addSubview:lable];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
[self.view addGestureRecognizer:tap];
}
- (void)tap
{
Next_ViewController *NVC = [[Next_ViewController alloc]init];
NVC.block = ^(NSString *content){
NSLog(@"%@",content);
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(100, 200, 100, 100)];
[button setTitle:content forState:UIControlStateNormal];
button.backgroundColor = [UIColor orangeColor];
[self.view addSubview:button];
};
[self presentViewController:NVC animated:YES completion:nil];
}
Next_ViewController.h里面
//block 是分配在棧里面的用copy @property(nonatomic,copy) void(^block)(NSString *content);
Next_ViewController.m里面
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">{</span></p>
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;"> void(^imageNameBlock_1)(NSString *imageName);</span></p>
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;"> void(^lableBlock)(NSString *tontentText);</span></p>
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">}</span></p>
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(100, 200, 100, 50);
[button setTitle:@"123456" forState:UIControlStateNormal];
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (void)buttonAction:(UIButton *)sender
{
// 點擊按鈕 返回上一個頁面 同時通過block 把這個值傳到上一個頁面
self.block(sender.titleLabel.text);
[self dismissViewControllerAnimated:nil completion:nil];
}
另外:block 還有兩個問題
1.怎么改變block里面的值
用上面的代碼 在ViewController.m viewDidLoad 里面 添加代碼
1.局部變量
定義一個圖片名字的Block
*/
// 局部變量
void(^imageNameBlock)(NSString *imageName);
// 如果想修改Block里面的值 需添加__block修飾
// __block UIImage *image;
imageNameBlock = ^(NSString *imageName)
{
image = [UIImage imageNamed:imageName];
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
};
imageNameBlock(@"17.jpg");
就會出現(xiàn) Use of undeclared identifier 'image' 錯誤情況 原因是我們試圖改變block里面的值 解決辦法就是 添加 __block 修飾(解注釋
__block UIImage *image;) 就行了
2.block的循環(huán)引用
用上面的代碼 在ViewController.m viewDidLoad 里面 添加代碼
// 全局變量
// block循環(huán) 引用 解決 我們用弱引用 __block
__weak ViewController *VC = self;
__block UIImage *image = nil;
imageNameBlock_1 = ^(NSString *imageName)
{
image = [UIImage imageNamed:imageName];
VC.view.backgroundColor = [UIColor colorWithPatternImage:image];
};
UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
lable.backgroundColor = [UIColor brownColor];
[self.view addSubview:lable];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
[self.view addGestureRecognizer:tap];
再添加兩個方法
- (void)loadData
{
imageNameBlock_1(@"17.jpg");
}
- (void)viewWillAppear:(BOOL)animated
{
[self loadData];
}
當(dāng)出現(xiàn)循環(huán)引用是我們用__weak修飾下 但具體機制還不太懂 希望高人指點,感謝大家對腳本之家的支持。
相關(guān)文章
iOS中解決Xcode9的Log日志無法輸出中文的問題小結(jié)
這篇文章主要介紹了iOS中解決Xcode9的Log日志無法輸出中文的問題小結(jié),需要的朋友可以參考下2017-11-11
iOS中UIActivityIndicatorView的用法及齒輪等待動畫實例
UIActivityIndicatorView活動指示器最常見的用法便是用來制作那個程序中的齒輪轉(zhuǎn)動的等待效果,接下來我們回來簡單整理iOS中UIActivityIndicatorView的用法及齒輪等待動畫實例:2016-05-05
iOS開發(fā)中使用Quartz2D繪圖及自定義UIImageView控件
這篇文章主要介紹了iOS開發(fā)中使用Quartz2D繪圖及自定義UIImageView控件的方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-11-11
分享一個關(guān)于Storyboard 跳轉(zhuǎn)與傳值
近日不忙,給大家分享一個關(guān)于storyboard跳轉(zhuǎn)傳值的相關(guān)知識,感興趣的朋友一起看看吧2015-12-12
iOS統(tǒng)計代碼總行數(shù)的命令(便捷且簡單)
在工作中有時候會需要統(tǒng)計我們工程的總代碼行數(shù),下面小編給大家分享一個超便捷超簡單的方法,通過一行命令統(tǒng)計ios代碼總行數(shù),需要的朋友參考下吧2017-11-11
iOS UILabel根據(jù)內(nèi)容自動調(diào)整高度
這篇文章主要為大家詳細介紹了iOS UILabel根據(jù)內(nèi)容自動調(diào)整高度,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06

