App Programming Guide for iOS讀書筆記

這是閱讀該指南的一些筆記,說說是筆記,其實就是把一些自己決定重要的知識給翻譯了一遍,因為英文讀著讀著就把前面的給忘了。。。所以就打算記錄一點。該文章會慢慢更新,這段時間打算將幾篇重要的指南都重新看一遍,每天都會更新這些筆記,英語不大好,可能有翻譯錯誤的地方,請大家指出,謝謝!

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)

在啟動時候要盡快完成,超過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文件中添加UIInterfaceOrientationKey值,設(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è)置密碼鎖

使用NSDataNSFileManager類可以通過添加屬性來設(shè)置保護(hù)等級。當(dāng)寫入新文件時,你可以使用NSDatawriteToFile:options:error:方法。對于已存在的文件,你可以使用NSFileManagersetAttributes: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:方法
  • 任何對象都可以注冊UIApplicationProtectedDataWillBecomeUnavailableUIApplicationProtectedDataDidBecomeAvailable通知
  • 可以通過UIApplicationprotectedDataAvailable屬性來知道當(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:
  • UIViewControllerdidReceiveMemoryWarning
  • 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 首選的圖片格式)。
懶加載資源 在需要使用要資源時再加載。

后面這些很多都在之前的文檔有講到,感興趣的朋友可以自己去翻閱一下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容