ios8 專題:
http://www.cocoachina.com/special/ios8/
應用擴展:
http://www.cocoachina.com/industry/20140627/8960.html
http://blog.csdn.net/songhongri/article/details/38709455
ios8 app extension
一、擴展概述
擴展(Extension)是iOS 8中引入的一個非常重要的新特性。擴展讓app之間的數據交互成為可能。用戶可以在app中使用其他應用提供的功能,而無需離開當前的應用。
在iOS 8系統之前,每一個app在物理上都是彼此獨立的,app之間不能互訪彼此的私有數據。
而在引入擴展之后,其他app可以與擴展進行數據交換?;诎踩托阅艿目紤],每一個擴展運行在一個單獨的進程中,它擁有自己的bundle, bundle后綴名是.appex。擴展bundle必須包含在一個普通應用的bundle的內部。
iOS 8系統有6個支持擴展的系統區域,分別是Today、Share、Action、Photo Editing、Storage Provider、Custom keyboard。支持擴展的系統區域也被稱為擴展點。
Today Widget
對于賽事比分,股票、天氣、快遞這類需要實時獲取的信息,可以在通知中心的Today視圖中創建一個Today擴展實現。Today擴展又稱為Widget。
Share
在iOS 8之前,用戶只有Facebook,Twitter等有限的幾個分享選項可以選擇。如果希望將內容分享到Pinterest,開發者則需要一些額外的努力。在iOS 8中,開發者可以創建自定義的分享選項。
Action
action在所有支持的擴展點中擴展性最強的一個。它可以實現轉換另一個app上下文中的內容。蘋果在WWDC大會上演示了一個Bing翻譯動作擴展,它可以將在Safari中選中的文本翻譯成不同的語言。
Photo Editing
在iOS 8之前,如果你想為你的照片添加一個特殊的濾鏡,你需要進入第三方app中,這個過程是相當繁瑣的。在iOS 8中,你可以直接在Photos中使用第三方app,如Instagram,VSCO cam、Aviary提供的Photo Editing擴展完成對圖片的編輯,而無需離開當前的app。
Storage Provider
Storage Provider讓跨多個文件存儲服務之間的管理變得更簡單。類似Dropbox、Google Drive等存儲提供商通過在iOS 8中提供一個Storage Provider擴展,app直接可以使用這些擴展檢索和存儲文件而不再需要創建不必要的拷貝。
Custom Keyboard
蘋果公司在2007年率先推出了觸摸屏鍵盤,但一直沒多大改進。在這一方面,Android則將鍵盤權限開放給了第三方開發者,所以出現了許多像Swype,SwiftKey等優秀的鍵盤輸入法。在iOS 8中,蘋果終于將鍵盤權限開發給了第三方開發者,自定義鍵盤輸入法可以讓用戶在整個系統范圍內使用。
2.幾個概念
extension是iOS8新開放的一種對幾個固定系統區域的擴展機制,它可以在一定程度上彌補iOS的沙盒機制對應用間通信的限制。
extension的出現,為用戶提供了在其它應用中使用我們應用提供的服務的便捷方式,比如用戶可以在Today的widgets中查看應用展示的簡略信息,而不用再進到我們的應用中,這將是一種全新的用戶體驗;但是,extension的出現可能會減少用戶啟動應用的次數,同時還會增大開發者的工作量。 幾個關鍵詞 extension point 系統中支持extension的區域,extension的類別也是據此區分的,iOS上共有Today、Share、Action、Photo Editing、Storage Provider、Custom keyboard幾種,其中Today中的extension又被稱為widget。 每種extension point的使用方式和適合干的活都不一樣,因此不存在通用的extension。 app extension 即為本文所說的extension。extension并不是一個獨立的app,它有一個包含在app bundle中的獨立bundle,extension的bundle后綴名是.appex。其生命周期也和普通app不同,這些后文將會詳述。 extension不能單獨存在,必須有一個包含它的containing app。 另外,extension需要用戶手動激活,不同的extension激活方式也不同,比如: 比如Today中的widget需要在Today中激活和關閉;Custom keyboard需要在設置中進行相關設置;Photo Editing需要在使用照片時在照片管理器中激活或關閉;Storage Provider可以在選擇文件時出現;Share和Action可以在任何應用里被激活,但前提是開發者需要設置Activation Rules,以確定extension需要在合適出現。 containing app 盡管蘋果開放了extension,但是在iOS中extension并不能單獨存在,要想提交到AppStore,必須將extension包含在一個app中提交,并且app的實現部分不能為空,這個包含extension的app就叫containing app。 extension會隨著containing app的安裝而安裝,同時隨著containing app的卸載而卸載。 **host app **能夠調起extension的app被稱為host app,比如widget的host app就是Today。 擴展是一個單獨的個體。擴展擁有獨立的target,獨立的bundle文件,獨立的運行進程,獨立的地址空間。
這意味著即使你的containing app不在運行,系統也可以啟動擴展?;蛘吣愕腸ontaining app處于掛起狀態,同樣不會影響擴展的運行。所以系統可以單獨對擴展執行優化。 ****3.
extension和containing app、host app
3.1 extension和host app
extension和host app之間可以通過extensionContext屬性直接通信,該屬性是新增加的UIViewController類別:
@interface UIViewController(NSExtensionAdditions) <NSExtensionRequestHandling>
// Returns the extension context. Also acts as a convenience method for a view controller to check if it participating in an extension request.
@property (nonatomic,readonly,retain) NSExtensionContext *extensionContext NS_AVAILABLE_IOS(8_0);
@end
實際上extension和host app之間是通過IPC(interprocess communication)實現的,只是蘋果把調用接口高度抽象了,我們并不需要關注那么底層的東西。
3.2 containing app和host app
他們之間沒有任何直接關系,也從來不需要通信。
3.3 extension和containing app
這二者之間的關系最復雜,糾糾纏纏扯不清關系。
每一個擴展目標模板包含一個頭文件和實現文件,一個Info.plist文件,以及一個storyboard文件。Info.plist文件包含了對擴展的配置信息,其中最重要的鍵是NSExtension。下面列出了一個NSExtension可能包含的常用鍵值對。
) NSExtensionActivationRule定義了當前的擴展支持的數據類型及數據項個數,例如當前的設置只支持圖片格式和視頻格式的數據,并且最多不超過10張圖片和1個視頻。
- NSExtensionJavaScriptPreprocessingFile用于配置與腳本交互的JS腳本文件的名字。
- NSExtensionMainStoryboard配置擴展的Storyboard文件名。
- NSExtensionPointIdentifier用于表示擴展點,每一個擴展點擁有一個唯一的名字。
- NSExtensionPrincipalClass配置當擴展啟動時,擴展點首先要實例化的類
為了將擴展提交蘋果商店,你需要提交你的containg app。并且需要注意,除了擴展必須包含功能以外,同時containg app還需要提供一些功能,而針對OS X平臺的擴展則無此限制。當用戶安裝了你的containg app,containg app中包含的擴展也會一同被安裝。
3.4 containing app能夠控制extension的出現和隱藏
通過以下代碼,containing app可以讓extension出現或隱藏(當然extension也可以讓自己隱藏):
//讓隱藏的插件重新顯示
- (void)showTodayExtension
{
[[NCWidgetController widgetController] setHasContent:YES forWidgetWithBundleIdentifier:@"com.wangzz.app.extension"];
}
//隱藏插件
- (void)hiddeTodayExtension
{
[[NCWidgetController widgetController] setHasContent:NO forWidgetWithBundleIdentifier:@"com.wangzz.app.extension"]; //plist中配置
}
創建2個工程;appleID上創建2個不同bundle identifier;
如果想要將帶有Extension的應用上傳到App Store,你需要為extension單獨的申請一個AppID(Bundle ID要對應XCode里面extension的Bundle ID,千萬別直接復制,會漏掉后面無法復制到呈灰白的字段),同時配備相對應的distribution profile.
3.5 app extension 中打開contain app
注意一定要添加:// 否則調用失??;
調試的時候,在contain app 中打斷點;
3.6 app group
指定同一個app entilement;
開啟方式和app中一樣,需要注意的是必須保證這里地App Groups名稱和app中的相同,即為group.wangzz。
3.6.1 通過NSUserDefaults共享數據
存數據
通過以下方式向NSUserDefaults中保存數據:
- (void)saveTextByNSUserDefaults
{
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.wangzz"];
[shared setObject:_textField.text forKey:@"wangzz"];
[shared synchronize];
}
需要注意的是:
1.保存數據的時候必須指明group id;
2.而且要注意NSUserDefaults能夠處理的數據只能是可plist化的對象,詳情見Property List Programming Guide。
3.為了防止出現數據同步問題,不要忘記調用[shared synchronize];
讀數據
對應的讀取數據方式:
-
(NSString *)readDataFromNSUserDefaults
{
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.wangzz"];
NSString *value = [shared valueForKey:@"wangzz"];return value;
}
3.6.2 通過NSUserDefaults共享數據
NSFileManager在iOS7提供了containerURLForSecurityApplicationGroupIdentifier方法,可以用來實現app group共享數據。
保存數據
-
(BOOL)saveTextByNSFileManager
{
NSError *err = nil;
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.wangzz"];
containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/good"];NSString *value = _textField.text;
BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&err];
if (!result) {
NSLog(@"%@",err);
} else {
NSLog(@"save value:%@ success.",value);
}return result;
}
讀數據
-
(NSString *)readTextByNSFileManager
{
NSError *err = nil;
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.wangzz"];
containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/good"];
NSString *value = [NSString stringWithContentsOfURL:containerURL encoding:NSUTF8StringEncoding error:&err];return value;
}
在這里我試著保存和讀取的是字符串數據,但讀寫SQlite我相信也是沒問題的。
3.7 extension和containing app代碼共享
和數據共享類似,extension和containing app很自然地會有一些業務邏輯上可以共用的代碼,這時可以通過iOS8中剛開放使用的framework實現。蘋果在App Extension Programming Guide中是這樣描述的:
In iOS 8.0 and later, you can use an embedded framework to share code between your extension and its containing app. For example, if you develop image-processing code that you want both your Photo Editing extension and its containing app to share, you can put the code into a framework and embed it in both targets.
即將framework分別嵌入到extension和containing app的target中實現代碼共享。但這樣豈不是需要分別要將framework分別copy到extension和containing app的main bundle中?
3.8 iOS8應用文件系統
參考資料:
http://blog.csdn.net/songhongri/article/details/38709455 http://www.cocoachina.com/industry/20140627/8960.html http://www.pingwest.com/apples-new-extension-eco-system/
http://blog.csdn.net/yongyinmg/article/details/40982791
demo例子:
http://pan.baidu.com/s/1o67f7AU
http://pan.baidu.com/s/1qW7b0Dm (swift 代碼)