From 788a84db3aafa961e9c232da1464725c005343c9 Mon Sep 17 00:00:00 2001 From: Alex Usbergo Date: Tue, 7 Mar 2017 10:48:57 +0100 Subject: [PATCH] style --- Buffer.podspec | 42 ++++ Buffer/AdapterType.swift | 45 +--- Buffer/AnyListItem.swift | 33 +-- Buffer/Buffer.swift | 87 +++----- Buffer/CollectionViewDiffAdapter.swift | 230 +++++++++----------- Buffer/LCS.swift | 40 +--- Buffer/PrototypeCell.swift | 287 ++++++++++++------------- Buffer/TableView.swift | 75 +++---- Buffer/TableViewDiffAdapter.swift | 228 +++++++++----------- LICENSE | 13 +- 10 files changed, 469 insertions(+), 611 deletions(-) create mode 100644 Buffer.podspec diff --git a/Buffer.podspec b/Buffer.podspec new file mode 100644 index 0000000..ce01ac3 --- /dev/null +++ b/Buffer.podspec @@ -0,0 +1,42 @@ +# +# Be sure to run `pod lib lint Render.podspec' to ensure this is a +# valid spec before submitting. +# +# Any lines starting with a # are optional, but their use is encouraged +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# + +Pod::Spec.new do |s| + s.name = "Buffer" + s.version = "2.1" + s.summary = "Swift and UIKit a la React." + +# This description is used to generate tags and improve search results. +# * Think: What does it do? Why did you write it? What is the focus? +# * Try to keep it short, snappy and to the point. +# * Write the description between the DESC delimiters below. +# * Finally, don't worry about the indent, CocoaPods strips it! + + s.description = <<-DESC + React-inspired swift library for writing UIKit UIs. + DESC + + s.homepage = "https://github.com/alexdrone/Render" + s.screenshots = "https://github.com/alexdrone/Render/raw/master/Doc/logo.png" + s.license = 'MIT' + s.author = { "Alex Usbergo" => "alexakadrone@gmail.com" } + s.source = { :git => "https://github.com/alexdrone/Render.git", :tag => s.version.to_s } + s.social_media_url = 'https://twitter.com/alexdrone' + + s.ios.deployment_target = '8.0' + + s.source_files = 'Render/**/*' + + # s.resource_bundles = { + # 'Render' => ['Render/Assets/*.png'] + # } + + # s.public_header_files = 'Pod/Classes/**/*.h' + # s.frameworks = 'UIKit', 'MapKit' + # s.dependency 'AFNetworking', '~> 2.3' +end diff --git a/Buffer/AdapterType.swift b/Buffer/AdapterType.swift index 02a61f4..7432cb9 100644 --- a/Buffer/AdapterType.swift +++ b/Buffer/AdapterType.swift @@ -1,29 +1,3 @@ -// -// AdapterType.swift -// Buffer -// -// Copyright (c) 2016 Alex Usbergo. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - - import Foundation public protocol AdapterType { @@ -31,23 +5,24 @@ public protocol AdapterType { associatedtype `Type` associatedtype ViewType - ///Returns the element currently on the front buffer at the given index path. + /** Returns the element currently on the front buffer at the given index path. */ func displayedElement(at index: Int) -> Type - ///The total number of elements currently displayed. + /** The total number of elements currently displayed. */ func countDisplayedElements() -> Int - ///Replace the elements buffer and compute the diffs. - /// - parameter newValues: The new values. - /// - parameter synchronous: Wether the filter, sorting and diff should be executed - /// synchronously or not. - /// - parameter completion: Code that will be executed once the buffer is updated. + /** Replace the elements buffer and compute the diffs. + * - parameter newValues: The new values. + * - parameter synchronous: Wether the filter, sorting and diff should be executed + * synchronously or not. + * - parameter completion: Code that will be executed once the buffer is updated. + */ func update(with values: [Type]?, synchronous: Bool, completion: ((Void) -> Void)?) - ///The section index associated with this adapter. + /** The section index associated with this adapter. */ var sectionIndex: Int { get set } - ///The target view. + /** The target view. */ var view: ViewType? { get } init(buffer: BufferType, view: ViewType) diff --git a/Buffer/AnyListItem.swift b/Buffer/AnyListItem.swift index f1d8a5a..5592cea 100644 --- a/Buffer/AnyListItem.swift +++ b/Buffer/AnyListItem.swift @@ -1,28 +1,3 @@ -// -// AnyListItemType.swift -// BufferDiff -// -// Copyright (c) 2016 Alex Usbergo. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - import Foundation public protocol ListContainerView: class { } @@ -42,13 +17,13 @@ public func ==(lhs: AnyListItem, rhs: AnyListItem) -> Bool { public struct AnyListItem: Equatable { - ///The reuse identifier for the cell passed as argument. + /** The reuse identifier for the cell passed as argument. */ public var reuseIdentifier: String - ///The actual item data. + /** The actual item data. */ public var state: Type - ///The TableView, or the CollectionView that will own this element. + /** The TableView, or the CollectionView that will own this element. */ public let referenceView: ListContainerView? public var cellConfiguration: ((ListViewCell, Type) -> Void)? @@ -61,7 +36,7 @@ public struct AnyListItem: Equatable { state: Type, configurationClosure: ((ListViewCell, Type) -> Void)? = nil) { - //registers the prototype cell if necessary. + // registers the prototype cell if necessary. if !Prototypes.isPrototypeCellRegistered(reuseIdentifer) { let cell = V(reuseIdentifier: reuseIdentifer) Prototypes.registerPrototypeCell(reuseIdentifer, cell: cell) diff --git a/Buffer/Buffer.swift b/Buffer/Buffer.swift index 6e762e6..ed264ac 100644 --- a/Buffer/Buffer.swift +++ b/Buffer/Buffer.swift @@ -1,78 +1,51 @@ - -// -// Buffer.swift -// Buffer -// -// Created by Alex Usbergo on 02/05/16. -// -// Copyright (c) 2016 Alex Usbergo. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - import Foundation public protocol BufferType { } public protocol BufferDelegate: class { - /// Notifies the receiver that the content is about to change + /** Notifies the receiver that the content is about to change */ func buffer(willChangeContent buffer: BufferType) - /// Notifies the receiver that rows were deleted. + /** Notifies the receiver that rows were deleted. */ func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) - /// Notifies the receiver that rows were inserted. + /** Notifies the receiver that rows were inserted. */ func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) - /// Notifies the receiver that the content updates has ended. + /** Notifies the receiver that the content updates has ended. */ func buffer(didChangeContent buffer: BufferType) - /// Notifies the receiver that the content updates has ended. - /// This callback method is called when the number of changes are too many to be - /// handled for the UI thread - it's recommendable to just reload the whole data in this case. - /// - Note: The 'diffThreshold' property in 'Buffer' defines what is the maximum number - /// of changes - /// that you want the receiver to be notified for. + /** Notifies the receiver that the content updates has ended. + * This callback method is called when the number of changes are too many to be + * handled for the UI thread - it's recommendable to just reload the whole data in this case. + * - Note: The 'diffThreshold' property in 'Buffer' defines what is the maximum number + * of changes + * that you want the receiver to be notified for. + */ func buffer(didChangeAllContent buffer: BufferType) - /// Called when one of the observed properties for this object changed + /** Called when one of the observed properties for this object changed. */ func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) } public class Buffer: NSObject, BufferType { - /// The object that will get notified every time changes occures to the array. + /** The object that will get notified every time changes occures to the array. */ public weak var delegate: BufferDelegate? - /// The elements in the array observer's buffer. + /** The elements in the array observer's buffer. */ public var currentElements: [ElementType] { return self.frontBuffer } - /// Defines what is the maximum number of changes that you want the receiver to be notified for. + /** Defines what is the maximum number of changes that you want the receiver to be notified for. */ public var diffThreshold = 50 - /// If set to 'true' the LCS algorithm is run synchronously on the main thread. + // If set to 'true' the LCS algorithm is run synchronously on the main thread. fileprivate var synchronous: Bool = false - /// The two buffers. + // The two buffers. fileprivate var frontBuffer = [ElementType]() { willSet { assert(Thread.isMainThread) @@ -85,13 +58,13 @@ public class Buffer: NSObject, BufferType { } fileprivate var backBuffer = [ElementType]() - /// Sort closure. + // Sort closure. fileprivate var sort: ((ElementType, ElementType) -> Bool)? - /// Filter closure. + // Filter closure. fileprivate var filter: ((ElementType) -> Bool)? - /// The serial operation queue for this controller. + // The serial operation queue for this controller. fileprivate let serialOperationQueue: OperationQueue = { let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 @@ -101,7 +74,7 @@ public class Buffer: NSObject, BufferType { fileprivate var flags = (isRefreshing: false, shouldRefresh: false) - /// Used if 'Element' is KVO-compliant. + // Used if 'Element' is KVO-compliant. fileprivate var trackedKeyPaths = [String]() public init(initialArray: [ElementType], @@ -117,7 +90,7 @@ public class Buffer: NSObject, BufferType { self.observe(shouldObserveTrackedKeyPaths: false) } - /// Compute the diffs between the current array and the new one passed as argument. + /** Compute the diffs between the current array and the new one passed as argument. */ public func update( with values: [ElementType]? = nil, synchronous: Bool = false, @@ -182,8 +155,9 @@ public class Buffer: NSObject, BufferType { } } - /// This message is sent to the receiver when the value at the specified key path relative - /// to the given object has changed. + /** This message is sent to the receiver when the value at the specified key path relative + * to the given object has changed. + */ public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, @@ -200,11 +174,11 @@ public class Buffer: NSObject, BufferType { } } -//MARK: KVO Extension +// MARK: KVO Extension extension Buffer where ElementType: AnyObject { - ///Observe the keypaths passed as argument. + /** Observe the keypaths passed as argument. */ public func trackKeyPaths(_ keypaths: [String]) { self.observe(shouldObserveTrackedKeyPaths: false) self.trackedKeyPaths = keypaths @@ -214,8 +188,9 @@ extension Buffer where ElementType: AnyObject { extension Buffer { - /// Adds or remove observations. - /// - Note: This code is executed only when 'Element: AnyObject'. + /** Adds or remove observations. + * - Note: This code is executed only when 'Element: AnyObject'. + */ fileprivate func observe(shouldObserveTrackedKeyPaths: Bool = true) { if self.trackedKeyPaths.count == 0 { return @@ -237,7 +212,7 @@ extension Buffer { } } - /// - Note: This code is executed only when 'Element: AnyObject'. + // - Note: This code is executed only when 'Element: AnyObject'. fileprivate func objectDidChangeValue(for keyPath: String?, in object: AnyObject?) { dispatchOnMainThread { self.update() { diff --git a/Buffer/CollectionViewDiffAdapter.swift b/Buffer/CollectionViewDiffAdapter.swift index e7f7ccf..c89edd2 100644 --- a/Buffer/CollectionViewDiffAdapter.swift +++ b/Buffer/CollectionViewDiffAdapter.swift @@ -1,154 +1,132 @@ -// -// Adapters.swift -// Buffer -// -// Copyright (c) 2016 Alex Usbergo. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - #if os(iOS) - import UIKit +import UIKit - open class CollectionViewDiffAdapter: - NSObject, AdapterType, UICollectionViewDataSource { +open class CollectionViewDiffAdapter: + NSObject, AdapterType, UICollectionViewDataSource { - public typealias `Type` = ElementType - public typealias ViewType = UICollectionView + public typealias `Type` = ElementType + public typealias ViewType = UICollectionView - open fileprivate(set) var buffer: Buffer + open fileprivate(set) var buffer: Buffer - open fileprivate(set) weak var view: ViewType? + open fileprivate(set) weak var view: ViewType? - /// Right now this only works on a single section of a collectionView. - /// If your collectionView has multiple sections, though, you can just use multiple - /// CollectionViewDiffAdapter, one per section, and set this value appropriately on each one. - open var sectionIndex: Int = 0 + /** Right now this only works on a single section of a collectionView. + * If your collectionView has multiple sections, though, you can just use multiple + * CollectionViewDiffAdapter, one per section, and set this value appropriately on each one. + */ + open var sectionIndex: Int = 0 - public required init(buffer: BufferType, view: ViewType) { - guard let buffer = buffer as? Buffer else { - fatalError() - } - self.buffer = buffer - self.view = view - super.init() - self.buffer.delegate = self + public required init(buffer: BufferType, view: ViewType) { + guard let buffer = buffer as? Buffer else { + fatalError() } + self.buffer = buffer + self.view = view + super.init() + self.buffer.delegate = self + } - public required init(initialElements: [ElementType], view: ViewType) { - self.buffer = Buffer(initialArray: initialElements) - self.view = view - super.init() - self.buffer.delegate = self - } + public required init(initialElements: [ElementType], view: ViewType) { + self.buffer = Buffer(initialArray: initialElements) + self.view = view + super.init() + self.buffer.delegate = self + } - fileprivate var indexPaths: (insertion: [IndexPath], deletion: [IndexPath]) = ([], []) + fileprivate var indexPaths: (insertion: [IndexPath], deletion: [IndexPath]) = ([], []) - fileprivate var cellForItemAtIndexPath: ((UICollectionView, ElementType, IndexPath) - -> UICollectionViewCell)? = nil + fileprivate var cellForItemAtIndexPath: ((UICollectionView, ElementType, IndexPath) + -> UICollectionViewCell)? = nil - /// Returns the element currently on the front buffer at the given index path. - open func displayedElement(at index: Int) -> ElementType { - return self.buffer.currentElements[index] - } + /** Returns the element currently on the front buffer at the given index path. */ + open func displayedElement(at index: Int) -> ElementType { + return self.buffer.currentElements[index] + } - /// The total number of elements currently displayed. - open func countDisplayedElements() -> Int { - return self.buffer.currentElements.count - } + /** The total number of elements currently displayed. */ + open func countDisplayedElements() -> Int { + return self.buffer.currentElements.count + } - /// Replace the elements buffer and compute the diffs. - /// - parameter newValues: The new values. - /// - parameter synchronous: Wether the filter, sorting and diff should be executed - /// synchronously or not. - /// - parameter completion: Code that will be executed once the buffer is updated. - open func update(with newValues: [ElementType]? = nil, - synchronous: Bool = false, - completion: ((Void) -> Void)? = nil) { - self.buffer.update(with: newValues, synchronous: synchronous, completion: completion) - } + /** Replace the elements buffer and compute the diffs. + * - parameter newValues: The new values. + * - parameter synchronous: Wether the filter, sorting and diff should be executed + * synchronously or not. + * - parameter completion: Code that will be executed once the buffer is updated. + */ + open func update(with newValues: [ElementType]? = nil, + synchronous: Bool = false, + completion: ((Void) -> Void)? = nil) { + self.buffer.update(with: newValues, synchronous: synchronous, completion: completion) + } - /// Configure the TableView to use this adapter as its DataSource. - /// - parameter automaticDimension: If you wish to use 'UITableViewAutomaticDimension' - /// as 'rowHeight'. - /// - parameter estimatedHeight: The estimated average height for the cells. - /// - parameter cellForRowAtIndexPath: The closure that returns a cell for the given - /// index path. - open func useAsDataSource(_ cellForItemAtIndexPath: - @escaping (UICollectionView, ElementType, IndexPath) -> UICollectionViewCell) { - self.view?.dataSource = self - self.cellForItemAtIndexPath = cellForItemAtIndexPath - } + /** Configure the TableView to use this adapter as its DataSource. + * - parameter automaticDimension: If you wish to use 'UITableViewAutomaticDimension' + * as 'rowHeight'. + * - parameter estimatedHeight: The estimated average height for the cells. + * - parameter cellForRowAtIndexPath: The closure that returns a cell for the given + * index path. + */ + open func useAsDataSource(_ cellForItemAtIndexPath: + @escaping (UICollectionView, ElementType, IndexPath) -> UICollectionViewCell) { + self.view?.dataSource = self + self.cellForItemAtIndexPath = cellForItemAtIndexPath + } - /// Tells the data source to return the number of rows in a given section of a table view. - open func collectionView(_ collectionView: UICollectionView, - numberOfItemsInSection section: Int) -> Int { - return self.buffer.currentElements.count - } + /** Tells the data source to return the number of rows in a given section of a table view. */ + open func collectionView(_ collectionView: UICollectionView, + numberOfItemsInSection section: Int) -> Int { + return self.buffer.currentElements.count + } - /// Asks the data source for a cell to insert in a particular location of the table view. - open func collectionView(_ collectionView: UICollectionView, - cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - return self.cellForItemAtIndexPath!( - collectionView, self.buffer.currentElements[(indexPath as NSIndexPath).row], indexPath) - } + /** Asks the data source for a cell to insert in a particular location of the table view. */ + open func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + return self.cellForItemAtIndexPath!( + collectionView, self.buffer.currentElements[(indexPath as NSIndexPath).row], indexPath) } +} - extension CollectionViewDiffAdapter: BufferDelegate { +extension CollectionViewDiffAdapter: BufferDelegate { - /// Notifies the receiver that the content is about to change. - public func buffer(willChangeContent buffer: BufferType) { - self.indexPaths = ([], []) - } + /** Notifies the receiver that the content is about to change. */ + public func buffer(willChangeContent buffer: BufferType) { + self.indexPaths = ([], []) + } - /// Notifies the receiver that rows were deleted. - public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) { - self.indexPaths.deletion = indices.map({ - IndexPath(row: Int($0), section: self.sectionIndex) - }) - } + /** Notifies the receiver that rows were deleted. */ + public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) { + self.indexPaths.deletion = indices.map({ + IndexPath(row: Int($0), section: self.sectionIndex) + }) + } - /// Notifies the receiver that rows were inserted. - public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) { - self.indexPaths.insertion = indices.map({ - IndexPath(row: Int($0), section: self.sectionIndex) - }) - } + /** Notifies the receiver that rows were inserted. */ + public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) { + self.indexPaths.insertion = indices.map({ + IndexPath(row: Int($0), section: self.sectionIndex) + }) + } - /// Notifies the receiver that the content updates has ended. - public func buffer(didChangeContent buffer: BufferType) { - self.view?.performBatchUpdates({ - self.view?.insertItems(at: self.indexPaths.insertion) - self.view?.deleteItems(at: self.indexPaths.deletion) - }, completion: nil) - } + /** Notifies the receiver that the content updates has ended. */ + public func buffer(didChangeContent buffer: BufferType) { + self.view?.performBatchUpdates({ + self.view?.insertItems(at: self.indexPaths.insertion) + self.view?.deleteItems(at: self.indexPaths.deletion) + }, completion: nil) + } - /// Called when one of the observed properties for this object changed. - public func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) { - self.view?.reloadItems( - at: [IndexPath(row: Int(index), section: self.sectionIndex)]) - } + /** Called when one of the observed properties for this object changed. */ + public func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) { + self.view?.reloadItems( + at: [IndexPath(row: Int(index), section: self.sectionIndex)]) + } - /// Notifies the receiver that the content updates has ended and the whole array changed. - public func buffer(didChangeAllContent buffer: BufferType) { - self.view?.reloadData() - } + /** Notifies the receiver that the content updates has ended and the whole array changed. */ + public func buffer(didChangeAllContent buffer: BufferType) { + self.view?.reloadData() } +} #endif diff --git a/Buffer/LCS.swift b/Buffer/LCS.swift index ec69ef1..df66e7f 100644 --- a/Buffer/LCS.swift +++ b/Buffer/LCS.swift @@ -1,25 +1,3 @@ -// -// LCS.swift -// BufferDiff -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// // Originally created by Jack Flintermann on 3/14/15. // Forked from github.com/jflinter/Dwifft // Copyright (c) 2015 jflinter. All rights reserved. @@ -49,8 +27,9 @@ public func + (left: Diff, right: DiffStep) -> Diff { return Diff(results: left.results + [right]) } -/// These get returned from calls to Array.diff(). -/// They represent insertions or deletions that need to happen to transform array A into array A. +/** These get returned from calls to Array.diff(). + * They represent insertions or deletions that need to happen to transform array A into array A. + */ public enum DiffStep { case insert(Int, Type) case delete(Int, Type) @@ -95,13 +74,13 @@ private struct MemoizedSequenceComparison { public extension Array where Element: Equatable { - /// Returns the sequence of ArrayDiffResults required to transform one array into another. + /** Returns the sequence of ArrayDiffResults required to transform one array into another. */ public func diff(_ other: [Element]) -> Diff { let table = MemoizedSequenceComparison.buildTable(self, other, self.count, other.count) return Array.diffFromIndices(table, self, other, self.count, other.count) } - /// Walks back through the generated table to generate the diff. + /** Walks back through the generated table to generate the diff. */ fileprivate static func diffFromIndices( _ table: [[Int]], _ x: [Element], _ y: [Element], _ i: Int, _ j: Int) -> Diff { @@ -120,8 +99,9 @@ public extension Array where Element: Equatable { } } - /// Applies a generated diff to an array. - /// Invariant: given x: [T], y: [T], x.apply(x.diff(y)) == y + /** Applies a generated diff to an array. + * Invariant: given x: [T], y: [T], x.apply(x.diff(y)) == y + */ fileprivate func apply(_ diff: Diff) -> Array { var copy = self for result in diff.deletions { @@ -136,13 +116,13 @@ public extension Array where Element: Equatable { public extension Array where Element: Equatable { - /// Returns the longest common subsequence between two arrays. + /** Returns the longest common subsequence between two arrays. */ public func LCS(_ other: [Element]) -> [Element] { let table = MemoizedSequenceComparison.buildTable(self, other, self.count, other.count) return Array.lcsFromIndices(table, self, other, self.count, other.count) } - /// Walks back through the generated table to generate the LCS. + // Walks back through the generated table to generate the LCS. fileprivate static func lcsFromIndices( _ table: [[Int]], _ x: [Element], _ y: [Element], _ i: Int, _ j: Int) -> [Element] { if i == 0 && j == 0 { diff --git a/Buffer/PrototypeCell.swift b/Buffer/PrototypeCell.swift index a6af112..3513b0d 100644 --- a/Buffer/PrototypeCell.swift +++ b/Buffer/PrototypeCell.swift @@ -1,202 +1,179 @@ -// -// Cell.swift -// BufferDiff -// -// Copyright (c) 2016 Alex Usbergo. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - #if os(iOS) - import UIKit +import UIKit - public protocol PrototypeViewCell: ListViewCell { +public protocol PrototypeViewCell: ListViewCell { - /// The TableView or CollectionView that owns this cell. - var referenceView: ListContainerView? { get set } + /** The TableView or CollectionView that owns this cell. */ + var referenceView: ListContainerView? { get set } - // /Apply the state. - /// - Note: This is used internally from the infra to set the state. - func applyState(_ state: T) + /** Apply the state. + * - Note: This is used internally from the infra to set the state. + */ + func applyState(_ state: T) - init(reuseIdentifier: String) - } + init(reuseIdentifier: String) +} - open class PrototypeTableViewCell : - UITableViewCell, PrototypeViewCell { +open class PrototypeTableViewCell : +UITableViewCell, PrototypeViewCell { - /// The wrapped view. - open var view: ViewType! + /** The wrapped view. */ + open var view: ViewType! - /// The state for this cell. - /// - Note: This is propagated to the associted- - open var state: StateType? { - didSet { - didSetStateClosure?(state) - } + open var state: StateType? { + didSet { + didSetStateClosure?(state) } + } - weak open var referenceView: ListContainerView? + weak open var referenceView: ListContainerView? - fileprivate var didInitializeCell = false - fileprivate var didSetStateClosure: ((StateType?) -> Void)? + fileprivate var didInitializeCell = false + fileprivate var didSetStateClosure: ((StateType?) -> Void)? - public required init(reuseIdentifier: String) { - super.init(style: .default, reuseIdentifier: reuseIdentifier) - } + public required init(reuseIdentifier: String) { + super.init(style: .default, reuseIdentifier: reuseIdentifier) + } - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - open func initializeCellIfNecessary(_ view: ViewType, - didSetState: ((StateType?) -> Void)? = nil) { + open func initializeCellIfNecessary(_ view: ViewType, + didSetState: ((StateType?) -> Void)? = nil) { - assert(Thread.isMainThread) + assert(Thread.isMainThread) - // make sure this happens just once. - if self.didInitializeCell { return } - self.didInitializeCell = true + // make sure this happens just once. + if self.didInitializeCell { return } + self.didInitializeCell = true - self.view = view - self.contentView.addSubview(view) - self.didSetStateClosure = didSetState - } + self.view = view + self.contentView.addSubview(view) + self.didSetStateClosure = didSetState + } - open func applyState(_ state: T) { - self.state = state as? StateType - } + open func applyState(_ state: T) { + self.state = state as? StateType + } - /// Asks the view to calculate and return the size that best fits the specified size. - /// - parameter size: The size for which the view should calculate its best-fitting size. - /// - returns: A new size that fits the receiver’s subviews. - open override func sizeThatFits(_ size: CGSize) -> CGSize { - let size = view.sizeThatFits(size) - return size - } + /** Asks the view to calculate and return the size that best fits the specified size. + * - parameter size: The size for which the view should calculate its best-fitting size. + * - returns: A new size that fits the receiver’s subviews. + */ + open override func sizeThatFits(_ size: CGSize) -> CGSize { + let size = view.sizeThatFits(size) + return size + } - /// Returns the natural size for the receiving view, considering only properties of the - /// view itself. - /// - returns: A size indicating the natural size for the receiving view based on its - /// intrinsic properties. - open override var intrinsicContentSize : CGSize { - return view.intrinsicContentSize - } + /** Returns the natural size for the receiving view, considering only properties of the + * view itself. + * - returns: A size indicating the natural size for the receiving view based on its + * intrinsic properties. + */ + open override var intrinsicContentSize : CGSize { + return view.intrinsicContentSize } +} - open class PrototypeCollectionViewCell : - UICollectionViewCell, PrototypeViewCell { +open class PrototypeCollectionViewCell : +UICollectionViewCell, PrototypeViewCell { - ///The wrapped view. - open var view: ViewType! + ///The wrapped view. + open var view: ViewType! - ///The state for this cell. - /// - Note: This is propagated to the associted. - open var state: StateType? { - didSet { - didSetStateClosure?(state) - } + ///The state for this cell. + /// - Note: This is propagated to the associted. + open var state: StateType? { + didSet { + didSetStateClosure?(state) } + } - weak open var referenceView: ListContainerView? + weak open var referenceView: ListContainerView? - fileprivate var didInitializeCell = false - fileprivate var didSetStateClosure: ((StateType?) -> Void)? + fileprivate var didInitializeCell = false + fileprivate var didSetStateClosure: ((StateType?) -> Void)? - public required init(reuseIdentifier: String) { - super.init(frame: CGRect.zero) - } + public required init(reuseIdentifier: String) { + super.init(frame: CGRect.zero) + } - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - open func initializeCellIfNecessary(_ view: ViewType, - didSetState: ((StateType?) -> Void)? = nil) { + open func initializeCellIfNecessary(_ view: ViewType, + didSetState: ((StateType?) -> Void)? = nil) { - assert(Thread.isMainThread) + assert(Thread.isMainThread) - //make sure this happens just once - if self.didInitializeCell { return } - self.didInitializeCell = true + // make sure this happens just once + if self.didInitializeCell { return } + self.didInitializeCell = true - self.view = view - self.contentView.addSubview(view) - self.didSetStateClosure = didSetState - } + self.view = view + self.contentView.addSubview(view) + self.didSetStateClosure = didSetState + } - open func applyState(_ state: T) { - self.state = state as? StateType - } + open func applyState(_ state: T) { + self.state = state as? StateType + } - /// Asks the view to calculate and return the size that best fits the specified size. - /// - parameter size: The size for which the view should calculate its best-fitting size. - /// - returns: A new size that fits the receiver’s subviews. - open override func sizeThatFits(_ size: CGSize) -> CGSize { - let size = view.sizeThatFits(size) - return size - } + /** Asks the view to calculate and return the size that best fits the specified size. + * - parameter size: The size for which the view should calculate its best-fitting size. + * - returns: A new size that fits the receiver’s subviews. + */ + open override func sizeThatFits(_ size: CGSize) -> CGSize { + let size = view.sizeThatFits(size) + return size + } - /// Returns the natural size for the receiving view, considering only properties of the - /// view itself. - /// - returns: A size indicating the natural size for the receiving view based on its - /// intrinsic properties. - open override var intrinsicContentSize : CGSize { - return view.intrinsicContentSize - } + /** Returns the natural size for the receiving view, considering only properties of the + * view itself. + * - returns: A size indicating the natural size for the receiving view based on its + * intrinsic properties. + */ + open override var intrinsicContentSize : CGSize { + return view.intrinsicContentSize } +} - public struct Prototypes { - fileprivate static var registeredPrototypes = [String: PrototypeViewCell]() +public struct Prototypes { + fileprivate static var registeredPrototypes = [String: PrototypeViewCell]() - ///Wether there's a prototype registered for a given reusedIdentifier. - public static func isPrototypeCellRegistered(_ reuseIdentifier: String) -> Bool { - guard let _ = Prototypes.registeredPrototypes[reuseIdentifier] else { return false } - return true - } + /** Wether there's a prototype registered for a given reusedIdentifier. */ + public static func isPrototypeCellRegistered(_ reuseIdentifier: String) -> Bool { + guard let _ = Prototypes.registeredPrototypes[reuseIdentifier] else { return false } + return true + } - ///Register a cell a prototype for a given reuse identifer. - public static func registerPrototypeCell(_ reuseIdentifier: String, cell: PrototypeViewCell) { - Prototypes.registeredPrototypes[reuseIdentifier] = cell - } + /** Register a cell a prototype for a given reuse identifer. */ + public static func registerPrototypeCell(_ reuseIdentifier: String, cell: PrototypeViewCell) { + Prototypes.registeredPrototypes[reuseIdentifier] = cell + } - ///Computes the size for the cell registered as prototype associate to the item passed - /// as argument. - /// - parameter item: The target item for size calculation. - public static func prototypeCellSize(_ item: AnyListItem) -> CGSize { - guard let cell = Prototypes.registeredPrototypes[item.reuseIdentifier] else { - fatalError("Unregistered prototype with reuse identifier \(item.reuseIdentifier).") - } - - cell.applyState(item.state) - cell.referenceView = item.referenceView - item.cellConfiguration?(cell, item.state) - - if let cell = cell as? UIView { - return cell.bounds.size - } else { - return CGSize.zero - } + /** Computes the size for the cell registered as prototype associate to the item passed + * as argument. + * - parameter item: The target item for size calculation. + */ + public static func prototypeCellSize(_ item: AnyListItem) -> CGSize { + guard let cell = Prototypes.registeredPrototypes[item.reuseIdentifier] else { + fatalError("Unregistered prototype with reuse identifier \(item.reuseIdentifier).") } - } + cell.applyState(item.state) + cell.referenceView = item.referenceView + item.cellConfiguration?(cell, item.state) + if let cell = cell as? UIView { + return cell.bounds.size + } else { + return CGSize.zero + } + } +} #endif diff --git a/Buffer/TableView.swift b/Buffer/TableView.swift index 0a0eecf..2828d8f 100644 --- a/Buffer/TableView.swift +++ b/Buffer/TableView.swift @@ -1,63 +1,40 @@ -// -// BufferDiffCollectionView.swift -// BufferDiff -// -// Copyright (c) 2016 Alex Usbergo. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// #if os(iOS) +import UIKit - open class TableView: UITableView { +open class TableView: UITableView { - /// The elements for the table view. - open var elements = [AnyListItem]() { - didSet { - self.adapter.buffer.update(with: self.elements) - } + /** The elements for the table view. */ + open var elements = [AnyListItem]() { + didSet { + self.adapter.buffer.update(with: self.elements) } + } - /// The adapter for this table view. - open lazy var adapter: TableViewDiffAdapter> = { - return TableViewDiffAdapter(initialElements: [AnyListItem](), view: self) - }() + /** The adapter for this table view. */ + open lazy var adapter: TableViewDiffAdapter> = { + return TableViewDiffAdapter(initialElements: [AnyListItem](), view: self) + }() - public convenience init() { - self.init(frame: CGRect.zero, style: .plain) - } + public convenience init() { + self.init(frame: CGRect.zero, style: .plain) + } - public override init(frame: CGRect, style: UITableViewStyle) { - super.init(frame: frame, style: style) + public override init(frame: CGRect, style: UITableViewStyle) { + super.init(frame: frame, style: style) - self.rowHeight = UITableViewAutomaticDimension - self.adapter.useAsDataSource() { tableView, item, indexPath in - let cell = tableView.dequeueReusableCell( - withIdentifier: item.reuseIdentifier, for: indexPath as IndexPath) - item.cellConfiguration?(cell, item.state) - return cell - } + self.rowHeight = UITableViewAutomaticDimension + self.adapter.useAsDataSource() { tableView, item, indexPath in + let cell = tableView.dequeueReusableCell( + withIdentifier: item.reuseIdentifier, for: indexPath as IndexPath) + item.cellConfiguration?(cell, item.state) + return cell } + } - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") } +} #endif diff --git a/Buffer/TableViewDiffAdapter.swift b/Buffer/TableViewDiffAdapter.swift index 2226712..1ae8b93 100644 --- a/Buffer/TableViewDiffAdapter.swift +++ b/Buffer/TableViewDiffAdapter.swift @@ -1,152 +1,130 @@ -// -// Adapters.swift -// Buffer -// -// Copyright (c) 2016 Alex Usbergo. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - #if os(iOS) - import UIKit +import UIKit - open class TableViewDiffAdapter: - NSObject, AdapterType, UITableViewDataSource { +open class TableViewDiffAdapter: + NSObject, AdapterType, UITableViewDataSource { - public typealias `Type` = ElementType - public typealias ViewType = UITableView + public typealias `Type` = ElementType + public typealias ViewType = UITableView - open fileprivate(set) var buffer: Buffer + open fileprivate(set) var buffer: Buffer - open fileprivate(set) weak var view: ViewType? + open fileprivate(set) weak var view: ViewType? - /// Right now this only works on a single section of a tableView. - /// If your tableView has multiple sections, though, you can just use multiple - /// TableViewDiffAdapter, one per section, and set this value appropriately on each one. - open var sectionIndex: Int = 0 + /** Right now this only works on a single section of a tableView. + * If your tableView has multiple sections, though, you can just use multiple + * TableViewDiffAdapter, one per section, and set this value appropriately on each one. + */ + open var sectionIndex: Int = 0 - public required init(buffer: BufferType, view: ViewType) { - guard let buffer = buffer as? Buffer else { - fatalError() - } - self.buffer = buffer - self.view = view - super.init() - self.buffer.delegate = self + public required init(buffer: BufferType, view: ViewType) { + guard let buffer = buffer as? Buffer else { + fatalError() } + self.buffer = buffer + self.view = view + super.init() + self.buffer.delegate = self + } - public required init(initialElements: [ElementType], view: ViewType) { - self.buffer = Buffer(initialArray: initialElements) - self.view = view - super.init() - self.buffer.delegate = self - } + public required init(initialElements: [ElementType], view: ViewType) { + self.buffer = Buffer(initialArray: initialElements) + self.view = view + super.init() + self.buffer.delegate = self + } - fileprivate var cellForRowAtIndexPath: - ((UITableView, ElementType, IndexPath) -> UITableViewCell)? = nil + fileprivate var cellForRowAtIndexPath: + ((UITableView, ElementType, IndexPath) -> UITableViewCell)? = nil - /// Returns the element currently on the front buffer at the given index path. - open func displayedElement(at index: Int) -> Type { - return self.buffer.currentElements[index] - } + /** Returns the element currently on the front buffer at the given index path. */ + open func displayedElement(at index: Int) -> Type { + return self.buffer.currentElements[index] + } - ///The total number of elements currently displayed. - open func countDisplayedElements() -> Int { - return self.buffer.currentElements.count - } + /** The total number of elements currently displayed. */ + open func countDisplayedElements() -> Int { + return self.buffer.currentElements.count + } - /// Replace the elements buffer and compute the diffs. - /// - parameter newValues: The new values. - /// - parameter synchronous: Wether the filter, sorting and diff should be - /// executed synchronously or not. - /// - parameter completion: Code that will be executed once the buffer is updated. - open func update(with newValues: [ElementType]? = nil, - synchronous: Bool = false, - completion: ((Void) -> Void)? = nil) { - self.buffer.update(with: newValues, synchronous: synchronous, completion: completion) - } + /** Replace the elements buffer and compute the diffs. + * - parameter newValues: The new values. + * - parameter synchronous: Wether the filter, sorting and diff should be + * executed synchronously or not. + * - parameter completion: Code that will be executed once the buffer is updated. + */ + open func update(with newValues: [ElementType]? = nil, + synchronous: Bool = false, + completion: ((Void) -> Void)? = nil) { + self.buffer.update(with: newValues, synchronous: synchronous, completion: completion) + } - /// Configure the TableView to use this adapter as its DataSource. - /// - parameter automaticDimension: If you wish to use 'UITableViewAutomaticDimension' - /// as 'rowHeight'. - /// - parameter estimatedHeight: The estimated average height for the cells. - /// - parameter cellForRowAtIndexPath: The closure that returns a cell for the - /// given index path. - open func useAsDataSource(_ cellForRowAtIndexPath: - @escaping (UITableView, ElementType, IndexPath) -> UITableViewCell) { - self.view?.dataSource = self - self.cellForRowAtIndexPath = cellForRowAtIndexPath - } + /** Configure the TableView to use this adapter as its DataSource. + * - parameter automaticDimension: If you wish to use 'UITableViewAutomaticDimension' + * as 'rowHeight'. + * - parameter estimatedHeight: The estimated average height for the cells. + * - parameter cellForRowAtIndexPath: The closure that returns a cell for the + * given index path. + */ + open func useAsDataSource(_ cellForRowAtIndexPath: + @escaping (UITableView, ElementType, IndexPath) -> UITableViewCell) { + self.view?.dataSource = self + self.cellForRowAtIndexPath = cellForRowAtIndexPath + } - /// Tells the data source to return the number of rows in a given section of a table view. - dynamic open func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - return self.buffer.currentElements.count - } + /** Tells the data source to return the number of rows in a given section of a table view. */ + dynamic open func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + return self.buffer.currentElements.count + } - /// Asks the data source for a cell to insert in a particular location of the table view. - open func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - return self.cellForRowAtIndexPath!( - tableView, self.buffer.currentElements[(indexPath as NSIndexPath).row], indexPath) - } + /** Asks the data source for a cell to insert in a particular location of the table view. */ + open func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + return self.cellForRowAtIndexPath!( + tableView, self.buffer.currentElements[(indexPath as NSIndexPath).row], indexPath) } +} - extension TableViewDiffAdapter: BufferDelegate { +extension TableViewDiffAdapter: BufferDelegate { - /// Notifies the receiver that the content is about to change. - public func buffer(willChangeContent buffer: BufferType) { - self.view?.beginUpdates() - } + /** Notifies the receiver that the content is about to change. */ + public func buffer(willChangeContent buffer: BufferType) { + self.view?.beginUpdates() + } - /// Notifies the receiver that rows were deleted. - public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) { - let deletionIndexPaths = indices.map({ - IndexPath(row: Int($0), section: self.sectionIndex) - }) - self.view?.deleteRows(at: deletionIndexPaths, with: .automatic) - } + /** Notifies the receiver that rows were deleted. */ + public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) { + let deletionIndexPaths = indices.map({ + IndexPath(row: Int($0), section: self.sectionIndex) + }) + self.view?.deleteRows(at: deletionIndexPaths, with: .automatic) + } - // /Notifies the receiver that rows were inserted. - public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) { - let insertionIndexPaths = indices.map({ - IndexPath(row: Int($0), section: self.sectionIndex) - }) - self.view?.insertRows(at: insertionIndexPaths, with: .automatic) - } + /** Notifies the receiver that rows were inserted. */ + public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) { + let insertionIndexPaths = indices.map({ + IndexPath(row: Int($0), section: self.sectionIndex) + }) + self.view?.insertRows(at: insertionIndexPaths, with: .automatic) + } - /// Notifies the receiver that the content updates has ended. - public func buffer(didChangeContent buffer: BufferType) { - self.view?.endUpdates() - } + /** Notifies the receiver that the content updates has ended. */ + public func buffer(didChangeContent buffer: BufferType) { + self.view?.endUpdates() + } - /// Called when one of the observed properties for this object changed. - public func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) { - self.view?.reloadRows( - at: [IndexPath(row: Int(index), section: self.sectionIndex)], - with: .automatic) - } + /** Called when one of the observed properties for this object changed. */ + public func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) { + self.view?.reloadRows( + at: [IndexPath(row: Int(index), section: self.sectionIndex)], + with: .automatic) + } - /// Notifies the receiver that the content updates has ended and the whole array changed. - public func buffer(didChangeAllContent buffer: BufferType) { - self.view?.reloadData() - } + /** Notifies the receiver that the content updates has ended and the whole array changed. */ + public func buffer(didChangeAllContent buffer: BufferType) { + self.view?.reloadData() } +} #endif diff --git a/LICENSE b/LICENSE index 9a554bd..6af782c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -The MIT License (MIT) +For Buffer -Copyright (c) 2016 Alex Usbergo +Copyright (c) 2016-present Alex Usbergo. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +9,14 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +