这是我应该创建课程的时候吗?

Posted

技术标签:

【中文标题】这是我应该创建课程的时候吗?【英文标题】:Is this when I should be creating a class? 【发布时间】:2018-05-28 11:57:11 【问题描述】:

我正在努力掌握 Swift 并希望得到一些建议......

我有一个存在于多个屏幕上的 UIView;具体来说,它是一个使用许多元素/参数来正确设置样式的徽标,即阴影、形状、图像等。

对于我的第一个视图控制器,我将其设置为从 viewDidLoad 函数调用的函数。然后在我的第二个视图控制器中,我有相同的徽标......这是我的问题,

我应该从情节提要加载第一个视图控制器,然后在第二个视图控制器中引用该函数,还是应该将徽标设置为任何一个视图控制器都可以引用的类?我的直觉说它应该是一个类......

提前致谢

【问题讨论】:

您也可以将函数移动到单例类并让该函数返回 UIView。现在,当您需要该视图时,只需调用该函数并获取视图,现在就可以对视图执行任何操作。 关键词是“我有一个UIView,它存在于一个数字上......” 虽然有许多设计模式,但几乎在任何一个- 特别是 MVC - 你想分离这个视图和它的控制器。现在唯一要问的问题是您如何创建视图 - 通过 IB 还是在代码中?如果是 IB,请考虑使用 NIB 文件。如果是代码,那就恭维 - 子类UIView 【参考方案1】:

对于可重用视图,您将创建一个用于设计视图的 XIB 以及一个用于实例化 xib 的视图控制器类,如下所示:

class ReusableView: UIView 
    override func awakeFromNib() 
        super.awakeFromNib()

        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: "ReusableView", bundle: bundle)

        if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView 
            view.frame = bounds
            addSubview(view)
        
    

在您的视图控制器中,您只需将占位符 UIView 放置在所需位置并将其自定义类型设置为 ReusableView。通过将此视图的出口连接到您的视图控制器,您将可以访问视图的属性。

请注意,您必须将 XIB 中的自定义视图属性设置为 UIView,并将文件的所有者设置为 ReusableView。否则你会创建一个无限循环。

【讨论】:

如果从 nib 实例化的视图也是ReusableView,这不就开始了无限循环吗? @Harry Robinson:不。实例化视图是ReusableViewinstance——您可以拥有任意数量的类实例。 但是 awakeFromNib 在从 nib 加载视图后调用。当从 nib 加载第一个视图时,然后从 nib 加载另一个视图。我看不出这怎么不会产生递归。 我刚刚创建了一个示例项目来测试它,它确实创建了一个无限循环。 @ABeard89:正确,这令人困惑......我已经更新了我的答案。感谢您指出。【参考方案2】:

警告!正如我在另一个答案中指出的那样,请勿awakeFromNib 中加载相同的笔尖,否则您将创建一个无限循环的加载笔尖。

我会说,你的直觉是正确的。为您的可重用视图创建一个自定义类。如果您决定为您的类创建一个 nib,我建议从静态函数实例化它。

class ReusableView: UIView 
    static func newFromNib() -> ReusableView 
        let bundle = Bundle(for: ReusableView.self)
        let nib = UINib(nibName: "ReusableView", bundle: bundle)
        guard let view = nib.instantiate(withOwner: self, options: nil).first as? ReusableView else 
            preconditionFailure("Could not instantiate ReusableView")
        
        return view
    
    override func awakeFromNib() 
        super.awakeFromNib()

        // Configuration ONLY if you use a Nib.
    

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

        // Configuration if you DO NOT use a nib
    

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

然后,您可以在视图控制器中使用它:

class ViewController: UIViewController 
    @IBOutlet weak var reusableViewContainer: UIView!

    override func viewDidLoad() 
        super.viewDidLoad()

        // Create a new instance of your reusable view
        let reusableView = ReusableView.newFromNib()

        // If not using a nib, just use the 'init(frame:)' method
//        let reusableView = ReusableView(frame: .zero)

        // Add your reusable view to the view hierarchy
        self.reusableViewContainer.addSubview(reusableView)

        // Layout your view as necessary:
        // For example, if using AutoLayout:
        self.reusableViewContainer.topAnchor.constraint(equalTo: reusableView.topAnchor).isActive = true
        self.reusableViewContainer.bottomAnchor.constraint(equalTo: reusableView.bottomAnchor).isActive = true
        self.reusableViewContainer.leadingAnchor.constraint(equalTo: reusableView.leadingAnchor).isActive = true
        self.reusableViewContainer.trailingAnchor.constraint(equalTo: reusableView.trailingAnchor).isActive = true
    

当然,您不必使用容器视图。将其放置在视图层次结构中您需要的任何位置,并像对其他视图一样进行布局。

【讨论】:

以上是关于这是我应该创建课程的时候吗?的主要内容,如果未能解决你的问题,请参考以下文章

Singleton在这种情况下是否合适?

新站点创建和安全/身份验证,- 我应该使用 ASP.net Membership Provider 吗?

Java - 如何只创建具有有效属性的对象?

我应该创建使用数据库图表所需的支持对象吗?

我应该啥时候创建 php 文件来在 mysql 数据库中创建表?

我应该将池或进程与队列一起使用吗?