??相信很多人發(fā)現(xiàn)被环,蘋果手機(jī)有個(gè)功能就是可以從相冊(cè)選擇照片分享到相應(yīng)的APP,比如將照片分享到微信好友详幽,操作如下:
?1、先選取照片浸锨,然后點(diǎn)擊分享按鈕:
?2唇聘、系統(tǒng)會(huì)彈出控制面板,這里你會(huì)發(fā)現(xiàn)有微信APP柱搜,如果沒有可以點(diǎn)擊更多按鈕開啟微信就行
?3迟郎、點(diǎn)擊微信,進(jìn)入下面頁面聪蘸,在這里你可以進(jìn)行自己想要的操作宪肖,比如發(fā)送圖片給好友
??那我們?cè)趺磳⒆约旱腁PP添加到這個(gè)控制面板上呢?然后方便用戶的操作健爬?首先這個(gè)功能屬于App Extension
應(yīng)用擴(kuò)展功能控乾,想要此功能,首先創(chuàng)建擴(kuò)展Target
??選擇Share Extension
,然后起個(gè)擴(kuò)展名娜遵,最后Finish:
??這時(shí)候會(huì)提示創(chuàng)建一個(gè)Scheme蜕衡,點(diǎn)擊
Activate
??這時(shí)候你會(huì)發(fā)現(xiàn)項(xiàng)目多個(gè)一個(gè)ImagePublish
擴(kuò)展
??這時(shí)創(chuàng)建Extension完成,我們進(jìn)行下測試设拟,選擇創(chuàng)建的擴(kuò)展慨仿,運(yùn)行,XCode中會(huì)彈出界面讓我們選擇一個(gè)應(yīng)用來運(yùn)行Extension纳胧,我們選擇照片镰吆,點(diǎn)擊Run,如圖:
??這時(shí)手機(jī)會(huì)打開應(yīng)用相冊(cè),選擇一張照片跑慕,點(diǎn)擊分享万皿,這時(shí)你會(huì)發(fā)現(xiàn),你的應(yīng)用出現(xiàn)在控制面板當(dāng)中了核行,這時(shí)說明我們創(chuàng)建成功了相寇。點(diǎn)擊我們自己的應(yīng)用,會(huì)彈出一個(gè)框钮科,如下圖:
??為什么會(huì)出現(xiàn)這個(gè)框呢唤衫?其實(shí)這時(shí)系統(tǒng)的模板,就是說你創(chuàng)建擴(kuò)展的時(shí)候系統(tǒng)自帶的樣式绵脯,這時(shí)候我們就要對(duì)擴(kuò)展進(jìn)行一些設(shè)置了佳励,打開擴(kuò)展Info.plist
文件
??我們需要設(shè)置哪些東西休里,首先了解這些字段的意思:
字段 | 說明 |
---|---|
Bundle display name | 擴(kuò)展的顯示名稱,默認(rèn)跟你的項(xiàng)目名稱相同赃承,可以通過修改此字段來控制擴(kuò)展的顯示名稱 |
NSExtension | 擴(kuò)展描述字段妙黍,用于描述擴(kuò)展的屬性、設(shè)置等 |
NSExtensionAttributes | 擴(kuò)展屬性集合字段瞧剖,用于描述擴(kuò)展的屬性 |
NSExtensionActivationRule | 激活擴(kuò)展的規(guī)則拭嫁。默認(rèn)為字符串“TRUEPREDICATE”,表示在分享菜單中一直顯示該擴(kuò)展抓于∽鲈粒可以將類型改為Dictionary類型,然后添加以下字段NSExtensionActivationSupportsAttachmentsWithMaxCount(附件最多限制捉撮。附件包括File怕品、Image和Movie三大類,單一巾遭、混選總量不超過指定數(shù)量)肉康、NSExtensionActivationSupportsAttachmentsWithMinCount(附件最少限制,默認(rèn)至少選擇1個(gè)附件灼舍,分享菜單中才顯示擴(kuò)展插件圖標(biāo))吼和、NSExtensionActivationSupportsImageWithMaxCount(圖片最多限制,超過不顯示)骑素、NSExtensionActivationSupportsMovieWithMaxCount(視頻最多限制纹安。單一、混選均不超過指定數(shù)量)砂豌、NSExtensionActivationSupportsWebPageWithMaxCount(Web頁面最多限制厢岂。默認(rèn)不支持Web頁面分享,需要自己設(shè)置一個(gè)數(shù)值)阳距、NSExtensionActivationSupportsWebURLWithMaxCount(Web鏈接最多限制塔粒。默認(rèn)不支持分享超鏈接,需要自己設(shè)置一個(gè)數(shù)值)筐摘、NSExtensionActivationSupportsFileWithMaxCount(文件最多限制卒茬,為數(shù)值類型。文件泛指除Image/Movie之外的附件咖熟,例如【郵件】附件圃酵、【語音備忘錄】等)、NSExtensionActivationSupportsText(是否支持文本類型馍管,布爾類型郭赐,默認(rèn)不支持。如【備忘錄】的分享) |
NSExtensionMainStoryboard | 設(shè)置主界面的Storyboard确沸,系統(tǒng)自帶模板 |
NSExtensionPointIdentifier | 擴(kuò)展標(biāo)識(shí)捌锭,在分享擴(kuò)展中為:com.apple.share-services |
NSExtensionPrincipalClass sionAttributes | 自定義UI的類名俘陷,當(dāng)不想用系統(tǒng)自帶模板可設(shè)置此參數(shù),指定自定義UIViewController子類名 |
??對(duì)于不同的應(yīng)用里面有可能出現(xiàn)只允許接受某種類型的內(nèi)容观谦,那么擴(kuò)展就不能一直出現(xiàn)在分享菜單中拉盾,因?yàn)椴煌膽?yīng)用提供的分享內(nèi)容不一樣,這就需要通過設(shè)置NSExtensionActivationRule字段來決定Share Extension是否顯示豁状。例如捉偏,只想接受其他應(yīng)用圖片到自己的應(yīng)用,那么可以通過下面的步驟來設(shè)置:
??將NSExtensionActivationRule字段類型由String改為Dictionary泻红。
展開NSExtensionActivationRule字段夭禽,創(chuàng)建其子項(xiàng)NSExtensionActivationSupportsImageWithMaxCount,并設(shè)置一個(gè)限制數(shù)量承桥,如圖
??這是就是當(dāng)出現(xiàn)圖片且小于9張時(shí),應(yīng)用就會(huì)出現(xiàn)在控制面板中根悼,點(diǎn)擊應(yīng)用彈出彈框時(shí)凶异,有個(gè)取消和發(fā)布按鈕,我們?cè)趺传@取點(diǎn)擊事件呢挤巡?在用系統(tǒng)模板中剩彬,我們發(fā)現(xiàn)有一個(gè)叫ShareViewController
的控制器,它繼承SLComposeServiceViewController
矿卑,.m
文件有幾個(gè)方法喉恋,就是點(diǎn)擊事件觸發(fā)的方法,輸入框輸入的內(nèi)容我們也能夠獲取
??當(dāng)用戶點(diǎn)擊提交按鈕的時(shí)候母廷,擴(kuò)展要做的事情就是要把數(shù)據(jù)取出來轻黑,比如圖片,并且放入一個(gè)與Containing App共享的數(shù)據(jù)介質(zhì)中(包括NSUserDefault琴昆、Sqlite氓鄙、CoreData),因?yàn)楸M管蘋果開放了Extension业舍,但是在iOS中Extension并不能單獨(dú)存在抖拦,要想提交到AppStore,必須將Extension包含在一個(gè)App中提交舷暮,并且App的實(shí)現(xiàn)部分不能為空,這個(gè)包含Extension的App就叫Containing app态罪,也就是宿主APP。Extension會(huì)隨著宿主APP的安裝而安裝下面,同時(shí)隨著宿主APP的卸載而卸載复颈。要跟宿主APP進(jìn)行數(shù)據(jù)交互需要借助AppGroups服務(wù)。怎么獲取擴(kuò)展中的數(shù)據(jù)呢沥割?
??在Extension中券膀,UIViewController包含一個(gè)extensionContext這樣的上下文對(duì)象君纫,可通過該對(duì)象獲取分享的內(nèi)容,具體代碼如下:
- (void)didSelectPost {
NSLog(@"點(diǎn)擊發(fā)布");
//獲取文本內(nèi)容
NSString *textString = self.textView.text;
self.imageDataArray = [NSMutableArray array];
//擴(kuò)展中的處理不能太長時(shí)間阻塞主線程,放入線程中處處理芹彬,否則可能導(dǎo)致蘋果拒絕你的應(yīng)用
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (NSExtensionItem *item in self.extensionContext.inputItems) {
NSInteger count = item.attachments.count;
for (NSItemProvider *itemProvider in item.attachments) {
if ([itemProvider hasItemConformingToTypeIdentifier:@"public.image"]) {
//獲取縮略圖蓄髓,但備忘錄獲取不到 item UIImage類型
[itemProvider loadPreviewImageWithOptions:nil completionHandler:^(id<NSSecureCoding> _Nullable item, NSError * _Null_unspecified error) {
}];
//item Url類型:file:///var/mobile/Media/PhotoData/OutgoingTemp/0F2F2637-0DBF-44F2-8F89-EFD9579BB76E/RenderedPhoto/IMG_0185.JPG
[itemProvider loadItemForTypeIdentifier:@"public.image" options:nil completionHandler:^(id<NSSecureCoding> _Nullable item, NSError * _Null_unspecified error) {
// 對(duì)itemProvider夾帶著的圖片進(jìn)行解析
NSURL *imageUrl = (NSURL *)item;
// 把圖片轉(zhuǎn)換為data數(shù)據(jù)
NSData *data = [NSData dataWithContentsOfURL:imageUrl];
[self.imageDataArray addObject:data];
dispatch_async(dispatch_get_main_queue(), ^{
if (self.imageDataArray.count == count) {
NSLog(@"%@", [NSString stringWithFormat:@"獲取全部%ld張照片",(long)count]);
//獲取全部再銷毀
[self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
}
});
}];
}
}
}
});
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
}
??通過以上操作,我們獲取了照片等信息(分享鏈接也是同樣操作舒帮,設(shè)置info.plist
,和獲取的時(shí)候改為public.url
就行)会喝,接下來就是將分享數(shù)據(jù)傳遞給容器程序,我們知道我們的應(yīng)用和擴(kuò)展是兩個(gè)獨(dú)立的TARGETS
玩郊,在默認(rèn)情況下肢执,iOS的應(yīng)用是存在一個(gè)沙盒里面的,不允許應(yīng)用與應(yīng)用直接進(jìn)行數(shù)據(jù)的交互译红。為此预茄,蘋果提供了一項(xiàng)叫App Groups的服務(wù),該服務(wù)允許開發(fā)者可以在自己的應(yīng)用之間通過NSUserDefaults侦厚、NSFileManager或者CoreData來進(jìn)行相互的數(shù)據(jù)傳輸耻陕,接下來介紹怎么開通App Groups服務(wù)。
??首先刨沦,到開發(fā)者中心為創(chuàng)建的擴(kuò)展工程添加App ID诗宣,操作步驟和普通項(xiàng)目創(chuàng)建App ID一樣,在APP Services勾選App Groups想诅,然后分別打開容器應(yīng)用和分享應(yīng)用的項(xiàng)目配置的Capabilities頁簽召庞,激活A(yù)pp Groups特性,點(diǎn)擊+
添加App groups ,命名格式為:“group.+bundle identifier”如圖:
??其實(shí)現(xiàn)在現(xiàn)在工程都是automatically manage signing来破,直接配置Capabilities頁簽篮灼,開啟App Groups后自動(dòng)生成App ID。經(jīng)過上圖操作徘禁,容器程序的App Groups已經(jīng)設(shè)置完成穿稳,接下來激活擴(kuò)展應(yīng)用App Groups服務(wù),進(jìn)入擴(kuò)展Capabilities頁簽晌坤,你會(huì)發(fā)現(xiàn)不需要?jiǎng)?chuàng)建新的App Group逢艘,只需要打鉤就行,這些操作其實(shí)就是實(shí)現(xiàn)兩個(gè)APP數(shù)據(jù)共享:
??添加成功后骤菠,會(huì)發(fā)現(xiàn)兩個(gè)項(xiàng)目多了一個(gè)東西:
??到這里應(yīng)用和擴(kuò)展的App Groups服務(wù)都已經(jīng)啟動(dòng)它改,接下來就是要進(jìn)行數(shù)據(jù)傳輸了,上面說到商乎,我們可以用NSUserDefaults央拖、NSFileManager以及CoreData三種方式進(jìn)行傳輸,在這里本人使用NSUserDefaults方法進(jìn)行數(shù)據(jù)傳輸,因?yàn)閭€(gè)人覺得更簡單鲜戒,但需要注意的是专控,要想設(shè)置或訪問Group的數(shù)據(jù),不能在使用standardUserDefaults方法來獲取一個(gè)NSUserDefaults對(duì)象了遏餐。應(yīng)該使用initWithSuiteName:
方法來初始化一個(gè)NSUserDefaults對(duì)象伦腐,其中的SuiteName就是創(chuàng)建的Group的名字,然后利用這個(gè)對(duì)象來實(shí)現(xiàn)失都,跨應(yīng)用的數(shù)據(jù)讀寫:
//name同App groups匹配
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.jhj.Share.ImagePublish"];
//存圖片數(shù)組
[userDefaults setObject:self.imageDataArray forKey:@"shareImageDataArray"];
//用于標(biāo)記是新的分享
[userDefaults setBool:YES forKey:@"newShare"];
//存文本內(nèi)容
[userDefaults setObject:textString forKey:@"shareTextString"];
??存儲(chǔ)成功后柏蘑,最后就是在容器APP獲取分享數(shù)據(jù),在容器APP中Appdelegate中applicationDidBecomeActive
實(shí)現(xiàn)獲取粹庞,代碼如下:
- (void)applicationDidBecomeActive:(UIApplication *)application {
//獲取共享的UserDefaults
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.jhj.Share.ImagePublish"];
if ([userDefaults boolForKey:@"newShare"]){
NSArray *imagesDataArray = [userDefaults valueForKey:@"shareImageDataArray"];
NSLog(@"新的分享 : %lu", (unsigned long)imagesDataArray.count);
//重置分享標(biāo)識(shí)
[userDefaults setBool:NO forKey:@"newShare"];
//自己相應(yīng)的操作咳焚,比如請(qǐng)求服務(wù)器
}
}
??這樣就基本實(shí)現(xiàn)了應(yīng)用擴(kuò)展和數(shù)據(jù)共享了!
??注意:
??1、有的時(shí)候擴(kuò)展中的一些功能和宿主APP的某些功能很類似庞溜,但是又不能直接引用革半,下面提供兩種解決辦法:
????1)復(fù)制一份代碼到擴(kuò)展應(yīng)用里,這種辦法傻瓜式流码,但不容易出錯(cuò)又官;
????2)直接打開需要共享使用類的.m文件,你想使用哪個(gè)文件就勾選哪個(gè)旅掂,這樣就可以赏胚,如下:
??但這樣有一個(gè)問題访娶,如果共享的文件又包含其他文件商虐,則得到其他文件繼續(xù)2操作,不然會(huì)報(bào)錯(cuò)计贰;
??2樊拓、在擴(kuò)展中用到的第三方庫怎么辦轻腺?在項(xiàng)目Podfile文件中,添加target 'ImagePublish' do
,記得加end
叮趴,然后和普通工程一樣添加需要的庫,回終端執(zhí)行pod install
命令权烧,就給擴(kuò)展安裝了第三方庫眯亦,如下:
??3、擴(kuò)展中的處理不能太長時(shí)間阻塞主線程般码,可以放入線程中處理妻率,否則可能導(dǎo)致蘋果拒絕你的應(yīng)用;
??4板祝、擴(kuò)展不能單獨(dú)提交審核宫静,必須要跟容器APP一起提交進(jìn)行審核;
??5、擴(kuò)展APP和容器APP的Build Version要保持一致孤里,否則在上傳審核包的時(shí)候會(huì)提示警告伏伯,導(dǎo)致程序無法正常提審;
聲明: 轉(zhuǎn)載請(qǐng)注明出處http://www.reibang.com/p/67ed14b1cee1