Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
# Conflicts:
#	Source/IGListAdapter.m
  • Loading branch information
Rawlings committed Oct 24, 2016
2 parents 1dbabbb + 8ccdc83 commit 17bb25e
Show file tree
Hide file tree
Showing 25 changed files with 321 additions and 33 deletions.
6 changes: 6 additions & 0 deletions .slather.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ci_service: travis_ci
coverage_service: coveralls
xcodeproj: IGListKit.xcodeproj
workspace: IGListKit.xcworkspace
scheme: IGListKit
source_directory: Source
7 changes: 5 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ script:


- if [ $RUN_TESTS == "YES" ]; then
xcodebuild test -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO | bundle exec xcpretty -c;
xcodebuild analyze test -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES ONLY_ACTIVE_ARCH=YES | bundle exec xcpretty -c;
else
xcodebuild build -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO | bundle exec xcpretty -c;
xcodebuild build analyze -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO | bundle exec xcpretty -c;
fi

after_success:
- cd $TRAVIS_BUILD_DIR && bundle exec slather
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

The changelog for `IGListKit`. Also see the [releases](https://github.com/instagram/IGListKit/releases) on GitHub.

1.1.0
2.0.0
-----

This release closes the [2.0.0 milestone](https://github.com/Instagram/IGListKit/milestone/1?closed=1).

### Enhancements

- Added support for supplementaryViews created from nibs. [Rawlinxx](https://github.com/rawlinxx) [(#90)](https://github.com/Instagram/IGListKit/pull/90)
Expand Down
17 changes: 17 additions & 0 deletions Example/IGListKitExamples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
2961B3AE1D68B0B5001C9451 /* SpinnerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2961B3A81D68B0B5001C9451 /* SpinnerCell.swift */; };
2961B3B01D68B28E001C9451 /* SearchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2961B3AF1D68B28E001C9451 /* SearchCell.swift */; };
29628F141D91905A0026B15A /* DetailLabelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29628F131D91905A0026B15A /* DetailLabelCell.swift */; };
2981BA351DB868A500A987F9 /* ImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2981BA341DB868A500A987F9 /* ImageCell.swift */; };
2981BA371DB869FF00A987F9 /* WorkingRangeSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2981BA361DB869FF00A987F9 /* WorkingRangeSectionController.swift */; };
2981BA391DB874BB00A987F9 /* WorkingRangeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2981BA381DB874BB00A987F9 /* WorkingRangeViewController.swift */; };
299068281D75BFEC00A62888 /* MixedDataViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299068271D75BFEC00A62888 /* MixedDataViewController.swift */; };
2991F9191D7BADC900B0C58F /* CenterLabelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2991F9181D7BADC900B0C58F /* CenterLabelCell.swift */; };
2991F91E1D7BB30C00B0C58F /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2991F91D1D7BB30C00B0C58F /* User.swift */; };
Expand Down Expand Up @@ -63,6 +66,9 @@
2961B3A81D68B0B5001C9451 /* SpinnerCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinnerCell.swift; sourceTree = "<group>"; };
2961B3AF1D68B28E001C9451 /* SearchCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchCell.swift; sourceTree = "<group>"; };
29628F131D91905A0026B15A /* DetailLabelCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailLabelCell.swift; sourceTree = "<group>"; };
2981BA341DB868A500A987F9 /* ImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCell.swift; sourceTree = "<group>"; };
2981BA361DB869FF00A987F9 /* WorkingRangeSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkingRangeSectionController.swift; sourceTree = "<group>"; };
2981BA381DB874BB00A987F9 /* WorkingRangeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorkingRangeViewController.swift; sourceTree = "<group>"; };
299068271D75BFEC00A62888 /* MixedDataViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MixedDataViewController.swift; sourceTree = "<group>"; };
2991F9181D7BADC900B0C58F /* CenterLabelCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CenterLabelCell.swift; sourceTree = "<group>"; };
2991F91D1D7BB30C00B0C58F /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -108,6 +114,7 @@
2942FF891D9F39E00015D24B /* RemoveSectionController.swift */,
2942FF8A1D9F39E00015D24B /* SearchSectionController.swift */,
2942FF8B1D9F39E00015D24B /* UserSectionController.swift */,
2981BA361DB869FF00A987F9 /* WorkingRangeSectionController.swift */,
);
path = SectionControllers;
sourceTree = "<group>";
Expand Down Expand Up @@ -155,6 +162,7 @@
2991F9231D7BB89F00B0C58F /* NestedAdapterViewController.swift */,
299B53FF1D6BD6630074A202 /* SearchViewController.swift */,
26271C8D1DAE9D3F0073E116 /* SingleSectionViewController.swift */,
2981BA381DB874BB00A987F9 /* WorkingRangeViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
Expand All @@ -171,6 +179,7 @@
2961B3A81D68B0B5001C9451 /* SpinnerCell.swift */,
26271C931DAE9F050073E116 /* NibCell.swift */,
26271C911DAE9EFC0073E116 /* NibCell.xib */,
2981BA341DB868A500A987F9 /* ImageCell.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -321,8 +330,10 @@
2961B3AE1D68B0B5001C9451 /* SpinnerCell.swift in Sources */,
2961B3B01D68B28E001C9451 /* SearchCell.swift in Sources */,
2942FF8C1D9F39E00015D24B /* DemoSectionController.swift in Sources */,
2981BA351DB868A500A987F9 /* ImageCell.swift in Sources */,
2942FF931D9F39E00015D24B /* SearchSectionController.swift in Sources */,
2942FF911D9F39E00015D24B /* LabelSectionController.swift in Sources */,
2981BA391DB874BB00A987F9 /* WorkingRangeViewController.swift in Sources */,
2961B3AC1D68B0B5001C9451 /* LoadMoreViewController.swift in Sources */,
26271C941DAE9F050073E116 /* NibCell.swift in Sources */,
2991F9191D7BADC900B0C58F /* CenterLabelCell.swift in Sources */,
Expand All @@ -340,6 +351,7 @@
26271C8E1DAE9D3F0073E116 /* SingleSectionViewController.swift in Sources */,
2961B3AD1D68B0B5001C9451 /* LabelCell.swift in Sources */,
2942FF901D9F39E00015D24B /* HorizontalSectionController.swift in Sources */,
2981BA371DB869FF00A987F9 /* WorkingRangeSectionController.swift in Sources */,
2961B3AB1D68B0B5001C9451 /* DemosViewController.swift in Sources */,
2942FF8E1D9F39E00015D24B /* ExpandableSectionController.swift in Sources */,
);
Expand Down Expand Up @@ -452,12 +464,15 @@
baseConfigurationReference = FE05AB853448A0705AF80427 /* Pods-IGListKitExamples.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = IGListKitExamples/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.instagram.IGListKitExamples;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
Expand All @@ -467,12 +482,14 @@
baseConfigurationReference = 4125DCD99578FDEF3C373BA0 /* Pods-IGListKitExamples.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = IGListKitExamples/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.instagram.IGListKitExamples;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_VERSION = 3.0;
};
name = Release;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class LabelSectionController: IGListSectionController, IGListSectionType {
}

func didUpdate(to object: Any) {
self.object = object as? String
self.object = String(describing: object)
}

func didSelectItem(at index: Int) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ protocol SearchSectionControllerDelegate: class {
func searchSectionController(_ sectionController: SearchSectionController, didChangeText text: String)
}

class SearchSectionController: IGListSectionController, IGListSectionType, IGListDisplayDelegate, UISearchBarDelegate {
class SearchSectionController: IGListSectionController, IGListSectionType, UISearchBarDelegate, IGListScrollDelegate {

weak var delegate: SearchSectionControllerDelegate?

override init() {
super.init()
displayDelegate = self
scrollDelegate = self
}

func numberOfItems() -> Int {
Expand Down Expand Up @@ -54,18 +54,16 @@ class SearchSectionController: IGListSectionController, IGListSectionType, IGLis
delegate?.searchSectionController(self, didChangeText: "")
}

//MARK: IGListDisplayDelegate
//MARK: IGListScrollDelegate

func listAdapter(_ listAdapter: IGListAdapter, didScrollSectionController sectionController: IGListSectionController) {
func listAdapter(_ listAdapter: IGListAdapter, didScroll sectionController: IGListSectionController) {
if let searchBar = (collectionContext?.cellForItem(at: 0, sectionController: self) as? SearchCell)?.searchBar {
searchBar.text = ""
searchBar.resignFirstResponder()
}
}

func listAdapter(_ listAdapter: IGListAdapter, willDisplay sectionController: IGListSectionController) {}
func listAdapter(_ listAdapter: IGListAdapter, willDisplay sectionController: IGListSectionController, cell: UICollectionViewCell, at index: Int) {}
func listAdapter(_ listAdapter: IGListAdapter, didEndDisplaying sectionController: IGListSectionController) {}
func listAdapter(_ listAdapter: IGListAdapter, didEndDisplaying sectionController: IGListSectionController, cell: UICollectionViewCell, at index: Int) {}
func listAdapter(_ listAdapter: IGListAdapter!, willBeginDragging sectionController: IGListSectionController!) {}
func listAdapter(_ listAdapter: IGListAdapter!, didEndDragging sectionController: IGListSectionController!, willDecelerate decelerate: Bool) {}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
Copyright (c) 2016-present, Facebook, Inc. All rights reserved.

The examples provided by Facebook are for non-commercial testing and evaluation
purposes only. Facebook reserves all rights not expressly granted.

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
FACEBOOK 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 UIKit
import IGListKit

class WorkingRangeSectionController: IGListSectionController, IGListSectionType, IGListWorkingRangeDelegate {

var height: Int?
var downloadedImage: UIImage?
var task: URLSessionDataTask?

var urlString: String? {
guard let height = height,
let width = collectionContext?.containerSize.width
else { return nil }
return "https://unsplash.it/" + width.description + "/" + height.description
}

deinit {
task?.cancel()
}

override init() {
super.init()
workingRangeDelegate = self
}

func numberOfItems() -> Int {
return 2
}

func sizeForItem(at index: Int) -> CGSize {
let width: CGFloat = collectionContext?.containerSize.width ?? 0
let height: CGFloat = CGFloat(index == 0 ? 55 : (self.height ?? 0))
return CGSize(width: width, height: height)
}

func cellForItem(at index: Int) -> UICollectionViewCell {
let cellClass: AnyClass = index == 0 ? LabelCell.self : ImageCell.self
let cell = collectionContext!.dequeueReusableCell(of: cellClass, for: self, at: index)
if let cell = cell as? LabelCell {
cell.label.text = urlString
} else if let cell = cell as? ImageCell {
cell.setImage(image: downloadedImage)
}
return cell
}

func didUpdate(to object: Any) {
self.height = object as? Int
}

func didSelectItem(at index: Int) {}

//MARK: IGListWorkingRangeDelegate

func listAdapter(_ listAdapter: IGListAdapter, sectionControllerWillEnterWorkingRange sectionController: IGListSectionController) {
guard downloadedImage == nil,
task == nil,
let urlString = urlString,
let url = URL(string: urlString)
else { return }

let section = collectionContext?.section(for: self) ?? 0
print("Downloading image \(urlString) for section \(section)")

task = URLSession.shared.dataTask(with: url, completionHandler: { data, response, err in
if let data = data, let image = UIImage(data: data) {
DispatchQueue.main.async {
self.downloadedImage = image
if let cell = self.collectionContext?.cellForItem(at: 1, sectionController: self) as? ImageCell {
cell.setImage(image: image)
}
}
} else {
print("Error downloading \(urlString): \(err)")
}
})
task?.resume()
}

func listAdapter(_ listAdapter: IGListAdapter, sectionControllerDidExitWorkingRange sectionController: IGListSectionController) {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ class DemosViewController: UIViewController, IGListAdapterDataSource {
lazy var adapter: IGListAdapter = {
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
}()
let collectionView = IGListCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())

let demos: [DemoItem] = [
DemoItem(name: "Tail Loading", controllerClass: LoadMoreViewController.self),
DemoItem(name: "Search Autocomplete", controllerClass: SearchViewController.self),
DemoItem(name: "Mixed Data", controllerClass: MixedDataViewController.self),
DemoItem(name: "Nested Adapter", controllerClass: NestedAdapterViewController.self),
DemoItem(name: "Empty View", controllerClass: EmptyViewController.self),
DemoItem(name: "Single Section Controller", controllerClass: SingleSectionViewController.self)
DemoItem(name: "Single Section Controller", controllerClass: SingleSectionViewController.self),
DemoItem(name: "Working Range", controllerClass: WorkingRangeViewController.self)
]

override func viewDidLoad() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class EmptyViewController: UIViewController, IGListAdapterDataSource, RemoveSect
lazy var adapter: IGListAdapter = {
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
}()
let collectionView = IGListCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())

let emptyLabel: UILabel = {
let label = UILabel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class LoadMoreViewController: UIViewController, IGListAdapterDataSource, UIScrol
lazy var adapter: IGListAdapter = {
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
}()
let collectionView = IGListCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())

lazy var words = "Maecenas faucibus mollis interdum Praesent commodo cursus magna, vel scelerisque nisl consectetur et".components(separatedBy: " ")
lazy var items = Array(0...20)
var loading = false
let spinToken = NSObject()

Expand All @@ -42,11 +42,13 @@ class LoadMoreViewController: UIViewController, IGListAdapterDataSource, UIScrol
//MARK: IGListAdapterDataSource

func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
var items: [IGListDiffable] = words as [IGListDiffable]
var objects = items as [IGListDiffable]

if loading {
items.append(spinToken)
objects.append(spinToken)
}
return items

return objects
}

func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
Expand All @@ -71,7 +73,8 @@ class LoadMoreViewController: UIViewController, IGListAdapterDataSource, UIScrol
sleep(2)
DispatchQueue.main.async {
self.loading = false
self.words.append(contentsOf: "Etiam porta sem malesuada magna mollis euismod".components(separatedBy: " "))
let itemCount = self.items.count
self.items.append(contentsOf: Array(itemCount..<itemCount + 5))
self.adapter.performUpdates(animated: true, completion: nil)
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class MixedDataViewController: UIViewController, IGListAdapterDataSource {
lazy var adapter: IGListAdapter = {
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
}()
let collectionView = IGListCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())

let data = [
"Maecenas faucibus mollis interdum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class NestedAdapterViewController: UIViewController, IGListAdapterDataSource {
lazy var adapter: IGListAdapter = {
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
}()
let collectionView = IGListCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())

let data = [
"Ridiculus Elit Tellus Purus Aenean",
Expand Down
Loading

0 comments on commit 17bb25e

Please sign in to comment.