idleTimer
idleTimer 是iOS內(nèi)置的時(shí)間監(jiān)測機(jī)制炫狱,當(dāng)在一段時(shí)間內(nèi)未操作即進(jìn)入鎖屏狀態(tài)。但有些應(yīng)用程序是不需要鎖住屏幕的剔猿,比如游戲视译,視頻這類應(yīng)用。 可以通過設(shè)置UIApplication的idleTimerDisabled屬性來指定iOS是否鎖屏艳馒。
// 禁用休閑時(shí)鐘
[[UIApplication sharedApplication] setIdleTimerDisabled: YES];
也可以使用這種語法
[UIApplication sharedApplication].idleTimerDisabled = YES;
但是憎亚,這個(gè)命令只能禁用自動鎖屏,如果點(diǎn)擊了鎖屏按鈕弄慰,仍然會進(jìn)入鎖屏的。有一點(diǎn)例外的是蝶锋,AVPlayer不用設(shè)置idleTimerDisabled=YES陆爽,也能屏幕常亮,播放完成后過一分鐘就自動關(guān)閉屏幕扳缕。有興趣的可以自己嘗試一下慌闭。
鎖屏和解鎖通知
iPhone的鎖屏監(jiān)測分為兩種方式監(jiān)聽:一種是程序在前臺,另一種程序在后臺躯舔。 程序在前臺驴剔,這種比較簡單。直接使用Darwin層的通知就可以了:
Darwin是由蘋果電腦于2000年所釋出的一個(gè)開放原始碼操作系統(tǒng)粥庄。Darwin 是MacOSX 操作環(huán)境的操作系統(tǒng)成份丧失。蘋果電腦于2000年把Darwin 釋出給開放原始碼社群。現(xiàn)在的Darwin皆可以在蘋果電腦的PowerPC 架構(gòu)和X86 架構(gòu)下執(zhí)行惜互,而后者的架構(gòu)只有有限的驅(qū)動程序支援布讹。
#import <notify.h>
#define NotificationLock CFSTR("com.apple.springboard.lockcomplete")
#define NotificationChange CFSTR("com.apple.springboard.lockstate")
#define NotificationPwdUI CFSTR("com.apple.springboard.hasBlankedScreen")
static void screenLockStateChanged(CFNotificationCenterRef center,void* observer,CFStringRef name,const void* object,CFDictionaryRef userInfo)
{
NSString* lockstate = (__bridge NSString*)name;
if ([lockstate isEqualToString:(__bridge NSString*)NotificationLock]) {
NSLog(@"locked.");
} else {
NSLog(@"lock state changed.");
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, screenLockStateChanged, NotificationLock, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, screenLockStateChanged, NotificationChange, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
return YES;
}
notify.h的具體內(nèi)容可以移步開發(fā)文檔琳拭。這種方法,程序在前臺是可以拿到的描验,在后臺情況下就無能為力了白嘁。
第二種是程序退后臺后,這時(shí)再鎖屏就收不到上面的那個(gè)通知了膘流,需要另外一種方式, 以循環(huán)的方式一直來檢測是否是鎖屏狀態(tài)絮缅,會消耗性能并可能被蘋果掛起,需要合理設(shè)置循環(huán)時(shí)間呼股。
static void setScreenStateCb()
{
uint64_t locked;
__block int token = 0;
notify_register_dispatch("com.apple.springboard.lockstate",&token,dispatch_get_main_queue(),^(int t){
});
notify_get_state(token, &locked);
NSLog(@"%d",(int)locked);
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
while (YES) {
setScreenStateCb();
sleep(5); // 循環(huán)5s
}
}
UIApplication
上面我們使用了UIApplication的IdleTimerDisabled方法耕魄,下面就大概了解下UIApplication吧。
UIApplication卖怜,每個(gè)程序只能有一個(gè)泡仗,系統(tǒng)使用的是單例模式,用[UIApplication sharedApplication]來得到一個(gè)實(shí)例涛漂。這個(gè)單例實(shí)例是在系統(tǒng)啟動時(shí)由main函數(shù)里面的UIApplicationMain方法生成看蚜,實(shí)現(xiàn)的是UIApplicationDelegate的Protocol,也就是AppDelegate的一個(gè)實(shí)例甩鳄。每次通過[UIApplication sharedApplication]調(diào)用的就是它逞度。UIApplication保存一個(gè)UIWindow對象序列,用來快速恢復(fù)views妙啃。
UIApplication在程序里的作用很多档泽,大致如下所示:
一、遠(yuǎn)程提醒揖赴,就是push notification注冊馆匿;
二、可以連接到UIUndoManager燥滑;在Cocoa中使用NSUndoManager可以很方便的完成撤銷操作渐北。NSUndoManager會記錄下修改、撤銷操作的消息铭拧。這個(gè)機(jī)制使用兩個(gè)NSInvocation對象棧赃蛛。當(dāng)進(jìn)行操作時(shí),控制器會添加一個(gè)該操作的逆操作的invocation到Undo棧中搀菩。當(dāng)進(jìn)行Undo操作時(shí)呕臂,Undo操作的逆操作會倍添加到Redo棧中,就這樣利用Undo和Redo兩個(gè)堆棧巧妙的實(shí)現(xiàn)撤銷操作肪跋。需要注意的是歧蒋,堆棧中存放的都是NSInvocation實(shí)例。
三、檢查能否打開某個(gè)URL疏尿,并且打開URL瘟芝;這個(gè)功能可以配合應(yīng)用的自定義URL功能,來檢測是否安裝了某個(gè)應(yīng)用褥琐。使用的是[[UIApplication sharedApplication] canOpenURL:url]方法锌俱。如果返回YES,可執(zhí)行[[UIApplication sharedApplication] openURL:url];
四敌呈、注冊Local Notification贸宏;
五、在后臺運(yùn)行以及從后臺轉(zhuǎn)為前臺時(shí)的操作磕洪;
六吭练、防止屏幕睡眠:即上面的[[UIApplication sharedApplication] setIdleTimerDisabled: YES];
七、手動調(diào)整status bar的位置和狀態(tài)析显,如設(shè)置為豎屏鲫咽、橫屏等;
八谷异、設(shè)置badge number分尸,就是圖標(biāo)右上角的數(shù)字;
九歹嘹、每當(dāng)應(yīng)用聯(lián)網(wǎng)時(shí)箩绍,在狀態(tài)欄上會顯示聯(lián)網(wǎng)小菊花。UIApplication可以設(shè)置是否出現(xiàn)尺上。
UIApplication *app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible =!app.networkActivityIndicatorVisible;//轉(zhuǎn)動
app.networkActivityIndicatorVisible = app.networkActivityIndicatorVisible;//不轉(zhuǎn)動
UIUndoManager示例
- (void) one
{
position = position + 10;
[[undoManager prepareWithInvocationTarget:self] two];
[self showTheChangesToThePostion];
}
- (void) two
{
position = position - 10;
[[undoManager prepareWithInvocationTarget:self] one];
[self showTheChangesToThePostion];
}
prepareWithInvocationTarget:方法記錄了target并返回UndoManager材蛛,然后UndoManager重載了forwardInvocation方法,也就將two方法的Invocation添加到undo棧中了怎抛。