標籤:
原始碼下載
淺談block使用方法
對於block他用著確實方便,好多人都非常迷茫,這裡寫了一個Demo解說block的使用方法
好多人都覺得block是用於後一個介面向前一個介面傳值用的,事實上更詳細的說是經常使用來介面之間的傳值,事實上僅僅要須要傳值不管是view之間還是controller之間還是view與controller之間都能夠用block,當傳值比較少時用block比使用代理更方便.
block建立後都在棧區存放的,block的語義特性必須用copy,通過copy能夠將block從棧區放到堆區,保證每次使用block時block都存在,因此我們使用時經常要定義屬性,使用屬性是為了儲存該block變數
例如以下舉個範例解說
首先在project中建立兩個類BlockViewController和BlockView
在BlockView中僅僅是為了建立幾個button,在BlockViewController中使用,能夠降低BlockViewController的代碼任務量,可是BlockView中僅僅有一個執行個體變數button是,而且在延展中定義的,外部無法訪問到,當我們為button加入點擊觸發事件就須要獲得button的tag值,這時就要把所點擊button的tag擷取到,來為不同的button加入響應事件
在BlockView.h中定義一個block變數和一個方法,方法的參數是block類型的
#import <UIKit/UIKit.h>//第一步:聲明blocktypedef void(^ButtonActionBlock)(NSInteger tag);@interface BlockView : UIView-(void)buttonActionBlock:(ButtonActionBlock)didClickButton;@end
在BlockView.m中
<pre name="code" class="objc">#import "BlockView.h"@interface BlockView ()//Block//block建立後都在棧區存放的,block的語義特性必須用copy,通過copy能夠將block從棧區放到堆區,保證每次使用block時block都存在@property (nonatomic, copy) ButtonActionBlock buttonActionBlock;@property (nonatomic, strong) UIButton *button;@end@implementation BlockView- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { CGFloat x = 5; CGFloat y = 5; CGFloat width = 65; CGFloat height = 40; //建立button for (int i = 0; i < 4; i ++) { self.button = [UIButton buttonWithType:(UIButtonTypeSystem)]; self.button.frame = CGRectMake(x + i * (width + 10), y, width, height); self.button.tag = 100 + i; self.button.backgroundColor = [UIColor cyanColor]; self.button.layer.cornerRadius = 5; self.button.layer.masksToBounds = YES; [self.button setTitle:[NSString stringWithFormat:@"%d",i] forState:UIControlStateNormal]; [self.button addTarget:self action:@selector(handleButton:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:_button]; } } return self;}//處理button的點擊事件,將tag值傳給block的參數回調block-(void)handleButton:(UIButton *)button{ NSLog(@"???????????????3"); NSInteger tag = button.tag; //第二步,回掉block self.buttonActionBlock(tag),NSLog(@"???????????????6"); NSLog(@"???????????????7"); }//該方法中self.buttonActionBlock = didClickButton;運行後會調用屬性buttonActionBlock的setter方法,將block變數didClickButton傳給setter方法的參數-(void)buttonActionBlock:(ButtonActionBlock)didClickButton{ NSLog(@"???????????????1"); NSLog(@"-----------didClickButton = %p",didClickButton); self.buttonActionBlock = didClickButton; }//重寫屬性buttonActionBlock的setter方法,在此重寫setter方法目的是為了表明該方法是把傳進來的block變數進行深拷貝,複製到了堆區,並賦給了執行個體變數buttonActionBlock,使我們在不論什麼時候都能使用block變數(block的建立後在棧區,出了方法就被回收,無法再使用)- (void)setButtonActionBlock:(ButtonActionBlock)buttonActionBlock{ NSLog(@"???????????????2"); if (_buttonActionBlock != buttonActionBlock) { NSLog(@"++++++++buttonActionBlock = %p",buttonActionBlock); _buttonActionBlock = [buttonActionBlock copy]; }}@end
BlockViewController.m檔案裡匯入BlockView.h檔案
BlockViewController.m檔案中代碼實現
#import "BlockViewController.h"#import "BlockView.h"// 擷取RGB顏色#define RGBA(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]@interface BlockViewController ()<UIScrollViewDelegate>@property (nonatomic, strong) UIImageView *YJFImageView;@end@implementation BlockViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { } return self;}- (void)viewDidLoad{ [super viewDidLoad]; self.view.backgroundColor = RGBA(252, 230, 201, 1.0); BlockView *blockView = [[BlockView alloc] initWithFrame:CGRectMake(10, 0, 320 - 20, 50)]; blockView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:blockView]; //BlockView的對象blockView調用其方法buttonActionBlock: //第三步。調用block [blockView buttonActionBlock:^(NSInteger tag) { //block的實現 NSLog(@"???????????????4"); [self handleButton:tag]; NSLog(@"???????????????5"); }]; [self createView];}//處理自己定義toolBar的點擊事件-(void)handleButton:(NSInteger)tag{ switch (tag) { //...button case 100: { self.YJFImageView.image = LOADIMAGE(@"2", @"jpg"); } break; //...button case 101: { self.YJFImageView.image = LOADIMAGE(@"5", @"jpg"); } break; //...button case 102: { self.YJFImageView.image = LOADIMAGE(@"6", @"jpg"); } break; //...button case 103: { self.YJFImageView.image = LOADIMAGE(@"4", @"jpg"); } break; default: break; }}-(void)createView{ self.YJFImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 52, 320 - 20, 568 - 64 - 75)]; self.YJFImageView.image = LOADIMAGE(@"8", @"jpg"); self.YJFImageView.userInteractionEnabled = YES; [self.view addSubview:_YJFImageView];}- (void)didReceiveMemoryWarning{ [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end
通過程式執行控制台輸出結果例如以下:
點擊button前:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWpmMTIzNTQ2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
由此結合代碼實現中打的log能夠看出
<pre name="code" class="objc">didClickButton和傳入屬性的setter方法的參數是一個地址,則
,BlockView.m檔案裡
<pre name="code" class="objc">buttonActionBlock:方法中把didClickButton拷貝了一份到棧區,賦值給執行個體變數_buttonActionBlock
點擊button後:
結合代碼實現中打的log能夠看出整個Block的運行過程,也能夠通過打斷的查看Block的運行過程
著作權聲明:本文博主原創文章。部落格,未經同意不得轉載。
iOS開展block說明