【问题标题】:How can I access an IBOutlet in ViewController from another class?如何从另一个类访问 ViewController 中的 IBOutlet?
【发布时间】:2015-12-24 05:46:41
【问题描述】:

我有一个班级是GCDAsyncUdpSocketDelegate。现在我正在通过 UDP(在后台线程中)获取一些数据,并且需要在我的 ViewController 中使用 IBOutlet 显示这些数据。但是 ViewController 只是一个类。它的对象实例在哪里定义?它叫什么名字?我该怎么做才能访问它,或者它的属性、方法之一?我见过这个UIApplication.sharedApplication().keyWindow?.rootViewController 方法,但这并不能保证我想访问的确切 ViewController。

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    我不知道你的应用的确切结构,但你可以试试这样:

    let rootViewController = UIApplication.sharedApplication().keyWindow?.rootViewController
    
    if let customViewController = rootViewController as? CustomViewController {
    
        customViewController.label.text = theData
    }
    else{ 
        let customViewController = storyoboard!.instantiateViewControllerWithIdentifier("CustomViewControllerID")
        // (This assumes CustomViewController is defined in the same 
        // storyboard as the view controller running this code. Otherwise, 
        // you need to get a reference to the storyboard first).
    
        rootViewController.presentViewController(customViewController, animated:true)
    
        customViewController.label.text = theData
    }
    

    编辑:如果接收您的异步服务器数据的对象与您的导航分离(顺便说一句,这很好),您可以拥有它:

    1. 将数据存储在某个位置,即使所述对象已被释放 (或使所述对象成为单例,如果适用)。

    2. 一旦数据可用,发布系统通知(使用NSNotificationCenter),并让您的主要ViewController“收听”(-addObserver:selector:name:object)。当通知发布并调用通知处理程序时,您的视图控制器可以从其(持久)位置(文件或上面提到的单例的属性,如果您选择该路由)检索数据。

    3. 最后,对于在 ViewController 实例化时数据已经可用的情况,请检查数据可用性并检索它(如果存在),例如你的主视图控制器的viewDidLoad()

    【讨论】:

    • 尽管这种方法有效,但它是一个缓慢(而且看起来仍然很脏)的解决方案。这就是为什么我试图避免通过 UIApplication。还是没有我想的那么慢?我每秒收到大约 100-150 个 udp 数据包来处理和更新带有一些图表、图形和文本对象的显示。
    • 我再说一遍:我不知道您的应用程序的整体结构:当您收到数据时调用的代码,它驻留在哪里?在视图控制器内部?在模型对象或单例中?
    • 我的意思是,当数据从服务器到达时,您在应用导航的哪个位置?你需要设计那个。使用异步操作,您不知道操作完成时当前视图控制器将是什么。视图控制器通常作为导航中用户输入的结果进行实例化。
    • 它只是在一个独立于主 ViewController 的类中,并且将位于与主 ViewController.swift 不同的文件中(将来)。我只是认为必须有一个全局变量,它是我可以简单引用的主 VC 的一个实例。但我想我错了。
    【解决方案2】:

    有很多方法可以实现这一点,

    1.使用协议或委托

    您说“我有一个类是 GCDAsyncUdpSocketDelegate。”在该类中编写协议实现并让您的视图控制器订阅该委托,当您为您的 GCDAsyncUdpSocketDelegate 获取委托回调时,请执行必要的检查并将您的自定义委托触发到视图控制器,将数据作为参数传递给委托方法。在视图控制器中获取数据并更新 IBOutlet。

    2。使用 NSNotificationCenter(肮脏的做事方式,但要小心)

    在你的视图控制器类中为你要发布的通知添加一个观察者,

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateUI:", name: "didRecieveDataFromUDP", object: nil)
    

    在你的 VC 中添加一个方法

     func updateUI(notifObject:NSNotification){
      let responseString = notifObject.object
      self.yourOutlet.string = responseString
    }
    

    当你用完 VC 后也移除通知观察者。 在 GCDAsyncUdpSocketDelegate 委托类中,当您收到带有结果的回调时会触发此通知,

      NSNotificationCenter.defaultCenter().postNotificationName("didRecieveDataFromUDP"", object: theResposenObjectYouNeedToSend)
    

    3.使用 sharedInstances 或滥用 AppDelegate(不推荐)

    创建将贯穿应用生命周期的共享实例或单例类,并使用它们存储/检索来自任何类或任何线程的数据。

    希望这会有所帮助,我希望您选择第一种或第二种方式。

    【讨论】:

    • 你认为第一种方法是最快的吗?
    • 当然很快,就像普通的iOS基础课一样。
    猜你喜欢
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多