標籤:限制 tail iphone 需要 共用資源 day source blog
一.iOS8擴充外掛程式概述
WWDC14除了發布了OS X v10.10和switf外,iOS8.0也開始變得更加開放了。說到開放,當然要數應用擴充(App Extension)了。顧名思義,應用擴充允許開發人員擴充應用的自訂功能和內容,能夠讓使用者在使用其他應用程式時使用該項功能,從而實現各個應用程式間的功能和資源共用。可以將擴充理解為一個輕量級(nimble and lightweight)的分身。
以下為常見的三類外掛程式:
Target Type |
Extension point identifier |
Scenarios |
Today Extension |
com.apple.widget-extension |
系統通知欄下拉顯示 |
Share Extension |
com.apple.share-services |
Host App(照片、Safari、郵件、語音等)分享菜單第一行 |
Action Extension(UI) |
com.apple.ui-services |
Host App(照片、Safari、郵件、語音等)分享菜單第二行 |
為iPhone/iOS8中的【照片】分享:
例如【】最多支援分享9張(NSExtensionActivationSupportsImageWithMaxCount=9)照片給好友或到朋友圈。
二.外掛程式工作機制
1.外掛程式只能與Host App通過上下文直接通訊
2.外掛程式可通過共用資源區與Containing App間接通訊
3.Host App-Extension-Containing App工作流程
- Host App通過點擊系統分享菜單中的外掛程式表徵圖調起擴充程式——Share/ActionExtension (*.appex)。
- iOS系統(Host App)通過擴充上下文(NSExtensionContext)向Share/ActionExtension傳遞欲分享的資料。
- Share/Action Extension提取資料並序列化到以AppGroup ID標識的共用資源區NSUserDefaults/AppGroup Container(containerURLForSecurityApplicationGroupIdentifier)中。
- Share/Action Extension通過URL Scheme呼起ContainingApp,同時外掛程式通過上下文向iOS系統(HostApp)發出request completion通知,以便返回到Host App(iOS系統會dismiss外掛程式UIViewController)。
- Containing App通過App Group ID從NSUserDefaults/containerURL中讀取分享過來的資料,並對分享資料進行後續處理。
由此可見,擴充外掛程式將Host App與Containing App勾搭起來,而App Group Container則架起了資料互動的鵲橋。
這裡需要注意的是,在iOS 8.0中,只有Today Extension才支援直接調用NSExtensionContext的openURL:completionHandler:開啟URL連結;Share/Action Extension要想實現URL Scheme,只能建立一個Sink UIWebVew對URL進行loadRequest實現曲線救國(所謂“Sink”是指隱而不顯,例如frame=CGRectZero)。
4.外掛程式的UI形態
外掛程式在UI上以UIViewController模式存在,被parentViewController(Host App)以模態視窗形式彈出(present as modal viewController)。
外掛程式工程在Info.plist的NSExtension中通過NSExtensionMainStoryboard指定UI視圖入口。當然,如果不想使用storyboard,也可以使用NSExtensionPrincipalClass指定自訂UIViewController子類名(也可以封裝到UINavigationController)。
注意:
- 建立Extension Target後(Deployment Target≥8.0),需在Build Settings|Architectures|Valid Architectures中增加arm64!
- 初始安裝Containing App時,擴充外掛程式並未使能,需要到【更多】中開啟開關。
三.外掛程式的局限性
以下文位元組選自《App Extension Programming Guide》,主要列舉了外掛程式的局限性,以知其可為不可為。
--------------------------------------------------------------------------------
1.Design a Streamlined UI
- An extension`s UI should be simple, restrained, and focused on facilitating a single task.
- To improve performance and the user`s experience, avoid including extraneous UI that doesn`t support your extension`s main task.
2.Optimize Efficiency and Performance
(1)App extensions should feel nimble and lightweight to users.
- Design your app extension to launch quickly, aiming for well under one second.
- An extension that launches too slowly is terminated by the system.
(2)Memory limits for running app extensions are significantly lower than the memory limits imposed on a foreground app.
- On both platforms, the system may aggressively terminate extensions because users want to return to their main goal in the host app.
- Some extensions may have lower memory limits than others.
(3)Your app extension doesn`t own the main run loop, so it`s crucial that you follow the established rules for good behavior in main runloops.
- For example, if your extension blocks the main runloop, it can create a bad user experience in another extension or app.
(4)Keep in mind that theGPU is a shared resource in the system.
- App extensions do not get top priority for shared resources; for example, a Today widget that runs a graphics-intensive game might give users a bad experience. The system is likely to terminate such an extension because of memory pressure.
- Functionality that makes heavy use of system resources is appropriate for an app, not an app extension.
--------------------------------------------------------------------------------
由此可見,iOS系統對外掛程式要求簡潔至上:UI啟動要快、記憶體消耗要少、runloop執行耗時要短。
iOS系統對外掛程式的限制決定了開發的外掛程式必須輕量,發點Twitter/微博分享、小圖片檔案分享、URL跳轉還是可以的;奢望豐富絢麗的UI或者用來傳大檔案等大動作是不合適的。
當然,如果希望擴充(即使退出)執行長時間任務(比如上傳/下載),可以使用NSURLSession來建立一個上傳/下載session,並初始化一個後台上傳/下載任務。
注意:
Apple也限制了擴充在API使用方面的許可權,在擴充中禁用的API原型聲明被標上了NS_EXTENSION_UNAVAILABLE宏。例如:
+ (UIApplication*)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS;
對sharedApplication的限制實際上就是不讓外掛程式直接擷取訪問宿主應用(Host App的UIApplication)對象。
四.Share/Action擴充外掛程式支援的媒體類型
配置
Info.plist中的NSExtension|NSExtensionAttributes|NSExtensionActivationRule Dictionary可以配置外掛程式支援的媒體類型及數量:
iOS擴充外掛程式支援媒體類型配置鍵 |
描述 |
配置 |
說明 |
NSExtensionActivationSupportsAttachmentsWithMaxCount |
附件最多限制 |
20 |
附件包括下面的File、Image和Movie三大類,單一、混選總量不超過20 |
NSExtensionActivationSupportsAttachmentsWithMinCount |
附件最少限制 |
上面非零時,default=1 |
預設至少選擇1個附件,【分享】中才顯示擴充外掛程式表徵圖 |
NSExtensionActivationSupportsFileWithMaxCount |
檔案最多限制 |
20 |
檔案泛指除Image/Movie之外的附件,例如【郵件】附件、【語音備忘錄】等。 單一、混選均不超過20。 |
NSExtensionActivationSupportsImageWithMaxCount |
圖片最多限制 |
20 |
單一、混選均不超過20 |
NSExtensionActivationSupportsMovieWithMaxCount |
視頻最多限制 |
20 |
單一、混選均不超過20 |
NSExtensionActivationSupportsText |
文本類型 |
default=0 |
預設不支援文本分享,例如【備忘錄】 |
NSExtensionActivationSupportsWebURLWithMaxCount |
Web連結最多限制 |
default=0 |
預設不支援分享超連結,例如【Safari】 |
NSExtensionActivationSupportsWebPageWithMaxCount |
Web頁面最多限制 |
default=0 |
預設不支援Web頁面分享,例如【Safari】 |
宿主應用(Host App)提供一個上下文(NSExtensionContext)向擴充(appex)傳遞資料,包含了待處理的資料(inputItems)。其傳遞的資料是一組NSExtensionItem對象,其中要分享的圖片、視頻、URL等附件就儲存在NSExtensionItem的attachments數組中。
關於UTIs,參考UniformType Identifiers Reference | System-Declared Uniform Type Identifiers。
媒體類型 |
檔案UTI |
圖片(public.image) |
kUTTypeImage kUTTypeJPEG kUTTypePNG kUTTypeGIF kUTTypeTIFF kUTTypeBMP kUTTypeICO |
視頻(public.movie) |
kUTTypeMovie kUTTypeQuickTimeMovie kUTTypeMPEG kUTTypeMPEG4 kUTTypeAVIMovie @"public.3gpp" @"com.real.realmedia" @"com.microsoft.windows-media-wmv" @"com.microsoft.advanced-systems-format" |
音頻(public.audio) |
kUTTypeAudio kUTTypeMP3 kUTTypeMPEG4Audio kUTTypeWaveformAudio @"com.microsoft.windows-media-wma" |
文檔 |
kUTTypePDF @"com.microsoft.word.doc" @"com.microsoft.excel.xls" kUTTypePresentation @"com.microsoft.powerpoint.ppt" @"com.apple.keynote.key" |
壓縮包 |
kUTTypeZipArchive kUTTypeGNUZipArchive kUTTypeBzip2Archive @"public.tar-archive" @"org.gnu.gnu-zip-tar-archive" |
五.外掛程式與Containing App的App Group認證配置
Containing App及其Extension是通過以App Group ID標識的共用資源區—App Group Container來實現資料共用的。
Containing App及其Extension的App ID必須是Explicit,且Extension App ID必須以Containing App ID為Prefix/Seed,並且配置到同一App Group下。
App ID配置到Info.plist的BundleIdentifier中;App Group在target的【Xcode Target|Capabilities】中啟用,配置到【Xcode Target|Build Settings|Code Signing|Code Signing Entitlements】中的*.entitlements檔案的com.apple.security.application-groups
鍵中。
認證和Provisioning Profile的申請以及Code Signing配置流程同以前普通的App,詳情請參考《iOS開發認證要點詳解》。
六.Containing App的Build Phases配置(embed app extensions)
Containing App 的【Xcode target|BuildPhases|Target Dependencies】中可以添加或移除外掛程式target。
Containing App 的【Xcode target|BuildPhases|Embed App Extensions】下Destination為Plugins中可以添加或移除外掛程式product(*.appex)。
注意:預設了勾選“Copy only when installing”,表示從AppStore安裝(包括升級覆蓋)時才拷貝外掛程式。Xcode串連真機調試時,需取消該改項,否則系統【分享】菜單中不會出現外掛程式
iOS8擴充外掛程式開發配置