這是閱讀該指南的一些筆記,說說是筆記,其實就是把一些自己決定重要的知識給翻譯了一遍,因為英文讀著讀著就把前面的給忘了。。。所以就打算記錄一點。該文章會慢慢更新,這段時間打算將幾篇重要的指南都重新看一遍,每天都會更新這些筆記,英語不大好,可能有翻譯錯誤的地方,請大家指出,謝謝!
APP狀態(tài)
在任何時間上,你的APP只有一個狀態(tài),看表Table 2-3.系統(tǒng)切換APP狀態(tài)來響應(yīng)系統(tǒng)事件.舉例,當(dāng)用戶按下Home鍵,一個電話打來,或者其他中斷的行為,當(dāng)前運行的APP改變狀態(tài)來響應(yīng).Figure 2-3 顯示一個APP改變狀態(tài)的路徑.
狀態(tài) | 描述 |
---|---|
沒有運行 | 該APP沒有運行或者正在運行但被系統(tǒng)終止 |
不活躍的 | 該APP在前臺運行,但沒有接受到事件,APP一般都處在這個狀態(tài) |
活躍 | 該APP在前臺運行并且接受事件,這是前臺運行APP正常狀態(tài) |
后臺 | 該APP在后臺且在執(zhí)行代碼,大部分APP在該狀態(tài)會停留一段事件 |
暫停 | 該APP在后臺且沒有執(zhí)行代碼,系統(tǒng)會自動將APP設(shè)置到這個狀態(tài)并不會通知APP.暫停后,APP保留在內(nèi)存內(nèi)但不會執(zhí)行代碼.當(dāng)內(nèi)存低時,系統(tǒng)會殺死APP來使前臺有更多內(nèi)存 |
大多數(shù)狀態(tài)的改變都伴隨著系統(tǒng)方法的調(diào)用。你可以在這些方法內(nèi)響應(yīng)狀態(tài)。
-
application:willFinishLaunchingWithOptions
: 啟動時執(zhí)行第一次代碼 -
application:didFinishLaunchingWithOptions
:允許在程序顯示之前進(jìn)行最終的初始化 -
applicationDidBecomeActive
: 即將成為前臺應(yīng)用 -
applicationWillResignActive
: 過渡狀態(tài),即將不活躍 -
applicationDidEnterBackground
: 正在后臺運行,會隨時暫停 -
applicationWillEnterForeground
: 應(yīng)用從后臺到前臺,但不活躍 -
applicationWillTerminate
: 應(yīng)用正在被終止,暫停不會調(diào)用這個方法
本節(jié)講了應(yīng)用各種運行的狀態(tài)和appdelgate里一些方法具體是什么時候被調(diào)用的
APP終止
APP應(yīng)該隨時準(zhǔn)備被終止而不應(yīng)該等待保存用戶數(shù)據(jù)或者執(zhí)行關(guān)鍵任務(wù),系統(tǒng)發(fā)起的終止是APP生命周期里的一個正常環(huán)節(jié)。
如果APP正在后臺運行且沒有暫停,系統(tǒng)會在應(yīng)用終止前調(diào)用applicationWillTerminate
,如果系統(tǒng)重啟,不會調(diào)用這個方法
線程和并發(fā)
系統(tǒng)創(chuàng)建主要的線程,你也可以創(chuàng)建額外的線程。對于iOS APP,你應(yīng)該首選GCD,操作隊列和其他的異步接口而不是自己創(chuàng)建和管理線程,使用GCD可以讓你更好的專注于工作,讓系統(tǒng)去處理線程相關(guān)的事情。
在思考線程和并發(fā)時,你應(yīng)該注意以下幾點
- 包括視圖,核心動畫,還有很多UIKit的類通常都運行在主線程上,但也有例外,譬如圖像的操作就在后臺
- 耗時操作應(yīng)該在后臺處理,包括網(wǎng)絡(luò)請求,文件訪問或者大量的數(shù)據(jù)處理都應(yīng)該使用異步的GCD或者操作隊列管理。
- 在啟動時,應(yīng)該盡快的顯示界面,除了必須的建立視圖的操作,其他的耗時操作都應(yīng)該放在后臺
更多的GCD或者操作隊列信息請看 Concurrency Programming Guide
本節(jié)講了耗時操作能放在子線程就丟到子線程,除了創(chuàng)建視圖,刷新視圖等等。。
Strategies for Handling App State Transitions
可以在UIApplicationDelegate
協(xié)議方法里面知道狀態(tài)改變。
What to Do at Launch Time
當(dāng)APP啟動時(無論是前臺還是后臺),在application:willFinishLaunchingWithOptions:
和application:didFinishLaunchingWithOptions:
方法內(nèi)做以下幾點:
- 檢查Info.plist文件
- 初始化關(guān)鍵數(shù)據(jù)
- 準(zhǔn)備顯示視圖
- OpenGL ES應(yīng)該在
applicationDidBecomeActive:
方法內(nèi)繪制 - 顯示窗口在
application:willFinishLaunchingWithOptions:
方法內(nèi),顯示視圖在application:didFinishLaunchingWithOptions:
方法內(nèi)
- OpenGL ES應(yīng)該在
在啟動時候要盡快完成,超過5秒系統(tǒng)會自動殺死該進(jìn)程。
The Launch Cycle
應(yīng)用進(jìn)入運行狀態(tài)流程圖
應(yīng)用在后臺會處理事件,并會在某個時間點暫停。它仍會加載界面文件但不會顯示
可以通過applicationState
屬性區(qū)別當(dāng)前應(yīng)用狀態(tài),在前臺時為UIApplicationStateInactive
,后臺時為UIApplicationStateBackground
Launching in Landscape Mode
應(yīng)用必須設(shè)置朝向,如果支持橫向和縱向,那么默認(rèn)是縱向。如果只支持橫向,需要做到以下幾點:
- 在info.plist文件中添加
UIInterfaceOrientation
Key值,設(shè)置屬性為UIInterfaceOrientationLandscapeLeft
或者UIInterfaceOrientationLandscapeRight.
- 確保約束是正確的
What to Do When Your App Is Interrupted Temporarily
當(dāng)應(yīng)用暫時中斷時,系統(tǒng)仍在前臺但是不能接受觸摸事件,但可以接受類似陀螺儀事件,你需要在applicationWillResignActive:
方法內(nèi)做以下操作:
- 保存數(shù)據(jù)或者關(guān)鍵信息
- 停止定時器或者其他周期性任務(wù)
- 停止數(shù)據(jù)查詢
- 不初始化新的任務(wù)
- 停止視頻(除了AirPlay)
- 停止游戲
- 終止GCD或者操作隊列
在應(yīng)用進(jìn)入活躍狀態(tài)時,在applicationWillResignActive
方法內(nèi)你應(yīng)該重啟定時器,恢復(fù)隊列。游戲不應(yīng)該恢復(fù),這應(yīng)該讓用戶手動開始。
Responding to Temporary Interruptions
假如有電話打來,應(yīng)用會進(jìn)入inactive狀態(tài),直到用戶結(jié)束通話,應(yīng)用回到活躍狀態(tài)或者后臺。
用戶拉下通知橫幅會造成應(yīng)用進(jìn)入inactive狀態(tài)。
用戶按下鎖屏鍵,系統(tǒng)禁用觸摸事件并且使應(yīng)用進(jìn)入后臺,這時候數(shù)據(jù)文件會被加密保護(hù)起來。
What to Do When Your App Enters the Foreground
當(dāng)應(yīng)用進(jìn)入前臺狀態(tài)時,applicationWillEnterForeground:
方法會撤銷所有applicationDidEnterBackground:
方法里的事情,并在applicationDidBecomeActive:
方法里做激活任務(wù)。
UIApplicationWillEnterForegroundNotification
這個枚舉也可以用來監(jiān)聽?wèi)?yīng)用進(jìn)入前臺狀態(tài)。
Be Prepared to Process Queued Notifications
Event | Notifications |
---|---|
配件斷開或鏈接 | EAAccessoryDidConnectNotification |
屏幕旋轉(zhuǎn) | UIDeviceOrientationDidChangeNotification |
完整一天過去 | UIApplicationSignificantTimeChangeNotification |
偏好設(shè)置改變 | NSUserDefaultsDidChangeNotification |
語言改變或者區(qū)域改變 | NSCurrentLocaleDidChangeNotification |
應(yīng)用在后臺時仍然能調(diào)用setNeedsDisplay
或者setNeedsDisplayInRect:
,但是因為視圖是不顯示的,所以會在下次應(yīng)用進(jìn)入前臺時更新視圖。
What to Do When Your App Enters the Background
從前臺進(jìn)入后臺,在applicationDidEnterBackground:
方法里做以下幾點:
- 給你應(yīng)用準(zhǔn)備一張圖片。如果用戶退出前臺前的那個頁面包含了敏感信息,你應(yīng)該隱藏或者修改這張圖片在
applicationDidEnterBackground:
方法返回前。 - 保存有關(guān)應(yīng)用的狀態(tài)信息
- 釋放不需要的內(nèi)存。因為系統(tǒng)會殺掉占用內(nèi)存大的應(yīng)用,所以應(yīng)該讓你的應(yīng)用在進(jìn)入后臺前釋放圖片資源,緩存和一些不需要的數(shù)據(jù)。
應(yīng)用在applicationDidEnterBackground:
方法里大概有5秒的時間來完成任務(wù)。實際上,這個方法應(yīng)該盡可能快的返回。如果方法沒有在時間耗盡前返回,系統(tǒng)會殺掉應(yīng)用并釋放內(nèi)存。如果你需要長時間進(jìn)行任務(wù),你應(yīng)該在beginBackgroundTaskWithExpirationHandler:
方法里進(jìn)行,并且在secondary線程上。不管你在applicationDidEnterBackground:
方法內(nèi)進(jìn)行任何操作都必須在5秒內(nèi)返回。
Note:
UIApplicationDidEnterBackgroundNotification
這個枚舉可以知道系統(tǒng)進(jìn)入后臺
The Background Transition Cycle
當(dāng)用戶按下Home鍵,關(guān)機(jī)鍵或者打開其他應(yīng)用,前臺應(yīng)用會變到inactive狀態(tài)然后到background狀態(tài)。這些轉(zhuǎn)變結(jié)果會調(diào)用到applicationWillResignActive:
和applicationDidEnterBackground:
方法。在applicationDidEnterBackground:
方法返回后,大多數(shù)應(yīng)用會在不久后變到suspended
狀態(tài)。如果應(yīng)用需要特殊的后臺任務(wù)(像播放音樂)或者執(zhí)行額外的長時間任務(wù),background狀態(tài)會延長。
Prepare for the App Snapshot
在applicationDidEnterBackground:
方法返回不久后,系統(tǒng)會生成一張應(yīng)用快照用于顯示。同樣,當(dāng)應(yīng)用被喚醒來處理一些后臺任務(wù),系統(tǒng)也許需要生成一張新的快照來反映改變。
如果你想對顯示的快照做更改,你需要調(diào)用snapshotViewAfterScreenUpdates:
來更新視圖,這個方法能馬上更新視圖,調(diào)用setNeedsDisplay
方法是沒用的,這個上面文檔講過了。
Strategies for Implementing Specific App Features
不同的應(yīng)用有不同的需要,但是有些行為應(yīng)該是相同的。下面的章節(jié)會介紹這些特定的功能如何實現(xiàn)。
Privacy Strategies
保護(hù)用戶隱私對于應(yīng)用來說是很重要的。系統(tǒng)已經(jīng)提供了保護(hù)隱私的方法。
Protecting Data Using On-Disk Encryption
設(shè)備鎖屏以后,是不能訪問被保護(hù)的文件的,就算文件是應(yīng)用創(chuàng)建的也不可以。想訪問保護(hù)文件必須在設(shè)備解鎖之后。
數(shù)據(jù)保護(hù)在大部分設(shè)備上是可用的,只需要遵循以下幾點:
- 文件系統(tǒng)必須支持?jǐn)?shù)據(jù)保護(hù),這在大部分設(shè)備上是可行的
- 用戶必須設(shè)置密碼鎖
使用NSData
和NSFileManager
類可以通過添加屬性來設(shè)置保護(hù)等級。當(dāng)寫入新文件時,你可以使用NSData
的writeToFile:options:error:
方法。對于已存在的文件,你可以使用NSFileManager
的setAttributes:ofItemAtPath:error:
方法,使用這些方法,你可以設(shè)置以下幾個保護(hù)等級:
- No protection -> 文件被加密但是當(dāng)設(shè)備被鎖屏?xí)r不能被密碼保護(hù)。選擇
NSDataWritingFileProtectionNone
這個枚舉。 - Complete -> 文件被加密且不能被訪問當(dāng)設(shè)備被鎖屏。選擇
NSDataWritingFileProtectionComplete
枚舉。 - Complete unless already open -> 文件被加密且不能被訪問當(dāng)設(shè)備被鎖屏,當(dāng)文件被訪問時設(shè)備鎖屏,應(yīng)用仍然可以在鎖屏狀態(tài)下訪問文件。選擇
NSDataWritingFileProtectionCompleteUnlessOpen
枚舉 - Complete until first login -> 文件被加密且不能訪問直到設(shè)備啟動,用戶解鎖一次。
如果你保護(hù)了文件,那么應(yīng)用會隨時不能訪問文件。當(dāng)設(shè)備鎖屏?xí)r,你可以通過幾點知道是否可以訪問文件:
- 可以在app delegate里實現(xiàn)
applicationProtectedDataWillBecomeUnavailable:
和applicationProtectedDataDidBecomeAvailable:
方法 - 任何對象都可以注冊
UIApplicationProtectedDataWillBecomeUnavailable
和UIApplicationProtectedDataDidBecomeAvailable
通知 - 可以通過
UIApplication
的protectedDataAvailable
屬性來知道當(dāng)前是否可以訪問文件
反正就是推薦文件保護(hù)。
Identifying Unique Users of Your App
你應(yīng)該區(qū)別每一個用戶,并且這一行為應(yīng)該是透明的。
在以下幾種情況下,也許你需要這樣做
- 登錄
- 給不同的用戶觀看不同的廣告
如果你需要在不同設(shè)備上辨認(rèn)是否是一個用戶,你需要提供自己的一套識別系統(tǒng)。
Supporting Multiple Versions of iOS
一個在多個版本運行的應(yīng)用應(yīng)該檢查系統(tǒng)版本,防止在舊系統(tǒng)上使用了新系統(tǒng)的API。
有幾個檢查方法你可以選擇:
- 確定這個類是否存在
if ([UIPrintInteractionController class]) {
// Create an instance of the class and use it.
}
else {
// The print interaction controller is not available so use an alternative technique.
}
- 判斷一個類是否可以使用這個方法,通過
instancesRespondToSelector:
類方法或者respondsToSelector:
實例方法。 - 判斷基于C語言的函數(shù)是否可用
if (UIGraphicsBeginPDFPage != NULL) {
UIGraphicsBeginPDFPage();
}
想知道這方面更多的知識,可以看 SDK Compatibility Guide.
Preserving Your App’s Visual Appearance Across Launches
Enabling State Preservation and Restoration in Your App
狀態(tài)保存和恢復(fù)不是自動的,系統(tǒng)必須選擇使用。如果要使用這些功能,需要實現(xiàn)以下方法
application:shouldSaveApplicationState:
,application:shouldRestoreApplicationState:
一般來說,返回YES是表明功能可用。但是有些時候需要返回NO,比如應(yīng)用更新了,你不應(yīng)該恢復(fù)舊的頁面。
The Preservation and Restoration Process
在保存和恢復(fù)過程中,應(yīng)用也有少量的任務(wù):
- 保存過程
- 告訴UIKit支持保存
- 告訴UIKit什么控制器和視圖需要被保存
- 給保存的對象編碼
- 恢復(fù)過程
- 告訴UIKit支持恢復(fù)
- 提供需要的UIKit對象
- 讓保存的對象恢復(fù)原樣
Figure 5-1 顯示了簡單的視圖控制器的層次結(jié)構(gòu)。如果沒有狀態(tài)恢復(fù),只有main storyboard文件里的控制器在隨后的啟動中恢復(fù)。當(dāng)你的應(yīng)用支持狀態(tài)恢復(fù),你可以保存所有的控制器
UIKit保存對象需要一個保存identifier,假如控制器沒有這個identifier,他和他的子視圖都不會被保存。Figure 5-2 展示了部分擁有identifier的控制器
這些功能對于應(yīng)用來說也許是毫無意思的,因為UIKit本身就能簡單的保存和恢復(fù)。
對于你保存的所有控制器 ,你也需要決定如果去恢復(fù)它們。UIKit 提供了兩種方式去創(chuàng)建對象。你可以去重新創(chuàng)建它們或者通過 view controller 去恢復(fù)它們。restoration class實現(xiàn)UIViewControllerRestoration
協(xié)議,并且在恢復(fù)的時候去負(fù)責(zé)尋找或者創(chuàng)建指定的對象。這里有幾個建議:
- 如果你的控制器是通過 main storyboard 文件加載的,就不用這樣搞了,讓UIKit自己去恢復(fù)吧
- 如果不是第一種情況,那么最簡單恢復(fù)辦法就是讓每一個控制器都實現(xiàn)協(xié)議。
在保存過程中,UIKit 保存對象并且寫入到磁盤。每個控制器也有一次機(jī)會來保存數(shù)據(jù)。
Flow of the Preservation Process
Figure 5-3 展示了直到保存狀態(tài)前的高級事件和應(yīng)用是如何被影響的。在保存之前,UIKit 會調(diào)用application:shouldSaveApplicationState:
方法,如果返回YES的話會開始保存視圖。
下次應(yīng)用啟動的時候會自動尋找保存狀態(tài)的文件,如果有的話就恢復(fù)。因為這些文件只適用于上次和當(dāng)前的周期,在啟動后會刪除上次的保存狀態(tài)文件。在恢復(fù)過程中有錯誤也會刪除保存狀態(tài)文件。舉例,在一次恢復(fù)過程中應(yīng)用崩潰了,那么系統(tǒng)會自動刪除文件防止下次恢復(fù)再崩潰。
What Happens When You Exclude Groups of View Controllers?
Figure 5-5 展示了當(dāng)導(dǎo)航控制器沒有保存identifier,他的子控制器和視圖都不會被保存
即使你不保存控制器,也不意味著所有控制器從視圖層次中消失了。舉個例子,如果有控制器是從 storyboard 文件中加載的,他會一直顯示。
Checklist for Implementing State Preservation and Restoration
你如果想通過代碼來實現(xiàn)保存和恢復(fù)狀態(tài),你應(yīng)該看看以下幾點:
- 實現(xiàn)
application:shouldSaveApplicationState:
和application:shouldRestoreApplicationState:
方法 - 給你想要保存的控制器添加非空字符串的
restorationIdentifier
屬性 - 在
application:willFinishLaunchingWithOptions:
展示窗口 - 給適當(dāng)?shù)目刂破髦付?restoration classes
- 使用
encodeRestorableStateWithCoder:
和decodeRestorableStateWithCoder:
編碼解碼控制器狀態(tài) - 編碼解碼任意的版本信息或者狀態(tài)信息使用
application:willEncodeRestorableStateWithCoder:
和application:didDecodeRestorableStateWithCoder:
方法 - 數(shù)據(jù)源實現(xiàn)
UIDataSourceModelAssociation
協(xié)議,雖然這不是必須的,但是這個協(xié)議可以幫助我們保存選中的和可見的視圖
Preserving the State of Your View Controllers
保存單獨的控制器狀態(tài),你需要做到以下幾點:
- 必須有 restoration identifier
- 必須在啟動的時候創(chuàng)建或者找到新的控制器
- 可選的來實現(xiàn)
encodeRestorableStateWithCoder:
和decodeRestorableStateWithCoder:
方法
Marking Your View Controllers for Preservation
UIKit 只會恢復(fù)擁有有效 restorationIdentifier 的對象。
恢復(fù)路徑是從上往下。
Restoring Your View Controllers at Launch Time
在恢復(fù)過程中,UIKit 會通過幾種辦法去恢復(fù):
- 如果控制器有 restoration class ,那么 UIKit 會去恢復(fù)控制器。調(diào)用
viewControllerWithRestorationIdentifierPath:coder:
方法,如果返回nil的話就代表不想創(chuàng)建控制器,UIKit 會放棄尋找。 - 如果控制器沒有 restoration class ,UIKit 會讓 app delegate 去恢復(fù)控制器。調(diào)用
application:viewControllerWithRestorationIdentifierPath:coder:
- 如果控制器已經(jīng)存在正確的恢復(fù)路徑,UIKit 會使用這個對象
- 如果控制器是通過 storyboard 去加載的,UIKit 會通過 storyboard 去尋找和創(chuàng)建控制器。
以下代碼展示了如果在恢復(fù)過程中創(chuàng)建控制器。
+ (UIViewController*) viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents
coder:(NSCoder *)coder {
MyViewController* vc;
UIStoryboard* sb = [coder decodeObjectForKey:UIStateRestorationViewControllerStoryboardKey];
if (sb) {
vc = (PushViewController*)[sb instantiateViewControllerWithIdentifier:@"MyViewController"];
vc.restorationIdentifier = [identifierComponents lastObject];
vc.restorationClass = [MyViewController class];
}
return vc;
}
Inter-App Communication
應(yīng)用之間可以通過 URL 來進(jìn)行通信。
Supporting AirDrop
AirDrop 可以發(fā)送圖片,文件,URLs,和其他類型的數(shù)據(jù)給附近的設(shè)備。AirDrop 通過 peer-to-peer 網(wǎng)絡(luò)來尋找附近的設(shè)備。
Sending Files and Data to Another App
如果想通過 AirDrop 發(fā)送文件和數(shù)據(jù),使用UIActivityViewController
對象。當(dāng)你創(chuàng)建了這個控制器,
你可以指定你想顯示什么。你也可以顯示自定義對象,只要遵守UIActivityItemSource
協(xié)議。
你可以通過excludedActivityTypes
屬性來指定不顯示的類型。當(dāng)顯示一個 activity view controller 在iPad上時,你必須使用popover
。
在iPhone上顯示 activity view controller
- (void)displayActivityControllerWithDataObject:(id)obj {
UIActivityViewController* vc = [[UIActivityViewController alloc]
initWithActivityItems:@[obj] applicationActivities:nil];
[self presentViewController:vc animated:YES completion:nil];
}
Receiving Files and Data Sent to Your App
使用 AirDrop 接受文件你需要注意以下幾點:
- 在 Xcode 里,聲明你的應(yīng)用能打開的文件
- 在 app delegate 里,實現(xiàn)
application:openURL:sourceApplication:annotation:
方法來接受數(shù)據(jù) - 在 Documents/Inbox 里查看文件,如果需要的話把文件移出來(需要修改的話)
傳輸?shù)?Documents/Inbox 中的文件你只能讀取或者刪除,但不能修改
Using URL Schemes to Communicate with Apps
Apple 內(nèi)置了很多 URL schemes。如果你的 URL 定義了一個和 Apple 相同的東西,那么在你應(yīng)用啟動時會打開 Apple 的應(yīng)用。
Sending a URL to Another App
當(dāng)你實現(xiàn)自定義的 URL scheme 來發(fā)送數(shù)據(jù)給別的應(yīng)用,調(diào)用openURL:
方法。
以下代碼展示了一個應(yīng)用如何打開另一個應(yīng)用
NSURL *myURL = [NSURL URLWithString:@"todolist://www.acme.com?Quarterly%20Report#200806231300"];
[[UIApplication sharedApplication] openURL:myURL];
如果應(yīng)用自定義了一個 URL scheme ,請看Implementing Custom URL Schemes
PS: iOS9新增了一個白名單,蘋果規(guī)定開發(fā)者只能設(shè)置50個 URL scheme 來打開別的應(yīng)用,在openURL:
之前還需要做個判斷canOpenURL:
,返回到前一個應(yīng)用不用這樣做。
Implementing Custom URL Schemes
如果你的應(yīng)用可以接收特定的 URLs,你應(yīng)該在系統(tǒng)里注冊相應(yīng)的 URL schemes。
Registering Custom URL Schemes
在應(yīng)用里注冊 URL 類型,你應(yīng)該在 Info.plist 文件中加入CFBundleURLTypes
key。這個 key 包含一個字典數(shù)組,每一個都定義了一個 URL schemes。
Key | Value |
---|---|
CFBundleURLName | 字符串包含了一個 URL scheme。為了確保唯一性,推薦指定一個反向域名格式的標(biāo)識,舉個例子, com.acme.myscheme。 |
CFBundleURLSchemes | 字符串?dāng)?shù)組包含了 URL scheme 名字,舉個例子,http, mailto, tel, 和 sms。 |
Note: 如果多個第三方應(yīng)用使用了相同的 URL scheme,目前還沒有好的辦法來解決。
Handling URL Requests
每個應(yīng)用都有自己自定義的 URL scheme 并且也該知道如何去處理它們。你應(yīng)該在 delegate 中實現(xiàn)以下方法:
- 使用
application:willFinishLaunchingWithOptions:
和application:didFinishLaunchingWithOptions:
方法來檢查 URL 的信息并決定是否打開。如果其中一個方法返回 NO,你應(yīng)用處理 URL 的代碼不會被調(diào)用。 - 使用
application:openURL:sourceApplication:annotation:
方法來打開文件。(iOS9廢棄了,應(yīng)該使用application:openURL:options:
)
Figure 6-1 展示了在一個要求打開網(wǎng)址的應(yīng)用上顯示修改好的啟動順序
Figure 6-2 展示了切換到前臺狀態(tài)打開 URL
Displaying a Custom Launch Image When a URL is Opened
應(yīng)用支持自定義的 URL schemes 可以提供自定義的啟動圖片。當(dāng)系統(tǒng)啟動你的應(yīng)用通過 URL 時并沒有有效的快照,他會顯示你指定的啟動圖片。指定一個啟動圖片,提供一張使用以下名字格式的 PNG 圖片:
basename代表了基本的圖片名字,假如名字是 Default,url_scheme 是你的 URL scheme 的一部分名字,假如 URL scheme 是 myapp,那么你的啟動圖片名字就是 Default-myapp@2x.png。
Performance Tips
本章講述整體性能的幾點。
Reduce Your App’s Power Consumption
功耗始終是移動設(shè)備上的一個大問題。你可以通過優(yōu)化以下幾個功能來提高電池壽命:
- CPU
- WiFi,藍(lán)牙,基帶
- 定位
- 加速劑
- 訪問硬盤
你應(yīng)該經(jīng)常使用 Instruments 來優(yōu)化算法。但是即使最優(yōu)算法也會對電池壽命有意向。你應(yīng)該在寫代碼的時候注意以下幾點:
- 避免使用 polling。polling 不會讓 CPU 進(jìn)入休眠。應(yīng)該使用
NSRunLoop
或者NSTime
代替。 - 設(shè)置
idleTimerDisabled
屬性為 NO,這個屬性默認(rèn)就是 NO,當(dāng)用戶不再輸入時會關(guān)閉屏幕。如果你需要屏幕不被關(guān)閉,你應(yīng)該修改代碼而不是設(shè)置屬性為 YES。 - 盡可能的合并一些任務(wù)來增加 CPU 空閑時間。因為一些很小的任務(wù)常常會喚醒 CPU。
- 避免經(jīng)常訪問硬盤。
- 需要多少內(nèi)容繪制多少內(nèi)容。繪制很耗電,不要依靠硬件來控制幀數(shù),應(yīng)該是內(nèi)容需要幾幀繪制幾幀。
- 如果你使用
UIAccelerometer
來接收加速計時間。PS:看了下好像這個類在5.0就廢棄了。
訪問網(wǎng)絡(luò)數(shù)據(jù)是很耗電的,通過以下幾點來使訪問數(shù)據(jù)次數(shù)最小化:
- 僅在需要的時候訪問網(wǎng)絡(luò)并且不 poll 服務(wù)。
- 當(dāng)你必須訪問網(wǎng)絡(luò)時,發(fā)送最少的數(shù)據(jù)量。
- 發(fā)送數(shù)據(jù)而不是發(fā)送數(shù)據(jù)包。系統(tǒng)會在空閑的時候關(guān)閉 WiFi 和 無線電。當(dāng)你使用
NSURLSession
來進(jìn)行多個上傳或下載任務(wù)時,應(yīng)該讓他們同時進(jìn)行而不是一個個來。系統(tǒng)會自動管理隊列。 - 盡可能的使用WiFi來訪問網(wǎng)絡(luò)。
- 如果使用定位,你應(yīng)該使用最適合的 distance filter 和精確度
Instruments 應(yīng)用包含了幾個收集電池信息的 Instruments。還可以收集指定硬件耗電量。你也可以使用診斷記錄來收集信息。PS:這個在手機(jī)設(shè)置里可以看。
Use Memory Efficiently
系統(tǒng)的可用內(nèi)存會影響應(yīng)用的性能。
Observe Low-Memory Warnings
系統(tǒng)發(fā)出內(nèi)存警告時應(yīng)該移除不需要的對象。回應(yīng)這個警告是很重要的否則系統(tǒng)可能會終止應(yīng)用。系統(tǒng)通過以下幾個 API 來發(fā)送內(nèi)存警告:
- app delegate 的
applicationDidReceiveMemoryWarning:
-
UIViewController
的didReceiveMemoryWarning
-
UIApplicationDidReceiveMemoryWarningNotificationnotification
通知 - GCD 的
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
類型。這是你唯一能用來辨別內(nèi)存壓力大不大。
收到內(nèi)存警告你應(yīng)該釋放掉不需要的內(nèi)存。例如清理緩存,釋放圖片。如果你有一個不用的大數(shù)據(jù),應(yīng)該把它寫進(jìn)磁盤。
你可以通過UIApplicationDidReceiveMemoryWarningNotification
通知來直接刪除不需要的資源。
Reduce Your App’s Memory Footprint
Table 7-1 減少應(yīng)用內(nèi)存占用空間
Tip | Actions to take |
---|---|
清楚內(nèi)存泄露 | 在iOS中內(nèi)存是很關(guān)鍵的資源,你的應(yīng)用不應(yīng)該有內(nèi)存泄露。使用 Instruments 查看是否有內(nèi)存泄露。 |
資源文件盡可能的小 | 文件寫入到磁盤之前會在內(nèi)存中存在。盡可能的壓縮圖片文件(PNG 圖片是 iOS 首選的圖片格式)。 |
懶加載資源 | 在需要使用要資源時再加載。 |
后面這些很多都在之前的文檔有講到,感興趣的朋友可以自己去翻閱一下。