Skip to content

Commit 76f27a6

Browse files
committed
Added reloadRow() reloadRows() and reloadAllRows() methods
1 parent 0c67cb0 commit 76f27a6

File tree

8 files changed

+118
-29
lines changed

8 files changed

+118
-29
lines changed

ScrollStackControllerDemo/VC1.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import UIKit
1010

1111
public class VC1: UIViewController, ScrollStackContainableController {
1212

13-
private var bestSize = CGFloat.random(in: 100..<500)
13+
public var bestSize = CGFloat.random(in: 100..<500)
1414

1515
public static func create(backColor: UIColor) -> VC1 {
1616
let storyboard = UIStoryboard(name: "Main", bundle: nil)
@@ -19,8 +19,12 @@ public class VC1: UIViewController, ScrollStackContainableController {
1919
return vc
2020
}
2121

22-
public func sizeForAxis(_ axis: NSLayoutConstraint.Axis, row: ScrollStackRow, in stackView: ScrollStack) -> CGFloat? {
22+
public func scrollStackRowSizeForAxis(_ axis: NSLayoutConstraint.Axis, row: ScrollStackRow, in stackView: ScrollStack) -> CGFloat? {
2323
return bestSize
2424
}
2525

26+
public func reloadContentFromStackViewRow() {
27+
28+
}
29+
2630
}

ScrollStackControllerDemo/VC2.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,20 @@ import UIKit
1010

1111
public class VC2: UIViewController, ScrollStackContainableController {
1212

13+
1314
public static func create(backColor: UIColor) -> VC2 {
1415
let storyboard = UIStoryboard(name: "Main", bundle: nil)
1516
let vc = storyboard.instantiateViewController(identifier: "VC2") as! VC2
1617
vc.view.backgroundColor = backColor
1718
return vc
1819
}
1920

20-
public func sizeForAxis(_ axis: NSLayoutConstraint.Axis, row: ScrollStackRow, in stackView: ScrollStack) -> CGFloat? {
21+
public func scrollStackRowSizeForAxis(_ axis: NSLayoutConstraint.Axis, row: ScrollStackRow, in stackView: ScrollStack) -> CGFloat? {
2122
return 140
2223
}
2324

25+
public func reloadContentFromStackViewRow() {
26+
27+
}
28+
2429
}

ScrollStackControllerDemo/ViewController.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ class ViewController: UIViewController {
4040
@IBAction public func toggleAxis() {
4141
let stackView = stackController.stackView
4242

43-
let randomVC = VC2.create(backColor: UIColor.random())
44-
let position = Int.random(in: 0..<stackView.rows.count)
45-
stackView.addRow(controller: randomVC, at: .atIndex(position), animated: true)
43+
// let randomVC = VC2.create(backColor: UIColor.random())
44+
// let position = Int.random(in: 0..<stackView.rows.count)
45+
// stackView.addRow(controller: randomVC, at: .atIndex(position), animated: true)
46+
47+
(stackView.rows[0].controller as! VC1).bestSize = 50
48+
(stackView.rows[1].controller as! VC1).bestSize = 30
49+
stackController.stackView.reloadRows(indexes: [0,1], animated: true)
4650

4751

4852
// stackController.stackView.setRowHidden(index: 0, isHidden: true, animated: true)

Sources/ScrollStackController/ScrollStack.swift

Lines changed: 87 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

Sources/ScrollStackController/ScrollStackRow.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
251251
}
252252

253253
let currentAxis = stackView!.axis
254-
guard let bestSize = customizableController.sizeForAxis(currentAxis, row: self, in: self.stackView!) else {
254+
guard let bestSize = customizableController.scrollStackRowSizeForAxis(currentAxis, row: self, in: self.stackView!) else {
255255
return // ignore, use autolayout in place for content view.
256256
}
257257

Sources/ScrollStackController/Support/ScrollStack+Protocols.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ public protocol ScrollStackContainableController: UIViewController {
4949
/// - Parameter axis: axis of the stackview.
5050
/// - Parameter row: row where the controller is placed.
5151
/// - Parameter stackView: stackview where the row is placed.
52-
func sizeForAxis(_ axis: NSLayoutConstraint.Axis, row: ScrollStackRow, in stackView: ScrollStack) -> CGFloat?
52+
func scrollStackRowSizeForAxis(_ axis: NSLayoutConstraint.Axis, row: ScrollStackRow, in stackView: ScrollStack) -> CGFloat?
53+
54+
/// Method is called when you call a `reloadRow` function on a row where this controller is contained in.
55+
func reloadContentFromStackViewRow()
5356

5457
}
5558

Sources/ScrollStackController/Support/UIView+AutoLayout_Extensions.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,13 @@ extension UIView {
6565
}
6666
}
6767

68-
public static func animate(_ callback: @escaping (() -> Void), completion: (() -> Void)? = nil) {
68+
public static func execute(animated: Bool = true, _ callback: @escaping (() -> Void), completion: (() -> Void)? = nil) {
69+
guard animated else {
70+
callback()
71+
completion?()
72+
return
73+
}
74+
6975
UIView.animate(withDuration: 0.3, animations: callback) { isFinished in
7076
if isFinished {
7177
completion?()

0 commit comments

Comments
 (0)