iOS_UI_08_界面通信

第八章 界面通信

一、屬性傳值
1.屬性傳值:從視圖層級的前面傳到后面,必須獲取接收值的對象,并且在接收的類中聲明一個所傳值的類型,可以是字符串、數組、集合、字典等,將要傳遞的內容賦值給這個屬性,在后面的視圖中接受就可以了,步驟如下
第一步:SecondViewController* secondVC = [[SecondViewController alloc] init];
第二步:@property(nonatomic,strong) NSString* receiveString;
第三步:secondVC.receiveString = valueString;
第四步:mTextField.text = self.receiveString;
2.單例傳值:
      1.創建一個類繼承于NSObject
      2.聲明所傳值的屬性,可以是字符串、數組、集合、字典等
      3.聲明一個便利構造器方法(類方法,加號方法),返回值可以是當前類的類型(Singleton)、id、instancetype,方法名一般為SharedSingleton。
      4.實現類方法,方法體內
        第一步:創建靜態的類對象,賦值為nil;賦值為nil的方法只會執行一次
               static Singleton* singletan = nil;
        第二步:判斷當前類對象是否被初始化
               if(singletan == nil){
                  singletan = [[Singleton alloc] init];
                }
        第三步:返回singleton
               return Singleton;
       5.將要傳值的內容賦值給單例對象的屬性,然后再把值傳過去之后從單例中取出既可以了
二、協議傳值
協議傳值:本質上就是屬性傳值,是把當前類對象作為屬性傳到后面的視圖,然后后面的視圖再通過屬性傳值將要傳的內容傳過來,兩次屬性傳值,這里我們為了防止出現傳值多個界面時代碼的冗余,提高代碼的可擴展性(需要做別的事時只需要在協議里添加方法就可以了),使用協議傳值
1.在要傳內容的類中聲明協議,類型一般是類名后面加上delegate
2.聲明協議方法,帶參數(參數的類型就是要傳值的類型)
3.在類中聲明協議的代理方,注意內存管理的特性一定要用assign修飾
4.在按鈕事件中執行協議方法進行傳值
5.在接收值得類中遵循協議
6.在接受值的類中的按鈕跳轉事件的方法中指定代理對象
7.在接受值的類中實現代理方法
8.注意:在調用的時候判斷協議方法是否實現
      if (self.delegate && [self.delegate respondsToSelector:@selector(passValue:)]){
         [self.delegate passValue:self.mTextfield.text];
        }
三、Block傳值
1.block的使用,一個特殊的函數
    void(^block_1)(void) = ^(void){
    
    };
    1.方法解釋:void:返回值類型
              (^block):方法名
              (void):參數
              void(^block)(void):方法的聲明
              ^(void){}; :方法的實現
    2.四種類型:
            無參無返回值:void(^block_1)(void) = ^(void){};
            有參無返回值:void(^block_2)(NSString* name) = ^ (NSString* name){};
            有參有返回值:NSString*(^block_3)(NSString* name) = ^ NSString*(NSString* name){ return name; };
            無參有返回值的:NSString*(^block_4)(void) = ^NSString*(void){return @"無參有返回值的";};
    3.注意:在實現的部分(等號的右邊)返回值可以省略不寫,如果沒有參數,在實現部分,參數部分也可以省略。
    4.block的使用:
            //實現一個方法,方法有三個參數,前兩個參數都是整型,第三個參數為block類型,并且在block中求出前兩個參數的和并在block中打印出來
            1.方法的聲明
            - (void)testBlockWithA:(int)a b:(int)b completion: (int(^)(int sum)) threeBlock{
                 第一種
                 threeBlock(a + b);
                //調用普通的方法
                [self sum:a + b];
                 };
            第二種
            - (void)sum:(int)s{
               NSLog(@"s ==== %d",s);
                }
            block就相當于將方法的實現換了個方法
            2.方法的調用
            [self testBlockWithA:6 b:4 completion:^int(int sum) {
                NSLog(@"a + b == %d",sum);
                return  sum;
                }];
    5.block的別名的聲明(重定義):
            1.當block作為類型來使用的時候,我們為了與我們的語法習慣保持一致,需要為block類型起一個別名作為類型的名稱
            2.typedef void(^Block)(NSString* name);
            3.@property (nonatomic,copy) Block myBlock;
2.block的傳值:
    1.Block起別名(后面VC.h):typedef void(^PassBlock)(NSString* title);
    2.聲明Block屬性(后面VC.h):@property (nonatomic,copy) PassBlock passBlock;
    3.調用block,進行傳值:self.passBlock(self.mTextfield.text);
       判斷block是否實現,block的實現就相當于賦值操作,沒實現就相當于未賦值,那么此處就為空,不會進入if分支,如果實現了就相當于賦值了,就會進行if分支
        if(self.passBlock){
           self.passBlock(self.mTextfield.text);
         }
    4.實現block方法:
         blockVC.passBlock = ^(NSString* title){
            self.navigationItem.title = title;
         };
3.關于block的問題:
    1.block作為屬性要用copy修飾的原因:1.因為block有可能會持有需要我們釋放的資源,如果我們不管理他的內存,就可能會造成內存溢出;2.因為block有可能是在全局區、棧區、堆區,但是我們只能管理堆區的內存,所以我們需要將block copy到堆區,所以我們這里使用copy,不使用retain。
    2.block的內存管理:Malloc:堆區;  Global:全局
       1.沒有局部變量的block,是在全局,不用管理內存
           void(^block)(void) = ^{
           };
       2.帶有局部變量的block,__block的作用只是告訴編輯器該局部變量 不管在當前方法中有效,在該方法的block(匿名函數)中也有效,有效區域擴大;將block在堆區生成,以方便我們管理改block的內存
           __block int a = 100;//局部變量
           //block的本質上就是一個函數(方法),他相對于viewDidLoad方法來說就是另外一個方法
           void(^block1)(void) = ^{
             a = 1000;
            };
        3.在block中使用屬性  
           錯誤舉例:
                在聲明block作為當前類的屬性后,又在block的方法體中通過點語法調用當前類的屬性
                  void(^block2)(void) = ^{
                     self.testString = @"kk";
                       };
                結果:這樣使用會造成循環引用,block2作為self(當前類的一個屬性),而在block2 的方法體內又調用當前類中的屬性,造成block2 和 當前類相互持有,所以在系統管理內存的時候容易導致循環引用;
                解決方法:
                     第一種;在block的方法體中調用當前類的屬性不使用點語法,而使用下劃線
                     第二種:告知編譯器或者系統self要在被它持有的block中使用,請不要糾結block中該self的內存情況。
                       MRC下:__block ViewController* vc = self;
                       ARC下:__weak ViewController* vc = self;
                       調用屬性的時候通過vc調用就行
                     
4.關于協議中是否可以定義屬性:協議聲明出來的是方法,雖然看起來是屬性,其實只有getter、setter 這兩個方法,內部是沒有實例變量的,并且你不能去重定義它,只能在 getter、setter 里處理 
   http://blog.csdn.net/yuanchunzi/article/details/47104907
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容