在另一个View Controller中引用IBOutlet

时间:2017-05-14 19:48:02

标签: ios swift xcode

所以,我在解决这个问题时遇到了一些重大问题,我已经广泛搜索了一个解决方案,但我出乎意料地找不到一个。我正在尝试为用户创建一个多页面(准确地说是5个)。

我首先向您展示第1页和第5页的布局(因为解决该问题将解决第2-4页的问题):

Sign Up Page #1

Sign Up Page #5

正如您所看到的(从页面控制点),我使用页面视图控制器允许用户从一个页面滚动到另一个页面。我想要完成的是让用户能够在第1-5页输入他们的注册信息,然后一次提交(可以在第5页找到)。

以下是我用于第1页的当前代码:

class SignUpInfoViewController: UIViewController {

   @IBOutlet weak var emailTextField: UITextField!
   @IBOutlet weak var passwordTextField: UITextField!

   override func viewDidLoad() {
      super.viewDidLoad()
      // Do any additional setup after loading the view.

   }

   override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
   }
}

以下是我用于第5页的当前代码:

class TermsOfUseViewController: UIViewController {

let minPasswordCharCount = 6

@IBAction func signUpAction(_ sender: Any) {

    let providedEmailAddress = SignUpInfoViewController().emailTextField.text!
    let providedPassword = SignUpInfoViewController().passwordTextField.text!
    let trimmedPassword = providedPassword.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)

    if !(validEmail(enteredEmail: providedEmailAddress) && validPassword(enteredPassword: trimmedPassword)) {
        invalidCredentialsAlert()
    }
    else {
        FIRAuth.auth()?.createUser(withEmail: providedEmailAddress, password: providedPassword) { user, error in
            if error == nil {
                FIRAuth.auth()!.signIn(withEmail: providedEmailAddress,
                                       password: providedPassword)
            }
            else {
                let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)

                let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
                alertController.addAction(defaultAction)

                self.present(alertController, animated: true, completion: nil)
            }
        }
    }
}

// Email is valid if it has a standard email format
func validEmail(enteredEmail: String) -> Bool {
    let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)

    return emailPredicate.evaluate(with: enteredEmail)
}

// Password is valid if it is not empty or greater than a specified number of characters
func validPassword(enteredPassword: String) -> Bool {
    if (enteredPassword != "" && enteredPassword.characters.count >= minPasswordCharCount) {
        return true
    }

    return false
}

在TermsOfUseViewController类中,我试图使用SignUpInfoViewController中的emailTextField和passwordTextField出口,但是我收到以下错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

我调试了错误,发现SignUpInfoViewController的emailTextField属性为nil,因此强行展开会导致应用程序崩溃(注意:我已经正确地将IBOutlets连接到SignUpInfoViewController,所以没有问题)。

如何安全地将IBOutlets的使用从SignUpInfoViewController类转移到TermsOfUseViewController类而不会崩溃?换句话说,当我在TermsOfUseViewController类中引用IBOutlets时,如何将它发送到IBOutlets不再为零的位置?

谢谢!

2 个答案:

答案 0 :(得分:1)

这是delegate pattern

的完美场景
protocol SignUpProtocol: class { 
   func didProvideUserData(username: String ,password: String)
}

在您的注册类中声明委托:public weak var delegate:SignUpProtocol?

我假设当用户提供了需求信息时,他们需要按某个按钮进入下一步:因此在该按钮中你应该提出代表

@IBAction func nextButton(sender:UIButton) {
   guard let username = usernameTextfield?.text, let password = passwordTextField?.text, else { fatalError("textfields were empty") }
     if delegate != nil { // this saying when someone is listening to me, I will expose any method associated to me 
        delegate?.didProvideUserData(username:username, password:password) // passing the username and password from textfield 
     }
}

如果您没有按钮,请查看property observer,您可以在哪里找到属性

var didFulfill:Bool? = nil {
    didSet {
          if didFulfill != nil && didFulfill == true {}
        // here you check if your textfields are sets then raise the delegate
  }
}

设置此属性didFulfill = when both textfields are not empty :)

现在在您的条款课程中,只需订阅该代表

class TermsOfUseViewController: UIViewController, SignUpProtocol {
     var signUpVc: SignUpInfoViewController?
     override func viewDidLoad() {
       super.viewDidLoad()
        signUpVc = SignUpInfoViewController()
        signUpVc?.delegate = self 
    }

    func didProvideUserData(username: String, password:String) {
      // there is your data 
    }
}

答案 1 :(得分:0)

您必须考虑到您并非始终拥有所有UIPageViewController的所有引用。话虽这么说,我建议要么在UIPageViewController中保留对象的更新信息,要么使用 Singleton Pattern 来使用它来存储信息并稍后使用它。 UIPageViewController正在被重用,你可能有一个之前和一个之后,并依赖它们是错误的。

您可以将UIPageViewController用作self.parentViewController或类似的东西。