当前位置:  开发笔记 > IOS > 正文

锁定解锁事件iphone

如何解决《锁定解锁事件iphone》经验,为你挑选了5个好方法。

如何在iPhone上检测锁定/解锁事件?假设它只能用于越狱设备,你能指出我正确的API吗?

通过锁定事件,我的意思是显示或隐藏锁定屏幕(可能需要密码才能解锁).



1> Nate..:

您可以使用Darwin通知来侦听事件.从我在越狱的iOS 5.0.1 iPhone 4上的测试中,我认为其中一个事件可能就是你所需要的:

com.apple.springboard.lockstate
com.apple.springboard.lockcomplete

注意:根据海报对我在这里回答的类似问题的评论,这也适用于非越狱手机.

要使用它,请注册这样的事件(这只注册上面的第一个事件,但你也可以添加一个观察者lockcomplete):

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                (void*)self, // observer (can be NULL)
                                lockStateChanged, // callback
                                CFSTR("com.apple.springboard.lockstate"), // event name
                                NULL, // object
                                CFNotificationSuspensionBehaviorDeliverImmediately);

lockStateChanged你的事件回调在哪里:

static void lockStateChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
    NSLog(@"event received!");
    if (observer != NULL) {
        MyClass *this = (MyClass*)observer;
    }

    // you might try inspecting the `userInfo` dictionary, to see 
    //  if it contains any useful info
    if (userInfo != nil) {
        CFShow(userInfo);
    }
}

lockstate设备锁定解锁时会发生此事件,但lockcomplete仅在设备锁定时触发事件.确定事件是用于锁定还是解锁事件的另一种方法是使用notify_get_state().你会得到锁定与解锁不同的值,如本文所述.



2> BadPirate..:

回答:

应用程序将在各种情况下调用活动调用...并且从我的所有测试中,即使您的应用程序在后台运行时保持清醒状态,也无法确定屏幕是否已锁定(CPU速度未报告,总线速度保持不变,mach_time denom/numer不会改变)......

但是,当设备锁定时,Apple似乎关闭了加速计... 在屏幕锁定时启用iPhone加速计 (在iPhone 4上测试iOS4.2有此行为)

从而...

在您的应用程序委托中:

- (void)applicationWillResignActive:(UIApplication *)application
{
    NSLog(@"STATUS - Application will Resign Active");
    // Start checking the accelerometer (while we are in the background)
    [[UIAccelerometer sharedAccelerometer] setDelegate:self];
    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:1]; // Ping every second
    _notActiveTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(deviceDidLock) userInfo:nil repeats:NO]; // 2 seconds for wiggle

}
//Deprecated in iOS5
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    NSLog(@"STATUS - Update from accelerometer");
    [_notActiveTimer invalidate];
    _notActiveTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(deviceDidLock) userInfo:nil repeats:NO];
}

- (void)deviceDidLock
{
    NSLog(@"STATUS - Device locked!");
    [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
    _notActiveTimer = nil;
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    NSLog(@"STATUS - Application did become active");
    [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
    [_notActiveTimer invalidate];
    _notActiveTimer = nil;
}

我知道......这是一种黑客行为,但到目前为止,它对我来说就像是一种魅力.如果您发现任何阻止其工作的问题,请更新.



3> Lvsti..:

有一种更漂亮的方法可以分辨任务切换和屏幕锁定发起的applicationWillResignActive:回调,甚至不涉及无记录功能,如加速度计状态.

当应用程序移动到后台时,应用程序委托首先发送一个applicationWillResignActive:,然后发送一个applicationDidEnterBackground:.当通过按下"锁定"按钮或来电来中断应用程序时,不会调用后一种方法.我们可以使用此信息来区分这两种情况.

假设您希望screenLockActivated在屏幕被锁定时在方法中回调.这是魔术:

- (void)applicationWillResignActive:(UIApplication*)aApplication
{
    [self performSelector:@selector(screenLockActivated)
               withObject:nil
               afterDelay:0];
}

- (void)applicationDidEnterBackground:(UIApplication*)aApplication
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
}

- (void)screenLockActivated
{
    NSLog(@"yaay");
}

说明:

默认情况下,我们假设每次调用applicationWillResignActive:都是因为活动 - >非活动状态转换(如锁定屏幕时),但我们慷慨地让系统通过延迟在超时(在这种情况下,单个runloop循环)中证明相反打电话给screenLockActivated.如果屏幕被锁定,系统将完成当前的runloop循环,而不会触及任何其他委托方法.但是,如果这是一个active-> background状态转换,它也会applicationDidEnterBackground:在循环结束之前调用,这允许我们从那里简单地取消先前调度的请求,从而防止它在不应该被调用时被调用.

请享用!


我现在无法在iOS 5.1中重现这一点,applicationDidEnterBackground总是通过锁定屏幕来调用

4> Warpling..:

截至撰写本文时,有两种相当可靠的方法来检测设备锁定:


数据保护

通过启用数据保护权利,您的应用可以订阅applicationProtectedDataWillBecomeUnavailable:applicationProtectedDataDidBecomeAvailable:通知,以很可能确定锁定/解锁使用密码/ TouchID身份验证的设备的时间。LAContext可以查询以确定设备是否使用密码/ TouchID 。

注意事项:此方法依赖于与手机被锁定相一致的“受保护的数据变得不可用”。当手机使用TouchID并按下睡眠/锁定按钮时,手机将被锁定,受保护的数据将不可用,并且将需要立即输入密码来再次解锁。这意味着受保护的数据将变得不可用,本质上表示电话已被锁定。当某人仅使用密码时,这不一定是正确的,因为他们可以将“需要密码”的时间设置为从立即4小时之类的任何时间。在这种情况下,手机将报告能够处理受保护的数据,但是锁定手机不会导致受保护的数据在相当长的时间内不可用。


生命周期计时

如果您的应用位于前台,则这两个生命周期事件之间的时差将发生明显变化UIApplicationWillResignActiveNotificationUIApplicationDidEnterBackgroundNotification具体取决于触发它们的原因。

(这已在iOS 10中进行了测试,并可能在将来的版本中更改)

按下主屏幕按钮会导致两者之间有很大的延迟(即使启用了“降低动作”设置):

15:23:42.517 willResignActive
15:23:43.182 didEnterBackground
15:23:43.184 difference: 0.666346

在应用打开时锁定设备会在两个事件之间产生更微不足道的(<〜0.2s)延迟:

15:22:59.236 willResignActive
15:22:59.267 didEnterBackground
15:22:59.267 difference: 0.031404



5> david..:

在iOS 8中,您可以锁定屏幕或按下主屏幕按钮,所有这些操作都会使应用程序在后台推送,但是您不知道是哪个操作员导致了这种情况。我的解决方案与Nits007ak相同,请使用notify_register_dispatch获取状态。

#import 
        int notify_token
        notify_register_dispatch("com.apple.springboard.lockstate",
                             ¬ify_token,
                             dispatch_get_main_queue(),
                             ^(int token)
                             {
                                 uint64_t state = UINT64_MAX;
                                 notify_get_state(token, &state);
                                 if(state == 0) {
                                     NSLog(@"unlock device");
                                 } else {
                                     NSLog(@"lock device");
                                 }
                             }
                             );

只要应用程序在前台或后台运行。不暂停,您可以获取此事件。

而且您可以将notify_token用作notify_get_state的参数以在任何地方获取当前状态,这在您希望了解状态和屏幕状态不变的情况下非常有用。

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有