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的使用就是通知传值的一些用法
相关文章
相关标签/搜索