iOS分享扩展流程 [英] iOS Share Extension flow

查看:166
本文介绍了iOS分享扩展流程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在创建共享扩展名(例如Pinterest应用的共享扩展名)时遇到问题.当用户未登录到包含应用程序时,共享扩展名仅显示警报,并带有log incancel的选项.

I have problems with creating share extension like share extension of the Pinterest app. When user is not logged to the containing app the share extension only presents alert with an option to log in and cancel.

在代码中的何处决定在共享扩展中显示哪个视图控制器.我看到这样的情况,就像我需要从共享容器中检查授权状态,如果此状态为not logged,则需要提供警报控制器.如果状态为logged,则需要显示主视图控制器ShareViewController,它是SLComposeServiceViewController

Where in code decide which view controller to show in my shared extension. I see this like I need to check authorization status from shared container and if this status is not logged I need to present alert controller. If status is logged I need to show my main view controller ShareViewController which is a subclass of SLComposeServiceViewController

我的问题与UI不相关,但在哪里放置此检查代码.我没有找到启动应用扩展的任何方法,因此我可以根据某些状态为扩展选择一些初始视图控制器.

My question is not UI related but where to put this check code. I didn't find any method where app extension starts so I can select some initial view controller for extension based on some state.

在Pinterest扩展程序中,当用户从其包含的应用程序注销时,我看不到其主视图控制器.我只看到带有选项的警报.

In Pinterest extension I don't see their main view controller when user is logged out from their containing app. I see only alert with options.

第二个问题:如何以编程方式从共享扩展名切换到包含应用程序.当用户需要进行身份验证时,此Pinterest共享扩展插件将如何执行此操作?

Second question: How to programatically switch from share extension to containing app. How this Pinterest share extension is doing this when user need to authenticate?

我正在使用最新的iOS SDK 10.2

I'm working on latest iOS SDK 10.2

推荐答案

由于我对此没有收到任何反馈,因此我知道了如何执行此操作.这是答案.

Since I didn't receive any feedback for this and I figure it out how to do this. Here is the answer.

为了控制哪个视图负载,我使用了UIViewController生命周期中的loadView方法.当应用程序首先需要从UIViewController获取view属性时,将触发此方法.因此,这是延迟加载.当用户从UIViewController api调用loadViewIfNeeded()时,也会触发此方法.在此方法的主体中,您需要非常小心,不要读取view属性,因为这将再次调用loadView,并且您将具有递归循环.

To control which view load I used loadView method from UIViewController lifecycle. This method is fired when application first need to get view property from UIViewController. So this is lazy loading. This method is also fired when user invoke loadViewIfNeeded() from UIViewController api. In the body of this method You need to be very careful to not read view property because this will invoke loadView again and You will have recursive loop.

以下是我对该方法的实现.我需要告诉用户是否已登录包含应用程序,并基于此选择要加载的视图.

My implementation for this method is following. I need to tell if user is logged in or not in containing app and based on this choose which view to load.

override func loadView() {
    // check in shared Keychain if user is authenticated
    self.userAuthenticated = userService.isAuthenticated()

    if self.userAuthenticated {
        // load default view of the ShareViewController
        super.loadView()
    } else {
        // if user is not logged in show only alert view controller with transparent dummy view
        let view = UIView()
        self.view = view
    }
}

如果用户未登录,我会在其中显示警报

And if user is not logged in I show alert in

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let context = self.extensionContext!
    if !self.userAuthenticated {
        let alert = UIAlertController(title: "Error", message: "User not logged in", preferredStyle: .alert)
        let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in
            context.completeRequest(returningItems: nil, completionHandler: nil)
        }
        let login = UIAlertAction(title: "Log In", style: .default, handler: { _ in
            let url = URL(string: "fashionapp://login")!
            // This is utility method written in Objective-C.
            // I don't know yet if it passes Apple Review process or not.
            // We will see ;)
            self.open(url, options: [:], completionHandler: nil)
            context.completeRequest(returningItems: nil, completionHandler: nil)
        })

        alert.addAction(cancel)
        alert.addAction(login)
        present(alert, animated: true, completion: nil)
    }
}

这是从共享扩展中打开包含应用程序的方法.我希望它会有用,Apple会对此进行检查,不会出现任何问题.它是用Objective-C编写的,因为在Swift中没有NSInvocation类,因此只能执行最多两个参数的选择器.

And here is the method for opening containing app from share extension. I hope it will be useful and Apple will review this without any problems. It is written in Objective-C because in Swift there is no NSInvocation class so you can only perform selectors with max two arguments.

#import <UIKit/UIKit.h>

@interface UIViewController (OpenURL)

- (void)openURL:(nonnull NSURL *)url
        options:(nonnull NSDictionary<NSString *, id> *)options
completionHandler:(void (^ __nullable)(BOOL success))completion;

@end

实施.

#import "UIViewController+OpenURL.h"

@implementation UIViewController (OpenURL)


- (void)openURL:(nonnull NSURL *)url
        options:(nonnull NSDictionary<NSString *, id> *)options
completionHandler:(void (^ __nullable)(BOOL success))completion {

    SEL selector = NSSelectorFromString(@"openURL:options:completionHandler:");

    UIResponder* responder = self;
    while ((responder = [responder nextResponder]) != nil) {
        if([responder respondsToSelector:selector] == true) {
            NSMethodSignature *methodSignature = [responder methodSignatureForSelector:selector];
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];

            [invocation setTarget: responder];
            [invocation setSelector: selector];
            [invocation setArgument: &url atIndex: 2];
            [invocation setArgument: &options atIndex:3];
            [invocation setArgument: &completion atIndex: 4];
            [invocation invoke];
            break;
        }
    }
}

@end

这篇关于iOS分享扩展流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆