iOS - Tips - 通过线程通信实现主线程处理通知

#import "DetailViewController.h"

static NSString *notificationName = @"notification1";

@interface DetailViewController () <NSMachPortDelegate>

@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor yellowColor];
    self.title = @"Detail";
    
    [self baseInit];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(processNotification:) name:notificationName object:@"obj1"];
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         for (NSInteger i = 0; i < 100; i++) {
             
             NSLog(@"postNotificationName --- %@", [NSThread currentThread]);
             [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:@"obj1" userInfo:@{}];
         }
     });
    
}

#pragma mark - delegate

- (void)handleMachMessage:(void *)msg {
//    NSLog(@"%s --- %@", __func__, [NSThread currentThread]);
    
    dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
    while ([self.notificationList count]) {
        dispatch_semaphore_signal(self.semaphore);
        
        NSNotification *notification = [self.notificationList firstObject];
        [self processNotification:notification];
        [self.notificationList removeObject:notification];
        
        dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
    }
    dispatch_semaphore_signal(self.semaphore);
}

#pragma mark - Private

- (void)baseInit {
    if (self.notificationList) {
        return;
    }
    
    self.notificationList = [[NSMutableArray alloc] init];
    self.expectedThread = [NSThread currentThread];
    self.semaphore = dispatch_semaphore_create(1);
    self.machPort = [[NSMachPort alloc] init];
    self.machPort.delegate = self;
    
    [[NSRunLoop currentRunLoop] addPort:self.machPort forMode:NSRunLoopCommonModes];
}

- (void)processNotification:(NSNotification *)notification {
    
    if ([NSThread currentThread] == self.expectedThread) {
        NSLog(@"processNotification - in mainThread");
    } else {
        NSLog(@"processNotification - in %@", [NSThread currentThread]);
        dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
        
        [self.notificationList addObject:notification];
        
        dispatch_semaphore_signal(self.semaphore);
        
        [self.machPort sendBeforeDate:[NSDate date] components:nil from:nil reserved:0];
    }
}

@end
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容