在主视图控制器中单击后更新外部视图控制器中的 UITextField

Posted

技术标签:

【中文标题】在主视图控制器中单击后更新外部视图控制器中的 UITextField【英文标题】:Update UITextField in external view controller after a click in main view controller 【发布时间】:2016-11-04 06:05:35 【问题描述】:

当设备通过 HDMI 连接时,我试图在 MainViewController 上显示一个按钮,在 ExternalViewController 中显示一个 UITextField。当 MainViewController 中发生单击时,我需要更新 ExternalViewController 中的 UITextField。我可以在输出窗口中看到打印,但文本字段没有更新。

MainViewController.swift

import UIKit
import WebKit

class MainViewController: UIViewController 
  fileprivate var externalWindow: UIWindow?

  override func viewDidLoad() 
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    if UIScreen.screens.count > 1 
      setupExternalScreen(UIScreen.screens[1])
    

    let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
    button.backgroundColor = UIColor.blue

    button.setTitle("Click Me", for: UIControlState.normal)
    button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)

    self.view.addSubview(button)

  

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


  /*
   // MARK: - Navigation

   // In a storyboard-based application, you will often want to do a little preparation before navigation
   override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
   // Get the new view controller using segue.destinationViewController.
   // Pass the selected object to the new view controller.
   
   */
  fileprivate func setupExternalScreen(_ screen: UIScreen) 
    guard externalWindow == nil,
      let vc = self.storyboard?.instantiateViewController(withIdentifier: "ExternalScreen") as? ExternalViewController else 
        return
    

    externalWindow = UIWindow(frame: screen.bounds)
    externalWindow!.rootViewController = vc
    externalWindow!.screen = screen
    externalWindow!.isHidden = false
  

  func buttonAction(sender: UIButton) 
    print("Button tapped")
    ExternalViewController().updateLabel()
  


ExternalViewController.swift

import UIKit

class ExternalViewController: UIViewController 

    let output = UITextField(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 300, height: 100)))

    override func viewDidLoad() 
        super.viewDidLoad()
        self.addTextField()
    

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

    func addTextField() 
      output.textColor = UIColor.black
      output.text = "This is the other text field"
      view.addSubview(output)
    

    func updateLabel() 
      print("inside updateLabel")
      output.text = "button was clicked"
    


这就是它的样子。

这是我第一个使用 Swift 的项目,如果是一个不好的问题,我深表歉意。

【问题讨论】:

您需要将数据作为字符串或使用委托传递。 检查我的答案。如果你在 ios 上,你应该考虑展示 ExternalViewController 而不是在新窗口中显示它,这至少可以说是一种奇怪的方法 【参考方案1】:

尝试使用 NotificationCentre 。 在外部VC中

override func viewDidLoad() 
    super.viewDidLoad()
     NotificationCenter.default.addObserver(self, selector: #selector(receivedDataFromNotification(notification:)), name: NSNotification.Name(rawValue: "passdata"), object: nil)
    

   func receivedDataFromNotification(notification : NSNotification) -> Void 
        print(notification.object);
      output.text = "button was clicked"
    

在主视图控制器中

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "passdata"), object: "your string pass here")

【讨论】:

【参考方案2】:

虽然您可以使用通知在之间传输数据,但我更喜欢创建委托来传输数据。 首先创建一个协议

protocol ExternalViewControllerDelegate: class
    func shouldUpdateLabel(withText text: String)

然后适当地更新 ExternalViewController 以包含当然是弱引用的委托

class ExternalViewController: UIViewController 
    weak var delegate: ExternalViewControllerDelegate?
    let output = UITextField(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 300, height: 100)))

    override func viewDidLoad() 
        super.viewDidLoad()
        self.addTextField()
    

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

    func addTextField() 
        output.textColor = UIColor.black
        output.text = "This is the other text field"
        view.addSubview(output)
    

    func updateLabel() 
        print("inside updateLabel")
        output.text = "button was clicked"
        delegate?.shouldUpdateLabel(withText: "Your text")
    

记得在委托中调用方法。我在类中使用了updateLabel方法来调用该方法。我假设您也想使用它

最后在 MainViewController 中实现协议,记得设置委托。

extension MainViewController: ExternalViewControllerDelegate
    func shouldUpdateLabel(withText text: String) 
        //Do what you want with the text
    

然后更新 setupExternalScreen 方法来设置委托

 func setupExternalScreen(_ screen: UIScreen) 
    guard externalWindow == nil,
        let vc = self.storyboard?.instantiateViewController(withIdentifier: "ExternalScreen") as? ExternalViewController else 
            return
    
    vc.delegate = self

    externalWindow = UIWindow(frame: screen.bounds)
    externalWindow!.rootViewController = vc
    externalWindow!.screen = screen
    externalWindow!.isHidden = false

【讨论】:

以上是关于在主视图控制器中单击后更新外部视图控制器中的 UITextField的主要内容,如果未能解决你的问题,请参考以下文章

如何在 xcode 中从控制器外部更新视图

当被模态视图控制器覆盖时,iOS 6 视图控制器布局在方向更改后不会更新

加载外部视图控制器,从按钮​​单击另一个视图控制器

如何通过单击按钮在 Swift UI 中从一个视图导航到另一个视图

关闭 Popover 后更新第一个视图

ViewController 操作后,Swift UIView 自定义视图不会更新