Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ishkawa committed Sep 2, 2018
1 parent 0357db7 commit bcd5af9
Show file tree
Hide file tree
Showing 13 changed files with 397 additions and 46 deletions.
50 changes: 46 additions & 4 deletions DataSourceKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@

/* Begin PBXBuildFile section */
7FB64C00213B552B0071FC26 /* DataSourceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FB64BF6213B552B0071FC26 /* DataSourceKit.framework */; };
7FB64C05213B552B0071FC26 /* DataSourceKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C04213B552B0071FC26 /* DataSourceKitTests.swift */; };
7FB64C07213B552B0071FC26 /* DataSourceKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 7FB64BF9213B552B0071FC26 /* DataSourceKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
7FB64C11213B55830071FC26 /* CellsDeclarator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C10213B55830071FC26 /* CellsDeclarator.swift */; };
7FB64C13213B55CB0071FC26 /* CellBinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C12213B55CB0071FC26 /* CellBinder.swift */; };
7FB64C15213B56630071FC26 /* BindableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C14213B56630071FC26 /* BindableCell.swift */; };
7FB64C17213B56E20071FC26 /* CollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C16213B56E20071FC26 /* CollectionViewDataSource.swift */; };
7FB64C19213B58E40071FC26 /* CollectionViewDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C18213B58E40071FC26 /* CollectionViewDataSourceTests.swift */; };
7FB64C1B213B59300071FC26 /* TestCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C1A213B59300071FC26 /* TestCollectionView.swift */; };
7FB64C1D213B5BC20071FC26 /* TestCellA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C1C213B5BC20071FC26 /* TestCellA.swift */; };
7FB64C1F213B5BC80071FC26 /* TestCellB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB64C1E213B5BC80071FC26 /* TestCellB.swift */; };
7FB64C21213B5BD90071FC26 /* TestCellA.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7FB64C20213B5BD90071FC26 /* TestCellA.xib */; };
7FB64C23213B5C0A0071FC26 /* TestCellB.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7FB64C22213B5C0A0071FC26 /* TestCellB.xib */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -27,8 +36,17 @@
7FB64BF9213B552B0071FC26 /* DataSourceKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataSourceKit.h; sourceTree = "<group>"; };
7FB64BFA213B552B0071FC26 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7FB64BFF213B552B0071FC26 /* DataSourceKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DataSourceKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
7FB64C04213B552B0071FC26 /* DataSourceKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSourceKitTests.swift; sourceTree = "<group>"; };
7FB64C06213B552B0071FC26 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7FB64C10213B55830071FC26 /* CellsDeclarator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellsDeclarator.swift; sourceTree = "<group>"; };
7FB64C12213B55CB0071FC26 /* CellBinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellBinder.swift; sourceTree = "<group>"; };
7FB64C14213B56630071FC26 /* BindableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableCell.swift; sourceTree = "<group>"; };
7FB64C16213B56E20071FC26 /* CollectionViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewDataSource.swift; sourceTree = "<group>"; };
7FB64C18213B58E40071FC26 /* CollectionViewDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewDataSourceTests.swift; sourceTree = "<group>"; };
7FB64C1A213B59300071FC26 /* TestCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestCollectionView.swift; sourceTree = "<group>"; };
7FB64C1C213B5BC20071FC26 /* TestCellA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestCellA.swift; sourceTree = "<group>"; };
7FB64C1E213B5BC80071FC26 /* TestCellB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestCellB.swift; sourceTree = "<group>"; };
7FB64C20213B5BD90071FC26 /* TestCellA.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TestCellA.xib; sourceTree = "<group>"; };
7FB64C22213B5C0A0071FC26 /* TestCellB.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TestCellB.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -72,6 +90,10 @@
isa = PBXGroup;
children = (
7FB64BF9213B552B0071FC26 /* DataSourceKit.h */,
7FB64C10213B55830071FC26 /* CellsDeclarator.swift */,
7FB64C16213B56E20071FC26 /* CollectionViewDataSource.swift */,
7FB64C12213B55CB0071FC26 /* CellBinder.swift */,
7FB64C14213B56630071FC26 /* BindableCell.swift */,
7FB64BFA213B552B0071FC26 /* Info.plist */,
);
path = DataSourceKit;
Expand All @@ -80,7 +102,12 @@
7FB64C03213B552B0071FC26 /* DataSourceKitTests */ = {
isa = PBXGroup;
children = (
7FB64C04213B552B0071FC26 /* DataSourceKitTests.swift */,
7FB64C1A213B59300071FC26 /* TestCollectionView.swift */,
7FB64C20213B5BD90071FC26 /* TestCellA.xib */,
7FB64C1C213B5BC20071FC26 /* TestCellA.swift */,
7FB64C22213B5C0A0071FC26 /* TestCellB.xib */,
7FB64C1E213B5BC80071FC26 /* TestCellB.swift */,
7FB64C18213B58E40071FC26 /* CollectionViewDataSourceTests.swift */,
7FB64C06213B552B0071FC26 /* Info.plist */,
);
path = DataSourceKitTests;
Expand Down Expand Up @@ -148,6 +175,7 @@
TargetAttributes = {
7FB64BF5213B552B0071FC26 = {
CreatedOnToolsVersion = 10.0;
LastSwiftMigration = 1000;
};
7FB64BFE213B552B0071FC26 = {
CreatedOnToolsVersion = 10.0;
Expand Down Expand Up @@ -184,6 +212,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7FB64C23213B5C0A0071FC26 /* TestCellB.xib in Resources */,
7FB64C21213B5BD90071FC26 /* TestCellA.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -194,14 +224,21 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7FB64C15213B56630071FC26 /* BindableCell.swift in Sources */,
7FB64C11213B55830071FC26 /* CellsDeclarator.swift in Sources */,
7FB64C13213B55CB0071FC26 /* CellBinder.swift in Sources */,
7FB64C17213B56E20071FC26 /* CollectionViewDataSource.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
7FB64BFB213B552B0071FC26 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7FB64C05213B552B0071FC26 /* DataSourceKitTests.swift in Sources */,
7FB64C1F213B5BC80071FC26 /* TestCellB.swift in Sources */,
7FB64C1D213B5BC20071FC26 /* TestCellA.swift in Sources */,
7FB64C1B213B59300071FC26 /* TestCollectionView.swift in Sources */,
7FB64C19213B58E40071FC26 /* CollectionViewDataSourceTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -341,6 +378,7 @@
7FB64C0B213B552B0071FC26 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
Expand All @@ -357,6 +395,7 @@
PRODUCT_BUNDLE_IDENTIFIER = org.ishkawa.DataSourceKit;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
Expand All @@ -365,6 +404,7 @@
7FB64C0C213B552B0071FC26 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
Expand All @@ -389,6 +429,7 @@
7FB64C0E213B552B0071FC26 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = DataSourceKitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -406,6 +447,7 @@
7FB64C0F213B552B0071FC26 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = DataSourceKitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
Expand Down
14 changes: 14 additions & 0 deletions DataSourceKit/BindableCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// BindableCell.swift
// DataSourceKit
//
// Created by Yosuke Ishikawa on 2018/09/02.
// Copyright © 2018年 Yosuke Ishikawa. All rights reserved.
//

import Foundation

public protocol BindableCell {
associatedtype Value
static func makeBinder(value: Value) -> CellBinder
}
28 changes: 28 additions & 0 deletions DataSourceKit/CellBinder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// CellBinder.swift
// DataSourceKit
//
// Created by Yosuke Ishikawa on 2018/09/02.
// Copyright © 2018年 Yosuke Ishikawa. All rights reserved.
//

import Foundation

public struct CellBinder {
public let nib: UINib
public let reuseIdentifier: String

internal let configureCell: (Any) -> Void

public init<Cell>(cellType: Cell.Type, nib: UINib, reuseIdentifier: String, configureCell: @escaping (Cell) -> Void) {
self.nib = nib
self.reuseIdentifier = reuseIdentifier
self.configureCell = { cell in
guard let cell = cell as? Cell else {
fatalError("Could not cast UICollectionView cell to \(Cell.self)")
}

configureCell(cell)
}
}
}
22 changes: 22 additions & 0 deletions DataSourceKit/CellsDeclarator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// CellsDeclarator.swift
// DataSourceKit
//
// Created by Yosuke Ishikawa on 2018/09/02.
// Copyright © 2018 Yosuke Ishikawa. All rights reserved.
//

public protocol CellsDeclarator {
associatedtype CellDeclaration
func declareCells(_ cell: (CellDeclaration) -> Void)
}

extension CellsDeclarator {
public var cellDeclarations: [CellDeclaration] {
var declarations = [] as [CellDeclaration]
declareCells { declaration in
declarations.append(declaration)
}
return declarations
}
}
38 changes: 38 additions & 0 deletions DataSourceKit/CollectionViewDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// CollectionViewDataSource.swift
// DataSourceKit
//
// Created by Yosuke Ishikawa on 2018/09/02.
// Copyright © 2018年 Yosuke Ishikawa. All rights reserved.
//

import UIKit

public class CollectionViewDataSource<CellDeclaration>: NSObject, UICollectionViewDataSource {
public var cellDeclarations = [] as [CellDeclaration]

private var registeredReuseIdentifiers = [] as [String]
private let binderFromDeclaration: (CellDeclaration) -> CellBinder

public init(binderFromDeclaration: @escaping (CellDeclaration) -> CellBinder) {
self.binderFromDeclaration = binderFromDeclaration
super.init()
}

public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cellDeclarations.count
}

public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cellBinder = binderFromDeclaration(cellDeclarations[indexPath.item])
if !registeredReuseIdentifiers.contains(cellBinder.reuseIdentifier) {
collectionView.register(cellBinder.nib, forCellWithReuseIdentifier: cellBinder.reuseIdentifier)
registeredReuseIdentifiers.append(cellBinder.reuseIdentifier)
}

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellBinder.reuseIdentifier, for: indexPath)
cellBinder.configureCell(cell)

return cell
}
}
9 changes: 1 addition & 8 deletions DataSourceKit/DataSourceKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,10 @@
// DataSourceKit
//
// Created by Yosuke Ishikawa on 2018/09/02.
// Copyright © 2018年 Yosuke Ishikawa. All rights reserved.
// Copyright © 2018 Yosuke Ishikawa. All rights reserved.
//

#import <UIKit/UIKit.h>

//! Project version number for DataSourceKit.
FOUNDATION_EXPORT double DataSourceKitVersionNumber;

//! Project version string for DataSourceKit.
FOUNDATION_EXPORT const unsigned char DataSourceKitVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <DataSourceKit/PublicHeader.h>


85 changes: 85 additions & 0 deletions DataSourceKitTests/CollectionViewDataSourceTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// CollectionViewDataSourceTests.swift
// DataSourceKitTests
//
// Created by Yosuke Ishikawa on 2018/09/02.
// Copyright © 2018年 Yosuke Ishikawa. All rights reserved.
//

import Foundation
import XCTest
import DataSourceKit

class CollectionViewDataSourceTests: XCTestCase {
enum CellDeclaration {
case a(A)
case b(B)
}

struct Data: CellsDeclarator {
var a: [A]
var b: [B]

func declareCells(_ cell: (CellDeclaration) -> Void) {
for a in a {
cell(.a(a))
}
for b in b {
cell(.b(b))
}
}
}

var dataSource: CollectionViewDataSource<CellDeclaration>!
var collectionView: TestCollectionView!

override func setUp() {
super.setUp()

dataSource = CollectionViewDataSource<CellDeclaration> { declaration in
switch declaration {
case .a(let a):
return TestCellA.makeBinder(value: a)
case .b(let b):
return TestCellB.makeBinder(value: b)
}
}

collectionView = TestCollectionView(frame: UIScreen.main.bounds, collectionViewLayout: UICollectionViewFlowLayout())
collectionView.dataSource = dataSource
}

func test() {
let data = Data(a: [A(id: 1), A(id: 2)], b: [B(id: 1)])
dataSource.cellDeclarations = data.cellDeclarations
collectionView.reloadData()
collectionView.layoutIfNeeded()

XCTAssertEqual(dataSource.collectionView(collectionView, numberOfItemsInSection: 0), 3)
XCTAssertEqual(collectionView.nibRegistrations.map({ $0.reuseIdentifier }), ["TestCellA", "TestCellB"])

let verifiers: [(UICollectionViewCell?) -> Void] = [
{ cell in
let cell = cell as? TestCellA
XCTAssertNotNil(cell)
XCTAssertEqual(cell?.idLabel.text, "1")
},
{ cell in
let cell = cell as? TestCellA
XCTAssertNotNil(cell)
XCTAssertEqual(cell?.idLabel.text, "2")
},
{ cell in
let cell = cell as? TestCellB
XCTAssertNotNil(cell)
XCTAssertEqual(cell?.idLabel.text, "1")
},
]

for (index, verifier) in verifiers.enumerated() {
let indexPath = IndexPath(item: index, section: 0)
let cell = collectionView.cellForItem(at: indexPath)
verifier(cell)
}
}
}
34 changes: 0 additions & 34 deletions DataSourceKitTests/DataSourceKitTests.swift

This file was deleted.

Loading

0 comments on commit bcd5af9

Please sign in to comment.