iOS 屬性 代理協議 Block用法

  • 前言

本文用最基本的界面通訊(傳個字符串)來舉例子, 傳遞時要分清楚, 控制器出現的先后順序.(當傳遞數據時, 下一個界面都沒有初始化就肯定不行) 協議和Block不僅可以傳遞數據, 還可以調用其他頁面的函數方法.


屬性傳值

  • 例如:第一頁內容, 傳給后一頁
1. 因為要傳遞給下一頁,  下一頁一定要有一個儲存的載體, 所以聲明一個屬性
@interface SecondViewController ()
@property (nonatomic, copy)NSString *string;
@end
2. push下一頁時候賦值
@implementation FirstViewController
- (void)didClicked:(UIButton *)sender
{
  SecondViewController *svc = [[SecondViewController alloc]init];
  svc.string = @"蘋果"; 
  [self.navigationController pushViewController:svc animated:YES];
}
@end
3. 在下一頁secondViewController.h中就可以打印出來了
@implementation SecondViewController
- (void)viewDidLoad
{
  [super viewDidLoad];
  NSLog(@"%@", self.string)
}
@end
  • 優點 最簡單的傳值方法
  • 缺點 只能從前往后傳值

代理協議

  • 完成協議傳值大致分6步
    1. 聲明協議
    2. 聲明屬性 (設置代理人屬性)
    3. 執行協議方法 (何時觸發方法)
    4. 簽協議 (代理人引頭文件)
    5. 指定代理人 (.delegate = self)
    6. 實現方法
  • SecondViewController.h
//在SecondViewController.h中
//聲明協議和代理人的屬性
@protocol secondViewControllerDelegate <NSObject>//第1步
-(void)passString:(NSString *)string;
@end
@interface secondViewController : UIViewController
//必須是assign,其他會有循環引用問題
@property (nonatomic, assign)id<secondViewControllerDelegate>delegate;//第2步
@end

//在SecondViewController.m中
@implementation secondViewController
-(void)ViewDidLoad
{
  //第3步  這個是控制何時觸發協議方法的,當程序走到這行代碼時,程序會跳轉到代理人界面,調用代理人頁面下的協議方法
  [self.delegate passString:@"蘋果"];
}
@end
  • FirstViewController.m
// 引頭文件和簽協議(必須得有這兩步)//第4步
@interface FirstViewController ()< secondViewControllerDelegate >
@end
@implementation FirstViewController
-(void)ViewDidLoad
{
SecondViewController *vc = [[SecondViewController alloc]init];
vc.delegate = self;//第5步
//設置的代理人必須是當前的VC!!!!!!!!!!!!!!!!!!!!
}
-(void)passString:(NSString *)string//第6步  實現協議方法
{
    UITextField *textField = [[UITextField alloc]init];
    textField.text = string;//這時string參數就是傳過來的"蘋果"
}
@end
  • 優點: 好理解, 最常用的一種設計模式, 可以解決代碼的耦合性
  • 缺點: 寫的麻煩

Block傳值

(1). block的寫法及分類
  • Block的寫法: 返回值類型(^起個名字)(參數類型, 參數類型 *) = ^(參數類型, 參數類型 *){具體實現的方法};
  • Block的四種類型的定義
    • 1.無參數無返回值
       void(^block1)(void) = ^(void){...};
    
    • 2.有參數無返回值
        void(^block2)(int age, NSString *string) = ^(int age, NSString *string)  {...};
    
    • 3.有返回值,無參數
      int (^block3)(void) = ^(void){ return 3; }
    
    • 4.有返回值,有參數
       NSInteger (^block4)(NSInteger *) = ^(NSInteger num) { return num; };
    
(2).Block傳值
  1. 傳值頁面聲明block屬性
//在想要回傳的界面中定義,block必須用copy來修飾(*注:SecondViewController.h中聲明)
//@property (nonatomic, copy)NSArray *(^Block)(NSString *string);后面必須兩個括號
@property (nonatomic, copy)void(^Block)(NSString *string);
  1. 傳值頁面調用block, 把"蘋果"傳過去
這個就相當于屬性的get方法, 會執行- (void(^)(NSString *))Block
self.Block(@"蘋果"); 
//當程序走到這行代碼時,  程序會自動跳轉到block內部, 執行下面的方法
  1. 被傳值的頁面block參數就會有值了
//初始化一個secondVC對象
SecondViewController *secondVC. = [[SecondViewController alloc]init];
這個就相當于屬性的set方法 會走 - (void)setBlock:(void(^)(NSString *))Block
secondVC.Block = ^(NSString *string)
{
        firstVC.label.text = string;
      // 這時string這個參數就是"蘋果"了
};
//Block與屬性區別,  就是可以將代碼當參數,  后期調用block時, 被保存的代碼就會執行, 跟協議傳值大同小異

//關于block的內存問題
//1.如果要使用block作為一個屬性, 必須用copy
//2.為了防止循環引用, 可以用弱指針代替
//ARM寫法: __weak typeof( 類型 *) weakSelf = self;
//MRC寫法: __ block typeof( 類型 *) weakSelf = self;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容