UIActivityViewController分享及自定义

UIActivityShareDemo

UIActivityShareDemo

前言
之前在app内做跨app分享内容时,一般都会引入各种常见三方app的开发sdk,或者使用已经集成了各种三方分享的sdk如友盟啥的,但是现在越来越多的app开始使用苹果系统自带的分享功能,其中用到的类是UIActivityViewController

demo:
https://github.com/eye1234456/UIActivityViewControllerShareDemo

[站外图片上传中...(image-26b5f8-1648016233691)]

[站外图片上传中...(image-920e3f-1648016233691)]

一、普通使用方式

优点:调用简单,系统会自动根据分享的内容展示不同的UI样式及可分享的三方app和系统功能

缺点:展示出的系统UI弹窗内容固定,自定义差

- (void) showNormalActivityShare {
    NSArray *activityItems = @[];
    // 分享的是普通文本
    activityItems = @[@"hello world"];
    // 分享的是链接
    //activityItems = @[[NSURL URLWithString:@"http://www.baidu.com"]];
    // 分享的是图片
    //activityItems = @[[UIImage imageNamed:@"xxx"]];
    // 分享多个内容
    //activityItems = @[[UIImage imageNamed:@"xxx"],[NSURL URLWithString:@"http://www.baidu.com"],@"hello world"];
    
    UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
    __weak typeof(self) weakself = self;
    activityVC.completionWithItemsHandler = ^(UIActivityType  _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) {
      if (activityType == nil && activityError == nil && completed == NO) {
          NSLog(@"关闭分享弹窗");
       }else if (activityType != nil && completed) {
               // 分享成功
               
      }else if (activityType != nil && activityError != nil) {
               // 操作失败];
      }else if (activityType != nil && completed == NO) {
               // 操作失败
               // 备忘录取消操作
      }else {
    
       }
    };
        
    [self presentViewController:activityVC animated:YES completion:^{
        
    }];
}
二、LinkPresentationLPLinkMetadata自定义分享头部的icon、主标题、子标题方式

优点:调用相对复杂,但能自定义头部的icon、主标题、子标题,适合大部分应用常见

缺点:相对复杂

原理:对默认分享的字符串、链接或图片等内容进行下包装,分享一个包装的内容,包装的类要实现UIActivityItemSource协议

具体实现如下:

1、UI及数据model

@interface ShareModel : NSObject
/// 用于展示分享弹出顶部左侧的图片
@property(nonatomic, strong) UIImage * __nullable showIcon;
/// 用于展示分享弹窗顶部的大标题
@property(nonatomic, copy) NSString * __nullable showTitle;
/// 用于展示分享弹出顶部大标题下面的小标题
@property(nonatomic, copy) NSString * __nullable showSubTitle;
/// 真正分享的内容(如果没有配置show的三个字段,直接使用data进行自动分享展示)
/// NSURL、NSString、UIImage。。。
@property(nonatomic, strong) id data;
@end

@implementation ShareModel
@end

2、封装的实现UIActivityItemSource分享Model

#import <UIKit/UIKit.h>
#import "ShareModel.h"

NS_ASSUME_NONNULL_BEGIN

@interface ShareViewModel : NSObject
@property(nonatomic, strong) ShareModel *model;
+ (instancetype)viewModelWithModel:(ShareModel *)model;
@end

NS_ASSUME_NONNULL_END

#import "ShareViewModel.h"
#import <UIKit/UIKit.h>
#import <LinkPresentation/LPLinkMetadata.h>

@interface ShareViewModel() <UIActivityItemSource>

@end

@implementation ShareViewModel
+ (instancetype)viewModelWithModel:(ShareModel *)model {
    ShareViewModel *vm = [ShareViewModel new];
    vm.model = model;
    return vm;
}
#pragma mark - UIActivityItemSource protocol procedures to support sharesheet
/**
 * 告诉系统分享的类型同类型的数据
 */
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
    return self.model.data;
}
/**
 * 真正操作时的回调,表示要操作什么数据
 */
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
    // 真正分享的内容
    return self.model.data;
}

/**
 * UIActivityViewController弹窗上展示的icon、主标题、子标题配置
 */
- (LPLinkMetadata *)activityViewControllerLinkMetadata:(UIActivityViewController *)activityViewController  API_AVAILABLE(ios(13.0)){
    
    LPLinkMetadata * metaData = [[LPLinkMetadata alloc] init];
    // 只有分享的是URL或UIImage时,设置title才生效
    // text时,一直固定显示Plain Text
    if (self.model.showTitle) {
        metaData.title = self.model.showTitle;
    }
    
    if (self.model.showSubTitle) {
        metaData.originalURL = [NSURL fileURLWithPath:self.model.showSubTitle];
    }
    
    // 设置icon
    if (self.model.showIcon) {
        UIImage *iconImage = self.model.showIcon;
        NSItemProvider *iconProvider = [[NSItemProvider alloc] initWithObject:iconImage];
        metaData.iconProvider = iconProvider;
    }
    
    return metaData;
}
@end

3、真正分享

- (void)showCustomActivityShare {
          NSArray *activityItems = @[];
        // 分享的是普通文本,指定icon、主标题、子标题、分享的文本
        ShareModel *originShareTextModel = [ShareModel modelWithShowIcon:icon showTitle:@"主标题" showSubTitle:@"子标题" data:shareText];
        ShareViewModel *wrapShareShareTextModel = [ShareViewModel viewModelWithModel: originShareText];
        activityItems = @[wrapShareShareTextModel];
        // 分享的是链接
        //ShareModel *originShareURLModel = [ShareModel modelWithShowIcon:icon showTitle:@"主标题" showSubTitle:@"子标题" data:[NSURL URLWithString:@"http://www.baidu.com"]];
        //ShareViewModel *wrapShareShareURLModel = [ShareViewModel viewModelWithModel: originShareURLModel];
        //activityItems = @[wrapShareShareURLModel];
        // 分享的是图片
        //activityItems = @[[UIImage imageNamed:@"xxx"]];
            //ShareModel *originShareImageModel = [ShareModel modelWithShowIcon:icon showTitle:@"主标题" showSubTitle:@"子标题" data:[UIImage imageNamed:@"xxx"]];
        //ShareViewModel *wrapShareShareImageModel = [ShareViewModel viewModelWithModel: originShareImageModel];
        //activityItems = @[wrapShareShareImageModel];
        // 分享多个内容
        
        
        UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
        __weak typeof(self) weakself = self;
        activityVC.completionWithItemsHandler = ^(UIActivityType  _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) {
          if (activityType == nil && activityError == nil && completed == NO) {
              NSLog(@"关闭分享弹窗");
           }else if (activityType != nil && completed) {
                   // 分享成功
                   
          }else if (activityType != nil && activityError != nil) {
                   // 操作失败];
          }else if (activityType != nil && completed == NO) {
                   // 操作失败
                   // 备忘录取消操作
          }else {
        
           }
        };
            
        [self presentViewController:activityVC animated:YES completion:^{
            
        }];
    }
}

过程中遇到的问题

1、在模拟器运行时,分享的弹窗一直展示英文,没有根据模拟器设置成中文展示成中文,这是需要在Info.plist里设置语言根据设备来展示

增加 Localized resources can be mixed设置成YES


2、在分享图片时没有出现存储图像的操作,这是因为我创建的demo项目没有配置使用相册的权限,在Info.plist里配置下就好了

增加 Privacy - Photo Library Additions Usage Description设置成$(DISPLAY_NAME)需要你的同意,才能添加图片到相册

增加 Privacy - Photo Library Usage Description设置成$(DISPLAY_NAME)想要访问您的相册,请允许

最后效果图如下所示:

     NSString *testToShare = @"AI高清壁纸";

//                NSURL *urlToShare = [NSURL URLWithString:@"http://www.baidu.com"];

//                UIImage *imageToShare = image;

//                  NSArray *activityItems = @[testToShare,imageToShare,urlToShare];

                

//                UIImage *imageToShare = image;

//                NSArray *activityItems = @[imageToShare];

                

                NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];

                //获取app中所有icon名字数组

                NSArray *iconsArr = infoDict[@"CFBundleIcons"][@"CFBundlePrimaryIcon"][@"CFBundleIconFiles"];

                //取最后一个icon的名字

                NSString *iconLastName;

                if (iconsArr.count > 0) {

                    iconLastName = [iconsArr lastObject];

                }

                else {

                    iconLastName = infoDict[@"CFBundleIcons"][@"CFBundlePrimaryIcon"][@"CFBundleIconName"];

                }

                

                UIImage *icon = [UIImage imageNamed:iconLastName];

                

                NSArray *activityItems = @[];

                     // 分享的是普通文本,指定icon、主标题、子标题、分享的文本

                ShareModel *originShareTextModel = [ShareModel modelWithShowIcon:icon showTitle:@"AI高清壁纸" showSubTitle:@"每天都更新的壁纸APP" data:image];

                ShareViewModel *wrapShareShareTextModel = [ShareViewModel viewModelWithModel: originShareTextModel];

                activityItems = @[wrapShareShareTextModel];

                

                UIActivityViewController *activityVc = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];

                

                activityVc.excludedActivityTypes = @[UIActivityTypePrint,UIActivityTypeCopyToPasteboard,UIActivityTypeAssignToContact,UIActivityTypeSaveToCameraRoll];

                

  

                activityVc.completionWithItemsHandler = ^(UIActivityType  _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) {

                    if (activityType == nil && activityError == nil && completed == NO) {

//                        NSLog(@"关闭分享弹窗");

                    }

                    else if (activityType != nil && completed) {

                        // 分享成功

                    }

                    else if (activityType != nil && activityError != nil) {

                        // 操作失败];

                    }

                    else if (activityType != nil && completed == NO) {

                        // 操作失败

                        // 备忘录取消操作

                    }

                    else {

                        

                    }

                };

                [self presentViewController:activityVc animated:YES completion:nil];

猜你喜欢

转载自blog.csdn.net/u013712343/article/details/131636186