如何使用 xib 创建单例 UIView 以在不同的 VC 上使用一个实例?

Posted

技术标签:

【中文标题】如何使用 xib 创建单例 UIView 以在不同的 VC 上使用一个实例?【英文标题】:How to create singleton UIView with xib for using one instance on different VCs? 【发布时间】:2018-04-18 15:19:34 【问题描述】:

我有一个自定义 UIView 子类,它有 xib。我需要在我的 App 中的不同 ViewController 上使用一个实例。

我的自定义视图初始化如下:

@IBOutlet var contentView: UIView!

override init(frame: CGRect) 
    super.init(frame: frame)
    commitInit()


required init?(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)
    commitInit()


private func commitInit() 

    contentView = loadFromNib(named: "ChartWithPoints")// Extension for UIView class, loading by name
    contentView.frame = self.bounds
    contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
    addSubview(contentView)

单例如何修改这段代码,修改后如何使用这个类?

感谢所有回答。

【问题讨论】:

【参考方案1】:

我不认为你想要一个单例,你也需要为每个视图控制器使用一个实例。管理一个视图的所有权是完全没有必要的。一个类的全部意义在于拥有多个对象。你不需要有一个单身人士。

对于每个视图控制器,继续做你现在正在做的事情,并为每个控制器实例化一个新的自定义视图。

要回答有关使用子类的问题,请将视图属性更改为子类而不是 UIView

@IBOutlet var contentView: SubclassView!

要详细了解单例解决的问题,请查看上面的 Wikipedia article。


编辑

既然您询问了模型-视图关系是什么样的,我将尝试给出一个基本示例。

说,在您看来,您想显示用户的姓名和爱好。单例模型类看起来像这样:

class UserData 
    static let singletonUserData = UserData()

    var name: String
    var hobbies: [String]

    private init() 
        self.name = "Bob Appleseed"
        self.hobbies = ["Swimming", "Planting Apples", "Drawing"]
    

然后您将能够通过以下方式访问单例:

UserData.singletonUserData

在你的视图类中,你可能有一些标签:

@IBOutlet var nameLabel: UILabel!
@IBOutlet var favoriteHobbyLabel: UILabel!

然后,在初始化之后,您可以使用单例填充标签:

contentView.nameLabel.text = UserData.singletonUserData.name
contentView.favoriteHobbyLabel.text = UserData.singletonUserData.hobbies.first!

如果你想修改单例的属性,你可以从任何地方改变它们:

UserData.singletonUserData.name = "John Appleseed"

【讨论】:

我不需要每个 ViewController 的个人实例。我想创建一次实例,如果用户更改了该视图上的任何信息,其他 ViewControllers 上的视图也会更改 @GolovanovDmitrii 不要使用单例视图。使用模型对象并让视图引用该对象。当您对该对象进行更改时,您可以更新每个视图。 “一个类的全部意义在于拥有多个对象”。那为什么单身人士会存在呢?如果只需要一个实例,则不需要从一个类中拥有多个对象 @tktsubota,这听起来像是 OOP 的好模式。如果您将添加一些带有图像和代码的示例,我将不胜感激! @J.Doe 类的基本原理是拥有多个对象并让它们符合相同的“模板”。单例满足了持久的、通用的状态的必要性,如果它们不存在,OOP 将缺乏这种状态,但它们不是大多数问题的答案(参见依赖注入),包括这个。【参考方案2】:
import  UIKit
import Foundation

class CustomView : UIView
   
    @IBOutlet weak var titleLabel : UILabel!

    // Singleton instance
    static let shared : CustomView = CustomView.sharedInstanceFromNib(size: CGSize(width: 100, height: 100))

    // You can modify argument list as per your need.
    class private func sharedInstanceFromNib(size : CGSize)->(CustomView)
    
        // This will connect your IBOutlet's with view's in Xib.
        let view = Bundle.main.loadNibNamed("CustomView", owner: self, options: nil)?.first as! CustomView
        view.frame.size = size
        return view
    

注意 - 第一次使用共享实例时,必须在主线程上使用,否则 Xcode 的控制台会显示一些警告消息。

【讨论】:

以上是关于如何使用 xib 创建单例 UIView 以在不同的 VC 上使用一个实例?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用不同的 init 方法在 XIB 中创建自定义视图?

iOS:从 UIView 创建 XIB

我可以使用 UIView(.xib 和类)作为许多视图的视图基础示例吗?

多次使用 UIView(使用 xib 创建)作为同一视图的子视图

在 xib 和代码之间具有不同高度的 UIView

如何转换 UIView 坐标以在 drawRect 中使用?