美文网首页通知
iOS 协议(protocol) 和通知(NSNotificat

iOS 协议(protocol) 和通知(NSNotificat

作者: 7分醉 | 来源:发表于2018-09-26 21:46 被阅读211次

    协议(protocol)

    关于协议的一些定义,简单使用方法就不多说了.

    协议可以添加哪些:

    1.添加方法(类方法/属性方法)
    2.添加属性

    关于协议添加属性来举个例子:

    #import <Foundation/Foundation.h>
    @protocol PersonProtocol <NSObject>
    @property (nonatomic, strong) NSString *name;//协议中的属性
    @end
    
    @interface Person : NSObject
    @property (nonatomic, weak) id<PersonProtocol> delegade;
    @end
    

    找个类实现协议

    #import "Student.h"
    
    @interface Student ()<PersonProtocol>
    @end
    
    @implementation Student
    //协议里的属性
    @synthesize name;
    
    @end
    
    

    应用以下:

    Person *onePerson = [Person new];
            Student *xiaoming = [Student new];
            onePerson.delegade = xiaoming;
            onePerson.delegade.name = @"xiaoming";
            NSLog(@"%@",xiaoming.name);
    

    打印结果如下

    xiaoming

    通知(NSNotification)

    先来看下常用的发通知的套路
    发送:

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        NSLog(@"要发通知啦");
        [[NSNotificationCenter defaultCenter] postNotificationName:@"aaa" object:nil];
        NSLog(@"通知发完啦");
    }
    

    接收:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(testNoti) name:@"aaa" object:nil];
        return YES;
    }
    
    - (void)testNoti {
        NSLog(@"收到通知啦 %@",[NSThread currentThread]);
    }
    

    看下打印:

    要发通知啦
     收到通知啦 <NSThread: 0x17406d880>{number = 1, name = main}
    通知发完啦
    

    总结:

    通过postNotificationName:发送通知是同步的, 会卡住当前线程. 就是说, 发送通知后,会等到对方接收到通知并执行完收到通知的方法后才会接着往下走.

    关于移除通知

    iOS 9以后UIViewController 添加通知后可以不用移除, 系统会自动给移除.

    异步发送通知

    异步发送通知需要三步
    1.创建通知(NSNotification)
    2.创建通知队列(NSNotificationQueue)
    3.将通知放入队列中执行

    发送:

     NSLog(@"发送通知前");
    //创建通知
        NSNotification *noti = [[NSNotification alloc] initWithName:@"aaa" object:nil userInfo:nil];
    //将通知加入队列,并设置为NSPostASAP,当当前runloop完成之后立即post
        [[NSNotificationQueue defaultQueue] enqueueNotification:noti postingStyle:NSPostASAP];
        NSLog(@"发送通知后");
    

    接收:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(testNoti) name:@"aaa" object:nil];
        return YES;
    }
    
    - (void)testNoti {
        NSLog(@"接收到通知了%@",[NSThread currentThread]);
    }
    

    打印:

     发送通知前
     发送通知后
     接收到通知了<NSThread: 0x282bb2e40>{number = 1, name = main}
    
    

    将通知加入到队列的方法有个枚举参数:

    typedef NS_ENUM(NSUInteger, NSPostingStyle) {
        NSPostWhenIdle = 1,      // 当runloop处于空闲状态时post
        NSPostASAP = 2,    // 当当前runloop完成之后立即post
        NSPostNow = 3    // 立即post,同步(会立即执行)
    };
    

    指定枚举参数后, 队列会根据type, 在合适的时机将NSNotification 发送到NSNotificationCenter,这就达到了异步执行的效果.

    NSPostWhenIdleNSPostASAP差不多, 都会异步执行,NSPostNow会立即执行

    通知合并

    将通知放入队列执行还有另外一个方法:
    - (void)enqueueNotification:(NSNotification *)notification postingStyle:(NSPostingStyle)postingStyle coalesceMask:(NSNotificationCoalescing)coalesceMask forModes:(nullable NSArray<NSRunLoopMode> *)modes;
    方法的第二个参数:(NSNotificationCoalescing)coalesceMask就是控制通知的合并策略.

    如下:

    typedef NS_OPTIONS(NSUInteger, NSNotificationCoalescing) {
        NSNotificationNoCoalescing = 0,  // 不合成
        NSNotificationCoalescingOnName = 1,  // 根据NSNotification的name字段进行合成
        NSNotificationCoalescingOnSender = 2  // 根据NSNotification的object字段进行合成
    };
    

    发送:

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        NSLog(@"发送通知前");
        NSNotification *noti = [[NSNotification alloc] initWithName:@"aaa" object:nil userInfo:nil];
        [[NSNotificationQueue defaultQueue] enqueueNotification:noti postingStyle:NSPostASAP];
        [[NSNotificationQueue defaultQueue] enqueueNotification:noti postingStyle:NSPostWhenIdle];
        [[NSNotificationQueue defaultQueue] enqueueNotification:noti postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];
        NSLog(@"发送通知后");
    }
    

    接收:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(testNoti) name:@"aaa" object:nil];
        return YES;
    }
    
    - (void)testNoti {
        NSLog(@"接收到通知了%@",[NSThread currentThread]);
    }
    

    打印:

    发送通知前
    发送通知后
    接收到通知了<NSThread: 0x280fbee40>{number = 1, name = main}
    

    注意, 如果直接使用postNotificationName:或者指定NSPostNow提交方式或者指定合并策略为NSNotificationNoCoalescing 时,不会合并通知

    参考:
    http://www.cocoachina.com/ios/20170426/19124.html

    相关文章

      网友评论

        本文标题:iOS 协议(protocol) 和通知(NSNotificat

        本文链接:https://www.haomeiwen.com/subject/cywcoftx.html