我有两个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,一切都是新的。
UPDATE
我在viewDidAppear中使用了以下块(如果localstorage中有电子邮件,然后显示扩展步骤视图而不是登录屏幕)和登录成功时内部登录功能,但它没有导航到该ExtensionStepsView
let controller = "ExtensionStepsViewController"
let subview = ExtensionStepsViewController(nibName: NSNib.Name(rawValue: controller), bundle: nil)
self.view.addSubview(subview.view)
用例是在初始时显示登录,但如果用户登录则显示另一个视图,但问题是现在视图已合并
你得到错误“类型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
}
视图已合并,因为您没有从superview中删除先前的视图,并将ExtensionStepsViewController中的视图添加到同一个superview。
您可以执行以下步骤来完成您的问题:
作为示例,但是您必须使用您的实现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.