-
-
Save hmchen/35f2fe01c6ef30d41c8a9c8c14c63f44 to your computer and use it in GitHub Desktop.
BufferingStackView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BufferingStackView: UIStackView { | |
private var viewBuffer: ViewBuffer = ViewBuffer() | |
func prepare<T: UIView>(viewCount: Int, config: @escaping (_ index: Int, _ view: T) -> Void) { | |
let currentViewCount = self.arrangedSubviews.count | |
let neededViewCount = viewCount | |
let diff = neededViewCount - currentViewCount | |
let absDiff = abs(diff) | |
let shouldDelete = diff < 0 | |
if shouldDelete { | |
(0..<absDiff).forEach({ _ in | |
let lastIndex = self.arrangedSubviews.count - 1 | |
self.arrangedSubviews[lastIndex].removeFromSuperview() | |
}) | |
} | |
self.viewBuffer.prepareForReuse() | |
let views = (0..<viewCount).flatMap { (index) -> T? in | |
return self.viewBuffer.dequeueView(withConfigBlock: { (v: T) in | |
config(index, v) | |
}) | |
} | |
views.forEach { (v) in | |
let needsToBeAdded = v.superview == nil | |
if needsToBeAdded { | |
self.addArrangedSubview(v) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let someObjects = ["test", "toast"] | |
self.bufferedStackView.prepare(viewCount:someObjects.count) { (index: Int, view: YourWantedViewClass) in | |
let string = someObjects[index] | |
// configure the view in here with your data | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class ViewBuffer<T> where T: UIView { | |
typealias ViewBufferConfigBlock = (_ view: T) -> Void | |
init(initialCapacity: Int) { | |
self.buffer = (0...initialCapacity).map({ _ in return self.dequeueView() }) | |
} | |
private var buffer: [T] = [] | |
private var usedViews: Set<T> = Set() | |
func dequeueView(withConfigBlock block: ViewBufferConfigBlock? = nil) -> T { | |
if let existingView = self.buffer.first(where: { (bufferedView) -> Bool in | |
let contains = !self.usedViews.contains(bufferedView) | |
return contains | |
}) { | |
self.usedViews.insert(existingView) | |
block?(existingView) | |
return existingView | |
} | |
let newView = T() | |
newView.translatesAutoresizingMaskIntoConstraints = false | |
block?(newView) | |
self.buffer.append(newView) | |
self.usedViews.insert(newView) | |
return newView | |
} | |
func prepareForReuse() { | |
self.usedViews.removeAll() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment