从另一个类访问 IBOutlet

Posted

技术标签:

【中文标题】从另一个类访问 IBOutlet【英文标题】:Accessing an IBOutlet from another class 【发布时间】:2014-07-24 14:22:30 【问题描述】:

我是 Swift/ios 新手,请多多包涵:

我正在尝试从另一个类访问一个类中的函数,并更新 UIImage 名称。

在我的视图控制器类中,我有

class Documents: UIViewController, UITableViewDataSource, UITableViewDelegate 

    @IBOutlet var UpdateImage: UIImageView

    override func viewDidLoad() 
        super.viewDidLoad()
        UpdateImage()
    

    func UpdateImage() 
        UpdateImage.image = UIImage(named: "NewImage")
    

一切正常,图片更新为“NewImage”

问题:我可以从另一个类访问 UpdateImage func,但为什么在尝试更改 Documents 类中的图像时会产生错误?

class GetChanges 

    var success =  operation:AFHTTPRequestOperation!, response:AnyObject!) -> Void in

        var MakeChange = Documents()
        MakeChange.UpdateImage()

    

这会在 Documents 类中的 "UpdateImage.image = UIImage(named: "NewImage")" 上生成错误; “致命错误:在展开可选值时意外发现 nil”

【问题讨论】:

【参考方案1】:

当您在类本身中调用它时,它会在自身上运行,并且已经从 nib/storyboard 创建。这意味着UpdateImage 存在。

当你从另一个类调用方法时,当你调用这一行时:

var MakeChange = Documents()

您正在创建Documents 的新实例。这不是通过 nib/storyboard 初始化的,因此它从未填充 IBOutletUpdateImage。因为这个值不存在,所以意外找到nil并抛出错误。

您需要以某种方式保留对您尝试显示的Documents 实例的引用。我需要更多信息来告诉你如何做到这一点。

另外,因为您提到您是新人,所以我想指出一些我注意到您的代码的问题,这些问题使得阅读变得非常困难。

    大写名称保留给Types 变量名称不应(几乎)以大写字母开头。

    变量名称应该反映它们所代表的对象。 UpdateImage 听起来像是一张图片。最好把这个命名为updateImageView

    函数也应该是小写的。以这种方式看到大写很奇怪,并且使代码读起来有点不舒服。

祝你好运!

【讨论】:

感谢 cmets re:我的代码的可读性,我来自另一种语言,所以我会继续观察这些问题......但这并不能真正解决我遇到的问题. @MrSparkle2014 我想了很多,但是我的 cmets 对维护对 Documents 特定实例的引用有帮助吗? 不,很遗憾它对我没有帮助。 @MrSparkle2014 - 没有理由时髦,我只是想帮忙。我特别告诉过你,如果你需要帮助来解决你的问题,我需要更多信息。没有人可以用给定的信息回答你的问题,因为你不理解这个概念。如果您需要帮助,请按照我提供的详细说明。没有其他人回答这个问题是有原因的,这与我的回答无关。【参考方案2】:

了解 View Contoller 的生命周期,这对 iOS 开发者来说是非常重要的知识。

正如洛根所说:

您正在创建 Documents 的新实例。这不是通过 nib/storyboard 初始化的,因此它从未填充 IBOutlet 值 UpdateImage

这意味着在调用 init for ViewController(即Documents()nib 后未加载。只有在 viewDidLoad 阶段之后,您才能在另一个代码中使用 viewController 的出口。 Apple docs:

您指定的 nib 文件不会立即加载。它在第一次访问视图控制器的视图时加载。如果您想在加载 nib 文件后执行其他初始化,请覆盖 viewDidLoad() 方法并在那里执行您的任务。

您可以删除MakeChange.UpdateImage(),因为它将在viewDidLoad 中调用。或者,如果您想将特定图像名称传递给视图控制器:

class Documents: UIViewController, UITableViewDataSource, 

    UITableViewDelegate 

        @IBOutlet var UpdateImage: UIImageView
        var imageName: String?

        override func viewDidLoad() 
            super.viewDidLoad()
            updateImageView()
        

        func updateImageView() 
            if let imageName = imageName 
                UpdateImage.image = UIImage(named: imageName)
            
        
    

之后就可以使用了

let documentsViewController = Documents
documentsViewController.imageName = "newImage"

当你加载documentsViewController时,会出现newImage

【讨论】:

以上是关于从另一个类访问 IBOutlet的主要内容,如果未能解决你的问题,请参考以下文章

从另一个类访问 UI 图像

从另一个类 c++ 访问 UI 元素

UIImageView 范围。从另一个类访问

从另一个类访问 viewController 元素

从另一个类访问 MainWindow 类成员

从另一个类访问 UISegmentedControl @IBOoutlet