應用間通信
應用程式只能間接與設備上的其他應用進行通信。您可以使用AirDrop與其他應用程序共享文件和數據。您還可以定義自定義網址方案,以便應用程序可以使用URL向應用發送信息。
注意:您也可以使用UIDocumentInteractionController對象或文檔選擇器在應用程序之間發送文件。有關添加對文檔交互控制器的支持的信息,請參閱iOS的文檔交互編程主題。Document Interaction Programming Topics for iOS,有關使用文檔選擇器打開文件的信息,請參閱文檔選擇器編程指南。Document Picker Programming Guide
支持AirDrop
AirDrop可讓您與附近的設備共享照片,文檔,URL和其他類型的數據。 AirDrop利用對等網絡查找附近的設備并連接到它們。
將文件和數據發送到另一個應用程序
要使用AirDrop發送文件和數據,請使用UIActivityViewController對象從您的用戶界面中顯示活動表。創建此視圖控制器時,指定要共享的數據對象。視圖控制器僅顯示支持指定數據的活動。對于AirDrop,您可以指定圖像,字符串,URL和其他幾種類型的數據。您還可以傳遞采用UIActivityItemSource協議的自定義對象。
要顯示活動視圖控制器,可以使用類似于清單6-1所示的代碼。活動視圖控制器自動使用指定對象的類型來確定在活動表中顯示的活動。您不必明確指定AirDrop活動。但是,您可以使用視圖控制器的excludedActivityTypes屬性來防止工作表顯示特定類型。在iPad上顯示活動視圖控制器時,必須使用彈出窗口。
清單6-1在iPhone上顯示活動表
- (void)displayActivityControllerWithDataObject:(id)obj{
UIActivityViewController * vc =[[UIActivityViewController alloc]
initWithActivityItems:@ [obj] applicationActivities:nil];
[self presentViewController:vcanimated:YES completion:nil];
}
有關使用活動視圖控制器的更多信息,請參閱UIActivityViewController類參考UIActivityViewController Class Reference。有關活動及其支持的數據類型的完整列表,請參閱UIActivity類參考。UIActivity Class Reference
接收文件和數據發送到您的應用程序
要使用AirDrop接收發送到您的應用程序的文件,請執行以下操作:
在Xcode中,聲明支持您的應用程序能夠打開的文檔類型。
在你的應用程序委托中,實現應用程序:openURL:sourceApplication:annotation:method。使用該方法接收其他應用程序發送的數據。
您的Xcode項目的“信息”選項卡包含一個“文檔類型”部分,用于指定應用程序支持的文檔類型。至少必須指定文檔類型的名稱和表示數據類型的一個或多個UTI。例如,要聲明對PNG文件的支持,您將包含public.png作為UTI字符串。iOS使用指定的UTI來確定您的應用是否有資格打開給定的文檔。
將符合條件的文檔轉移到應用程序的容器后,iOS會啟動應用程序(如果需要),并調用應用程序:openURL:sourceApplication:annotation:其應用程序委托的方法。如果您的應用程序處于前臺,則應使用此方法打開該文件并將其顯示給用戶。如果您的應用程序在后臺,您可能只會確定該文件在那里,以便以后打開它。因為通過AirDrop傳輸的文件是使用數據保護進行加密的,除非設備當前被解鎖,否則無法打開文件。
您的應用程序有權讀取和刪除它收到的文件,但沒有權限寫入該文件。如果您打算修改文件,則必須將其移出當前位置才能執行此操作。建議您刪除文件的原始版本。
有關在應用程序中支持文檔類型的更多信息,請參閱基于文檔的iOS應用程序編程指南。Document-Based App Programming Guide for iOS
使用URL方案與Apps通信
URL方案允許您通過您定義的協議與其他應用程序進行通信。要與實現這種方案的應用程序通信,您必須創建一個格式正確的URL,并要求系統將其打開。要實現對自定義方案的支持,您必須聲明對該方案的支持,并處理使用該方案的傳入URL。
注意:Apple為http,mailto,tel和sms URL方案提供了內置的支持。它還支持針對地圖,YouTube和iPod應用程序的基于http的URL。這些方案的處理程序是固定的,不能更改。如果您的網址類型包含與Apple定義的方案相同的方案,則Apple提供的應用程序將會啟動,而不是您的應用程序。有關Apple支持的方案的信息,請參閱AppleURL Scheme Reference。Apple URL Scheme Reference
發送一個URL到另一個應用程序
當您要將數據發送到實現自定義URL方案的應用程序時,請創建一個適當格式的URL并調用該應用對象的openURL:方法。openURL:方法使用注冊的方案啟動該應用,并將您的URL傳遞給它。在這一點上,控制傳遞給新的應用程序。
以下代碼片段說明了一個應用程序如何請求另一個應用程序的服務(在本示例中為“todolist”是應用程序注冊的假設自定義方案):
NSURL * myURL = [NSURL URLWithString:@“todolist://www.acme.com?Quarterly%20Report#200806231300”];
[UIApplication sharedApplication] openURL:myURL];
如果您的應用程序定義了自定義URL方案,那么它應該實現該方案的處理程序,如實現自定義URL方案中所述。有關系統支持的URL方案的詳細信息,包括有關如何格式化URL的信息,請參閱AppleURL Scheme Reference。Apple URL Scheme Reference.
實現自定義URL方案
如果您的應用程序可以接收特殊格式的URL,則應該使用系統注冊相應的URL方案。應用程序經常使用自定義URL方案向其他應用程序提供服務。例如,“地圖”應用程序支持顯示特定地圖位置的URL。
注冊自定義URL方案
要為您的應用注冊URL類型,請在應用的Info.plist文件中包含CFBundleURLTypes密鑰。CFBundleURLTypes鍵包含一系列字典,每個字典都定義了應用程序支持的URL方案。表6-1說明了要包含在每個字典中的鍵和值。
表6-1 CFBundleURLTypes屬性的鍵和值
鍵
值
CFBundleURLName
包含URL方案的抽象名稱的字符串。為了確保唯一性,建議您指定反向DNS風格的標識符,例如com.acme.myscheme。
您指定的字符串也用作應用程序的InfoPlist.strings文件中的鍵。密鑰的值是可讀取的方案名稱。
CFBundleURLSchemes
包含URL方案名稱的字符串數組,例如http,mailto,tel和sms。
注意:如果有多個第三方應用程序注冊以處理相同的URL方案,則目前沒有確定哪個應用程序將被賦予該方案的過程。
處理URL請求
具有自己的自定義URL方案的應用程序必須能夠處理傳遞給它的URL。所有網址都會在啟動時或應用程序運行時或后臺傳遞到您的應用程序代理。要處理傳入的URL,您的代理應該實現以下方法:
使用應用程序:willFinishLaunchingWithOptions:和應用程序:didFinishLaunchingWithOptions:方法來檢索有關URL的信息,并決定是否要打開它。如果任一方法返回NO,您的應用程序的URL處理代碼不被調用。
使用應用程序:openURL:sourceApplication:annotation:打開文件的方法。
如果您的應用程序在URL請求到達時未運行,則會將其啟動并移動到前臺,以便可以打開該URL。您的應用程序的實現:willFinishLaunchingWithOptions:或應用程序:didFinishLaunchingWithOptions:方法應從其選項字典中檢索URL,并確定應用程序是否可以打開它。如果可以,返回YES并讓您的應用程序:openURL:sourceApplication:annotation:((或application:handleOpenURL :)方法處理URL的實際打開。 (如果您實現這兩種方法,兩者都必須返回YES才能打開URL)。圖6-1顯示了要求打開URL的應用程序的修改啟動順序。
圖6-1啟動應用程序以打開URL
如果您的應用正在運行,但是在后臺發生或在URL請求到達時被暫停,則將其移動到前臺以打開該URL。 此后不久,系統調用委托人的應用程序:openURL:sourceApplication:annotation:檢查URL并將其打開。圖6-2顯示了將應用程序移動到前臺以打開URL的修改過程。
圖6-2 喚醒一個后臺應用來打開一個URL
注意:支持自定義URL方案的應用程序可以指定在啟動應用程序以處理URL時顯示不同的啟動映像。有關如何指定這些啟動映像的詳細信息,請參閱打開URL時顯示自定義啟動映像。Displaying a Custom Launch Image When a URL is Opened.
所有網址都傳遞到NSURL對象中的應用程序。您可以定義URL的格式,但NSURL類符合RFC1808規范,因此支持大多數URL格式約定。具體來說,該類包括返回由RFC 1808定義的URL的各個部分的方法,包括用戶,密碼,查詢,片段和參數字符串。您的自定義方案的“協議”可以使用這些URL部分來傳送各種信息。
在應用程序的實現中:openURL:sourceApplication:annotation:如清單6-2所示,傳入的URL對象在其查詢和片段部分中傳達特定于應用程序的信息。代理提取此信息- 在這種情況下,即將完成任務的名稱以及該任務到期的日期 - 并與之建立應用程序的模型對象。此示例假定用戶正在使用公歷。如果您的應用程序支持非公歷日歷,則需要相應地設計您的URL方案,并準備好處理代碼中的其他日歷類型。
- (BOOL)application:(UIApplication *)applicationopenURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
if ([[url scheme]isEqualToString:@"todolist"]) {
ToDoItem *item =[[ToDoItem alloc] init];
NSString *taskName =[url query];
if (!taskName || ![selfisValidTaskString:taskName]) { // must have a task name
returnNO;
}
taskName = [taskNamestringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
item.toDoTask =taskName;
NSString *dateString =[url fragment];
if (!dateString ||[dateString isEqualToString:@"today"]) {
item.dateDue = [NSDate date];
} else {
if(![self isValidDateString:dateString]) {
return NO;
}
//format: yyyymmddhhmm (24-hour clock)
NSString*curStr = [dateString substringWithRange:NSMakeRange(0, 4)];
NSIntegeryeardigit = [curStr integerValue];
curStr =[dateString substringWithRange:NSMakeRange(4, 2)];
NSIntegermonthdigit = [curStr integerValue];
curStr =[dateString substringWithRange:NSMakeRange(6, 2)];
NSIntegerdaydigit = [curStr integerValue];
curStr =[dateString substringWithRange:NSMakeRange(8, 2)];
NSIntegerhourdigit = [curStr integerValue];
curStr =[dateString substringWithRange:NSMakeRange(10, 2)];
NSIntegerminutedigit = [curStr integerValue];
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setYear:yeardigit];
[dateComps setMonth:monthdigit];
[dateComps setDay:daydigit];
[dateComps setHour:hourdigit];
[dateComps setMinute:minutedigit];
NSCalendar *calendar = [s[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDate*itemDate = [calendar dateFromComponents:dateComps];
if(!itemDate) {
return NO;
}
item.dateDue = itemDate;
}
[(NSMutableArray*)self.list addObject:item];
return YES;
}
return NO;
}
一定要驗證從傳遞到您的應用程序的URL獲得的輸入;請參閱“安全編碼指南”Validating Input and Interprocess Communication,Secure Coding Guide中的驗證輸入和進程間通信,以了解如何避免與URL處理相關的問題。要了解Apple定義的URL方案,請參閱AppleURL Scheme Reference。Apple URL Scheme Reference
打開URL時顯示自定義啟動映像
支持自定義URL方案的應用程序可以為每個方案提供自定義的啟動映像。當系統啟動您的應用程序來處理URL并且沒有相關快照可用時,它會顯示您指定的啟動映像。要指定啟動映像,請提供名稱使用以下命名約定的PNG映像:
<basename>-<url_scheme><other_modifiers>.png
在這個命名約定中,basename表示由應用程序的Info.plist文件中的UILaunchImageFile鍵指定的基本映像名稱。如果不指定自定義基本名稱,請使用字符串Default。名稱的部分是您的URL方案名稱。要為myappURL方案指定一個通用啟動映像,您應該在應用程序的捆綁包中添加名為Default-myapp@2x.png的映像文件。 (@ 2x修飾符表示圖像用于Retina顯示器,如果您的應用程序還支持標準分辨率顯示,則還將提供Default-myapp.png圖像。)
有關可以在啟動映像名稱中包含的其他修飾符的信息,請參閱“信息屬性列表密鑰引用”Information Property List Key Reference.中的UILaunchImageFile名稱鍵的說明。
性能提示
在開發應用程序的每個步驟中,考慮您的設計選擇對應用程序整體性能的影響。電源使用和內存消耗是iOS應用程序的重要考慮因素,還有許多其他注意事項。以下部分將介紹在整個開發過程中應考慮的因素。
降低應用程序的功耗
移動設備上的功耗總是一個問題。 iOS中的電源管理系統通過關閉當前未使用的任何硬件功能來節省電力。您可以通過優化使用以下功能來幫助延長電池壽命:
CPU
Wi-Fi,藍牙和基帶(EDGE,3G)無線電
核心位置框架
加速度計
磁盤
您的優化目標應該是以盡可能最有效的方式進行最多的工作。您應該始終使用Instruments優化您的應用程序的算法。但即使最優化的算法仍然可能會對設備的電池壽命產生負面影響。在編寫代碼時,您應該考慮以下準則:
避免進行需要輪詢的工作。輪詢阻止CPU進入睡眠狀態。而不是輪詢,使用NSRunLoop或NSTimer類來根據需要安排工作。
將共享UIApplication對象的idleTimerDisabled屬性設置為NO,盡可能。閑置定時器在指定的不活動時間段后關閉設備的屏幕。如果您的應用程序不需要屏幕保持打開,請讓系統將其關閉。如果您的應用程序由于屏幕關閉而產生副作用,您應該修改代碼以消除副作用,而不必不必要地禁用空閑計時器。
合并工作盡可能最大限度地延長空閑時間。一般來說,一次執行一組計算的能力通常要比在較長時間內以小塊執行的方式更少。周期性地做一點點工作需要更頻繁地喚醒CPU,并使其進入可以執行任務的狀態。
避免頻繁訪問磁盤。例如,如果您的應用程序將狀態信息保存到磁盤,只有當該狀態信息發生變化時,才能進行此操作,并盡可能合并更改,以避免以頻繁的間隔寫入較小的更改。
不要比所需要的繪制圖像更快。繪圖是一個昂貴的操作,當談到電量。不要依靠硬件來調節幀速率。僅繪制與應用程序實際需要的幀數一樣多。
如果您使用UIAccelerometer類接收常規加速度計事件,則在不需要時將其禁用。類似地,將事件傳送的頻率設置為適合您需要的最小值。有關更多信息,請參閱UIKit應用程序的事件處理指南。Event Handling Guide for UIKit Apps.
傳輸到網絡的數據越多,運行無線電的功率就越多。實際上,訪問網絡是您可以執行的功耗最大的操作。您可以按照以下準則減少該時間:
只有在需要的時候才能連接到外部網絡服務器,不要輪詢這些服務器。
當您必須連接到網絡時,傳送完成該作業所需的最少數據量。使用緊湊的數據格式,不要包含被忽略的多余的內容。
以突發方式發送數據,而不是隨著時間擴散傳輸數據包。當檢測到缺少活動時,系統會關閉Wi-Fi和單元收音機。當它在更長的時間內傳輸數據時,您的應用程序使用的功率要比在較短時間內傳輸相同數據量的功率大得多。
當使用NSURLSession類排列多個上傳或下載任務時,將這些項目排隊在一起,而不是等待一個完成,然后再啟動下一個。當這樣做最有效時,系統管理自動執行排隊的任務。
只要有可能,使用Wi-Fi無線電連接到網絡。 Wi-Fi使用更少的功率,并且優于蜂窩無線電。
如果您使用Core Location框架來收集位置數據,請盡快禁用位置更新,并將距離過濾器和精度等級設置為適當的值。核心位置使用可用的GPS,小區和Wi-Fi網絡來確定用戶的位置。雖然核心位置很難最大限度地減少這些無線電的使用,但設置準確性和過濾器值可使核心位置在不需要的情況下完全關閉硬件。有關詳細信息,請參閱位置和地圖編程指南。Location and Maps Programming Guide.
儀器應用程序包含幾種用于收集電力相關信息的工具。您可以使用這些儀器來收集關于功耗的一般信息,并收集Wi-Fi和藍牙無線電,GPS接收器,顯示器和CPU等硬件的特定測量。您還可以啟用設備上的能量診斷日志記錄來收集信息。有關使用儀器收集電源相關數據的信息,請參閱“儀器用戶指南”Instruments User Guide。有關如何啟用設備上的能源診斷日志記錄的信息,請參閱Instruments幫助。Instruments Help.
有效地使用內存
鼓勵應用程序盡可能少地使用內存,以便系統可以在內存中保留更多的應用程序,或將更多的內存專用于真正需要它的前臺應用程序。系統可用內存量與應用程序的相對性能之間存在直接的相關性。較少的可用內存意味著系統更有可能在滿足未來內存請求時遇到問題。
為了確保有足夠的可用內存可用,您應該最小化應用程序的內存使用情況,并在系統要求您釋放內存時做出響應。
觀察低內存警告
當系統向您的應用發出低內存警告時,立即做出回應。低內存警告是您刪除對不需要的對象的引用的機會。響應這些警告是至關重要的,因為不這樣做的應用程序更有可能被終止。該系統使用以下API向您的應用程序提供內存警告:
應用程序委托的applicationDidReceiveMemoryWarning:方法。
你的UIViewController類的didReceiveMemoryWarning方法。
UIApplicationDidReceiveMemoryWarningNotification通知。
調度源類型為DISPATCH_SOURCE_TYPE_MEMORYPRESSURE。這種技術是唯一可以用來區分記憶壓力的嚴重性的技術。
收到任何這些警告后,您的處理程序方法應該立即釋放任何不需要的內存。使用警告來清除緩存并釋放圖像。如果您沒有使用大型數據結構,請將這些結構寫入磁盤并釋放數據的內存副本。
如果您的數據模型包含已知的可清除資源,則可以為UIApplicationDidReceiveMemoryWarningNotification通知提供相應的管理對象注冊,并直接刪除對其可清除資源的強引用。處理此通知直接避免了通過應用程序代理路由所有內存警告呼叫的需要。
注意:您可以使用iOS Simulator中的模擬內存警告命令在低內存條件下測試應用程序的行為。
減少應用程序的內存占用
從低占有率開始,您可以在以后擴大應用程序的空間。表7-1列出了有關如何減少應用程序整體內存占用的一些提示。
表7-1降低應用程序內存占用空間的技巧
小帖士
采取行動
消除內存泄漏。
由于內存是iOS中的關鍵資源,因此您的應用程序不應該有內存泄漏。使用儀器應用程序來跟蹤代碼中的泄漏,無論是在模擬器還是在實際的設備上。有關使用儀器的更多信息,請參閱儀器用戶指南。Instruments User Guide
使資源文件盡可能小。
文件駐留在磁盤上,但在使用之前必須加載到內存中。壓縮所有圖像文件使其盡可能小。 (要壓縮PNG圖像- iOS應用程序的首選圖像格式 - 請使用pngcrush工具。)您可以使用NSPropertyListSerialization類以二進制格式編寫屬性列表文件。
對于大型數據集使用Core Data或SQLite。
如果您的應用程序操作大量的結構化數據,請將其存儲在Core Data持久存儲或SQLite數據庫中,而不是在平面文件中。Core Data和SQLite都提供了管理大型數據集的有效方法,而不需要將整個集合一次存儲在內存中。
負載資源懶惰。
在實際需要之前,您不應該加載資源文件。預取資源文件可能似乎是節省時間的一種方式,但這種做法實際上會減慢您的應用程序的速度。另外,如果你最終不使用資源,加載它浪費內存沒有好的目的。
聰明地分配內存
表7-2列出了改善應用程序內存使用情況的提示。
表7-2分配內存的提示
小貼士
采取行動
對資源施加大小限制。
避免在較小的資源文件中加載大型資源文件。不要使用高分辨率圖像,而是使用適合iOS設備的尺寸。如果您必須使用大量資源文件,請查找在任何給定時間僅加載所需文件部分的方法。例如,不是將整個文件加載到內存中,而是使用mmap和munmap函數將文件的部分映射到內存中。有關將文件映射到內存的更多信息,請參閱“文件系統性能指南”。
避免無限制的問題集。
無限制的問題集可能需要任意大量的數據進行計算。如果該集合需要比可用內存更多的內存,您的應用程序可能無法完成計算。您的應用程序應盡可能避免此類設置,并處理已知內存限制的問題。
有關ARC和內存管理的詳細信息,請參閱Transition to to ARCRelease Notes。Transitioning to ARC Release Notes
調整您的網絡代碼
iOS中的網絡堆棧包括用于通過iOS設備的無線電硬件進行通信的多個接口。主要的編程接口是CFNetwork框架,它構建在CoreFoundation框架中的BSD套接字和不透明類型之上,以與網絡實體進行通信。您還可以在Foundation框架中使用NSStream類和在系統的CoreOS層中找到的低級BSD套接字。
有關如何使用CFNetwork框架進行網絡通信的信息,請參閱“CFNetwork編程指南”CFNetwork Programming Guide和“CFNetwork框架參考”CFNetwork Framework Reference。有關使用NSStream類的信息,請參閱FoundationFramework Reference。Foundation Framework Reference
高效網絡技巧
通過網絡實現接收或傳輸數據的代碼是設備上功耗最大的操作之一。最大限度地減少發送或接收數據的時間有助于延長電池壽命。為此,在編寫與網絡相關的代碼時,您應該考慮以下提示:
對于您所控制的協議,將數據格式定義為盡可能的緊湊。
避免使用聊天協議。
無論何時可以以突發方式發送數據包。
蜂窩和Wi-Fi無線電設計為在沒有活動時關閉電源。但是,根據收音機,這樣做可能需要幾秒鐘。如果您的應用程序每隔幾秒鐘發送一小段數據,無線電可能會保持上電狀態,即使沒有實際執行任何操作,也會繼續消耗電力。而不是更頻繁地發送少量數據,最好是以更大的間隔發送更大量的數據。
當通過網絡進行通信時,數據包可能隨時丟失。因此,在編寫網絡代碼時,應該確保在處理故障時盡可能的保持穩定。執行響應網絡條件變化的處理程序是完全合理的,但是如果這些處理程序不被稱為一致的,則不要感到驚訝。例如,Bonjour網絡回調可能不總是立即響應于網絡服務的消失而被調用。Bonjour系統服務在收到服務正在消失的通知時立即調用瀏覽回調,但網絡服務可能會在沒有通知的情況下消失。如果提供網絡服務的設備意外失去網絡連接或傳輸中的通知丟失,則可能會發生這種情況。
使用Wi-Fi
如果您的應用使用Wi-Fi無線電接入網絡,則必須通過將UIRequiresPersistentWiFi密鑰包含在應用的Info.plist文件中來通知系統。包含此鍵可以讓系統知道如果它檢測到任何活動的Wi-Fi熱點,它應該顯示網絡選擇對話框。它也讓系統知道在應用程序運行時不應該嘗試關閉Wi-Fi硬件。
為了防止Wi-Fi硬件使用太多的電源,iOS有一個內置計時器,如果沒有正在運行的應用程序通過UIRequiresPersistentWiFi鍵請求使用它,則在30分鐘后完全關閉硬件。如果用戶啟動包含該鍵的應用程序,則iOS會在應用程序的生命周期內有效地禁用計時器。然而,一旦該應用程序退出或暫停,系統將重新啟用計時器。
注意:請注意,即使UIRequiresPersistentWiFi的值為true,當設備空閑(即屏幕鎖定)時,也不起作用。該應用被視為無效,雖然它可能在某些級別上運行,但它沒有Wi-Fi連接。
有關UIRequiresPersistentWiFi鍵和Info.plist文件的鍵的更多信息,請參閱信息屬性列表文件。The Information Property List File
飛行模式警報
如果您的應用程序在設備處于飛行模式時啟動,系統可能會顯示警報以通知用戶該事實。僅當滿足以下所有條件時,系統才會顯示此警報:
您的應用程序的信息屬性列表(Info.plist)文件包含UIRequiresPersistentWiFi鍵,該鍵的值設置為true。
當設備當前處于飛行模式時,您的應用會啟動。
切換到飛行模式后,設備上的Wi-Fi尚未手動重新啟用。
改進文件管理
最小化寫入磁盤的數據量。文件操作相對較慢,涉及寫入到具有有限壽命的閃存驅動器。幫助您最大限度減少文件相關操作的一些具體技巧包括:
只寫文件的更改部分,并可以匯總更改。避免寫出整個文件只是為了更改幾個字節。
定義文件格式時,將經過頻繁修改的內容組合在一起,以最大限度地減少每次需要寫入磁盤的塊的總數。
如果您的數據由隨機訪問的結構化內容組成,請將其存儲在Core Data持久存儲或SQLite數據庫中,特別是如果您正在操縱的數據量可能增長到超過幾兆字節。
避免將緩存文件寫入磁盤。此規則的唯一例外是當您的應用程序退出時,您需要編寫狀態信息,以便在下次啟動時將應用重新設置為相同的狀態。
使應用程序備份更有效率
通過iCloud進行無線備份,或用戶通過iTunes同步設備。在備份期間,文件將從設備傳輸到用戶的計算機或iCloud帳戶。應用程序沙箱中文件的位置確定是否備份和還原這些文件。如果您的應用程序創建許多大型文件,并定期更改,并將其放置在備份的位置,則備份可能會減慢。在編寫文件管理代碼時,您需要注意這一事實。
應用程序備份最佳做法
您無需以任何方式準備應用程序進行備份和恢復操作。具有活動iCloud帳戶的設備在適當的時間將其應用數據備份到iCloud。對于插入計算機的設備,iTunes會對應用程序的數據文件進行增量備份。但是,iCloud和iTunes不會備份以下目錄的內容:
<application_Home>/AppName.app
<Application_Data>/Library/Caches
<Application_Data>/tmp
為了防止同步過程花費很長時間,請選擇將文件放在應用程序主目錄中的位置。存儲大文件的應用程序可能會減慢備份到iTunes或iCloud的過程。這些應用程序還可以消耗大量的用戶可用存儲空間,這可能會鼓勵用戶刪除應用程序或禁用將該應用的數據備份到iCloud。考慮到這一點,您應該按照以下準則存儲應用程序數據:
關鍵數據應存儲在 / Documents目錄中。關鍵數據是您的應用無法重新創建的任何數據,例如用戶文檔和其他用戶生成的內容。
支持文件包括應用程序下載或生成的文件,并且您的應用程序可以根據需要重新創建。存儲應用程序支持文件的位置取決于當前的iOS版本。
在iOS 5.1及更高版本中,將支持文件存儲在/ Library / Application Support目錄中,并使用setResourceValue:forKey:error:method將NSURLIsExcludedFromBackupKey屬性添加到相應的NSURL對象。(如果您使用的是Core Foundation,請使用CFURLSetResourcePropertyForKey函數將kCFURLIsExcludedFromBackupKey鍵添加到CFURLRef對象。)應用此屬性可防止將文件備份到iTunes或iCloud。如果您有大量的支持文件,您可以將它們存儲在自定義子目錄中,并將擴展屬性應用于目錄。
在iOS 5.0及更早版本中,將支持文件存儲在/ Library / Caches目錄中,以防止它們被備份。如果您定位到iOS 5.0.1,請參閱如何防止文件備份到iCloud和iTunes?How do I prevent files from being backed up to iCloud and iTunes有關如何從備份中排除文件的信息。
緩存數據應存儲在 / Library /Caches目錄中。您應該放在Caches目錄中的文件示例包括(但不限于)數據庫緩存文件和可下載內容,例如雜志,報紙和地圖應用程序使用的文件。您的應用程序應該能夠優雅地處理系統刪除緩存數據以釋放磁盤空間的情況。
臨時數據應存儲在 / tmp目錄中。臨時數據包括您不需要長時間持續的任何數據。記住在完成這些文件時刪除這些文件,以便它們不會繼續占用用戶設備上的空間。
雖然iTunes支持應用程序包本身,但在每次同步操作中都不會這樣做。直接從設備購買的應用程序將在該設備下一次與iTunes同步時進行備份。不過,在后續的同步操作中,應用程序不會備份,除非應用程序包本身已更改(例如,應用程序已更新)。
有關如何使用應用程序目錄的其他指導,請參閱文件系統編程指南。File System Programming Guide
應用更新期間保存的文件
當用戶下載應用程序更新時,iTunes會將更新安裝到新的應用程序目錄中。然后將用戶的數據文件從舊安裝移動到新的應用程序目錄,然后再刪除舊的安裝。在更新過程中,保證以下目錄中的文件被保留:
<Application_Data>/Documents
<Application_Data>/Library
雖然其他用戶目錄中的文件也可能會被移動,但是在更新后,您不應該依賴它們存在。
移動主線程
確保限制您在應用程序的主線程上所做的工作類型。主線程是您的應用程序處理觸摸事件和其他用戶輸入的位置。為了確保您的應用程序始終對用戶做出響應,您不應該使用主線程來執行長時間運行或潛在的無界任務,例如訪問網絡的任務。相反,您應該始終將這些任務移到后臺線程上。這樣做的首選方法是使用GrandCentral Dispatch(GCD)或NSOperation對象異步執行任務。
將任務移動到后臺使您的主線程可以自由地繼續處理用戶輸入,這在您的應用程序啟動或退出時尤其重要。在這些時期,您的應用程序有望及時響應事件。如果您的應用程序的主線程在啟動時被阻止,系統可能會在應用程序啟動之前終止應用程序。如果主線程在退出時被阻止,系統可以在應用程序有機會寫出關鍵的用戶數據之前,同樣可以殺死應用程序。
有關使用GCD,操作對象和線程的更多信息,請參閱并發編程指南。Concurrency Programming Guide