James Yu


写了那么多的if else 依然未能参透其精髓。。。


iOS 注册进程之间的通知

最近开发中为了方便自己测试,准备弄个简单业务错误日志统计。由于只是测试用,况且出现我认为可能错的情况几率很小。想在不改变现有代码的情况下,直接获取NSLog内容。查了些资料,知道NSLog输出的内容会写到控制台和系统日志(ASL)里面。我就想在输入到ASL的时候把特定的数据给保存下来。但是我无法知道NSLog什么时候输出内容,看到网上开源的DDLogger的源码,找到了解决的方法。原来只是需要注册下系统的通知就可以拿到输出的时机,然后通过提供的方法去操作系统设备log。

notify.h

这个头文件里面提供了用于进程之间的无状态通知方法。用法和我们通知使用差不多。

//通知的注册
int token;  
notify_register_dispatch("com.apple.system.logger.message", &token, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) {  
        NSLog(@"receive nofity");
    });
//发送通知。
notify_post("com.apple.system.logger.message");
//通知取消
notify_cancel(token);

从用法上,可以看出发通知只能用通知的名字,而且不能传递参数。由于这个是通过操作系统发出的,换句话说,只要不同的进程注册了同一个通知名,当发送notify_post的时候,所有的进程都会收到。自己做了个测试,开启两个app,随便弄个自己的通知,然后其中一个app进行注册,另一个app进行发送,的确能收到通知。

我们也可以通过CFNotificationCenter提供的方法去注册这些通知,它的实现也是基于里面的API。

状态的设置

当我们第一次注册某个通知时候,可能并不知道当前资源是否可以使用,必须等待下一次的通知回调。系统也提供了一个解决方法,如果是发送方,在资源可以使用的时候做一个标记位,接受方,在注册之前可以先检查下,当前资源是否可以使用,如果可以使用,可以直接进入自己的逻辑处理。

//发送方
int token;  
notify_register_check("customMessage", &token);

uint64_t state = 1;

notify_set_state(token, state);

//接受方

int token;  
notify_register_check("customMessage", &token);

uint64_t state;

notify_get_state(token, &state);

if (state) {  
    //logic
}
//注册通知
notify_register_dispatch("com.apple.system.logger.message", &token, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) {  
        NSLog(@"receive nofity");
    });

notify_keys.h

系统提供了一些我们可以注册的通知:

/*
 * Directory Service notifications
 * These are posted by the DirectoryService daemon to advise clients that
 * cached data should be invalidated.
 */
#define kNotifyDSCacheInvalidation "com.apple.system.DirectoryService.InvalidateCache"
#define kNotifyDSCacheInvalidationGroup "com.apple.system.DirectoryService.InvalidateCache.group"
#define kNotifyDSCacheInvalidationHost "com.apple.system.DirectoryService.InvalidateCache.host"
#define kNotifyDSCacheInvalidationService "com.apple.system.DirectoryService.InvalidateCache.service"
#define kNotifyDSCacheInvalidationUser "com.apple.system.DirectoryService.InvalidateCache.user"

/*
 * File System notifications
 * These advise clients of various filesystem events.
 */
#define kNotifyVFSMount "com.apple.system.kernel.mount"
#define kNotifyVFSUnmount "com.apple.system.kernel.unmount"
#define kNotifyVFSUpdate "com.apple.system.kernel.mountupdate"
#define kNotifyVFSLowDiskSpace "com.apple.system.lowdiskspace"
#define kNotifyVFSLowDiskSpaceRootFS "com.apple.system.lowdiskspace.system"
#define kNotifyVFSLowDiskSpaceOtherFS "com.apple.system.lowdiskspace.user"

/*
 * System Configuration notifications
 * These advise clients of changes in the system configuration
 * managed by the system configuration server (configd).
 * Note that a much richer set of notifications are available to
 * clients using the SCDynamicStore API.
 */
#define kNotifySCHostNameChange "com.apple.system.hostname"
#define kNotifySCNetworkChange "com.apple.system.config.network_change"

/*
 * ASL notifications
 * Sent by syslogd to advise clients that new log messages have been
 * added to the ASL database.
 */
#define kNotifyASLDBUpdate "com.apple.system.logger.message"

/*
 * Time Zone change notification
 * Sent by notifyd when the system's timezone changes.
 */
#define kNotifyTimeZoneChange "com.apple.system.timezone"

/*
 * System clock change notification
 * Sent when a process modifies the system clock using the settimeofday system call.
 */
#define kNotifyClockSet "com.apple.system.clock_set"

个人觉得里面kNotifyVFSLowDiskSpace,这个可以用来给app增加一个当手机存储空间很少的时候自动清理缓存的功能。对于网络切换,我们又多了一个监听方法。除了这些系统开放出来的,网上还有不少私有的通知,比如屏幕的亮度调节,锁屏的监听等等。有兴趣的可以看看其他的通知

comments powered by Disqus