合并视图而不是单独显示它们

问题描述 投票:4回答:1

我有两个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)

用例是在初始时显示登录,但如果用户登录则显示另一个视图,但问题是现在视图已合并

enter image description here

swift xcode macos safari swift4
1个回答
1
投票

你得到错误“类型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。

您可以执行以下步骤来完成您的问题:

  1. 使SafariExtensionViewController继承自SFSafariExtensionViewController,它将是两个子视图控制器(如LoginViewController和ExtensionStepsViewController)的容器(和父),并将用于在它们之间导航。
  2. 单独创建LoginViewController和ExtensionStepsViewController(都继承自简单的NSViewController)及其xib。
  3. 用户从LoginViewController到ExtensionStepsViewController登录transit之后

作为示例,但是您必须使用您的实现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:

  1. 使用允许从.storyboard文件加载NSViewController视图的NSStoryboard
let storyboard = NSStoryboard(name: NSStoryboard.Name("NameOfStoryboard"), bundle: nil)
let viewController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("NSViewControllerIdentifierInStoryboard"))
  1. 使用适当的NSViewController的initialiser从.xib文件加载它的视图:
let steps = ExtensionStepsViewController(nibName: NSNib.Name(rawValue: "ExtensionStepsViewController"), bundle: nil)
  1. 使用默认初始化器,但如果xib文件的名称与视图控制器类的名称不同,则必须通过重写loadView()方法直接加载视图:
let steps = ExtensionStepsViewController()
// Also you have to override loadView() method of ExtensionStepsViewController.
© www.soinside.com 2019 - 2024. All rights reserved.