NSNotification,NSNotificationCenter的使用、iOS中五種對象間傳值的方式

學習內容

NSNitification與NotificationCenter(通知與通知中心)

  1. 通知的使用ios

    • [[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector
       (noticeAction:) name:@"name" object:nil];

      註冊觀察者objective-c

    • NSNotification* notice = [NSNotification notificationWithName:@"name" object:nil userInfo:params];
      [[NSNotificationCenter defaultCenter]postNotification:notice];

      建立一個通知併發送網絡

    • 觀察者對象的註冊必定要比通知的發送提早,不然的話會接收不到通知併發

  2. 通知和delegate的基本區別異步

    • 通知是容許多對多的,而delegate只能是一對一的
    • 通知的耦合度較低,發送方不須要知道通知方的任何狀況,而delegate不行
    • 通知的效率比起delegate略差
  3. 通知是同步仍是異步的?async

    • postNotification:通知的發送老是會卡住當前線程,等待全部的observer對象執行(若是沒有通過特殊處理,接收者對象的selector與postNotification在同一線程執行)完成後纔會繼續往下執行,因此是同步的
  4. 通知的移除oop

    • 在iOS9以前的版本中,若是對一個觀察者對象在delloc以前之中沒有從通知中心移除(remove)的話,會產生BAD_ACCESS野指針錯誤,致使crash
    • iOS9.0及之後的版本中不會形成crash
    • 緣由:iOS9.0以前NSNotificationCenter持有的是observer的unsafe_uncertain指針,若是觀察者對象已經被釋放,可是沒有從通知中心移除,那麼postNotification方法會向觀察者已經被回收的內存發送消息,就會形成野指針訪問錯誤,iOS9.0之後,系統將unsafe_uncertain指針更改爲了weak指針(對象回收,自動置nil),向nil發送消息不會差生任何問題(同時這裏說明了oc是能夠向nil發送消息的)
  5. 異步通知post

    • [[NSNotificationQueue defaultQueue]enqueueNotification:notice postingStyle:NSPostASAP];
      ----------------------------------------------------------------------------------typedef NS_ENUM(NSUInteger, NSPostingStyle) {
      	//空閒發送通知 當運行循環處於等待或空閒狀態時,發送通知,對於不重要的通知可使用。
        NSPostWhenIdle = 1,
        //儘快發送通知 當前運行循環迭代完成時,通知將會被髮送,有點相似沒有延遲的定時器。
        NSPostASAP = 2,
        //和postNotification同樣是同步通知
        NSPostNow = 3
      };
    • 三種枚舉類型表明三種發送方式(異步/同步均可)學習

    • 一樣的,異步發送通知的話還可使用開啓一個新的線程的方式ui

    • dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [[NSNotificationCenter defaultCenter]postNotification:notice];
      });
  6. 通知的合併(待完善)

    • [[NSNotificationQueue defaultQueue] enqueueNotification:notice postingStyle:NSPostASAP coalesceMask:NSNotificationNoCoalescing forModes:nil];
      -----------------------------------------------------------------------------------
      typedef NS_OPTIONS(NSUInteger, NSNotificationCoalescing) {
      	  // 不合成
          NSNotificationNoCoalescing = 0,  
        	// 根據NSNotification的name字段進行合成
          NSNotificationCoalescingOnName = 1,  
        	// 根據NSNotification的object字段進行合成
          NSNotificationCoalescingOnSender = 2  
      };
    • NSNotificationQueue除了有異步通知的能力以外,也能對當前隊列的通知根據NSNotificationCoalescing類型進行合併,須要配合不一樣的NSRunLoopMode來進行

    • 經過合併通知咱們能夠用來保證相同的通知只被發送一次

  7. NSNotificationCenter實現原理

    • 通知中心用來管理通知的接收和發送,一開始將觀察者註冊到通知中心的通知調度表中,而後發送通知時利用標識符name和object識別出觀察者,並調用相應的觀察者方法,即傳遞消息(消息傳遞機制),若是是基於block建立的通知就調用NSNitification的block
  8. NSNotificationCenter使用block方式添加的觀察者

    • - (id<NSObject>)addObserverForName:(NSString *)name
                                  object:(id)obj
                                   queue:(NSOperationQueue *)queue
                              usingBlock:(void (^)(NSNotification *note))block
    • addObserver使用一個現存的對象做爲觀察者(通常爲self),而使用block方法會建立一個匿名的(id )對象做爲觀察者,這個匿名對象會在指定的隊列上去執行block

    • 若是queue爲nil,則消息是默認在post線程中同步處理,即通知的post與轉發是在同一線程中,不爲nil的話就會在咱們指定的隊列中執行

    • 若是一個給定的通知觸發了多個觀察者的block操做,則這些操做會在各自的Operation Queue中被併發執行。因此咱們不能去假設操做的執行會按照添加觀察者的順序來執行

    • 這個方法會返回一個匿名的觀察者對象,咱們須要手動釋放這個對象。

iOS中對象間的五種傳值方式(屬性、代理、單例、Block、通知)

  1. 屬性傳值

    • 經過對象的公有屬性進行傳值
  2. 代理傳值

    • 在委託方定義協議,協議中聲明@required/@optional方法,聲明一個代理屬性,使用weak修飾符

    • 在代理方遵照協議,實現協議中的方法

    • 初始化委託對象,將委託對象的代理設置爲self(代理對象自身)

    • 查看代理方是否實現了須要執行的選擇子(SEL),若是實現了便開始執行

    • if ([self.delegate respondsToSelector:@selector(codeIOS)]) {
        // 讓代理方執行協議中的方法
        [self.delegate SEL];
      }
    • 代理傳值通常用於逆向傳值,如:A控制器跳轉到B控制器,B控制器爲委託對象,A控制器爲代理對象,B對象的代理爲A對象,那麼在B對象中能夠傳值給A對象,並在A對象中執行相應的方法

  3. 單例模式傳值

    • 將一個類寫成單例(經常使用dispatch_once),這樣這個類就只含有全局惟一的實例,能夠向整個程序提供實例
    • 若是一個類建立實例會耗費不少資源,那麼能夠將這個類寫成單例類,節省alloc,init的時間
    • 在程序中若是多個類訪問同一個變量,那麼也能夠將將該變量寫入單例類中,調用起來更加方便
  4. 使用block代碼塊進行傳值

    • 能夠用於數據在多個對象間傳遞,網絡請求的回調等

    • //在對象B中block做爲方法參數
      - (void)getNextPage:(void (^)(BOOL))completeBlock{
        //block能夠嵌套,第一層block能夠在最後的block體中進行回調
          [self getPage:self.page complete:^(NSMutableArray *result) {
              if ([result count]) {
                  self.page++;
                  [self.musicList addObjectsFromArray:result];
                  if (completeBlock) {
                    //須要回調時,執行block
                      completeBlock(true);
                  }
              }else{
                  if (completeBlock) {
                      completeBlock(false);
                  }
              }
          }];
      }
      ------------------------------------------------------------------------------
      //在對象A中isSucceed爲回調回來的值
        [strongSelf.musicModel getNextPage:^(BOOL isSucceed) {
          if (isSucceed) {
            [strongSelf.waterFallCollectionView reloadData];
          }
        }];
  5. 通知傳值

    • NSNotification的使用就是通知傳值的一些用法
相關文章
相關標籤/搜索