Skip to content

Instantly share code, notes, and snippets.

@andreasmpet
Created November 23, 2017 15:10
Show Gist options
  • Save andreasmpet/932f275cb90de16035bace20cbf7d920 to your computer and use it in GitHub Desktop.
Save andreasmpet/932f275cb90de16035bace20cbf7d920 to your computer and use it in GitHub Desktop.
BufferingStackView
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)
}
}
}
}
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
}
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