IOS學習筆記67-IOS8系列之應用擴充套件
而在引入擴充套件之後,其他app可以與擴充套件進行資料交換。基於安全和效能的考慮,每一個擴充套件執行在一個單獨的程序中,它擁有自己的bundle, bundle字尾名是.appex。擴充套件bundle必須包含在一個普通應用的bundle的內部。
iOS 8系統有6個支援擴充套件的系統區域,分別是Today、Share、Action、Photo Editing、Storage Provider、Custom keyboard。支援擴充套件的系統區域也被稱為擴充套件點。
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中,蘋果終於將鍵盤許可權開發給了第三方開發者,自定義鍵盤輸入法可以讓使用者在整個系統範圍內使用。
二、建立擴充套件與釋出擴充套件 在建立擴充套件之前,你需要建立一個用來包含擴充套件的常規的app專案。這個包含擴充套件的app被稱為containing app。在建立好containg app之後,選擇File->New->Target選單,從彈出的對話方塊中選擇一個適當的擴充套件目標模板。每一個擴充套件目標模板都包含了與擴充套件點相關的檔案和設定。一個containing app可以包含多個不同型別的擴充套件。 每一個擴充套件目標模板包含一個頭檔案和實現檔案,一個Info.plist檔案,以及一個storyboard檔案。Info.plist檔案包含了對擴充套件的配置資訊,其中最重要的鍵是NSExtension。下面列出了一個NSExtension可能包含的常用鍵值對。
1) NSExtensionActivationRule定義了當前的擴充套件支援的資料型別及資料項個數,例如當前的設定只支援圖片格式和視訊格式的資料,並且最多不超過10張圖片和1個視訊。 2) NSExtensionJavaScriptPreprocessingFile用於配置與指令碼互動的JS指令碼檔案的名字。 3) NSExtensionMainStoryboard配置擴充套件的Storyboard檔名。 4) NSExtensionPointIdentifier用於表示擴充套件點,每一個擴充套件點擁有一個唯一的名字。 5) NSExtensionPrincipalClass配置當擴充套件啟動時,擴充套件點首先要例項化的類 為了將擴充套件提交蘋果商店,你需要提交你的containg app。並且需要注意,除了擴充套件必須包含功能以外,同時containg app還需要提供一些功能,而針對OS X平臺的擴充套件則無此限制。當用戶安裝了你的containg app,containg app中包含的擴充套件也會一同被安裝。 三、理解擴充套件如何運作 在安裝擴充套件之後,擴充套件並不會自動執行,使用者必須執行特定的操作來啟用擴充套件。如果是Today擴充套件,使用者可以在通知中心的Today檢視中編輯啟用擴充套件。如果是自定義鍵盤擴充套件,使用者需要在系統設定的通用選項下的鍵盤選項中啟用自定義鍵盤擴充套件。而如果是Share擴充套件,使用者只需點選系統提供的分享按鈕,即可在分享列表中找到分享擴充套件。 一個擴充套件並不是一個app,它的生命週期和執行環境不同於普通app。在生命週期方面,擴充套件的生命週期從使用者在另一個app中選擇了擴充套件開始,一直到擴充套件完成了使用者的請求生命週期結束。在執行環境方面,擴充套件的限制要比普通app更嚴格,擴充套件的可用記憶體上限以及可用的API都比普通app要少。嚴格限制擴充套件的記憶體是因為在同一時間可能會有多個擴充套件同時執行,如Widget擴充套件。如果API宣告包含NS_EXTENSION_UNAVAILABLE巨集,則此API在擴充套件中將不可用,常見的API如:
- <key>NSExtension</key>
- <dict>
- <key>NSExtensionAttributes</key>
- <dict>
- <key>NSExtensionActivationRule</key> <!--1-->
- <dict>
- <key>NSExtensionActivationSupportsImageWithMaxCount</key>
- <integer>10</integer>
- <key>NSExtensionActivationSupportsMovieWithMaxCount</key>
- <integer>1</integer>
- </dict>
- <key>NSExtensionJavaScriptPreprocessingFile</key> <!--2-->
- <string>MyJavaScriptFile</string>
- <key>NSExtensionPointVersion</key>
- <string>1.0</string>
- </dict>
- <key>NSExtensionMainStoryboard</key> <!--3-->
- <string>MainInterface</string>
- <key>NSExtensionPointIdentifier</key> <!--4-->
- <string>com.apple.ui-services</string>
- <key>NSExtensionPrincipalClass</key> <!--5-->
- <string>ActionViewController</string>
- </dict>
呼叫擴充套件的應用稱為host app,對於Widget擴充套件,host app就是Today。host app會在擴充套件的有效生命週期內定義一個擴充套件上下文。通過擴充套件上下文,host app可以和擴充套件互傳資料。注意,擴充套件只和host app直接通訊,擴充套件與containg app以及containing app與host app之間不存在通訊關係,如果擴充套件需要開啟containg app,則通過自定義URL scheme方式實現,而不是直接向containg app傳送訊息。三者的關係見下圖:
- + (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.");
擴充套件是一個單獨的個體。擴充套件擁有獨立的target,獨立的bundle檔案,獨立的執行程序,獨立的地址空間。這意味著即使你的containing app不在執行,系統也可以啟動擴充套件。或者你的containing app處於掛起狀態,同樣不會影響擴充套件的執行。所以系統可以單獨對擴充套件執行優化。擴充套件與containg app的關係:
四、設計擴充套件過程中常見的幾個問題 1. containg app與擴充套件如何通過擴充套件上下文互傳資料 在iOS 8中,UIViewController新增了一個擴充套件上下文屬性extensionContext。來處理containing app與擴充套件之間的通訊,上下文的型別是NSExtensionContext。假設你現在需要在host app中將一張圖片傳遞給擴充套件做濾鏡處理,host app中的程式碼如下:
當用戶在彈出的Action列表中選擇了擴充套件,擴充套件將被啟動,然後在擴充套件的viewDidLoad方法中,通過extensionContext檢索host app傳回的資料項。擴充套件中的程式碼如下:
- UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[[self.imageView image]] applicationActivities:nil];
- [self presentViewController:activityViewController animated:YES completion:nil];
上述程式碼中,extensionContext表示一個擴充套件到host app的連線。通過extionContent,你可以訪問一個NSExtensionItem的陣列,每一個NSExtensionItem項表示從host app傳回的一個邏輯資料單元。你可以從NSExtensionItem項的attachments屬性中獲得附件資料,如音訊,視訊,圖片等。每一個附件用NSItemProvider例項表示。上述程式碼中NSItemProvider的loadItemForTypeIdentifier例項方法的第一個引數是(NSString *)kUTTypeImage,如果你需要處理的是文字型別,引數則為(NSString *)kUTTypeText,相應的處理程式碼則變成:
- - (void)viewDidLoad {
- [super viewDidLoad];
- NSExtensionItem *imageItem = [self.extensionContext.inputItems firstObject];
- if(!imageItem){
- return;
- }
- NSItemProvider *imageItemProvider = [[imageItem attachments] firstObject];
- if(!imageItemProvider){
- return;
- }
- // 檢查是否包含文字
- if([imageItemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]){
- [imageItemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
- if(image){
- dispatch_async(dispatch_get_main_queue(), ^{
- self.imageView.image = image;
- });
- }
- }];
- }
- }
當擴充套件處理完host app傳回的圖片資料後,它需要將處理好的資料再傳給host app。在擴充套件中的程式碼如下:
- if([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeText]){
- [imageItemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeText options:nil completionHandler:^(NSAttributedString *string, NSError *error) {
- if (string) {
- // 在這裡處理文字
- }
- }];
- }
最後一步是host app接收來自擴充套件傳回的資料,在host app中的程式碼如下:
- -(IBAction)done:(id)sender{
- NSExtensionItem* extensionItem = [[NSExtensionItem alloc] init];
- [extensionItem setAttachments:@[[[NSItemProvider alloc] initWithItem:[self.imageView image] typeIdentifier:(NSString*)kUTTypeImage]]];
- [self.extensionContext completeRequestReturningItems:@[extensionItem] completionHandler:nil];
- }
上述程式碼主要是通過設定一個completionBlock處理資料回撥。 注意,所有的擴充套件都是一個UIViewController。所以UIViewController的所有生命週期方法,如viewWillAppear:、viewWillDisappear:等在擴充套件中都是可以使用的。 2. 如何在擴充套件中開啟containing app 在一般情況下,擴充套件和containing app不存在通訊關係。但是有時候需要在擴充套件中開啟containing app,如iOS 7中預置的日曆Widget。在常規的app中,可以使用如下程式碼在A app中開啟B app:
- [activityViewController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError * error){
- if([returnedItems count] > 0){
- NSExtensionItem* extensionItem = [returnedItems firstObject];
- NSItemProvider* imageItemProvider = [[extensionItem attachments] firstObject];
- if([imageItemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]){
- [imageItemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *item, NSError *error) {
- if(item && !error){
- dispatch_async(dispatch_get_main_queue(), ^{
- [self.imageView setImage:item];
- });
- }
- }];
- }
- }
- }];
但是之前有講到,sharedApplication API在擴充套件中被禁止使用,所以為了實現同樣的功能,NSExtensionContext定義了一個新的方法用來開啟containing app:
- if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:customURL]]) {
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
- }
在呼叫此方法之前,需要在containg app中定義一個自定義URL Scheme。定義方法可參見連結,最終的結果如下圖:
- - (void)openURL:(NSURL *)URL completionHandler:(void (^)(BOOL success))completionHandler;
在擴充套件中開啟containing app的程式碼如下:
3. 如何實現containing app與擴充套件共享資料 擴充套件和containing app各自擁有自己的資料容器,雖然擴充套件內嵌在containing app的內部,但是它們並不可以互訪彼此的資料。為了實現containing app與擴充套件的資料共享,蘋果在iOS 8中引入了一個新的概念——App Group。為了開啟App Group,找到你的containing app目標,在右側找到Capabilities標籤,定位到App Groups分組,如下圖所示。
- - (IBAction)openContainingApp:(id)sender {
- NSURL *url = [NSURL URLWithString:@"ExtensionDemo://"];
- [self.extensionContext openURL:url completionHandler:^(BOOL success) {
- }];
- }
然後選擇你需要共享資料的擴充套件目標,重複執行一次操作,注意兩次的App Group名要相同,不要新增新的條目。當開啟App Group後,你可以使用NSUserDefaults方法訪問共享區域,如下述程式碼,注意不是[NSUserDefaults standardUserDefaults]:
你也可以使用NSFileManager的containerURLForSecurityApplicationGroupIdentifier方法訪問共享資料區:
- _sharedUserDefault= [[NSUserDefaults alloc] initWithSuiteName:@"group.com.aegeaon.ExtensionDemo"];
App Group區域在containing app與擴充套件之間所處的關係圖:
- - (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;
- }
相關推薦
IOS學習筆記67-IOS8系列之應用擴充套件
一、擴充套件概述 擴充套件(Extension)是iOS 8中引入的一個非常重要的新特性。擴充套件讓app之間的資料互動成為可能。使用者可以在app中使用其他應用提供的功能,而無需離開當前的應用。 在iOS 8系統之前,每一個app在物理上都是彼此獨立的,ap
dubbo學習筆記 九 dubbo-common之動態擴充套件extension
extension 動態擴充套件包,dubbo裡面有很多 @SPI @Activate @Adaptive 註解, 同時也有許多配置檔案。 如下面的路徑 private static final String SERVICES_DIRECTORY = "MET
神經網路系列學習筆記(四)——神經網路之RNN學習筆記
不同於傳統的FNNs(Feed-forward Neural Networks,前向反饋神經網路),RNNs引入了定向迴圈,能夠處理那些輸入之間前後關聯的問題。 RNNs的目的是用來處理序列資料。 具體的表現形式為網路會對前面的資訊進行記憶並應用於當前輸出的計算中,即隱藏層之間的節點不再無連線
嵌入式核心及驅動開發之學習筆記(二) 實現應用控制驅動
Linux系統根據驅動程式實現的模型框架將裝置驅動分成字元裝置驅動、塊裝置驅動、網路裝置驅動三大類。這裡簡單理解一下概念 字元裝置:裝置按位元組流處理資料,通常用的串列埠裝置、鍵盤裝置都是這種。 塊裝置:裝置按塊單位對資料處理,通常是儲存裝置。 網路裝置:顧名思義,建立在soc
基於TypeScript的Angular6.X系列學習筆記-建立第一個Angular應用
在上一節中,Angular框架的開發環境已經搭建完畢,在終端輸入命令:ng -v 檢查Angular框架的版本號,執行如下: 繼續使用Angular CLI腳手架建立專案,開啟VS-Code在終端輸入命令:ng new [專案名稱] 建立一個專案,操作如下:
ios學習筆記之-點選一個按鈕彈出撥打電話提示框
按鈕的程式碼就不寫了。直接寫主要程式碼。 <key>LSApplicationQueriesSchemes</key> <array> <string>tel</string> <string>telp
《瘋狂Workflow講義——基於Activiti的工作流應用開發》學習筆記之一·環境搭建之編碼問題
在對activiti有了一定了解之後,開始按《瘋狂Workflow講義——基於Activiti的工作流應用開發》中的步驟搭建環境,新建專案,建立resource資料夾,使用第2張的First.bpmn,activiti.cfg.xml,First.java,
iOS學習筆記之-C語言基礎01
一,C語言定義 C語言屬於一門高階計算機語言,用於人機互動 C語言程式是由多個程式段(函式)組成, C語言原始檔拓展名為.c C語言需要編譯之後才能執行 .o檔案為編譯.c檔案產生的連結檔案 .out為連結.o檔案時生成的可執行檔案 二,第一個C語
iOS學習筆記56(Runtime)-Objective-C Runtime 執行時之三:方法與訊息
前面我們討論了Runtime中對類和物件的處理,及對成員變數與屬性的處理。這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。不過在討論訊息之前,我們先來了解一下與方法相關的一些內容。 基礎資料型別 SEL
iOS學習筆記(八)——iOS網路通訊http之NSURLConnection
移動網際網路時代,網路通訊已是手機終端必不可少的功能。我們的應用中也必不可少的使用了網路通訊,增強客戶端與伺服器互動。這一篇提供了使用NSURLConnection實現http通訊的方式。 NSURLConnection提供了非同步請求、同步請求
IOS學習筆記之NSArray與NSSet
NSArray和NSMutableArray無需多說,是線性陣列和連結串列的包裝類。 NSSet和NSMutableSet則是無序的, 並且保證唯一性的資料集合。當插入相同的資料時,不會有任何效果。從內部實現來說是hash表,所以可以常數時間內查詢一個數據。 引用co
Java學習筆記——排序算法之O(n²)排序
blog sel != 而是 while bsp 優化 ++ logs 男兒何不帶吳鉤,收取關山五十州。請君暫上淩煙閣,若個書生萬戶侯? ——南園十三首 三種排序法: 1、冒泡法 2、簡單選擇法 3、直接插入法
Java學習筆記——排序算法之進階排序(堆排序與分治並歸排序)
進行 技術分享 ring http 沒有 oid 有序 重復 調整 春蠶到死絲方盡,蠟炬成灰淚始幹 ——無題 這裏介紹兩個比較難的算法: 1、堆排序 2、分治並歸排序 先說堆。 這裏請大家先自行了解完全二叉樹的數據結構。 堆是完全二叉樹。
RabbitMQ學習筆記五:RabbitMQ之優先級消息隊列
-c virtual 調用 itl 3.5 rri color images 執行順序 RabbitMQ優先級隊列註意點: 1、只有當消費者不足,不能及時進行消費的情況下,優先級隊列才會生效 2、RabbitMQ3.5以後才支持優先級隊列 代碼在博客:RabbitMQ學習筆
ios學習筆記---ios完整學習路線
size tle spa mage 技術分享 soft 分享 -s 學習筆記 ios完整學習路線 ios學習筆記---ios完整學習路線
Python學習筆記-數據報表之Excel操作模塊
工作表 excel 字符串 python 利用Python操作Excel的模塊XlsxWriter,可以操作多個工作表的文字、數字、公式、圖表等。XlsxWriter模塊具有以下功能:100%兼容的Excel XLSX文件,支持Excel 2003、Excel 2007等版本;支持所有Ex
Nginx學習筆記06負載均衡之(一)負載均衡介紹
最終 反向 結果 html proxy mime cnblogs 負載 cal 1.1.1. 負載均衡的介紹 Nginx中使用upstream配置塊,可以方便的配置出一個基於反向代理的負載均衡解決方案。 在upstream中可以包含多個server配置項,每個server配
iOS學習筆記(十七)——文件操作(NSFileManager)
技術分享 append hint pbo -cp fcm object 寫入 rtmp http://blog.csdn.net/xyz_lmn/article/details/8968213 iOS的沙盒機制,應用只能訪問自己應用目錄下的文件。ios不像Androi
iOS學習筆記23-音效與音樂
nslog ini post jpg outer 震動 ucc aml iboutlet 一、音頻 在iOS中,音頻播放從形式上能夠分為音效播放和音樂播放。 * 音效: * 主要指一些短音頻的播放,這類音頻一般不須要進行進度、循環等控制。 *
[javase學習筆記]-8.1 statickeyword之特點
之前 隨著 小強 pop dsm name 變量 popu tracking 這一節我們來學習java語言中一個新的keyword就是statickeyword。 當然對於每個keyword,我們都要明白的是它有什麽作用,怎麽用。我們先來看一個樣例: