Created
November 23, 2017 15:10
-
-
Save andreasmpet/932f275cb90de16035bace20cbf7d920 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