gpt4 book ai didi

ios - UICollectionViewLayout - invalidateLayout() 仅在屏幕旋转后有效

转载 作者:行者123 更新时间:2023-11-30 12:46:31 26 4
gpt4 key购买 nike

我对 UICollectionViewLayout 进行了子类化以创建日历。我想让用户能够更改一些设置,例如屏幕上显示的天数(默认为 7)。 enter image description here

我将daysToShow保存在UserDefaults中。每当 UIStepper 值发生更改时,它都会调用此方法:

func stepperValueChanged(sender:UIStepper){
stepperValue = String(Int(sender.value))
valueLabel.text = String(Int(sender.value))
UserDefaults.standard.set(String(Int(sender.value)), forKey: "daysToShow")
NotificationCenter.default.post(name: Notification.Name(rawValue: "calendarSettingsChanged"), object: nil, userInfo: nil)
}

因此,在将新值保存到 UserDefault 中后,我发布一条通知,然后调用 reloadForSettingsChange (实际上,当我在此处设置断点时会调用该通知):

override func viewDidLoad() {
super.viewDidLoad()

NotificationCenter.default.addObserver(self, selector: #selector(reloadForSettingsChange(notification:)), name: NSNotification.Name(rawValue: "calendarSettingsChanged"), object: nil)

// other code.....
}

func reloadForSettingsChange(notification:NSNotification){
// here I save the user setting in a variable declared in my custom UICollectionViewLayout
self.calendarView.daysToShow = Int(UserDefaults.standard.string(forKey: "daysToShow")!)
self.calendarView.daysToShowOnScreen = Int(UserDefaults.standard.string(forKey: "daysToShow")!)
self.calendarView.forceReload(reloadEvent: true)

}

func forceReload(reloadEvent:Bool){
DispatchQueue.main.async {
if reloadEvent{
self.groupEventsByDays()
self.weekFlowLayout?.invalidateCacheLayout()
self.collectionView.reloadData()
}
}
}
func invalidateCacheLayout(){

self.needsToPopulateAttributesForAllSections = true
self.cachedDayDateComponents?.removeAllObjects()
self.cachedStartTimeDateComponents?.removeAllObjects()
self.cachedEndTimeDateComponents?.removeAllObjects()
self.cachedCurrentDateComponents?.removeAllObjects()
self.cachedEarliestHour = Int.max
self.cachedLatestHour = Int.min
self.cachedMaxColumnHeight = CGFloat.leastNormalMagnitude
self.cachedColumnHeights?.removeAllObjects()
self.cachedEarliestHours?.removeAllObjects()
self.cachedLatestHours?.removeAllObjects()
self.itemAttributes?.removeAllObjects()
self.allAttributes?.removeAllObjects()
_layoutAttributes.removeAll()
self.invalidateLayout()
}

问题是,在我旋转屏幕设备(即从横向到纵向)之前,布局不会更新(无效?)。我用于旋转的函数调用的方法与我在 reloadForSettingsChange 中调用的方法完全相同,因此我不明白为什么它在旋转屏幕时起作用,而不是在旋转屏幕之前起作用:

 func rotated() {
switch UIDevice.current.orientation {
case .landscapeLeft, .landscapeRight:
calendarView.forceReload(reloadEvent: true)
default:
calendarView.forceReload(reloadEvent: true)
}
}

最佳答案

我找到了解决方案:我现在正在调用 setNeedsLayout():

func reloadForSettingsChange(notification:NSNotification){
self.calendarView.daysToShow = Int(UserDefaults.standard.string(forKey: "daysToShow")!)
self.calendarView.daysToShowOnScreen = Int(UserDefaults.standard.string(forKey: "daysToShow")!)
self.calendarView.forceReload(reloadEvent: true)
self.calendarView.setNeedsLayout() // this line has been added
}

我最初使用了 layoutSubviews() ,它有效,但是 Apple Documentation说:

You should not call this method directly. If you want to force a layout update, call the setNeedsLayout() method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded() method.

我尝试了 setNeedsLayout() 这似乎是调用的正确方法(?!?),但由于它不起作用,我使用了 setNeedsLayout():

Call this method on your application’s main thread when you want to adjust the layout of a view’s subviews. This method makes a note of the request and returns immediately. Because this method does not force an immediate update, but instead waits for the next update cycle, you can use it to invalidate the layout of multiple views before any of those views are updated. This behavior allows you to consolidate all of your layout updates to one update cycle, which is usually better for performance.

关于ios - UICollectionViewLayout - invalidateLayout() 仅在屏幕旋转后有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41575304/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com