如何在 swift 中使用自定义视图?

Posted

技术标签:

【中文标题】如何在 swift 中使用自定义视图?【英文标题】:How to use custom view with in swift? 【发布时间】:2019-01-14 11:22:54 【问题描述】:

我想在 TableViewHeader 中添加自定义视图。但是当我运行以下代码时,它会创建一个循环,并且应用程序会卡住任何用户交互。

import UIKit
class ExpandableView: UIView 

    @IBOutlet weak var userImgView: UIImageView!
    @IBOutlet weak var userNamelbl: UILabel!
    @IBOutlet weak var countLbl: UILabel!
    @IBOutlet weak var rightArrowImgView: UIImageView!
    var isExpanded = false
    var contentView: UIView!
    @IBOutlet weak var checkMarkView: UIImageView!

    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) 
        // Drawing code
    
    public override init(frame: CGRect) 
        super.init(frame: frame)
        setUpView()
    

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

    private func setUpView() 
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: "ExpandableView", bundle: bundle)
        self.contentView = nib.instantiate(withOwner: self, options: nil).first as? UIView
        addSubview(contentView)
        contentView.center = self.center
        contentView.autoresizingMask = []
        contentView.translatesAutoresizingMaskIntoConstraints = true
    

我是这样使用的:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? 
    let frame = CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 60)
    let expandabelView = ExpandableView(frame: frame)
    return expandabelView

它在运行时显示以下错误。

【问题讨论】:

仍然无法解决同样的问题 init(coder:) 将调用setupView() 调用UINib(nibName:bundle:) 所以它会再次调用init(coder:)。那么为什么在initWithCoder 中调用UINib(nibName:bundle:) 【参考方案1】:

可能还有很多其他方法,但我建议您让您的ExpandableView 可重复使用以提高性能。


首先,简化您的ExpandableView 类:

import UIKit

class ExpandableView: UITableViewHeaderFooterView 
    @IBOutlet weak var userImgView: UIImageView!
    @IBOutlet weak var userNamelbl: UILabel!
    @IBOutlet weak var countLbl: UILabel!
    @IBOutlet weak var rightArrowImgView: UIImageView!
    var isExpanded = false

    @IBOutlet weak var checkMarkView: UIImageView!

请不要错过超类是UITableViewHeaderFooterView,而不是UIView

第二,检查你的ExpandableView.xib的设置:

定义视图的自定义视图设置需要为ExpandableView

当您无法从下拉列表中选择ExpandableView时,您可能需要手动输入。不要忘记检查从目标继承模块

文件所有者的自定义视图设置需要为空。

如果已经设置了一些类,请手动删除它。

确认所有插座已正确连接到您的ExpandableView

(最好在修改 xib 后重新连接它们。)

您可能需要重新构建视图层次结构和/或约束

第三,修改你的视图控制器持有表格视图。

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        tableView.delegate = self
        tableView.dataSource = self
        //...
        let nib = UINib(nibName: "ExpandableView", bundle: nil)
        tableView.register(nib, forHeaderFooterViewReuseIdentifier: "ExpandableView")
        tableView.estimatedSectionHeaderHeight = 60
        tableView.sectionHeaderHeight = UITableView.automaticDimension
    

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? 
        let expandabelView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "ExpandableView")
        // Frame size should be represented with constraints.
        return expandabelView
    

【讨论】:

很好的解释。谢谢。【参考方案2】:

当您创建自定义UIView 时,如果您想将其与框架一起使用,则应遵循此规则。

class CustomView: UIView 
    //This should be contentview of your xib
    @IBOutlet var view: UIView!

    let nibName = "CustomView"

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

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

    private func xibSetup()
    
        Bundle.main.loadNibNamed(nibName, owner: self, options: nil)
        self.view.autoresizesSubviews = true
        self.translatesAutoresizingMaskIntoConstraints = false

        self.addSubview(self.view)
        self.view.frame = self.frame


    


【讨论】:

【参考方案3】:

由于您需要从 nib 加载视图,只需加载它,然后将子视图添加到您的视图。然后设置内容视图的frame 并正确设置内容视图的自动调整掩码

private func setUpView() 
    Bundle.main.loadNibNamed("ExpandableView", owner: self, options: nil)
    addSubview(contentView)
    contentView.frame = bounds
    contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

【讨论】:

以上是关于如何在 swift 中使用自定义视图?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 中使用自定义导航栏制作三个分页视图

在 Swift 的警报中使用自定义视图

iOS 自定义 .xib 视图按钮点击检测在视图控制器 (Swift)

如何在多个视图控制器中使用自定义工具栏而不重复代码和复制元素(swift)?

在 swift 中使用自定义视图创建 menulet osx 应用程序

如何在 Swift 3 中加载/删除带有动画的自定义视图