如何按需在UIViewController上重新加载视图?

时间:2019-04-12 19:01:05

标签: ios swift

我有一个带有一些标签的UIViewController和一个UICollectionView。 UICollectionView表示从xib加载的自制日历。当我点击一个集合视图单元格(例如,选择日历中的一天)时,我会相应地更改基础模型,并且需要更新标签。但是,点击时没有任何更新。

我有一个更新标签并在viewDidLoad()中调用它的方法。第一次加载后,所有标签都变为nil,将标签声明为'var'而不是'weak var'并没有帮助。当在viewController的self.view上调用一些诸如layoutSubviews()的函数时,标签似乎存在,viewDidLoad()(和updateLabels())被调用,但是屏幕上没有任何变化。 我尝试使用xib创建一个带有标签的UIView(子类),并以编程方式将这些标签直接放置在viewController中,将所有代码放在一个位置-结果相同。 setNeedsDisplay(),生命周期方法,删除-添加到superview-这些都不适合我。我是在做错什么还是错过了重要的事情?

    class ChallengeViewController: UIViewController {

        var challenge = Challenge(title: Challenge.sampleTitle, startDate: Challenge.sampleStartDate, durationInDays: 40, checkIns: [Bool](repeating: true, count: 40), cheatDaysPlanned: 2, isActive: true, roundNumber: 1, pointsScored: 0)

    @IBOutlet weak var titleLabel: UILabel!

    @IBOutlet weak var calendarView: CalendarView!

    @IBOutlet weak var statisticsView: ChallengeStatisticsView!
    //contains labels that should be updated

    override func viewDidLoad() {
            super.viewDidLoad()
            calendarView.challenge = challenge
            calendarView.updateMonthAndYearLabels(for: challenge)
            statisticsView.updateLabels()
            titleLabel.text = challenge.title
        }
}

class CalendarView: UIView {

var challenge: Challenge? 

//other code here

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "calendarCell", for: indexPath) as! CalendarCollectionViewCell

            collectionView.performBatchUpdates({
                if let challenge = challenge {
                cell.update(challenge: challenge)
                    let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ChallengeScreenViewController") as! ChallengeViewController
                    viewController.view.layoutSubviews()
                    viewController.challenge = challenge
                    viewController.updateLabels()
    collectionView.reloadItems(at: [indexPath])
            }
        }, completion: nil)
    }
}

4 个答案:

答案 0 :(得分:1)

您正在cell.update中创建一个全新的视图控制器,并且它永远不会出现在屏幕上,这就是为什么您看不到任何更新的原因。不知道您的update方法实际上是做什么的,但是似乎只需调用self.updateLabels()self.statisticsView.updateLabels()就可以解决问题。由于您似乎同时拥有两者,因此不确定。

答案 1 :(得分:0)

为什么要重新加载VC?

当您单击collectionViewCell时,创建一个委托协议来告诉VC用数据模型重新加载标签。

答案 2 :(得分:0)

  1. 使用cellForItem(at:)方法获取选定的单元格
  2. 要在当前视图控制器中更新视图,只需调用update方法。不要创建新的视图控制器。
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as! CalendarCollectionViewCell

    if let challenge = challenge {
        cell.update(challenge: challenge)
        collectionView.reloadItems(at: [indexPath])
        self.updateLabels()
    }
}

答案 3 :(得分:0)

我不知道UIStoryboard(name:, bundle:).instantiateViewController(withIdentifier:)创建了一个全新的vc,这是主要的错误。 因此,我决定使用Notification Center来使控制器响应模型的更改。 现在一切正常。

 class CalendarView: UIView {

    var challenge: Challenge? 

    //other code here

        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "calendarCell", for: indexPath) as! CalendarCollectionViewCell

                collectionView.performBatchUpdates({
                    if let challenge = challenge {
                    cell.update(challenge: challenge)

    // assigning a new value to calendarView's own variable, posting the notification
                         self.challenge = challenge
                    let name = Notification.Name("CellTapped")
                    NotificationCenter.default.post(name: name, object: nil)

        collectionView.reloadItems(at: [indexPath])
                }
            }, completion: nil)
        }
    }

class ChallengeViewController: UIViewController {

            var challenge = Challenge(title: Challenge.sampleTitle, startDate: Challenge.sampleStartDate, durationInDays: 40, checkIns: [Bool](repeating: true, count: 40), cheatDaysPlanned: 2, isActive: true, roundNumber: 1, pointsScored: 0)

        @IBOutlet weak var titleLabel: UILabel!

        @IBOutlet weak var calendarView: CalendarView!

        @IBOutlet weak var statisticsView: ChallengeStatisticsView!

// taking the changed variable from calendarView when the notification is posted
     @objc func updateAfterTap() {
        if let calendarViewChallenge = calendarView.challenge {
        self.challenge = calendarViewChallenge
        statisticsView.updateLabels()
        }
    }
        override func viewDidLoad() {
                super.viewDidLoad()
                calendarView.challenge = challenge
                calendarView.updateMonthAndYearLabels(for: challenge)
                statisticsView.updateLabels()
                titleLabel.text = challenge.title
NotificationCenter.default.addObserver(self, selector: #selector(self.updateAfterTap), name: Notification.Name("CellTapped"), object: nil)
            }
    }