Vic*_*nin 6 architecture macos iphone-privateapi nsnotificationcenter ios
我正在尝试编写一个代码来处理iOS上的打开/关闭屏幕(你可以看一下这个问题,讨论类似的问题).我为此问题添加了OSX标记,因为OSX具有相同的系统范围通知功能.并且下面描述的问题继承到通知工具(vs iOS或OSX).
众所周知,注册系统范围通知com.apple.springboard.hasBlankedScreen以在屏幕关闭或打开时接收通知.
仅供参考(以下是用于注册系统范围通知的API):
但是,这种方法存在两个相互关联的问题:
因此,结果我们需要实现一些不同的屏幕打开和关闭的解决方案(因为将调用相同的通知回调,并且没有参数将具有状态).
一般来说,状态与通知回调分离的核心问题.我不知道如何优雅地处理这个问题.
我提出了两种直截了当的方法(每种方法都有缺陷).并寻找关于这种方法的另一种方法或改进的想法.
我们可以实施一个计数器来计算我们已经收到多少通知,并根据这些信息,我们将知道是否有关于打开或关闭屏幕的通知(基于我们的计数器的奇怪性).
但是,它有两个缺点:
1)在这种情况下,如果系统(因设计时间原因未知)将发送具有相同名称的其他通知,我们的逻辑将被搞砸,因为它会破坏奇怪的检查.
2)另外,我们需要正确设置初始状态.所以代码中的某个地方我们会有类似的东西:
Run Code Online (Sandbox Code Playgroud)counter = getInitialState(); registerForNotification();
在这种情况下,我们有一个竞争条件.如果系统将在我们执行getInitialState()之后发送通知并更改状态,但在registerForNotification()之前,我们将以错误的计数器值结束.
如果我们将执行以下代码:
Run Code Online (Sandbox Code Playgroud)registerForNotification(); counter = getInitialState();
在这种情况下,我们有另一种竞争条件.如果系统将在我们执行registerForNotification()之后发送通知并更改状态,但在getInitialState()之前,我们将获得一个计数器,将进入通知回调并将增加一个计数器(这将使其错误).
在这种情况下,我们不存储任何计数器,而是在通知回调中使用API notify_get_state来获取当前状态.
这有它自己的问题:
1)异步传递给应用程序的通知.因此,如果您以非常快的速度关闭屏幕,则可以在屏幕已经打开时收到两个通知.因此,notify_check将获得当前状态(与发送通知时的状态相比).
因此,当应用程序在通知回调中使用notify_get_state时,它将确定有两个通知"屏幕已打开",而不是一个通知"屏幕已关闭"而另一个"屏幕已打开".
PS一般而言,所有描述的问题并非特定于屏幕开/关情况.对于具有独特状态并使用相同通知名称发送的任何系统范围的通知,它们都是实际的.
更新1
我没有测试完全打开/关闭屏幕的情况,并且从notify_get_state()获得相同的结果.
但是,当我收到两个通知com.apple.springboard.lockstate(通过CFNotificationCenterAddObserver订阅)并且我使用另一个API来获取当前设备锁定状态并且两个通知都收到相同的值时,我有类似的情况.
所以我只是假设notify_get_state也会返回相同的值.但是,我认为这是有根据的猜测.notify_get_state的输入参数对于两个调用将是相同的(它不会更改).我不认为系统存储应由notify_get_state返回的状态的FIFO队列.
所以,我建立了一个非常简单的实验.我在调试器外面的越狱iOS 6.1 iPhone 5上运行了这个.
我使用以下代码构建了一个消费者应用程序:
#define EVENT "com.mycompany.bs"
- (void)registerForNotifications {
int result = notify_register_dispatch(EVENT,
¬ifyToken,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0l),
^(int info) {
uint64_t state;
notify_get_state(notifyToken, &state);
NSLog(@"notify_register_dispatch() : %d", (int)state);
});
if (result != NOTIFY_STATUS_OK) {
NSLog(@"register failure = %d", result);
}
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
NULL, // observer
notifyCallback, // callback
CFSTR(EVENT), // event name
NULL, // object
CFNotificationSuspensionBehaviorDeliverImmediately);
}
static void notifyCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
uint64_t state;
notify_get_state(notifyToken, &state);
NSLog(@"notifyCallback(): %d", (int)state);
}
Run Code Online (Sandbox Code Playgroud)
因此,如您所见,它使用两种不同的方法来注册相同的自定义事件.我启动这个应用程序,让它注册该事件,然后将其放入后台(按下主页按钮).
然后,生产者应用程序,让我按下按钮生成事件:
double delayInSeconds = 0.001;
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0l);
dispatch_async(q, ^(void) {
notify_set_state(notifyToken, 2);
notify_post(EVENT);
});
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, q, ^(void){
notify_set_state(notifyToken, 3);
notify_post(EVENT);
});
Run Code Online (Sandbox Code Playgroud)
然后我运行了生产者应用程序,大约每两秒手动生成一对事件.正如您所看到的,生产者快速发布状态为的事件2,然后立即发布状态为的另一个事件3.因此,消费者应打印出来2,然后3,对于这两个回调方法,如果这是可以正常使用.它没有(你担心的):
Feb 13 21:46:12 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:12 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:12 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:12 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:18 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:18 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:18 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:18 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:22 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:22 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:22 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:22 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:26 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 2
Feb 13 21:46:26 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:26 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:26 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:30 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:30 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:30 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:30 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:33 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:33 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:33 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:33 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Feb 13 21:46:36 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 2
Feb 13 21:46:36 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:36 iPhone5 MyApp[1971] <Warning>: notify_register_dispatch() : 3
Feb 13 21:46:36 iPhone5 MyApp[1971] <Warning>: notifyCallback(): 3
Run Code Online (Sandbox Code Playgroud)
我尝试更改一个使用者注册方法CFNotificationSuspensionBehaviorCoalesce(而不是立即提供).结果:
Feb 13 21:48:17 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:17 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:17 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:17 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:20 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 2
Feb 13 21:48:20 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:20 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:20 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:24 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 2
Feb 13 21:48:24 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 2
Feb 13 21:48:24 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:24 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:29 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 2
Feb 13 21:48:29 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:29 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:29 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:32 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 2
Feb 13 21:48:32 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 2
Feb 13 21:48:32 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:32 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:35 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 2
Feb 13 21:48:35 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 2
Feb 13 21:48:35 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:35 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:38 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 2
Feb 13 21:48:38 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 2
Feb 13 21:48:38 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:38 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Feb 13 21:48:39 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 2
Feb 13 21:48:39 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:39 iPhone5 MyApp[1990] <Warning>: notify_register_dispatch() : 3
Feb 13 21:48:39 iPhone5 MyApp[1990] <Warning>: notifyCallback(): 3
Run Code Online (Sandbox Code Playgroud)
然后我尝试将notify_register_dispatch()消费者的队列优先级更改为高,而不是后台优先级.结果:
Feb 13 21:49:51 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:49:51 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:49:51 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:49:51 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:49:53 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:49:53 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 2
Feb 13 21:49:53 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:49:53 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:49:55 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:49:55 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 2
Feb 13 21:49:55 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:49:55 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:49:59 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:49:59 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 2
Feb 13 21:49:59 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:49:59 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:50:01 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:50:01 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:50:01 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:50:01 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:50:04 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 2
Feb 13 21:50:04 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:50:04 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:50:04 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:50:06 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:50:06 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 2
Feb 13 21:50:06 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:50:06 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:50:09 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:50:09 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 2
Feb 13 21:50:09 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:50:09 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Feb 13 21:50:10 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 2
Feb 13 21:50:10 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:50:10 iPhone5 MyApp[2006] <Warning>: notify_register_dispatch() : 3
Feb 13 21:50:10 iPhone5 MyApp[2006] <Warning>: notifyCallback(): 3
Run Code Online (Sandbox Code Playgroud)
SBGetScreenLockStatus通话.有时,消费者从未看到过这种状态2.notifyCallback()方法似乎首先被回调.即便如此,通常首先调用静态回调函数.很多时候,第一个回调的方法得到了正确的状态(2),而第二个没回复.所以,如果你不得不忍受这个问题,你可能会选择看起来效果最好的回调机制(或至少在你的应用程序中自己原型).suspensionBehavior参数有很大的不同.也就是说,根据iOS 发布事件的方式,他们可能正在使用可能忽略消费者行为请求的CFNotificationCenterPostNotification等调用.如果你看看这个Apple文档,你会看到两件事.
notify_set_state它不是原始API的一部分Darwin Notification API参考
这些例程允许进程交换无状态通知事件.
所以,也许我们只是想做一些与原始设计不一致的事情:(
notify_get_state并notify_set_state传达状态.他们将通知作为用户信息字典传递给它.显然,如果您正在观察Apple的iOS事件,则无法控制事件的发布方式.但是,在你可以创建生产者和消费者的应用程序中,我会远离notify_set_state.| 归档时间: |
|
| 查看次数: |
5834 次 |
| 最近记录: |