我在创建共享扩展程序时遇到问题,例如Pinterest应用程序的共享扩展程序。当用户未登录到包含应用时,共享扩展程序仅显示包含log in
和cancel
选项的提醒。
代码中的哪个位置决定在我的共享扩展中显示哪个视图控制器。我看到这就像我需要检查共享容器的授权状态,如果这个状态是not logged
,我需要提供警报控制器。如果状态为logged
,我需要显示我的主视图控制器ShareViewController
,它是SLComposeServiceViewController
我的问题不是UI相关,而是放置此检查代码的位置。我没有找到应用程序扩展启动的任何方法,因此我可以根据某些状态为扩展选择一些初始视图控制器。
在Pinterest扩展程序中,当用户从其包含的应用程序注销时,我看不到他们的主视图控制器。我只看到提示选项。
第二个问题:如何以编程方式从共享扩展切换到包含应用程序。当用户需要进行身份验证时,此Pinterest共享扩展如何执行此操作?
我正在使用最新的iOS SDK 10.2
答案 0 :(得分:2)
由于我没有收到任何反馈,我想出了如何做到这一点。这是答案。
要控制loadView
生命周期中使用UIViewController
方法的视图加载。当应用程序首先需要从view
获取UIViewController
属性时,会触发此方法。所以这是懒加载。当用户从loadViewIfNeeded()
api调用UIViewController
时,也会触发此方法。在这个方法的主体中你需要非常小心不要读取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