Процесс расширения iOS Share

У меня проблемы с созданием расширения общего доступа, такого как расширение общего доступа приложения Pinterest. Когда пользователь не вошел в приложение, содержащее его, расширение общего ресурса представляет только предупреждение с опцией log in и cancel.

Где в коде решить, какой контроллер представления отображать в моем общем расширении. Я вижу это так, будто мне нужно проверить статус авторизации из общего контейнера, и если этот статус not logged, мне нужно представить контроллер предупреждений. Если статус logged, мне нужно показать мой главный контроллер представления ShareViewController, который является подклассом SLComposeServiceViewController

Мой вопрос связан не с пользовательским интерфейсом, а с тем, где разместить этот проверочный код. Я не нашел ни одного метода, при котором запускается расширение приложения, поэтому я могу выбрать какой-то начальный контроллер представления для расширения на основе некоторого состояния.

В расширении Pinterest я не вижу их главный контроллер представления, когда пользователь выходит из своего приложения. Я вижу только оповещение с опциями.

Второй вопрос: как программно переключиться с расширения общего ресурса на содержащее приложение. Как это расширение Pinterest делает это, когда пользователю необходимо пройти аутентификацию?

Я работаю над последним iOS SDK 10.2


person Marcin Kapusta    schedule 17.03.2017    source источник


Ответы (1)


Поскольку я не получил отзывов по этому поводу, я понимаю, как это сделать. Вот и ответ.

Чтобы контролировать загрузку представления, я использовал loadView метод из UIViewController жизненного цикла. Этот метод запускается, когда приложению сначала нужно получить свойство view от UIViewController. Так что это ленивая загрузка. Этот метод также запускается, когда пользователь вызывает loadViewIfNeeded() из UIViewController api. В теле этого метода вам нужно быть очень осторожным, чтобы не прочитать свойство view, потому что это вызовет снова loadView, и у вас будет рекурсивный цикл.

Моя реализация для этого метода следующая. Мне нужно указать, вошел ли пользователь в систему или нет, и на основе этого выбрать, какое представление загрузить.

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
    }
}

И если пользователь не вошел в систему, я показываю предупреждение в

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, поэтому вы можете выполнять селекторы только с максимум двумя аргументами.

#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
person Marcin Kapusta    schedule 12.04.2017
comment
Не могли бы вы объяснить, как использовать этот код? Я застрял на этом обмене вещами и не нашел справки в сети. - person Sagar Panwala; 27.05.2017