我有两个xib文件,一个显示登录视图,另一个显示成功登录后的操作步骤。我很难使它工作。我创建了macos项目而不是ios,并使用了safariservices,以便它可以用于safari扩展。
这就是我所做的
import SafariServices
class SafariExtensionViewController: SFSafariExtensionViewController {
@IBOutlet weak var passwordMessage: NSTextField!
@IBOutlet weak var emailMessage: NSTextField!
@IBOutlet weak var message: NSTextField!
@IBOutlet weak var email: NSTextField!
@IBOutlet weak var password: NSSecureTextField!
static let shared = SafariExtensionViewController()
override func viewDidLoad() {
self.preferredContentSize = NSSize(width: 300, height: 250)
message.stringValue = ""
emailMessage.stringValue = ""
passwordMessage.stringValue = ""
}
override func viewDidAppear() {
if let storedEmail = UserDefaults.standard.object(forKey: "email") as? String {
if let stepView = Bundle.mainBundle.loadNibNamed(NSNib.Name(rawValue: "ExtensionStepsViewController"), owner: nil, topLevelObjects: nil)[0] {
self.view.addSubview(stepView)
}
}
}
@IBAction func userLogin(_ sender: Any) {
let providedEmailAddress = email.stringValue
let providedPassword = password.stringValue
let isEmailAddressValid = isValidEmailAddress(emailAddressString: providedEmailAddress)
self.message.stringValue = ""
emailMessage.stringValue = ""
passwordMessage.stringValue = ""
if isEmailAddressValid && providedPassword.count > 0 {
/* login process is handled here and store the email in local storage /*
/* TODO for now email is not stored in browser localstorage which has to be fixed */
let controller = "ExtensionStepsViewController"
let subview = ExtensionStepsViewController(nibName: NSNib.Name(rawValue: controller), bundle: nil)
self.view.addSubview(subview.view)
}
}
}
这样,我收到类似Type Bool has no subscript members
的错误,我的文件结构看起来像这样。
SafariExtensionViewController.xib(最初显示的主要一个 登录屏幕)
SafariExtensionViewController.swift
ExtensionStepsViewController.xib(该视图应在用户 登录而不是登录屏幕
ExtensionStepsViewController.swift
我正在使用xcode 10,swift 4,所有新功能。
更新
我在viewDidAppear中使用了以下代码块(如果localstorage中有电子邮件,则显示扩展步骤视图而不是登录屏幕),并且在登录成功但未导航至该ExtensionStepsView时在登录功能内部使用
let controller = "ExtensionStepsViewController"
let subview = ExtensionStepsViewController(nibName: NSNib.Name(rawValue: controller), bundle: nil)
self.view.addSubview(subview.view)
用例是最初显示登录名,但如果用户登录则显示另一个视图,但现在是视图合并了
答案 0 :(得分:1)
您收到错误“ Type Bool没有下标成员”的错误信息,因为loadNibNamed(_:owner:topLevelObjects:)的Bundle方法返回了没有Bool成员的subscript结构,因此您无法编写喜欢
true[0]
如何正确使用此方法,请参见link和示例:
var topLevelObjects : NSArray?
if Bundle.main.loadNibNamed(NSNib.Name(rawValue: "ExtensionStepsViewController"), owner: self, topLevelObjects: &topLevelObjects) {
let topLevelObjects!.first(where: { $0 is NSView }) as? NSView
}
视图被合并是因为您没有从超级视图中删除先前的视图,而是将视图从ExtensionStepsViewController添加到了同一超级视图中。
您可以按照以下步骤完成问题:
作为示例,您必须使用实现SafariExtensionViewController而不是ParentViewController,如我在第一步中上面所述。
public protocol LoginViewControllerDelegate: class {
func loginViewControllerDidLoginSuccessful(_ loginVC: LoginViewController)
}
public class LoginViewController: NSViewController {
weak var delegate: LoginViewControllerDelegate?
@IBAction func login(_ sender: Any) {
// login logic
let isLoginSuccessful = true
if isLoginSuccessful {
self.delegate?.loginViewControllerDidLoginSuccessful(self)
}
}
}
public class ExtensionStepsViewController: NSViewController {
}
public class ParentViewController: NSViewController, LoginViewControllerDelegate {
weak var login: LoginViewController! // using of force unwrap is anti-pattern. consider other solutions
weak var steps: ExtensionStepsViewController!
public override func viewDidLoad() {
let login = LoginViewController(nibName: NSNib.Name(rawValue: "LoginViewController"), bundle: nil)
login.delegate = self
// change login view frame if needed
login.view.frame = self.view.frame
self.view.addSubview(login.view)
// instead of setting login view frame you can add appropriate layout constraints
self.addChildViewController(login)
self.login = login
let steps = ExtensionStepsViewController(nibName: NSNib.Name(rawValue: "ExtensionStepsViewController"), bundle: nil)
steps.view.frame = self.view.frame
self.addChildViewController(steps)
self.steps = steps
}
// MARK: - LoginViewControllerDelegate
public func loginViewControllerDidLoginSuccessful(_ loginVC: LoginViewController) {
self.transition(from: self.login, to: self.steps, options: .slideLeft) {
// completion handler logic
print("transition is done successfully")
}
}
}
Here是这个示例的快速游乐场。
UPD:
您可以通过几种方式实例化NSViewController:
let storyboard = NSStoryboard(name: NSStoryboard.Name("NameOfStoryboard"), bundle: nil)
let viewController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("NSViewControllerIdentifierInStoryboard"))
let steps = ExtensionStepsViewController(nibName: NSNib.Name(rawValue: "ExtensionStepsViewController"), bundle: nil)
let steps = ExtensionStepsViewController()
// Also you have to override loadView() method of ExtensionStepsViewController.