iOS ShareExtension

使用系統(tǒng)分享髓梅。將Safari中的網(wǎng)頁(yè)分享給微信中的好友寡喝。


0.gif

1.新建ShareExtension拯田。

1.png
2.png
4.png
5.png
6.png
3.png

2.配置Share Extension圆仔,允許發(fā)送的數(shù)據(jù)類(lèi)型垃瞧,url,image,mp3,mp4,pdf,word,excel,ppt。


7.png

3.處理Share Extension中的數(shù)據(jù)荧缘。
Share Extension中默認(rèn)都會(huì)有一個(gè)數(shù)據(jù)展現(xiàn)的UI界面皆警。該界面繼承SLComposeServiceViewController這個(gè)類(lèi)型,如:

@interface ShareViewController : SLComposeServiceViewController

@end
10.gif

一般采用自定義控制器:

@interface ShareViewController : SLComposeServiceViewController

@end
8.png
11.gif

4.從inputItems中獲取數(shù)據(jù)截粗。

 [self.extensionContext.inputItems enumerateObjectsUsingBlock:^(NSExtensionItem *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
       
       if (obj.attributedContentText.string.length > 0)
       {
           self.contentText = obj.attributedContentText.string;
       }
       
       [obj.attachments enumerateObjectsUsingBlock:^(NSItemProvider *  _Nonnull itemProvider, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([itemProvider hasItemConformingToTypeIdentifier:@"public.url"])
            {
                [itemProvider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(id<NSSecureCoding>  _Nullable item, NSError * _Null_unspecified error) {
                    
                    if ([(NSObject *)item isKindOfClass:[NSURL class]])
                    {
                        self.url = (NSURL *)item;

                        NSInteger preValue = self.flag.integerValue;

                        if ([self.url isFileURL])
                        {
                            self.flag = [NSNumber numberWithInteger:(preValue|url_file)];
                        }
                        else
                        {
                            self.flag = [NSNumber numberWithInteger:(preValue|url_flag)];
                        }
                    }
                    
                    [self refreshView];
                }];
            }
           
           if ([itemProvider hasItemConformingToTypeIdentifier:@"public.image"])
            {
                [itemProvider loadItemForTypeIdentifier:@"public.image" options:nil completionHandler:^(id item, NSError *error) {
                    
                    if ([item isKindOfClass:[NSURL class]])
                    {
                        [self.arrImagePath addObject:item];
                        NSInteger preValue = self.flag.integerValue;
                        self.flag = [NSNumber numberWithInteger:(preValue | url_image)];
                        [self refreshView];
                        count ++;
                    }
                    else if ([item isKindOfClass:[UIImage class]] && !self.thumb)
                    {
                        self.thumb = (UIImage *)item;
                        NSInteger preValue = self.flag.integerValue;
                        self.flag = [NSNumber numberWithInteger:(preValue | url_image)];
                        [self refreshView];
                        count ++;
                    }
                }];
            }
           
            if ([itemProvider hasItemConformingToTypeIdentifier:(__bridge NSString *)kUTTypeText])
            {
                NSInteger preValue = self.flag.integerValue;
                self.flag = [NSNumber numberWithInteger:(preValue|url_text)];
                
                [itemProvider loadItemForTypeIdentifier:(__bridge NSString *)kUTTypeText options:nil completionHandler:^(id item, NSError *error) {
                    
                    if ([item isKindOfClass:[NSString class]])
                    {
                        NSString *str = (NSString *)item;
                        
                        if ([str containsString:@"http://"] || [str containsString:@"https://"] || [str containsString:@"file:///"])
                        {
                            if (!self.url)
                            {
                                self.url = [NSURL URLWithString:str];
                                
                                if ([self.url isFileURL])
                                {
                                    self.flag = [NSNumber numberWithInteger:(preValue|url_file)];
                                }
                                else
                                {
                                    self.flag = [NSNumber numberWithInteger:(preValue|url_flag)];
                                }
                            }
                        }
                        else
                        {
                            [self.text appendString:str];
                            [self.text appendString:@"\n"];
                        }
                    }

                    [self refreshView];
                }];
            }
           
           if ([itemProvider hasItemConformingToTypeIdentifier:@"public.movie"])
           {
               [itemProvider loadItemForTypeIdentifier:@"public.movie" options:nil completionHandler:^(id<NSSecureCoding>  _Nullable item, NSError * _Null_unspecified error)
               {
                   NSInteger preValue = self.flag.integerValue;
                   NSURL *fileurl = (NSURL *)item;
                   if ([fileurl isFileURL])
                   {
                       self.flag = [NSNumber numberWithInteger:(preValue | url_file)];
                       self.url = fileurl;
                       [self refreshView];
                   }
               }];
           }
           
        }];
       
    }];

上面的例子中遍歷了extensionContext的inputItems數(shù)組中所有NSExtensionItem對(duì)象信姓,然后從這些對(duì)象中遍歷attachments數(shù)組中的所有NSItemProvider對(duì)象。匹配第一個(gè)包含public.url標(biāo)識(shí)的附件(具體要匹配什么資源绸罗,數(shù)量是多少皆有自己的業(yè)務(wù)所決定)意推。注意:[self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];這行代碼,主要是使到視圖控制器不被關(guān)閉珊蟀,等到實(shí)現(xiàn)相應(yīng)的處理后再進(jìn)行調(diào)用該方法菊值,對(duì)分享視圖進(jìn)行關(guān)閉外驱。調(diào)用該方法則回到宿主App。

5.傳遞Share Extension中的數(shù)據(jù)腻窒。有個(gè)App Groups功能可以據(jù)此傳遞數(shù)據(jù)昵宇。


WX20190210-223758.png

WX20190210-224011.png

1.依據(jù)寫(xiě)文件傳遞數(shù)據(jù)。例如:要分享的App儲(chǔ)存登錄信息儿子。

 //獲取分組的共享目錄
      NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.cn.com.mengniu.oa.sharextension"];
      NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"login.txt"];
      if (success) {
        [@"isLogin" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
      } else {
        [@"isNotLogin" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:Nil];
      }
      
//獲取儲(chǔ)存在App Groups中的登錄信息瓦哎。
  NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.cn.com.mengniu.oa.sharextension"];
  NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"login.txt"];
  NSString *isLoginStatus = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:nil];

2.依據(jù)NSUserDefaults,儲(chǔ)存數(shù)據(jù),試了幾次沒(méi)有取成功過(guò)柔逼。

   NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.xxx.sharextension"];
  if (![userDefaults objectForKey:@"isLogin"])
  {
   UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"溫馨提示"
                                                                   message:@"請(qǐng)登錄"
                                                            preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"確定"
                                                            style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * action) {
                                                            UIResponder* responder = self;
                                                            while ((responder = [responder nextResponder]) != nil)
                                                            {
                                                              if([responder respondsToSelector:@selector(openURL:)] == YES)
                                                              {
                                                                [responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:@"sharefile://"]];
                                                              }
                                                            }
                                                          }];
    UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"取消"
                                                           style:UIAlertActionStyleCancel
                                                         handler:^(UIAlertAction * action) {}];
    [alert addAction:cancelAction];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
  }

會(huì)報(bào)錯(cuò):

[User Defaults] Couldn't read values in CFPrefsPlistSource<0x1c010e340> (Domain:
 group.cn.com.mengniu.oa.sharextension, User: kCFPreferencesAnyUser, ByHost: 
 Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, 
 detaching from cfprefsd

網(wǎng)上說(shuō)在儲(chǔ)存App Groups時(shí)要添加Team ID蒋譬。之后取值時(shí)雖然不會(huì)再報(bào)錯(cuò),但取出來(lái)的值為nil愉适。

6.其實(shí)蘋(píng)果官方除了Today Extension外犯助,其他Extension是不提供跳轉(zhuǎn)接口的。所以這里總結(jié)的是兩種非正常的方式维咸。

1.在Share Extension中無(wú)法獲取到UIApplication對(duì)象剂买,則通過(guò)拼接字符串獲取。

    NSURL *destinationURL = [NSURL URLWithString:[NSString stringWithFormat:@"sharefile://%@",saveFilePath]];
//     Get "UIApplication" class name through ASCII Character codes.
    NSString *className = [[NSString alloc] initWithData:[NSData dataWithBytes:(unsigned char []){0x55, 0x49, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E} length:13] encoding:NSASCIIStringEncoding];
    if (NSClassFromString(className)) {
      id object = [NSClassFromString(className) performSelector:@selector(sharedApplication)];
      [object performSelector:@selector(openURL:) withObject:destinationURL];
    }
    

2.這種方式主要實(shí)現(xiàn)原理是通過(guò)響應(yīng)鏈找到Host App的UIApplication對(duì)象腰湾,通過(guò)該對(duì)象調(diào)用openURL方法返回自己的應(yīng)用雷恃。

    UIResponder *responder = self;
    while ((responder = [responder nextResponder]) != nil) {
    if ([responder respondsToSelector:@selector(openURL:)] == YES) {
        [responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:@"sharefile://"]];
      }
    }
12.gif

7.未登錄的處理。登錄成功后先寫(xiě)文件儲(chǔ)存登錄信息到App Groups中费坊,退出登錄后倒槐,刪除儲(chǔ)存在App Groups中的登錄信息。到ShareViewController中先判斷是否登錄附井,若未登錄讨越,則彈窗提示登錄不再?gòu)椘鸢l(fā)送框。

1.登錄成功永毅,則保存登錄信息把跨。

      //獲取分組的共享目錄
      NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.cn.com.mengniu.oa.sharextension"];
      NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"login.txt"];
      if (success) {
        [@"isLogin" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
      } else {
        [@"isNotLogin" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:Nil];
      }
    });

2.退出登錄或未登錄,則清空已經(jīng)保存的登錄信息沼死。

  //獲取分組的共享目錄
  NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.cn.com.mengniu.oa.sharextension"];
  NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"login.txt"];
  [@"isNotLogin" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
  
  
  NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.cn.com.mengniu.oa.sharextension"];
  NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"login.txt"];
  NSString *isLoginStatus = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:nil];
 //如果未登錄提示登錄
  if (isLoginStatus && [isLoginStatus isEqualToString:@"isNotLogin"]) {
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"請(qǐng)先登錄辦隨着逐,再分享"
                                                                   message:nil
                                                            preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"確定"
                                                            style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * action) {
                                                            UIResponder* responder = self;
                                                            while ((responder = [responder nextResponder]) != nil)
                                                            {
                                                              if([responder respondsToSelector:@selector(openURL:)] == YES)
                                                              {
                                                                [responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:@"sharefile://"]];
                                                              }
                                                              [self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
                                                            }
                                                          }];
    UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"取消"
                                                           style:UIAlertActionStyleCancel
                                                         handler:^(UIAlertAction * action) {
                                                           [self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
                                                         }];
    [alert addAction:cancelAction];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
  }
  else//已登錄加載發(fā)送框
  {
    [self.view addSubview:container];
  }

9.gif

8.在ShareExtension中處理邏輯代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末意蛀,一起剝皮案震驚了整個(gè)濱河市耸别,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌县钥,老刑警劉巖秀姐,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異若贮,居然都是意外死亡省有,警方通過(guò)查閱死者的電腦和手機(jī)痒留,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蠢沿,“玉大人伸头,你說(shuō)我怎么就攤上這事∠象埃” “怎么了熊锭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)雪侥。 經(jīng)常有香客問(wèn)我,道長(zhǎng)精绎,這世上最難降的妖魔是什么速缨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮代乃,結(jié)果婚禮上旬牲,老公的妹妹穿的比我還像新娘。我一直安慰自己搁吓,他們只是感情好原茅,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著堕仔,像睡著了一般擂橘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上摩骨,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天通贞,我揣著相機(jī)與錄音,去河邊找鬼恼五。 笑死昌罩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的灾馒。 我是一名探鬼主播茎用,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼睬罗!你這毒婦竟也來(lái)了轨功?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤傅物,失蹤者是張志新(化名)和其女友劉穎夯辖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體董饰,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒿褂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年圆米,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啄栓。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娄帖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昙楚,到底是詐尸還是另有隱情近速,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布堪旧,位于F島的核電站削葱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淳梦。R本人自食惡果不足惜析砸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爆袍。 院中可真熱鬧首繁,春花似錦、人聲如沸陨囊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蜘醋。三九已至胁塞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間堂湖,已是汗流浹背闲先。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留无蜂,地道東北人伺糠。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像斥季,于是被迫代替她去往敵國(guó)和親训桶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容