2017-01-10 11 views
0

サブタイトルUICollectionViewLayoutは、カレンダーを作成するために使用します。私は、ユーザーに画面上に表示される日数(デフォルトでは7)のようないくつかの設定を変更する機能を提供したいと考えています。 enter image description hereUICollectionViewLayout - invalidateLayout()は、画面の回転後にのみ動作します。

UserDefaultsに保存すると、daysToShowに保存されます。 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) 
     } 
    } 

答えて

0

私は解決策を見つけた:私は今呼び出しています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は言う:

あなたが直接このメソッドを呼び出すべきではありません。 レイアウトの更新を強制する場合は、 の次の図面更新に先立ってsetNeedsLayout()メソッドを呼び出してください。すぐに ビューのレイアウトを更新する場合は、layoutIfNeeded()メソッドを呼び出します。 (?!?)

は私がコールする権利方法であると思われたsetNeedsLayout()しようとしたが、それは働いていなかったので、私はsetNeedsLayoutを()を使用:

コールアプリケーションのメインスレッド上でこの方法あなたが の場合、ビューのサブビューのレイアウトを調整します。このメソッドは、要求を のメモを作成し、すぐに戻ります。この方法では が即時更新を強制するのではなく、次回の更新を サイクルだけ待つ代わりに、それらのビューのいずれかが更新される前に複数のビュー のレイアウトを無効にすることができます。この動作により、 はすべてのレイアウトの更新を1つの更新サイクルに統合することができます。これは通常、パフォーマンスの点では です。

関連する問題