@@ -262,6 +262,37 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
262262
263263 }
264264 }
265+
266+ // MARK: - Reload Rows
267+
268+ /// Perform a reload method by updating any constraint of the stack view's row.
269+ /// If row's managed controller implements `ScrollStackContainableController` it also call
270+ /// the reload event.
271+ ///
272+ /// - Parameter index: index of the row to reload.
273+ /// - Parameter animated: `true` to animate reload (any constraint change).
274+ /// - Parameter completion: optional completion callback to call.
275+ open func reloadRow( index: Int , animated: Bool = false , completion: ( ( ) -> Void ) ? = nil ) {
276+ reloadRows ( indexes: [ index] , animated: animated, completion: completion)
277+ }
278+
279+ /// Perform a reload method on multiple rows.
280+ ///
281+ /// - Parameter indexes: indexes of the rows to reload.
282+ /// - Parameter animated: `true` to animate reload (any constraint change).
283+ /// - Parameter completion: optional completion callback to call.
284+ open func reloadRows( indexes: [ Int ] , animated: Bool = false , completion: ( ( ) -> Void ) ? = nil ) {
285+ let selectedRows = safeRowsAtIndexes ( indexes)
286+ reloadRows ( selectedRows, animated: animated, completion: completion)
287+ }
288+
289+ /// Reload all rows of the stack view.
290+ ///
291+ /// - Parameter animated: `true` to animate reload (any constraint change).
292+ /// - Parameter completion: optional completion callback to call.
293+ open func reloadAllRows( animated: Bool = false , completion: ( ( ) -> Void ) ? = nil ) {
294+ reloadRows ( rows, animated: animated, completion: completion)
295+ }
265296
266297 // MARK: - Remove Rows
267298
@@ -318,12 +349,12 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
318349
319350 stackView. setNeedsLayout ( )
320351
321- UIView . animate ( {
352+ UIView . execute ( {
322353 sourceRow. isHidden = true
323354 } ) {
324355 let newRow = self . createRowForController ( controller, insertAt: sourceIndex, animated: false )
325356 newRow. isHidden = true
326- UIView . animate ( {
357+ UIView . execute ( {
327358 newRow. isHidden = false
328359 } , completion: completion)
329360 }
@@ -358,7 +389,7 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
358389 }
359390
360391 stackView. setNeedsLayout ( )
361- UIView . animate ( executeMoveRow, completion: completion)
392+ UIView . execute ( executeMoveRow, completion: completion)
362393 }
363394
364395 // MARK: Show/Hide Rows
@@ -385,7 +416,7 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
385416 }
386417
387418 row. layoutIfNeeded ( )
388- UIView . animate ( {
419+ UIView . execute ( {
389420 row. isHidden = isHidden
390421 } , completion: completion)
391422 }
@@ -458,7 +489,7 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
458489 return . hidden
459490 }
460491
461- return isRowVisible ( row: row)
492+ return rowVisibilityType ( row: row)
462493 }
463494
464495 /// Return `true` if row is currently hidden.
@@ -530,14 +561,48 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
530561 didChangeAxis ( axis)
531562 }
532563
564+ /// Reload selected rows of the stackview.
565+ ///
566+ /// - Parameter rows: rows to reload.
567+ /// - Parameter animated: `true` to animate reload.
568+ /// - Parameter completion: completion callback to call at the end of the reload.
569+ private func reloadRows( _ rows: [ ScrollStackRow ] , animated: Bool = false , completion: ( ( ) -> Void ) ? = nil ) {
570+ guard rows. isEmpty == false else {
571+ return
572+ }
573+
574+ rows. forEach {
575+ $0. askForCutomizedSizeOfContentView ( )
576+ }
577+
578+ UIView . execute ( animated: animated, {
579+ self . layoutIfNeeded ( )
580+ } , completion: completion)
581+ }
582+
583+ /// Get the row at specified index; if index is invalid `nil` is returned.
584+ ///
585+ /// - Parameter index: index of the row to get.
533586 private func safeRowAtIndex( _ index: Int ) -> ScrollStackRow ? {
534- guard index >= 0 , index < rows. count else {
535- return nil
587+ return safeRowsAtIndexes ( [ index] ) . first
588+ }
589+
590+ /// Get the rows at specified indexes, invalid indexes are ignored.
591+ ///
592+ /// - Parameter indexes: indexes of the rows to get.
593+ private func safeRowsAtIndexes( _ indexes: [ Int ] ) -> [ ScrollStackRow ] {
594+ return indexes. compactMap { index in
595+ guard index >= 0 , index < rows. count else {
596+ return nil
597+ }
598+ return rows [ index]
536599 }
537- return rows [ index]
538600 }
539601
540- private func isRowVisible( row: ScrollStackRow ) -> RowVisibility {
602+ /// Get the row visibility type for a specific row.
603+ ///
604+ /// - Parameter row: row to get.
605+ private func rowVisibilityType( row: ScrollStackRow ) -> RowVisibility {
541606 let rowFrame = convert ( row. frame, to: self )
542607 guard bounds. intersects ( rowFrame) else {
543608 return . offscreen
@@ -597,7 +662,7 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
597662 postInsertRow ( newRow, animated: animated, completion: completion)
598663
599664 if animated {
600- UIView . animate ( {
665+ UIView . execute ( {
601666 self . layoutIfNeeded ( )
602667 } , completion: nil )
603668 }
@@ -620,6 +685,9 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
620685 animateCellVisibility ( row, animated: animated, hide: false , completion: completion)
621686 }
622687
688+ /// Update the separator visibility.
689+ ///
690+ /// - Parameter row: row target.
623691 private func updateRowSeparatorVisibility( _ row: ScrollStackRow ? ) {
624692 guard let row = row, row === stackView. arrangedSubviews. last else {
625693 return
@@ -653,6 +721,7 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
653721 }
654722 }
655723
724+ /// Animate transition of the cell to visible state.
656725 private func animateCellToVisibleState( _ row: ScrollStackRow , animated: Bool , hide: Bool , completion: ( ( ) -> Void ) ? = nil ) {
657726 guard animated else {
658727 row. alpha = 1.0
@@ -663,28 +732,26 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
663732
664733 row. alpha = 0.0
665734 layoutIfNeeded ( )
666- UIView . animate ( {
735+ UIView . execute ( {
667736 row. alpha = 1.0
668737 } , completion: completion)
669738 }
670739
740+ /// Animate transition of the cell to invisibile state.
671741 private func animateCellToInvisibleState( _ row: ScrollStackRow , animated: Bool , hide: Bool , completion: ( ( ) -> Void ) ? = nil ) {
672- guard animated else {
673- row. isHidden = true
674- completion ? ( )
675- return
676- }
677-
678- UIView . animate ( {
742+ UIView . execute ( animated: animated, {
679743 row. isHidden = true
680744 } , completion: completion)
681745 }
682746
683747 // MARK: - Axis Change Events
684748
749+ /// Update the constraint due to axis change of the stack view.
750+ ///
751+ /// - Parameter axis: new axis.
685752 private func didChangeAxis( _ axis: NSLayoutConstraint . Axis ) {
686753 didUpdateStackViewAxisTo ( axis)
687- didUpdateCellAxisTo ( axis)
754+ didReflectAxisChangeToRows ( axis)
688755 }
689756
690757 private func didUpdateStackViewAxisTo( _ axis: NSLayoutConstraint . Axis ) {
@@ -708,7 +775,7 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
708775 axisConstraint? . isActive = true
709776 }
710777
711- private func didUpdateCellAxisTo ( _ axis: NSLayoutConstraint . Axis ) {
778+ private func didReflectAxisChangeToRows ( _ axis: NSLayoutConstraint . Axis ) {
712779 rows. forEach {
713780 $0. separatorAxis = ( axis == . horizontal ? . vertical : . horizontal)
714781 }
0 commit comments