2.插件的局限性WWDC14除發布了OS X v10.10和switf外,iOS8.0也開始變得更加開放了。說到開放,固然要數利用擴大(App Extension)了。顧名思義,利用擴大允許開發者擴大利用的自定義功能和內容,能夠讓用戶在使用其他利用程序時使用該項功能,從而實現各個利用程序間的功能和資源同享。可以將擴大理解為1個輕量級(nimble and lightweight)的分身。
以下為常見的3類插件:
Target Type
Extension point identifier
Scenarios
Today Extension
com.apple.widget-extension
系統通知欄下拉顯示
Share Extension
com.apple.share-services
Host App(照片、Safari、郵件、語音等)分享菜單第1行
Action Extension(UI)
com.apple.ui-services
Host App(照片、Safari、郵件、語音等)分享菜單第2行
下圖為iPhone/iOS8中的【照片】分享:
例如【微信】最多支持分享9張(NSExtensionActivationSupportsImageWithMaxCount=9)照片給好友或到朋友圈。
以下文字節選自《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 theGPUis 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來創建1個上傳/下載session,并初始化1個后臺上傳/下載任務。
注意:
Apple也限制了擴大在API使用方面的權限,在擴大中禁用的API原型聲明被標上了NS_EXTENSION_UNAVAILABLE宏。例如:
+ (UIApplication*)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS;
3.插件工作機制對sharedApplication的限制實際上就是不讓插件直接獲得訪問宿主利用(Host App的UIApplication)對象。
4.插件與Containing App的App Group證書配置1.插件只能與Host App通過上下文直接通訊
2.插件可通過同享資源區與Containing App間接通訊
3.HostApp-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,只能創建1個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時,擴大插件并未使能,需要到【更多】中打開開關。
參考:Containing App及其Extension是通過以App Group ID標識的同享資源區―App Group Container來實現數據同享的。
Containing App及其Extension的App ID必須是Explicit,且Extension App ID必須以Containing App ID為Prefix/Seed,并且配置到同1App Group下。
App Group會被配置到各自【Xcode Target|Build Settings|Code Signing|Code Signing Entitlements】的*.entitlements文件中的鍵com.apple.security.application-groups下。
證書和Provisioning Profile的申請和Code Signing配置流程同之前普通的App,詳情請參考《iOS開發證書要點詳解》。
《App Extension Programming Guide》/《App Extension編程指南》
《App Extensions for iOS 8 in Depth》
《iOS8 Extensions》《iOS8通知中心擴大制作入門》