总结:

1、同一线程,添加多个观察者或者发送多次通知,就会响应多次方法

2、不管创建在哪个线程,发送在哪个线程接收就在哪个线程

3、接收在哪个线程可以由添加方法发来控制

4、接收在哪个线程可以由添加runloop端口的方法来控制

#import "ViewController.h"

#define TEST_NOTIFICATION @"TestNotification"

@interface ViewController ()

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

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

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

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

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

// [self test5];

// [self test4];

// [self test3];

// [self test2];

// [self test1];

}

#pragma mark -添加一个观察者,发送两次响应两次

-(void)test5{

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];

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

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

}

#pragma mark - 添加多个观察者,发送一次响应两次

-(void)test4{

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];

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

}

#pragma mark - 发送在子线程,接收在主线程(可以指定某一个线程,不一定非要主线程)

-(void)test3{

[[NSNotificationCenter defaultCenter] addObserverForName:TEST_NOTIFICATION object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {

NSLog(@"接收和处理通知的线程%@", [NSThread currentThread]);

}];

dispatch_async(dispatch_get_global_queue(0, 0), ^{

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

NSLog(@"发送通知的线程为%@", [NSThread currentThread]);

});

}

#pragma mark - 发送在子线程,接收在主线程(接收在添加port所在loop的线程)

-(void)test2{

NSLog(@"当前线程 = %@", [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(secondNotification:) name:TEST_NOTIFICATION object:nil];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

NSLog(@"发送线程 = %@", [NSThread currentThread]);

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

});

}

//notificationPort代理方法

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

NSLog(@"%s",__func__);

[self.notificationLock lock];

while ([self.notifications count]) {

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

[self.notifications removeObjectAtIndex:0];

[self.notificationLock unlock];

[self secondNotification:notification];

[self.notificationLock lock];

};

[self.notificationLock unlock];

}

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

NSLog(@"%s",__func__);

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(@"接收线程 = %@", [NSThread currentThread]);

NSLog(@"通知流程结束");

}

}

#pragma mark - 创建在同一个线程,发送和接收在一个线程

-(void)test1{

NSLog(@"当前线程为%@", [NSThread currentThread]);//0

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstNotification:) name:TEST_NOTIFICATION object:nil];

dispatch_async(dispatch_get_global_queue(0, 0), ^{

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

NSLog(@"发送通知的线程为%@", [NSThread currentThread]);//1

});

}

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

NSLog(@"接收线程%@", [NSThread currentThread]);//1

}

@end

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: