Created
April 14, 2017 09:45
-
-
Save chapayGhub/7c50a6634f54776f787b6649f8924002 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
| import IGListKit | |
| protocol SelfSizingCell { | |
| associatedtype ItemType: IGListDiffable | |
| var item: ItemType? { get set } | |
| } | |
| class SelfSizingCellSizeCache: NSObject { | |
| static let shared = SelfSizingCellSizeCache() | |
| private var cache = Dictionary<SizeCacheItemKey, CGFloat>() | |
| public func cacheCellSize<C: UICollectionViewCell> | |
| (forCell cell: C, | |
| item: IGListDiffable, | |
| forWidth: CGFloat, | |
| cellName: String) -> CGFloat | |
| where C: SelfSizingCell { | |
| let size = cell.contentView.systemLayoutSizeFitting(CGSize(width: forWidth, height: .greatestFiniteMagnitude)) | |
| let itemKey = SizeCacheItemKey(item: item, forWidth: forWidth, cellName: cellName) | |
| cache[itemKey] = size.height | |
| return size.height | |
| } | |
| public func cellHeight(forItem item: IGListDiffable, | |
| forWidth: CGFloat, | |
| cellName: String) -> CGFloat? { | |
| let itemKey = SizeCacheItemKey(item: item, forWidth: forWidth, cellName: cellName) | |
| guard let index = cache.index(forKey: itemKey) else { | |
| return nil | |
| } | |
| return cache[index].value | |
| } | |
| } | |
| fileprivate struct SizeCacheItemKey { | |
| let item: IGListDiffable | |
| let forWidth: CGFloat | |
| let cellName: String | |
| } | |
| extension SizeCacheItemKey: Hashable { | |
| var hashValue: Int { | |
| let value = item.diffIdentifier().hash ^ forWidth.hashValue ^ cellName.hashValue | |
| return value | |
| } | |
| } | |
| fileprivate func ==(lhs: SizeCacheItemKey, rhs: SizeCacheItemKey) -> Bool { | |
| return lhs.item.isEqual(toDiffableObject: rhs.item) && | |
| lhs.forWidth == rhs.forWidth && | |
| lhs.cellName == rhs.cellName | |
| } | |
| extension SelfSizingCell | |
| where Self: UICollectionViewCell { | |
| static func heightForSelfSizingCell(item: ItemType, width: CGFloat) -> CGFloat { | |
| let cellName = String(describing: self) | |
| if let height = SelfSizingCellSizeCache.shared.cellHeight(forItem: item, forWidth: width, cellName: cellName) { | |
| return height | |
| } | |
| guard var cell = self.cellForMeasuringCellOnly() as? Self else { | |
| assertionFailure("Unable to load cell") | |
| return 0 | |
| } | |
| cell.item = item | |
| return SelfSizingCellSizeCache.shared.cacheCellSize(forCell: cell, item: item, forWidth: width, cellName: cellName) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment