最近开发中为了方便自己测试,准备弄个简单业务错误日志统计。由于只是测试用,况且出现我认为可能错的情况几率很小。想在不改变现有代码的情况下,直接获取NSLog内容。查了些资料,知道NSLog输出的内容会写到控制台和系统日志(ASL)里面。我就想在输入到ASL的时候把特定的数据给保存下来。但是我无法知道NSLog什么时候输出内容,看到网上开源的DDLogger的源码,找到了解决的方法。原来只是需要注册下系统的通知就可以拿到输出的时机,然后通过<asl.h>提供的方法去操作系统设备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提供的方法去注册这些通知,它的实现也是基于<notify.h>里面的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增加一个当手机存储空间很少的时候自动清理缓存的功能。对于网络切换,我们又多了一个监听方法。除了这些系统开放出来的,网上还有不少私有的通知,比如屏幕的亮度调节,锁屏的监听等等。有兴趣的可以看看其他的通知。