1. 程式人生 > >iOS8擴展插件開發配置

iOS8擴展插件開發配置

public because users port ase source 執行 大文件 初始化

一.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才支持直接調用NSExtensionContextopenURL: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擴展插件開發配置