Notification多线程 重定向

如果我们的Notification是在二级线程中post的,如何能在主线程中对这个Notification进行处理呢?或者换个提法,如果我们希望一个Notification的post线程与转发线程不是同一个线程,应该怎么办呢?

“重定向”:

就是我们在Notification所在的默认线程中捕获这些分发的通知,然后将其重定向到指定的线程中。

一种重定向的实现思路是自定义一个通知队列(注意,不是NSNotificationQueue对象,而是一个数组),让这个队列去维护那些我们需要重定向的Notification。我们仍然是像平常一样去注册一个通知的观察者,当Notification来了时,先看看post这个Notification的线程是不是我们所期望的线程,如果不是,则将这个Notification存储到我们的队列中,并发送一个信号(signal)到期望的线程中,来告诉这个线程需要处理一个Notification。指定的线程在收到信号后,将Notification从队列中移除,并进行处理



@interface ViewController ()<NSMachPortDelegate>

@property (nonatomic) NSMutableArray    * notifications;         // 通知队列

@property (nonatomic) NSThread          * notificationThread;    // 期望线程

@property (nonatomic) NSLock            * notificationLock;      // 用于对通知队列加锁的锁对象,避免线程冲突

@property (nonatomic) NSMachPort        * notificationPort;      // 用于向期望线程发送信号的通信端口

@end


@implementation ViewController

- (void)viewDidLoad

{

    [super viewDidLoad];


    NSLog(@"current thread = %@", [NSThread currentThread]);


    // 初始化

    self.notifications = [[NSMutableArray alloc] init];

    self.notificationLock = [[NSLock alloc] init];


    self.notificationThread = [NSThread currentThread];

    self.notificationPort = [[NSMachPort alloc] init];

    self.notificationPort.delegate = self;


    // 往当前线程的run loop添加端口源

    // Mach消息到达而接收线程的run loop没有运行时,则内核会保存这条消息,直到下一次进入run loop

    [[NSRunLoop currentRunLoop] addPort:self.notificationPort

                                forMode:(__bridge NSString *)kCFRunLoopCommonModes];


    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(processNotification:) name:@"TestNotification" object:nil];


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{


        [[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:@"" userInfo:nil];


    });

}


- (void)handleMachMessage:(void *)msg {


    [self.notificationLock lock];


    while ([self.notifications count]) {

        NSNotification *notification = [self.notifications objectAtIndex:0];

        [self.notifications removeObjectAtIndex:0];

        [self.notificationLock unlock];

        [self processNotification:notification];

        [self.notificationLock lock];

    };


    [self.notificationLock unlock];

}


- (void)processNotification:(NSNotification *)notification {


    if ([NSThread currentThread] != _notificationThread) {

        // Forward the notification to the correct thread.

        [self.notificationLock lock];

        [self.notifications addObject:notification];

        [self.notificationLock unlock];

        [self.notificationPort sendBeforeDate:[NSDate date]

                                   components:nil

                                         from:nil

                                     reserved:0];

    }

    else {

        // Process the notification here;

        NSLog(@"current thread = %@", [NSThread currentThread]);

        NSLog(@"process notification");

    }

}

运行后,其输出如下:

1
2
3
2015-03-11 23:38:31.637 test[1474:92483] current thread = {number = 1, name = main}
2015-03-11 23:38:31.663 test[1474:92483] current thread = {number = 1, name = main}
2015-03-11 23:38:31.663 test[1474:92483] process notification

可以看到,我们在全局dispatch队列中抛出的Notification,如愿地在主线程中接收到了



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值