首页 > 解决方案 > 创建自定义 UIView 或子 VC

问题描述

所以,我有以下情况。我有一个自定义选项卡布局,即带有分页的水平 UIScollview。在每个页面中都有一些控件和一个 UITablevie,“捆绑”在一个自定义 UIView 中。

我创建了一个具有滚动视图的 ContainerVC,然后我初始化了两个 UIView 并将它们作为子视图添加到 ContainerVC 中。为此,我创建了一个自定义 UIView 类并将此 UIView 设置为 .xib 文件的所有者。我还将 .xib 类添加为我的自定义 UIView。

尽管这可行,但至少在 UI 方面,我有一些功能问题,如下所示。在每个 UIView 的 init 方法中,我使用

Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)

然后将 UITableViewDelegate 和 UITableViewDateSource 设置为 self.

但是,当提供表格的数据到达视图时,我重新加载 tableview,没有任何反应(重新加载方法在主线程中运行),直到我滚动 UITableview。

这是正确的做法吗?

风险投资

 func createUsageHistoryTabs() -> [Consumption] {
    var tabs = [Consumption]()

    let v1 = Consumption(pageIndex: 0, viewModel: viewModel)
    let v2 = Consumption(pageIndex: 1, viewModel: viewModel)

    tabs.append(v1)
    tabs.append(v2)
    return tabs
}

func setupScrollView() {

    if(!hasBeenCreated) {
        let tabs = createUsageHistoryTabs()
        scrollview.frame = CGRect(x: 0, y: 0, width: container.frame.width, height: container.frame.height)
        scrollview.contentSize = CGSize(width: view.frame.width * CGFloat(tabs.count), height: 1.0)
        scrollview.isPagingEnabled = true

        for i in 0 ..< tabs.count {
            let slideView = tabs[i]
            slideView.frame = CGRect(x: view.frame.width * CGFloat(i), y: scrollview.frame.origin.y, width: scrollview.frame.width, height: scrollview.frame.height)
            scrollview.addSubview(slideView)
        }

        hasBeenCreated.toggle()
    }


}

界面视图:

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

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

convenience init(pageIndex: Int, viewModel: UsageHistoryViewModel) {
    self.init(frame: CGRect.zero)
    self.pageIndex = pageIndex
    self.viewModel = viewModel

    commonInit()
}

func commonInit() {
    Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
    contentView.fixInView(self)
    setupView()

    footer.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleFooterTap)))

    viewModel?.cdrDelegate = self

    tableView.register(EmptyCell.self, forCellReuseIdentifier: "EmptyCell")
    tableView.register(UINib(nibName: "TVCell", bundle: nil), forCellReuseIdentifier: "TVCell")

    tableView.allowsSelection = false
    tableView.delegate = self
    tableView.dataSource = self


}

标签: iosuitableviewuiviewuiviewcontrollerxib

解决方案


在这个函数中:

func setupScrollView() {

    if(!hasBeenCreated) {

        // this line creates a LOCAL array
        let tabs = createUsageHistoryTabs()

        scrollview.frame = CGRect(x: 0, y: 0, width: container.frame.width, height: container.frame.height)
        scrollview.contentSize = CGSize(width: view.frame.width * CGFloat(tabs.count), height: 1.0)
        scrollview.isPagingEnabled = true

        for i in 0 ..< tabs.count {
            let slideView = tabs[i]
            slideView.frame = CGRect(x: view.frame.width * CGFloat(i), y: scrollview.frame.origin.y, width: scrollview.frame.width, height: scrollview.frame.height)
            scrollview.addSubview(slideView)
        }

        hasBeenCreated.toggle()
    }


}

您正在创建一个本地对象数组Consumption。从每个对象,您将其视图添加到您的滚动视图。一旦该函数退出,tabs就不再存在......它“超出范围”。

你想创建一个类级变量:

var tabsArray: [Consumption]?

然后修改该 var 而不是创建本地实例:

func setupScrollView() {

    if(!hasBeenCreated) {

        // this line creates a LOCAL array
        tabsArray = createUsageHistoryTabs()

        ...

然后,您的自定义类应该可用,直到您删除它们(或tabsArray超出范围)。

您可能需要进行一些其他更改,但这至少应该是一个开始。


评论讨论后编辑...

如果表格视图正在工作,但在滚动之前没有“更新” - 你说正在主线程上调用重新加载 - 你可以尝试这些选项中的任何一个(或两者都......实验):

    tableView.reloadData()
    tableView.setNeedsLayout()
    tableView.layoutIfNeeded()

    tableView.reloadData()
    tableView.beginUpdates()
    tableView.endUpdates()

推荐阅读