iOS--系統(tǒng)相冊(cè)分享照片十嘿、鏈接到自己的APP(擴(kuò)展)

??相信很多人發(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ā)送圖片給好友

WX20190522-114017.png

??那我們?cè)趺磳⒆约旱腁PP添加到這個(gè)控制面板上呢?然后方便用戶的操作健爬?首先這個(gè)功能屬于App Extension應(yīng)用擴(kuò)展功能控乾,想要此功能,首先創(chuàng)建擴(kuò)展Target

創(chuàng)建擴(kuò)展Target

??選擇Share Extension,然后起個(gè)擴(kuò)展名娜遵,最后Finish:

選擇Share Extension

起擴(kuò)展名

??這時(shí)候會(huì)提示創(chuàng)建一個(gè)Scheme蜕衡,點(diǎn)擊Activate

Activate

??這時(shí)候你會(huì)發(fā)現(xiàn)項(xiàng)目多個(gè)一個(gè)ImagePublish擴(kuò)展

擴(kuò)展

??這時(shí)創(chuàng)建Extension完成,我們進(jìn)行下測試设拟,選擇創(chuàng)建的擴(kuò)展慨仿,運(yùn)行,XCode中會(huì)彈出界面讓我們選擇一個(gè)應(yīng)用來運(yùn)行Extension纳胧,我們選擇照片镰吆,點(diǎn)擊Run,如圖:


選擇創(chuàng)建的擴(kuò)展

Choose an app to 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文件

系統(tǒng)模板

??我們需要設(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ù)量承桥,如圖

設(shè)置NSExtensionActivationSupportsImageWithMaxCount

??這是就是當(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)容我們也能夠獲取

觸發(fā)事件

??當(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”如圖:

激活A(yù)pp Groups

??其實(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ù)共享:


容器APP添加

分享APP添加

??添加成功后骤菠,會(huì)發(fā)現(xiàn)兩個(gè)項(xiàng)目多了一個(gè)東西:


多了兩個(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捌袜,一起剝皮案震驚了整個(gè)濱河市说搅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌琢蛤,老刑警劉巖蜓堕,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異博其,居然都是意外死亡套才,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門慕淡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來背伴,“玉大人,你說我怎么就攤上這事峰髓∩导牛” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵携兵,是天一觀的道長疾掰。 經(jīng)常有香客問我,道長徐紧,這世上最難降的妖魔是什么静檬? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮并级,結(jié)果婚禮上拂檩,老公的妹妹穿的比我還像新娘。我一直安慰自己嘲碧,他們只是感情好稻励,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著愈涩,像睡著了一般望抽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上履婉,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天煤篙,我揣著相機(jī)與錄音,去河邊找鬼谐鼎。 笑死舰蟆,一個(gè)胖子當(dāng)著我的面吹牛趣惠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播身害,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼味悄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了塌鸯?” 一聲冷哼從身側(cè)響起侍瑟,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丙猬,沒想到半個(gè)月后涨颜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茧球,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年庭瑰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抢埋。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弹灭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出揪垄,到底是詐尸還是另有隱情穷吮,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布饥努,位于F島的核電站捡鱼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏酷愧。R本人自食惡果不足惜驾诈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伟墙。 院中可真熱鬧翘鸭,春花似錦滴铅、人聲如沸戳葵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拱烁。三九已至,卻和暖如春噩翠,著一層夾襖步出監(jiān)牢的瞬間戏自,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工伤锚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留擅笔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像猛们,于是被迫代替她去往敵國和親念脯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344