iOS-Share Extension

原创
2016/12/22 09:55
阅读数 405

前言

IOS扩展主要的目的是用户可以在 app 中使用其他应用提供的功能,而无需离开当前的应用,因此可以发现在浏览图片或者是打开safari,点击分享的按钮,可以分享至很多其他的应用,这都是归功于IOS share extension扩展强大之处,据我的了解目前大部分的应用都没有实现扩展功能,所以网络上能查询到的资料很少,我也是尝试着去了解其如何使用,我今天要讲的并不是如何去为应用创建一个扩展,因为网络上是有这方面的内容的,我侧重讲的自定义分享界面,因为可能系统自带的UI界面并不能满足我们应用的要求,自定义界面是势在必行的;

 

一、如何为当前的应用添加share extension扩展,这个网络上都有操作步骤,我就不再重复。

二、在创建好share extension中,去修改info.plist文件,如

如此设置代表着,扩展的入口为CustomShareViewController(默认的是ShareViewController),接下来就是自定义布局,你可以在控制器中定义自己的UI交互,比如我做的简单的布局;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.6];
    //定义一个容器视图来存放分享内容和两个操作按钮
    container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 175)];
    container.center = self.view.center;
    container.layer.cornerRadius = 7;
    container.layer.borderColor = [UIColor lightGrayColor].CGColor;
    container.layer.borderWidth = 1;
    container.layer.masksToBounds = YES;
    container.backgroundColor = [UIColor whiteColor];
    container.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
    [self.view addSubview:container];
    
    oldRect = container.frame;
    
    othorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 220)];
    othorView.center = self.view.center;
    othorView.layer.cornerRadius = 7;
    othorView.layer.borderColor = [UIColor lightGrayColor].CGColor;
    othorView.layer.borderWidth = 1;
    othorView.alpha = 0;
    othorView.layer.masksToBounds = YES;
    othorView.backgroundColor = [UIColor whiteColor];
    othorView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
    [self.view addSubview:othorView];
    
    UIButton *backBut = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 65, 44)];
    [backBut setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [backBut setTitle:@"返回" forState:UIControlStateNormal];
    [backBut addTarget:self action:@selector(goBack:) forControlEvents:UIControlEventTouchUpInside];
    
    
    textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 50, 200, 50)];
    textView.text = @"测试";
    
    [othorView addSubview:backBut];
    
    [othorView addSubview:textView];
    
    
    testBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 300, 44)];
    UINavigationItem *ite = [[UINavigationItem alloc] initWithTitle:@"测试"];
    
    //定义Post和Cancel按钮
    UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeSystem];
    [cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
    cancelBtn.frame = CGRectMake(-15, 0, 65, 40);
    [cancelBtn addTarget:self action:@selector(cancelBtnClickHandler:) forControlEvents:UIControlEventTouchUpInside];
    [container addSubview:cancelBtn];
    
    UIButton *postBtn = [UIButton buttonWithType:UIButtonTypeSystem];
    [postBtn setTitle:@"发送" forState:UIControlStateNormal];
    postBtn.frame = CGRectMake(15, 0, 65, 40);
    [postBtn addTarget:self action:@selector(postBtnClickHandler:) forControlEvents:UIControlEventTouchUpInside];
    [container addSubview:postBtn];
    
    ite.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:cancelBtn];
    ite.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:postBtn];
    
    [testBar setItems:@[ite]];
    [container addSubview:testBar];
    [container addSubview:self.tableView];
    
    //定义一个分享链接标签
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(8,
                                                               cancelBtn.frame.origin.y + cancelBtn.frame.size.height + 8,
                                                               container.frame.size.width - 16,
                                                               container.frame.size.height - 16 - cancelBtn.frame.origin.y - cancelBtn.frame.size.height)];
    label.numberOfLines = 0;
    label.textAlignment = NSTextAlignmentCenter;
    [container addSubview:label];
    
    //获取分享链接
    __block BOOL hasGetUrl = NO;
    [self.extensionContext.inputItems enumerateObjectsUsingBlock:^(NSExtensionItem *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
       
        [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]])
                    {
                        dispatch_async(dispatch_get_main_queue(), ^{
                           
                            label.text = ((NSURL *)item).absoluteString;
                            
                        });
                    }
                    
                }];
                
                hasGetUrl = YES;
                *stop = YES;
            }
            
            *stop = hasGetUrl;
            
        }];
        
    }];
    
    for (NSString *notificationName in @[UIKeyboardWillShowNotification, UIKeyboardWillHideNotification]) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:notificationName object:nil];
    }
}

其实就是简单的视图切换,当然你也可以定制更加丰富的界面交互,这是跟业务需求挂钩的;

其中还需要注意的两个方法:cancelRequestWithError与completeRequestReturningItems,这个是操作必须的方法,一个是错误执行,另一个是成功执行返回,且执行都会关闭扩展程序界面。

- (void)cancelBtnClickHandler:(id)sender
{
    [self.extensionContext cancelRequestWithError:[NSError errorWithDomain:@"CustomShareError" code:NSUserCancelledError userInfo:nil]];
}

- (void)postBtnClickHandler:(id)sender
{
    //执行分享内容处理
    
    coverView = [[CoverView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:coverView];
    
    [self performSelector:@selector(testAnima) withObject:nil afterDelay:0.1];
    
    //[self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
}

 

三、扩展中使用AFNetworking,网络请求肯定是必须的,具体的使用与在app中使用的一样,如

AFHTTPSessionManager *httpClient = [AFAppHFAPIClient sharedClient];
    [httpClient GET:urlString parameters:model progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (success) {
            
            success(responseObject);
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (failed) {
            
            failed(error);
        }
    }];

但是,特别需要注意的是,扩展中是没有[UIApplication sharedApplication]对象的,所以在操作提示界面的时候,这个是需要注意的。

 

四、提交AppStore注意事项:

(1)扩展中的处理不能太长时间阻塞主线程(建议放入线程中处处理),否则可能导致苹果拒绝你的应用。

(2)扩展不能单独提审,必须要跟容器程序一起提交AppStore进行审核。

(3)提审的扩展和容器程序的Build Version要保持一致,否则在上传审核包的时候会提示警告,导致程序无法正常提审。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部