diff --git a/.DS_Store b/.DS_Store index 2351a99..1bd6031 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Buffer.xcodeproj/project.pbxproj b/Buffer.xcodeproj/project.pbxproj index a4eb66e..60a8913 100644 --- a/Buffer.xcodeproj/project.pbxproj +++ b/Buffer.xcodeproj/project.pbxproj @@ -135,6 +135,7 @@ TargetAttributes = { 160E255E1CF44C3700A5F828 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; }; }; }; @@ -290,6 +291,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -307,6 +309,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.s.Buffer; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Buffer/AdapterType.swift b/Buffer/AdapterType.swift index d03fc9a..02a61f4 100644 --- a/Buffer/AdapterType.swift +++ b/Buffer/AdapterType.swift @@ -28,11 +28,11 @@ import Foundation public protocol AdapterType { - associatedtype Type + associatedtype `Type` associatedtype ViewType ///Returns the element currently on the front buffer at the given index path. - func displayedElementAtIndex(index: Int) -> Type + func displayedElement(at index: Int) -> Type ///The total number of elements currently displayed. func countDisplayedElements() -> Int @@ -42,7 +42,7 @@ public protocol AdapterType { /// - 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(newValues: [Type]?, synchronous: Bool, completion: ((Void) -> Void)?) + func update(with values: [Type]?, synchronous: Bool, completion: ((Void) -> Void)?) ///The section index associated with this adapter. var sectionIndex: Int { get set } diff --git a/Buffer/AnyListItem.swift b/Buffer/AnyListItem.swift index 9e63398..f1d8a5a 100644 --- a/Buffer/AnyListItem.swift +++ b/Buffer/AnyListItem.swift @@ -54,11 +54,12 @@ public struct AnyListItem: Equatable { public var cellConfiguration: ((ListViewCell, Type) -> Void)? #if os(iOS) - public init(type: V.Type, - referenceView: ListContainerView, - reuseIdentifer: String = String(V.self), - state: Type, - configurationClosure: ((ListViewCell, Type) -> Void)? = nil) { + public init( + type: V.Type, + referenceView: ListContainerView, + reuseIdentifer: String = String(describing: V.self), + state: Type, + configurationClosure: ((ListViewCell, Type) -> Void)? = nil) { //registers the prototype cell if necessary. if !Prototypes.isPrototypeCellRegistered(reuseIdentifer) { @@ -70,33 +71,34 @@ public struct AnyListItem: Equatable { self.cellConfiguration = configurationClosure self.referenceView = referenceView self.state = state - self.configureRefenceView(type) + self.registerReferenceView(with: type) } #endif - public init(type: V.Type, - referenceView: ListContainerView? = nil, - reuseIdentifer: String = String(V.self), - state: Type, - configurationClosure: ((ListViewCell, Type) -> Void)? = nil) { + public init( + type: V.Type, + referenceView: ListContainerView? = nil, + reuseIdentifer: String = String(describing: V.self), + state: Type, + configurationClosure: ((ListViewCell, Type) -> Void)? = nil) { self.reuseIdentifier = reuseIdentifer self.cellConfiguration = configurationClosure self.referenceView = referenceView self.state = state - self.configureRefenceView(type) + self.registerReferenceView(with: type) } - private func configureRefenceView(cellClass: AnyClass) { + fileprivate func registerReferenceView(with cellClass: AnyClass) { #if os(iOS) if let tableView = self.referenceView as? UITableView { - tableView.registerClass(cellClass, + tableView.register(cellClass, forCellReuseIdentifier: self.reuseIdentifier) } if let collectionView = self.referenceView as? UICollectionView { - collectionView.registerClass(cellClass, + collectionView.register(cellClass, forCellWithReuseIdentifier: self.reuseIdentifier) } #endif } -} \ No newline at end of file +} diff --git a/Buffer/Buffer.swift b/Buffer/Buffer.swift index 31814bf..6e762e6 100644 --- a/Buffer/Buffer.swift +++ b/Buffer/Buffer.swift @@ -1,3 +1,4 @@ + // // Buffer.swift // Buffer @@ -32,16 +33,16 @@ public protocol BufferType { } public protocol BufferDelegate: class { /// Notifies the receiver that the content is about to change - func bufferWillChangeContent(buffer: BufferType) + func buffer(willChangeContent buffer: BufferType) /// Notifies the receiver that rows were deleted. - func bufferDidDeleteElementAtIndices(buffer: BufferType, indices: [UInt]) + func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) /// Notifies the receiver that rows were inserted. - func bufferDidInsertElementsAtIndices(buffer: BufferType, indices: [UInt]) + func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) /// Notifies the receiver that the content updates has ended. - func bufferDidChangeContent(buffer: BufferType) + 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 @@ -49,10 +50,10 @@ public protocol BufferDelegate: class { /// - Note: The 'diffThreshold' property in 'Buffer' defines what is the maximum number /// of changes /// that you want the receiver to be notified for. - func bufferDidChangeAllContent(buffer: BufferType) + func buffer(didChangeAllContent buffer: BufferType) /// Called when one of the observed properties for this object changed - func bufferDidChangeElementAtIndex(buffer: BufferType, index: UInt) + func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) } public class Buffer: NSObject, BufferType { @@ -69,39 +70,39 @@ public class Buffer: NSObject, BufferType { public var diffThreshold = 50 /// If set to 'true' the LCS algorithm is run synchronously on the main thread. - private var synchronous: Bool = false + fileprivate var synchronous: Bool = false /// The two buffers. - private var frontBuffer = [ElementType]() { + fileprivate var frontBuffer = [ElementType]() { willSet { - assert(NSThread.isMainThread()) - self.observeTrackedKeyPaths(false) + assert(Thread.isMainThread) + self.observe(shouldObserveTrackedKeyPaths: false) } didSet { - assert(NSThread.isMainThread()) - self.observeTrackedKeyPaths(true) + assert(Thread.isMainThread) + self.observe(shouldObserveTrackedKeyPaths: true) } } - private var backBuffer = [ElementType]() + fileprivate var backBuffer = [ElementType]() /// Sort closure. - private var sort: ((ElementType, ElementType) -> Bool)? + fileprivate var sort: ((ElementType, ElementType) -> Bool)? /// Filter closure. - private var filter: ((ElementType) -> Bool)? + fileprivate var filter: ((ElementType) -> Bool)? /// The serial operation queue for this controller. - private let serialOperationQueue: NSOperationQueue = { - let operationQueue = NSOperationQueue() + fileprivate let serialOperationQueue: OperationQueue = { + let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 return operationQueue }() - private var flags = (isRefreshing: false, + fileprivate var flags = (isRefreshing: false, shouldRefresh: false) /// Used if 'Element' is KVO-compliant. - private var trackedKeyPaths = [String]() + fileprivate var trackedKeyPaths = [String]() public init(initialArray: [ElementType], sort: ((ElementType, ElementType) -> Bool)? = nil, @@ -113,19 +114,19 @@ public class Buffer: NSObject, BufferType { } deinit { - self.observeTrackedKeyPaths(false) + self.observe(shouldObserveTrackedKeyPaths: false) } /// Compute the diffs between the current array and the new one passed as argument. public func update( - newValues: [ElementType]? = nil, + with values: [ElementType]? = nil, synchronous: Bool = false, completion: ((Void) -> Void)? = nil) { - let new = newValues ?? self.frontBuffer + let new = values ?? self.frontBuffer // Should be called on the main thread. - assert(NSThread.isMainThread()) + assert(Thread.isMainThread) self.backBuffer = new @@ -137,7 +138,7 @@ public class Buffer: NSObject, BufferType { self.flags.isRefreshing = true - self.dispatchOnSerialQueue(synchronous) { + self.dispatchOnSerialQueue(synchronous: synchronous) { var backBuffer = self.backBuffer @@ -146,34 +147,34 @@ public class Buffer: NSObject, BufferType { backBuffer = backBuffer.filter(filter) } if let sort = self.sort { - backBuffer = backBuffer.sort(sort) + backBuffer = backBuffer.sorted(by: sort) } // Compute the diff on the background thread. let diff = self.frontBuffer.diff(backBuffer) - self.dispatchOnMainThread(synchronous) { + self.dispatchOnMainThread(synchronous: synchronous) { //swaps the buffers. self.frontBuffer = backBuffer if diff.insertions.count < self.diffThreshold && diff.deletions.count < self.diffThreshold { - self.delegate?.bufferWillChangeContent(self) - self.delegate?.bufferDidInsertElementsAtIndices( - self, indices: diff.insertions.map({ UInt($0.idx) })) - self.delegate?.bufferDidDeleteElementAtIndices( - self, indices: diff.deletions.map({ UInt($0.idx) })) - self.delegate?.bufferDidChangeContent(self) + self.delegate?.buffer(willChangeContent: self) + self.delegate?.buffer(didInsertElementsAtIndices: self, + indices: diff.insertions.map({ UInt($0.idx) })) + self.delegate?.buffer(didDeleteElementAtIndices: self, + indices: diff.deletions.map({ UInt($0.idx) })) + self.delegate?.buffer(didChangeContent: self) } else { - self.delegate?.bufferDidChangeAllContent(self) + self.delegate?.buffer(didChangeAllContent: self) } //re-rerun refresh if necessary. self.flags.isRefreshing = false if self.flags.shouldRefresh { self.flags.shouldRefresh = false - self.update(self.backBuffer) + self.update(with: self.backBuffer) } completion?() @@ -183,17 +184,17 @@ 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. - public override func observeValueForKeyPath(keyPath: String?, - ofObject object: AnyObject?, - change: [String : AnyObject]?, - context: UnsafeMutablePointer) { + public override func observeValue(forKeyPath keyPath: String?, + of object: Any?, + change: [NSKeyValueChangeKey : Any]?, + context: UnsafeMutableRawPointer?) { if context != &__observationContext { - super.observeValueForKeyPath(keyPath, ofObject:object, change:change, context:context) + super.observeValue(forKeyPath: keyPath, of:object, change:change, context:context) return } if self.trackedKeyPaths.contains(keyPath!) { - self.objectDidChangeValueForKeyPath(keyPath, object: object) + self.objectDidChangeValue(for: keyPath, in: object as AnyObject?) } } @@ -204,28 +205,28 @@ public class Buffer: NSObject, BufferType { extension Buffer where ElementType: AnyObject { ///Observe the keypaths passed as argument. - public func trackKeyPaths(keypaths: [String]) { - self.observeTrackedKeyPaths(false) + public func trackKeyPaths(_ keypaths: [String]) { + self.observe(shouldObserveTrackedKeyPaths: false) self.trackedKeyPaths = keypaths - self.observeTrackedKeyPaths() + self.observe() } } extension Buffer { - ///Adds or remove observations. - ///- Note: This code is executed only when 'Element: AnyObject'. - private func observeTrackedKeyPaths(observe: Bool = true) { + /// 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 } for keyPath in trackedKeyPaths { for item in self.frontBuffer { - if let object = item as? AnyObject { - if observe { + if let object = item as? NSObject { + if shouldObserveTrackedKeyPaths { object.addObserver(self, forKeyPath: keyPath, - options: NSKeyValueObservingOptions.New, + options: NSKeyValueObservingOptions.new, context: &__observationContext) } else { @@ -236,8 +237,8 @@ extension Buffer { } } - ///- Note: This code is executed only when 'Element: AnyObject'. - private func objectDidChangeValueForKeyPath(keyPath: String?, object: AnyObject?) { + /// - Note: This code is executed only when 'Element: AnyObject'. + fileprivate func objectDidChangeValue(for keyPath: String?, in object: AnyObject?) { dispatchOnMainThread { self.update() { var idx = 0 @@ -246,7 +247,7 @@ extension Buffer { idx += 1 } if idx < self.frontBuffer.count { - self.delegate?.bufferDidChangeElementAtIndex(self, index: UInt(idx)) + self.delegate?.buffer(didChangeElementAtIndex: self, index: UInt(idx)) } } } @@ -257,24 +258,26 @@ private var __observationContext: UInt8 = 0 //MARK: Dispatch Helpers -extension Buffer { +fileprivate extension Buffer { - private func dispatchOnMainThread(synchronous: Bool = false, block: (Void) -> (Void)) { + func dispatchOnMainThread(synchronous: Bool = false, + block: @escaping (Void) -> (Void)) { if synchronous { - assert(NSThread.isMainThread()) + assert(Thread.isMainThread) block() } else { - if NSThread.isMainThread() { block() - } else { dispatch_async(dispatch_get_main_queue(), block) } + if Thread.isMainThread { block() + } else { DispatchQueue.main.async(execute: block) } } } - private func dispatchOnSerialQueue(synchronous: Bool = false, block: (Void) -> (Void)) { + func dispatchOnSerialQueue(synchronous: Bool = false, + block: @escaping (Void) -> (Void)) { if synchronous { block() } else { - self.serialOperationQueue.addOperationWithBlock(){ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), block) + self.serialOperationQueue.addOperation(){ + DispatchQueue.global().async(execute: block) } } } diff --git a/Buffer/CollectionViewDiffAdapter.swift b/Buffer/CollectionViewDiffAdapter.swift index 526f68c..e7f7ccf 100644 --- a/Buffer/CollectionViewDiffAdapter.swift +++ b/Buffer/CollectionViewDiffAdapter.swift @@ -26,20 +26,20 @@ #if os(iOS) import UIKit - public class CollectionViewDiffAdapter: + open class CollectionViewDiffAdapter: NSObject, AdapterType, UICollectionViewDataSource { - public typealias Type = ElementType + public typealias `Type` = ElementType public typealias ViewType = UICollectionView - public private(set) var buffer: Buffer + open fileprivate(set) var buffer: Buffer - public private(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. - public var sectionIndex: Int = 0 + open var sectionIndex: Int = 0 public required init(buffer: BufferType, view: ViewType) { guard let buffer = buffer as? Buffer else { @@ -58,18 +58,18 @@ self.buffer.delegate = self } - private var indexPaths: (insertion: [NSIndexPath], deletion: [NSIndexPath]) = ([], []) + fileprivate var indexPaths: (insertion: [IndexPath], deletion: [IndexPath]) = ([], []) - private var cellForItemAtIndexPath: ((UICollectionView, ElementType, NSIndexPath) + fileprivate var cellForItemAtIndexPath: ((UICollectionView, ElementType, IndexPath) -> UICollectionViewCell)? = nil /// Returns the element currently on the front buffer at the given index path. - public func displayedElementAtIndex(index: Int) -> Type { + open func displayedElement(at index: Int) -> ElementType { return self.buffer.currentElements[index] } /// The total number of elements currently displayed. - public func countDisplayedElements() -> Int { + open func countDisplayedElements() -> Int { return self.buffer.currentElements.count } @@ -78,10 +78,10 @@ /// - 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. - public func update(newValues: [ElementType]? = nil, - synchronous: Bool = false, - completion: ((Void) -> Void)? = nil) { - self.buffer.update(newValues, synchronous: synchronous, completion: completion) + 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. @@ -90,64 +90,63 @@ /// - parameter estimatedHeight: The estimated average height for the cells. /// - parameter cellForRowAtIndexPath: The closure that returns a cell for the given /// index path. - public func useAsDataSource(cellForItemAtIndexPath: - (UICollectionView, ElementType, NSIndexPath) -> UICollectionViewCell) { + 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. - public func collectionView(collectionView: UICollectionView, + 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. - public func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath - indexPath: NSIndexPath) -> UICollectionViewCell { - return self.cellForItemAtIndexPath!(collectionView, - self.buffer.currentElements[indexPath.row], - indexPath) + open func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + return self.cellForItemAtIndexPath!( + collectionView, self.buffer.currentElements[(indexPath as NSIndexPath).row], indexPath) } } extension CollectionViewDiffAdapter: BufferDelegate { /// Notifies the receiver that the content is about to change. - public func bufferWillChangeContent(buffer: BufferType) { + public func buffer(willChangeContent buffer: BufferType) { self.indexPaths = ([], []) } /// Notifies the receiver that rows were deleted. - public func bufferDidDeleteElementAtIndices(buffer: BufferType, indices: [UInt]) { + public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) { self.indexPaths.deletion = indices.map({ - NSIndexPath(forRow: Int($0), inSection: self.sectionIndex) + IndexPath(row: Int($0), section: self.sectionIndex) }) } /// Notifies the receiver that rows were inserted. - public func bufferDidInsertElementsAtIndices(buffer: BufferType, indices: [UInt]) { + public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) { self.indexPaths.insertion = indices.map({ - NSIndexPath(forRow: Int($0), inSection: self.sectionIndex) + IndexPath(row: Int($0), section: self.sectionIndex) }) } /// Notifies the receiver that the content updates has ended. - public func bufferDidChangeContent(buffer: BufferType) { + public func buffer(didChangeContent buffer: BufferType) { self.view?.performBatchUpdates({ - self.view?.insertItemsAtIndexPaths(self.indexPaths.insertion) - self.view?.deleteItemsAtIndexPaths(self.indexPaths.deletion) + 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 bufferDidChangeElementAtIndex(buffer: BufferType, index: UInt) { - self.view?.reloadItemsAtIndexPaths( - [NSIndexPath(forRow: Int(index), inSection: self.sectionIndex)]) + 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 bufferDidChangeAllContent(buffer: BufferType) { + public func buffer(didChangeAllContent buffer: BufferType) { self.view?.reloadData() } } diff --git a/Buffer/LCS.swift b/Buffer/LCS.swift index b4212c4..ec69ef1 100644 --- a/Buffer/LCS.swift +++ b/Buffer/LCS.swift @@ -29,17 +29,17 @@ import Foundation public struct Diff { public let results: [DiffStep] public var insertions: [DiffStep] { - return results.filter({ $0.isInsertion }).sort { $0.idx < $1.idx } + return results.filter({ $0.isInsertion }).sorted { $0.idx < $1.idx } } public var deletions: [DiffStep] { - return results.filter({ !$0.isInsertion }).sort { $0.idx > $1.idx } + return results.filter({ !$0.isInsertion }).sorted { $0.idx > $1.idx } } public func reversed() -> Diff { - let reversedResults = self.results.reverse().map { + let reversedResults = self.results.reversed().map { (result: DiffStep) -> DiffStep in switch result { - case .Insert(let i, let j): return .Delete(i, j) - case .Delete(let i, let j): return .Insert(i, j) + case .insert(let i, let j): return .delete(i, j) + case .delete(let i, let j): return .insert(i, j) } } return Diff(results: reversedResults) @@ -52,31 +52,31 @@ public func + (left: Diff, right: DiffStep) -> Diff { /// 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) + case insert(Int, Type) + case delete(Int, Type) var isInsertion: Bool { switch(self) { - case .Insert: return true - case .Delete: return false + case .insert: return true + case .delete: return false } } public var idx: Int { switch(self) { - case .Insert(let i, _): return i - case .Delete(let i, _): return i + case .insert(let i, _): return i + case .delete(let i, _): return i } } public var value: Type { switch(self) { - case .Insert(let j): return j.1 - case .Delete(let j): return j.1 + case .insert(let j): return j.1 + case .delete(let j): return j.1 } } } private struct MemoizedSequenceComparison { - private static func buildTable(x: [Type], _ y: [Type], _ n: Int, _ m: Int) -> [[Int]] { - var table = Array(count: n + 1, repeatedValue: Array(count: m + 1, repeatedValue: 0)) + fileprivate static func buildTable(_ x: [Type], _ y: [Type], _ n: Int, _ m: Int) -> [[Int]] { + var table = Array(repeating: Array(repeating: 0, count: m + 1), count: n + 1) for i in 0...n { for j in 0...m { if (i == 0 || j == 0) { @@ -96,25 +96,25 @@ private struct MemoizedSequenceComparison { public extension Array where Element: Equatable { /// Returns the sequence of ArrayDiffResults required to transform one array into another. - public func diff(other: [Element]) -> Diff { + 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. - private static func diffFromIndices( - table: [[Int]], _ x: [Element], _ y: [Element], _ i: Int, _ j: Int) -> Diff { + fileprivate static func diffFromIndices( + _ table: [[Int]], _ x: [Element], _ y: [Element], _ i: Int, _ j: Int) -> Diff { if i == 0 && j == 0 { return Diff(results: []) } else if i == 0 { - return diffFromIndices(table, x, y, i, j-1) + DiffStep.Insert(j-1, y[j-1]) + return diffFromIndices(table, x, y, i, j-1) + DiffStep.insert(j-1, y[j-1]) } else if j == 0 { - return diffFromIndices(table, x, y, i - 1, j) + DiffStep.Delete(i-1, x[i-1]) + return diffFromIndices(table, x, y, i - 1, j) + DiffStep.delete(i-1, x[i-1]) } else if table[i][j] == table[i][j-1] { - return diffFromIndices(table, x, y, i, j-1) + DiffStep.Insert(j-1, y[j-1]) + return diffFromIndices(table, x, y, i, j-1) + DiffStep.insert(j-1, y[j-1]) } else if table[i][j] == table[i-1][j] { - return diffFromIndices(table, x, y, i - 1, j) + DiffStep.Delete(i-1, x[i-1]) + return diffFromIndices(table, x, y, i - 1, j) + DiffStep.delete(i-1, x[i-1]) } else { return diffFromIndices(table, x, y, i-1, j-1) } @@ -122,13 +122,13 @@ 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 - private func apply(diff: Diff) -> Array { + fileprivate func apply(_ diff: Diff) -> Array { var copy = self for result in diff.deletions { - copy.removeAtIndex(result.idx) + copy.remove(at: result.idx) } for result in diff.insertions { - copy.insert(result.value, atIndex: result.idx) + copy.insert(result.value, at: result.idx) } return copy } @@ -137,14 +137,14 @@ public extension Array where Element: Equatable { public extension Array where Element: Equatable { /// Returns the longest common subsequence between two arrays. - public func LCS(other: [Element]) -> [Element] { + 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. - private static func lcsFromIndices( - table: [[Int]], _ x: [Element], _ y: [Element], _ i: Int, _ j: Int) -> [Element] { + fileprivate static func lcsFromIndices( + _ table: [[Int]], _ x: [Element], _ y: [Element], _ i: Int, _ j: Int) -> [Element] { if i == 0 && j == 0 { return [] } else if i == 0 { diff --git a/Buffer/PrototypeCell.swift b/Buffer/PrototypeCell.swift index 5921534..a6af112 100644 --- a/Buffer/PrototypeCell.swift +++ b/Buffer/PrototypeCell.swift @@ -33,38 +33,42 @@ // /Apply the state. /// - Note: This is used internally from the infra to set the state. - func applyState(state: T) + func applyState(_ state: T) init(reuseIdentifier: String) } - public class PrototypeTableViewCell : + open class PrototypeTableViewCell : UITableViewCell, PrototypeViewCell { /// The wrapped view. - public var view: ViewType! + open var view: ViewType! /// The state for this cell. /// - Note: This is propagated to the associted- - public var state: StateType? { + open var state: StateType? { didSet { didSetStateClosure?(state) } } - weak public var referenceView: ListContainerView? + weak open var referenceView: ListContainerView? - private var didInitializeCell = false - private var didSetStateClosure: ((StateType?) -> Void)? + fileprivate var didInitializeCell = false + fileprivate var didSetStateClosure: ((StateType?) -> Void)? public required init(reuseIdentifier: String) { - super.init(style: .Default, reuseIdentifier: reuseIdentifier) + super.init(style: .default, reuseIdentifier: reuseIdentifier) } - public func initializeCellIfNecessary(view: ViewType, + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + open func initializeCellIfNecessary(_ view: ViewType, didSetState: ((StateType?) -> Void)? = nil) { - assert(NSThread.isMainThread()) + assert(Thread.isMainThread) // make sure this happens just once. if self.didInitializeCell { return } @@ -75,14 +79,14 @@ self.didSetStateClosure = didSetState } - public func applyState(state: T) { + 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. - public override func sizeThatFits(size: CGSize) -> CGSize { + open override func sizeThatFits(_ size: CGSize) -> CGSize { let size = view.sizeThatFits(size) return size } @@ -91,38 +95,42 @@ /// view itself. /// - returns: A size indicating the natural size for the receiving view based on its /// intrinsic properties. - public override func intrinsicContentSize() -> CGSize { - return view.intrinsicContentSize() + open override var intrinsicContentSize : CGSize { + return view.intrinsicContentSize } } - public class PrototypeCollectionViewCell : + open class PrototypeCollectionViewCell : UICollectionViewCell, PrototypeViewCell { ///The wrapped view. - public var view: ViewType! + open var view: ViewType! ///The state for this cell. /// - Note: This is propagated to the associted. - public var state: StateType? { + open var state: StateType? { didSet { didSetStateClosure?(state) } } - weak public var referenceView: ListContainerView? + weak open var referenceView: ListContainerView? - private var didInitializeCell = false - private var didSetStateClosure: ((StateType?) -> Void)? + fileprivate var didInitializeCell = false + fileprivate var didSetStateClosure: ((StateType?) -> Void)? public required init(reuseIdentifier: String) { super.init(frame: CGRect.zero) } - public func initializeCellIfNecessary(view: ViewType, + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + open func initializeCellIfNecessary(_ view: ViewType, didSetState: ((StateType?) -> Void)? = nil) { - assert(NSThread.isMainThread()) + assert(Thread.isMainThread) //make sure this happens just once if self.didInitializeCell { return } @@ -133,14 +141,14 @@ self.didSetStateClosure = didSetState } - public func applyState(state: T) { + 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. - public override func sizeThatFits(size: CGSize) -> CGSize { + open override func sizeThatFits(_ size: CGSize) -> CGSize { let size = view.sizeThatFits(size) return size } @@ -149,29 +157,29 @@ /// view itself. /// - returns: A size indicating the natural size for the receiving view based on its /// intrinsic properties. - public override func intrinsicContentSize() -> CGSize { - return view.intrinsicContentSize() + open override var intrinsicContentSize : CGSize { + return view.intrinsicContentSize } } public struct Prototypes { - private static var registeredPrototypes = [String: PrototypeViewCell]() + fileprivate static var registeredPrototypes = [String: PrototypeViewCell]() ///Wether there's a prototype registered for a given reusedIdentifier. - public static func isPrototypeCellRegistered(reuseIdentifier: String) -> Bool { + 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) { + 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 { + public static func prototypeCellSize(_ item: AnyListItem) -> CGSize { guard let cell = Prototypes.registeredPrototypes[item.reuseIdentifier] else { fatalError("Unregistered prototype with reuse identifier \(item.reuseIdentifier).") } diff --git a/Buffer/TableView.swift b/Buffer/TableView.swift index 8079c94..0a0eecf 100644 --- a/Buffer/TableView.swift +++ b/Buffer/TableView.swift @@ -25,22 +25,22 @@ #if os(iOS) - public class TableView: UITableView { + open class TableView: UITableView { /// The elements for the table view. - public var elements = [AnyListItem]() { + open var elements = [AnyListItem]() { didSet { - self.adapter.buffer.update(self.elements) + self.adapter.buffer.update(with: self.elements) } } /// The adapter for this table view. - public lazy var adapter: TableViewDiffAdapter> = { + open lazy var adapter: TableViewDiffAdapter> = { return TableViewDiffAdapter(initialElements: [AnyListItem](), view: self) }() public convenience init() { - self.init(frame: CGRect.zero, style: .Plain) + self.init(frame: CGRect.zero, style: .plain) } public override init(frame: CGRect, style: UITableViewStyle) { @@ -48,12 +48,16 @@ self.rowHeight = UITableViewAutomaticDimension self.adapter.useAsDataSource() { tableView, item, indexPath in - let cell = tableView.dequeueReusableCellWithIdentifier( - item.reuseIdentifier, forIndexPath: indexPath) + 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") + } } -#endif \ No newline at end of file +#endif diff --git a/Buffer/TableViewDiffAdapter.swift b/Buffer/TableViewDiffAdapter.swift index c28f9b6..2226712 100644 --- a/Buffer/TableViewDiffAdapter.swift +++ b/Buffer/TableViewDiffAdapter.swift @@ -26,20 +26,20 @@ #if os(iOS) import UIKit - public class TableViewDiffAdapter: + open class TableViewDiffAdapter: NSObject, AdapterType, UITableViewDataSource { - public typealias Type = ElementType + public typealias `Type` = ElementType public typealias ViewType = UITableView - public private(set) var buffer: Buffer + open fileprivate(set) var buffer: Buffer - public private(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. - public var sectionIndex: Int = 0 + open var sectionIndex: Int = 0 public required init(buffer: BufferType, view: ViewType) { guard let buffer = buffer as? Buffer else { @@ -58,16 +58,16 @@ self.buffer.delegate = self } - private var cellForRowAtIndexPath: - ((UITableView, ElementType, NSIndexPath) -> UITableViewCell)? = nil + fileprivate var cellForRowAtIndexPath: + ((UITableView, ElementType, IndexPath) -> UITableViewCell)? = nil /// Returns the element currently on the front buffer at the given index path. - public func displayedElementAtIndex(index: Int) -> Type { + open func displayedElement(at index: Int) -> Type { return self.buffer.currentElements[index] } ///The total number of elements currently displayed. - public func countDisplayedElements() -> Int { + open func countDisplayedElements() -> Int { return self.buffer.currentElements.count } @@ -76,10 +76,10 @@ /// - 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. - public func update(newValues: [ElementType]? = nil, - synchronous: Bool = false, - completion: ((Void) -> Void)? = nil) { - self.buffer.update(newValues, synchronous: synchronous, completion: completion) + 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. @@ -88,64 +88,63 @@ /// - parameter estimatedHeight: The estimated average height for the cells. /// - parameter cellForRowAtIndexPath: The closure that returns a cell for the /// given index path. - public func useAsDataSource(cellForRowAtIndexPath: - (UITableView, ElementType, NSIndexPath) -> UITableViewCell) { + 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 public func tableView(tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { + 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. - public func tableView(tableView: UITableView, cellForRowAtIndexPath - indexPath: NSIndexPath) -> UITableViewCell { - return self.cellForRowAtIndexPath!(tableView, - self.buffer.currentElements[indexPath.row], - indexPath) + open func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + return self.cellForRowAtIndexPath!( + tableView, self.buffer.currentElements[(indexPath as NSIndexPath).row], indexPath) } } extension TableViewDiffAdapter: BufferDelegate { /// Notifies the receiver that the content is about to change. - public func bufferWillChangeContent(buffer: BufferType) { + public func buffer(willChangeContent buffer: BufferType) { self.view?.beginUpdates() } /// Notifies the receiver that rows were deleted. - public func bufferDidDeleteElementAtIndices(buffer: BufferType, indices: [UInt]) { + public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) { let deletionIndexPaths = indices.map({ - NSIndexPath(forRow: Int($0), inSection: self.sectionIndex) + IndexPath(row: Int($0), section: self.sectionIndex) }) - self.view?.deleteRowsAtIndexPaths(deletionIndexPaths, withRowAnimation: .Automatic) + self.view?.deleteRows(at: deletionIndexPaths, with: .automatic) } // /Notifies the receiver that rows were inserted. - public func bufferDidInsertElementsAtIndices(buffer: BufferType, indices: [UInt]) { + public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) { let insertionIndexPaths = indices.map({ - NSIndexPath(forRow: Int($0), inSection: self.sectionIndex) + IndexPath(row: Int($0), section: self.sectionIndex) }) - self.view?.insertRowsAtIndexPaths(insertionIndexPaths, withRowAnimation: .Automatic) + self.view?.insertRows(at: insertionIndexPaths, with: .automatic) } /// Notifies the receiver that the content updates has ended. - public func bufferDidChangeContent(buffer: BufferType) { + public func buffer(didChangeContent buffer: BufferType) { self.view?.endUpdates() } /// Called when one of the observed properties for this object changed. - public func bufferDidChangeElementAtIndex(buffer: BufferType, index: UInt) { - self.view?.reloadRowsAtIndexPaths( - [NSIndexPath(forRow: Int(index), inSection: self.sectionIndex)], - withRowAnimation: .Automatic) + 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 bufferDidChangeAllContent(buffer: BufferType) { + public func buffer(didChangeAllContent buffer: BufferType) { self.view?.reloadData() } } diff --git a/Demo/.DS_Store b/Demo/.DS_Store index 969eccf..f2c55e6 100644 Binary files a/Demo/.DS_Store and b/Demo/.DS_Store differ diff --git a/Demo/BufferDemo.xcodeproj/project.pbxproj b/Demo/BufferDemo.xcodeproj/project.pbxproj index bdeaada..0f6c7a9 100644 --- a/Demo/BufferDemo.xcodeproj/project.pbxproj +++ b/Demo/BufferDemo.xcodeproj/project.pbxproj @@ -13,8 +13,9 @@ 160E25921CF45CFE00A5F828 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 160E25911CF45CFE00A5F828 /* Assets.xcassets */; }; 160E25951CF45CFE00A5F828 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 160E25931CF45CFE00A5F828 /* LaunchScreen.storyboard */; }; 160E25A21CF4604600A5F828 /* Lorem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 160E25A11CF4604600A5F828 /* Lorem.swift */; }; - 16A868A41D6AF5B700F84FD0 /* Buffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16A868A21D6AF5AC00F84FD0 /* Buffer.framework */; }; - 16A868A51D6AF5B700F84FD0 /* Buffer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 16A868A21D6AF5AC00F84FD0 /* Buffer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 16A8002C1D87316900A8B3F3 /* Buffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16A8002B1D87316900A8B3F3 /* Buffer.framework */; }; + 16A8002D1D87317B00A8B3F3 /* Buffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16A8002B1D87316900A8B3F3 /* Buffer.framework */; }; + 16A8002E1D87317B00A8B3F3 /* Buffer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 16A8002B1D87316900A8B3F3 /* Buffer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -24,7 +25,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 16A868A51D6AF5B700F84FD0 /* Buffer.framework in Embed Frameworks */, + 16A8002E1D87317B00A8B3F3 /* Buffer.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -40,7 +41,7 @@ 160E25941CF45CFE00A5F828 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 160E25961CF45CFE00A5F828 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 160E25A11CF4604600A5F828 /* Lorem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lorem.swift; sourceTree = ""; }; - 16A868A21D6AF5AC00F84FD0 /* Buffer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Buffer.framework; path = BufferDemo/Buffer.framework; sourceTree = ""; }; + 16A8002B1D87316900A8B3F3 /* Buffer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Buffer.framework; path = BufferDemo/Buffer.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -48,7 +49,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 16A868A41D6AF5B700F84FD0 /* Buffer.framework in Frameworks */, + 16A8002D1D87317B00A8B3F3 /* Buffer.framework in Frameworks */, + 16A8002C1D87316900A8B3F3 /* Buffer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -58,9 +60,9 @@ 160E257E1CF45CFE00A5F828 = { isa = PBXGroup; children = ( - 16A868A21D6AF5AC00F84FD0 /* Buffer.framework */, 160E25891CF45CFE00A5F828 /* BufferDemo */, 160E25881CF45CFE00A5F828 /* Products */, + 16A8002B1D87316900A8B3F3 /* Buffer.framework */, ); sourceTree = ""; }; @@ -119,6 +121,7 @@ TargetAttributes = { 160E25861CF45CFE00A5F828 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; }; }; }; @@ -284,6 +287,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.s.BufferDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -300,6 +304,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.s.BufferDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Demo/BufferDemo/AppDelegate.swift b/Demo/BufferDemo/AppDelegate.swift index 2c60c8e..2918766 100644 --- a/Demo/BufferDemo/AppDelegate.swift +++ b/Demo/BufferDemo/AppDelegate.swift @@ -6,25 +6,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { } } diff --git a/Demo/BufferDemo/Buffer.framework/Buffer b/Demo/BufferDemo/Buffer.framework/Buffer index 66c273c..3d4924e 100755 Binary files a/Demo/BufferDemo/Buffer.framework/Buffer and b/Demo/BufferDemo/Buffer.framework/Buffer differ diff --git a/Demo/BufferDemo/Buffer.framework/Headers/Buffer-Swift.h b/Demo/BufferDemo/Buffer.framework/Headers/Buffer-Swift.h index 69320c8..21b2c77 100644 --- a/Demo/BufferDemo/Buffer.framework/Headers/Buffer-Swift.h +++ b/Demo/BufferDemo/Buffer.framework/Headers/Buffer-Swift.h @@ -1,4 +1,4 @@ -// Generated by Apple Swift version 2.2 (swiftlang-703.0.18.8 clang-703.0.31) +// Generated by Apple Swift version 3.0 (swiftlang-800.0.46.2 clang-800.0.38) #pragma clang diagnostic push #if defined(__has_include) && __has_include() @@ -28,6 +28,9 @@ typedef double swift_double4 __attribute__((__ext_vector_type__(4))); typedef int swift_int2 __attribute__((__ext_vector_type__(2))); typedef int swift_int3 __attribute__((__ext_vector_type__(3))); typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); +typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); +typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); #endif #if !defined(SWIFT_PASTE) @@ -37,6 +40,13 @@ typedef int swift_int4 __attribute__((__ext_vector_type__(4))); #if !defined(SWIFT_METATYPE) # define SWIFT_METATYPE(X) Class #endif +#if !defined(SWIFT_CLASS_PROPERTY) +# if __has_feature(objc_class_property) +# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ +# else +# define SWIFT_CLASS_PROPERTY(...) +# endif +#endif #if defined(__has_attribute) && __has_attribute(objc_runtime_name) # define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) @@ -48,6 +58,11 @@ typedef int swift_int4 __attribute__((__ext_vector_type__(4))); #else # define SWIFT_COMPILE_NAME(X) #endif +#if defined(__has_attribute) && __has_attribute(objc_method_family) +# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) +#else +# define SWIFT_METHOD_FAMILY(X) +#endif #if !defined(SWIFT_CLASS_EXTRA) # define SWIFT_CLASS_EXTRA #endif @@ -91,6 +106,9 @@ typedef int swift_int4 __attribute__((__ext_vector_type__(4))); # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) SWIFT_ENUM(_type, _name) # endif #endif +#if !defined(SWIFT_UNAVAILABLE) +# define SWIFT_UNAVAILABLE __attribute__((unavailable)) +#endif #if defined(__has_feature) && __has_feature(modules) @import UIKit; #endif diff --git a/Demo/BufferDemo/Buffer.framework/Info.plist b/Demo/BufferDemo/Buffer.framework/Info.plist index 8625202..0a0cf54 100644 Binary files a/Demo/BufferDemo/Buffer.framework/Info.plist and b/Demo/BufferDemo/Buffer.framework/Info.plist differ diff --git a/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftdoc b/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftdoc index b9058e7..7ddcebb 100644 Binary files a/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftdoc and b/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftdoc differ diff --git a/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftmodule b/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftmodule index 052fefa..33bdd79 100644 Binary files a/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftmodule and b/Demo/BufferDemo/Buffer.framework/Modules/Buffer.swiftmodule/x86_64.swiftmodule differ diff --git a/Demo/BufferDemo/Buffer.framework/_CodeSignature/CodeResources b/Demo/BufferDemo/Buffer.framework/_CodeSignature/CodeResources new file mode 100644 index 0000000..74603cc --- /dev/null +++ b/Demo/BufferDemo/Buffer.framework/_CodeSignature/CodeResources @@ -0,0 +1,186 @@ + + + + + files + + Headers/Buffer-Swift.h + + 4DnClDGkUlQ8q0dNyjSO6QD/fHQ= + + Headers/Buffer.h + + d19TPuGr66CDg89i4BJI2gU+dZk= + + Info.plist + + Q6OOW7FK/91FOV77Q8rE25uRbUc= + + Modules/Buffer.swiftmodule/x86_64.swiftdoc + + p4fZIvj/1IQq5Ikl+SM3hDaY2S0= + + Modules/Buffer.swiftmodule/x86_64.swiftmodule + + 7OdwdRgUqaUAUd+2V7Rt+N8nd/k= + + Modules/module.modulemap + + FIUM9dX1U3Pm+PbCH9wjUdO9Qrk= + + + files2 + + Headers/Buffer-Swift.h + + hash + + 4DnClDGkUlQ8q0dNyjSO6QD/fHQ= + + hash2 + + rk5jnXJfqvaBPSOrQnjfumc3ByNJlrJ6fvXYN/HKJSQ= + + + Headers/Buffer.h + + hash + + d19TPuGr66CDg89i4BJI2gU+dZk= + + hash2 + + XcB2mi5JIIHAWqhB6zMYwA9lrZCEfZXHPpJKaTXAnrk= + + + Modules/Buffer.swiftmodule/x86_64.swiftdoc + + hash + + p4fZIvj/1IQq5Ikl+SM3hDaY2S0= + + hash2 + + z01HJIpqucZQbeBA9OtCJrRHL80dP3kpqEhqiRYp6D0= + + + Modules/Buffer.swiftmodule/x86_64.swiftmodule + + hash + + 7OdwdRgUqaUAUd+2V7Rt+N8nd/k= + + hash2 + + F0Dq5yq//mgv8qDjo+W+eOa3ZM6lNsumA9zKKkz52iQ= + + + Modules/module.modulemap + + hash + + FIUM9dX1U3Pm+PbCH9wjUdO9Qrk= + + hash2 + + 25V+t5iOt2HNePZFs6yx60FWnCbzCbIRBvVWLEW+nog= + + + + rules + + ^ + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^ + + weight + 20 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/Demo/BufferDemo/Lorem.swift b/Demo/BufferDemo/Lorem.swift index 21415a3..e474d20 100644 --- a/Demo/BufferDemo/Lorem.swift +++ b/Demo/BufferDemo/Lorem.swift @@ -8,38 +8,38 @@ import Foundation -public class Lorem { +open class Lorem { - public static var word: String { + open static var word: String { return allWords.randomElement } - public static func words(count: Int) -> String { + open static func words(_ count: Int) -> String { return compose({ word }, count: count, middleSeparator: .Space) } - public static var sentence: String { + open static var sentence: String { let numberOfWordsInSentence = Int.random(min: 4, max: 16) - let capitalizeFirstLetterDecorator: String -> String = { $0.stringWithCapitalizedFirstLetter } + let capitalizeFirstLetterDecorator: (String) -> String = { $0.stringWithCapitalizedFirstLetter } return compose({ word }, count: numberOfWordsInSentence, middleSeparator: .Space, endSeparator: .Dot, decorator: capitalizeFirstLetterDecorator) } - public static func sentences(count: Int) -> String { + open static func sentences(_ count: Int) -> String { return compose({ sentence }, count: count, middleSeparator: .Space) } - public static var paragraph: String { + open static var paragraph: String { let numberOfSentencesInParagraph = Int.random(min: 3, max: 9) return sentences(numberOfSentencesInParagraph) } - public static func paragraphs(count: Int) -> String { + open static func paragraphs(_ count: Int) -> String { return compose({ paragraph }, count: count, middleSeparator: .NewLine) } - public static var title: String { + open static var title: String { let numberOfWordsInTitle = Int.random(min: 2, max: 7) - let capitalizeStringDecorator: String -> String = { $0.capitalizedString } + let capitalizeStringDecorator: (String) -> String = { $0.capitalized } return compose({ word }, count: numberOfWordsInTitle, middleSeparator: .Space, decorator: capitalizeStringDecorator) } @@ -47,56 +47,56 @@ public class Lorem { // MARK: - Misc // ======================================================= // - public static var firstName: String { + open static var firstName: String { return firstNames.randomElement } - public static var lastName: String { + open static var lastName: String { return lastNames.randomElement } - public static var name: String { + open static var name: String { return "\(firstName) \(lastName)" } - public static var email: String { + open static var email: String { let delimiter = emailDelimiters.randomElement let domain = emailDomains.randomElement - return "\(firstName)\(delimiter)\(lastName)@\(domain)".lowercaseString + return "\(firstName)\(delimiter)\(lastName)@\(domain)".lowercased() } - public static var URL: NSURL { - return NSURL(string: "http://\(domains.randomElement)/")! + open static var URL: Foundation.URL { + return Foundation.URL(string: "http://\(domains.randomElement)/")! } - public static var tweet: String { + open static var tweet: String { return tweets.randomElement } - public static var date: NSDate { - let currentDate = NSDate() - let currentCalendar = NSCalendar.currentCalendar() - let referenceDateComponents = NSDateComponents() + open static var date: Date { + let currentDate = Date() + let currentCalendar = Calendar.current + var referenceDateComponents = DateComponents() referenceDateComponents.year = -4 - let calendarOptions = NSCalendarOptions(rawValue: 0) - let referenceDate = currentCalendar.dateByAddingComponents(referenceDateComponents, toDate: currentDate, options: calendarOptions)! - let timeIntervalSinceReferenceDate = currentDate.timeIntervalSinceDate(referenceDate) - let randomTimeInterval = NSTimeInterval(Int.random(max: Int(timeIntervalSinceReferenceDate))) - return referenceDate.dateByAddingTimeInterval(randomTimeInterval) + let calendarOptions = NSCalendar.Options(rawValue: 0) + let referenceDate = (currentCalendar as NSCalendar).date(byAdding: referenceDateComponents, to: currentDate, options: calendarOptions)! + let timeIntervalSinceReferenceDate = currentDate.timeIntervalSince(referenceDate) + let randomTimeInterval = TimeInterval(Int.random(max: Int(timeIntervalSinceReferenceDate))) + return referenceDate.addingTimeInterval(randomTimeInterval) } // ======================================================= // // MARK: - Private // ======================================================= // - private enum Separator: String { + fileprivate enum Separator: String { case None = "" case Space = " " case Dot = "." case NewLine = "\n" } - private static func compose(provider: () -> String, count: Int, middleSeparator: Separator, endSeparator: Separator = .None, decorator: (String -> String)? = nil) -> String { + fileprivate static func compose(_ provider: () -> String, count: Int, middleSeparator: Separator, endSeparator: Separator = .None, decorator: ((String) -> String)? = nil) -> String { var composedString = "" for index in 0.. Int { + static func random(min: Int = 0, max: Int) -> Int { assert(min >= 0) assert(min < max) @@ -155,9 +155,9 @@ extension Array { extension String { var stringWithCapitalizedFirstLetter: String { - let firstLetterRange = startIndex.. else { return } var newElements = tableView.elements - newElements.removeAtIndex(indexPath.row) + newElements.remove(at: (indexPath as NSIndexPath).row) tableView.elements = newElements } } diff --git a/README.md b/README.md index 8a3d506..79fe673 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ # Buffer -[![Swift](https://img.shields.io/badge/swift-2.2-orange.svg?style=flat)](#) +[![Swift](https://img.shields.io/badge/swift-3-orange.svg?style=flat)](#) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](https://img.shields.io/badge/platform-ios | macos | tvos | watchos-lightgrey.svg?style=flat)](#) [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT) Swift μ-framework for efficient array diffs, collection observation and data source implementation. +[(Swift 2.3 branch here)](https://github.com/alexdrone/Buffer/tree/swift_2_3) ## Installation @@ -56,32 +57,32 @@ class MyClass: BufferDelegate { // When the elements are changed the buffer object will compute the difference and trigger // the invocation of the delegate methods. // The `synchronous` and `completion` arguments are optional. - self.buffer.update(newValues, synchronous: false, completion: nil) + self.buffer.update(with: newValues, synchronous: false, completion: nil) } } //These methods will be called when the buffer has changedd. - public func bufferWillChangeContent(buffer: BufferType) { + public func buffer(willChangeContent buffer: BufferType) { //e.g. self.tableView?.beginUpdates() } - public func bufferDidDeleteElementAtIndices(buffer: BufferType, indices: [UInt]) { + public func buffer(didDeleteElementAtIndices buffer: BufferType, indices: [UInt]) { //e.g. Remove rows from a tableview } - public func bufferDidInsertElementsAtIndices(buffer: BufferType, indices: [UInt]) { + public func buffer(didInsertElementsAtIndices buffer: BufferType, indices: [UInt]) { } - public func bufferDidChangeContent(buffer: BufferType) { + public func buffer(didChangeContent buffer: BufferType) { } - public func bufferDidChangeElementAtIndex(buffer: BufferType, index: UInt) { + public func buffer(didChangeElementAtIndex buffer: BufferType, index: UInt) { } - public func bufferDidChangeAllContent(buffer: BufferType) { + public func buffer(didChangeAllContent buffer: BufferType) { } } ``` @@ -118,7 +119,7 @@ class MyClass: UITableViewController { // When the elements are changed the buffer object will compute the difference and trigger // the invocation of the delegate methods. // The `synchronous` and `completion` arguments are optional. - self.buffer.update(newValues, synchronous: false, completion: nil) + self.buffer.update(with: newValues, synchronous: false, completion: nil) } }