From ba65b56a9b11e46d718acd6930a4c31916d99f69 Mon Sep 17 00:00:00 2001 From: Ryan Nystrom Date: Fri, 7 Apr 2017 11:20:37 -0700 Subject: [PATCH 1/2] Improve the ObjC demo to reflect best-practices Summary: Couple best practices I want to make sure our examples reflect: - Multiple cells in a section controller - Unique models returned in `objectsForListAdapter:` (no dupes!) - Dynamic item count (`comments` array) Issue fixed: #595 - [x] All tests pass. Demo project builds and runs. Closes https://github.com/Instagram/IGListKit/pull/615 Differential Revision: D4852192 Pulled By: jessesquires fbshipit-source-id: f4a89800f90e6b5ea4b6dd7c0d9a78ca5d65082c --- .../project.pbxproj | 42 +++------ .../Models/{UserInfo.h => Post.h} | 21 +++-- .../Models/{UserInfo.m => Post.m} | 21 +++-- .../CommentSectionController.h | 19 ---- .../CommentSectionController.m | 48 ---------- .../ImageSectionController.m | 64 ------------- .../InteractiveSectionController.h | 19 ---- .../InteractiveSectionController.m | 43 --------- ...onController.h => PostSectionController.h} | 6 +- .../PostSectionController.m | 74 +++++++++++++++ .../UserInfoSectionController.h | 19 ---- .../UserInfoSectionController.m | 50 ---------- .../ViewControllers/ObjcDemoViewController.m | 92 ++++++------------- 13 files changed, 146 insertions(+), 372 deletions(-) rename Examples/Examples-iOS/IGListKitExamples/Models/{UserInfo.h => Post.h} (61%) rename Examples/Examples-iOS/IGListKitExamples/Models/{UserInfo.m => Post.m} (64%) delete mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.h delete mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.m delete mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/ImageSectionController.m delete mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.h delete mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.m rename Examples/Examples-iOS/IGListKitExamples/SectionControllers/{ImageSectionController.h => PostSectionController.h} (89%) create mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/PostSectionController.m delete mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.h delete mode 100644 Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.m diff --git a/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj b/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj index 957f9f0e3..040d9dfa2 100644 --- a/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj +++ b/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 2942FF931D9F39E00015D24B /* SearchSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2942FF8A1D9F39E00015D24B /* SearchSectionController.swift */; }; 2942FF941D9F39E00015D24B /* UserSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2942FF8B1D9F39E00015D24B /* UserSectionController.swift */; }; 29459C001DBE48E200F05375 /* DiffTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29459BFF1DBE48E200F05375 /* DiffTableViewController.swift */; }; + 295D8A9A1E92EC96001F7C06 /* PostSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 295D8A991E92EC96001F7C06 /* PostSectionController.m */; }; + 295D8A9D1E92ECDE001F7C06 /* Post.m in Sources */ = {isa = PBXBuildFile; fileRef = 295D8A9C1E92ECDE001F7C06 /* Post.m */; }; 2961B38E1D68B031001C9451 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2961B38D1D68B031001C9451 /* AppDelegate.swift */; }; 2961B3951D68B031001C9451 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2961B3941D68B031001C9451 /* Assets.xcassets */; }; 2961B3981D68B031001C9451 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2961B3961D68B031001C9451 /* LaunchScreen.storyboard */; }; @@ -70,11 +72,6 @@ 56C05B721E49B32A0026DB39 /* CommentCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B711E49B32A0026DB39 /* CommentCell.m */; }; 56C05B751E49B33C0026DB39 /* InteractiveCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B741E49B33C0026DB39 /* InteractiveCell.m */; }; 56C05B781E49B3A50026DB39 /* PhotoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B771E49B3A50026DB39 /* PhotoCell.m */; }; - 56C05B7B1E49B4030026DB39 /* UserInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B7A1E49B4030026DB39 /* UserInfo.m */; }; - 56C05B7E1E49B49C0026DB39 /* UserInfoSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B7D1E49B49C0026DB39 /* UserInfoSectionController.m */; }; - 56C05B811E49B4AB0026DB39 /* ImageSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B801E49B4AB0026DB39 /* ImageSectionController.m */; }; - 56C05B841E49B4B40026DB39 /* CommentSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B831E49B4B40026DB39 /* CommentSectionController.m */; }; - 56C05B871E49B4C40026DB39 /* InteractiveSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C05B861E49B4C40026DB39 /* InteractiveSectionController.m */; }; 696C69AF297B6455C862314F /* Pods_IGListKitTodayExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D64E902433068998DDE711FB /* Pods_IGListKitTodayExample.framework */; }; 75B39B8327726E4F6AA04B13 /* Pods_IGListKitMessageExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60AF908234A48B4187E68DAB /* Pods_IGListKitMessageExample.framework */; }; 814F1E00410200822610BB49 /* Pods_IGListKitExamples.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52A8DC2D07A93D7AA55BC993 /* Pods_IGListKitExamples.framework */; }; @@ -162,6 +159,10 @@ 2942FF8A1D9F39E00015D24B /* SearchSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchSectionController.swift; sourceTree = ""; }; 2942FF8B1D9F39E00015D24B /* UserSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserSectionController.swift; sourceTree = ""; }; 29459BFF1DBE48E200F05375 /* DiffTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffTableViewController.swift; sourceTree = ""; }; + 295D8A981E92EC96001F7C06 /* PostSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PostSectionController.h; sourceTree = ""; }; + 295D8A991E92EC96001F7C06 /* PostSectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PostSectionController.m; sourceTree = ""; }; + 295D8A9B1E92ECDE001F7C06 /* Post.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Post.h; sourceTree = ""; }; + 295D8A9C1E92ECDE001F7C06 /* Post.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Post.m; sourceTree = ""; }; 2961B38A1D68B031001C9451 /* IGListKitExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IGListKitExamples.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2961B38D1D68B031001C9451 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 2961B3941D68B031001C9451 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -216,16 +217,6 @@ 56C05B741E49B33C0026DB39 /* InteractiveCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteractiveCell.m; sourceTree = ""; }; 56C05B761E49B3A50026DB39 /* PhotoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoCell.h; sourceTree = ""; }; 56C05B771E49B3A50026DB39 /* PhotoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoCell.m; sourceTree = ""; }; - 56C05B791E49B4030026DB39 /* UserInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInfo.h; sourceTree = ""; }; - 56C05B7A1E49B4030026DB39 /* UserInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserInfo.m; sourceTree = ""; }; - 56C05B7C1E49B49C0026DB39 /* UserInfoSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInfoSectionController.h; sourceTree = ""; }; - 56C05B7D1E49B49C0026DB39 /* UserInfoSectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserInfoSectionController.m; sourceTree = ""; }; - 56C05B7F1E49B4AB0026DB39 /* ImageSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageSectionController.h; sourceTree = ""; }; - 56C05B801E49B4AB0026DB39 /* ImageSectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageSectionController.m; sourceTree = ""; }; - 56C05B821E49B4B40026DB39 /* CommentSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommentSectionController.h; sourceTree = ""; }; - 56C05B831E49B4B40026DB39 /* CommentSectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommentSectionController.m; sourceTree = ""; }; - 56C05B851E49B4C40026DB39 /* InteractiveSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteractiveSectionController.h; sourceTree = ""; }; - 56C05B861E49B4C40026DB39 /* InteractiveSectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteractiveSectionController.m; sourceTree = ""; }; 5CA315001853FD08906AD911 /* Pods-IGListKitTodayExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IGListKitTodayExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-IGListKitTodayExample/Pods-IGListKitTodayExample.release.xcconfig"; sourceTree = ""; }; 60AF908234A48B4187E68DAB /* Pods_IGListKitMessageExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IGListKitMessageExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 821BC4B51DB8B3DC00172ED0 /* StoryboardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryboardViewController.swift; sourceTree = ""; }; @@ -317,8 +308,6 @@ 2942FF821D9F39E00015D24B /* SectionControllers */ = { isa = PBXGroup; children = ( - 56C05B821E49B4B40026DB39 /* CommentSectionController.h */, - 56C05B831E49B4B40026DB39 /* CommentSectionController.m */, 2942FF831D9F39E00015D24B /* DemoSectionController.swift */, 29D2E4AC1DD69B6000CD255D /* DisplaySectionController.swift */, 2942FF841D9F39E00015D24B /* EmbeddedSectionController.swift */, @@ -326,19 +315,15 @@ 29C6297E1DCFD9E9004A5BB1 /* FeedItemSectionController.swift */, 2942FF861D9F39E00015D24B /* GridSectionController.swift */, 2942FF871D9F39E00015D24B /* HorizontalSectionController.swift */, - 56C05B7F1E49B4AB0026DB39 /* ImageSectionController.h */, - 56C05B801E49B4AB0026DB39 /* ImageSectionController.m */, - 56C05B851E49B4C40026DB39 /* InteractiveSectionController.h */, - 56C05B861E49B4C40026DB39 /* InteractiveSectionController.m */, 2942FF881D9F39E00015D24B /* LabelSectionController.swift */, 29F7E2AE1E92858500197586 /* ListeningSectionController.swift */, 292658631E74A2550041B56D /* MonthSectionController.swift */, + 295D8A981E92EC96001F7C06 /* PostSectionController.h */, + 295D8A991E92EC96001F7C06 /* PostSectionController.m */, 2942FF891D9F39E00015D24B /* RemoveSectionController.swift */, 2942FF8A1D9F39E00015D24B /* SearchSectionController.swift */, 296DD7541DD2150600206780 /* SelfSizingSectionController.swift */, 821BC4B91DB8B61200172ED0 /* StoryboardLabelSectionController.swift */, - 56C05B7C1E49B49C0026DB39 /* UserInfoSectionController.h */, - 56C05B7D1E49B49C0026DB39 /* UserInfoSectionController.m */, 2942FF8B1D9F39E00015D24B /* UserSectionController.swift */, 2981BA361DB869FF00A987F9 /* WorkingRangeSectionController.swift */, ); @@ -452,10 +437,10 @@ children = ( 29C6297C1DCFD8E5004A5BB1 /* FeedItem.swift */, 292658581E749F820041B56D /* Month.swift */, + 295D8A9B1E92ECDE001F7C06 /* Post.h */, + 295D8A9C1E92ECDE001F7C06 /* Post.m */, 296DD75C1DD21ADA00206780 /* SelectionModel.swift */, 2991F91D1D7BB30C00B0C58F /* User.swift */, - 56C05B791E49B4030026DB39 /* UserInfo.h */, - 56C05B7A1E49B4030026DB39 /* UserInfo.m */, 2926585C1E74A0360041B56D /* ViewModels */, ); path = Models; @@ -826,7 +811,6 @@ 299068281D75BFEC00A62888 /* MixedDataViewController.swift in Sources */, 299B54001D6BD6630074A202 /* SearchViewController.swift in Sources */, 292658661E74A49D0041B56D /* CalendarDayCell.swift in Sources */, - 56C05B7E1E49B49C0026DB39 /* UserInfoSectionController.m in Sources */, 2961B3AE1D68B0B5001C9451 /* SpinnerCell.swift in Sources */, 292658591E749F820041B56D /* Month.swift in Sources */, 296DD7591DD2174200206780 /* NibSelfSizingCell.swift in Sources */, @@ -842,15 +826,15 @@ 82D91B691DBA0EF300E62758 /* SingleSectionStoryboardViewController.swift in Sources */, 29D2E4AF1DD69C0E00CD255D /* DisplayViewController.swift in Sources */, 2942FF911D9F39E00015D24B /* LabelSectionController.swift in Sources */, + 295D8A9D1E92ECDE001F7C06 /* Post.m in Sources */ 29F7E2AD1E92843A00197586 /* IncrementAnnouncer.swift in Sources */, 2981BA391DB874BB00A987F9 /* WorkingRangeViewController.swift in Sources */, - 56C05B841E49B4B40026DB39 /* CommentSectionController.m in Sources */, 29C629831DCFDB57004A5BB1 /* UserHeaderView.swift in Sources */, 2961B3AC1D68B0B5001C9451 /* LoadMoreViewController.swift in Sources */, 26271C941DAE9F050073E116 /* NibCell.swift in Sources */, 2991F9191D7BADC900B0C58F /* CenterLabelCell.swift in Sources */, + 295D8A9A1E92EC96001F7C06 /* PostSectionController.m in Sources */, 29628F141D91905A0026B15A /* DetailLabelCell.swift in Sources */, - 56C05B811E49B4AB0026DB39 /* ImageSectionController.m in Sources */, 56C05B751E49B33C0026DB39 /* InteractiveCell.m in Sources */, 2991F9301D7BC0E400B0C58F /* EmptyViewController.swift in Sources */, 29F7E2AF1E92858500197586 /* ListeningSectionController.swift in Sources */, @@ -861,7 +845,6 @@ 2942FF941D9F39E00015D24B /* UserSectionController.swift in Sources */, 29459C001DBE48E200F05375 /* DiffTableViewController.swift in Sources */, 2991F92C1D7BBE5400B0C58F /* RemoveCell.swift in Sources */, - 56C05B871E49B4C40026DB39 /* InteractiveSectionController.m in Sources */, 2942FF8D1D9F39E00015D24B /* EmbeddedSectionController.swift in Sources */, 29C6297B1DCFD857004A5BB1 /* SupplementaryViewController.swift in Sources */, 296DD7551DD2150600206780 /* SelfSizingSectionController.swift in Sources */, @@ -889,7 +872,6 @@ 29F7E2AA1E9283FF00197586 /* AnnouncingDepsViewController.swift in Sources */, 56C05B721E49B32A0026DB39 /* CommentCell.m in Sources */, 821BC4BA1DB8B61200172ED0 /* StoryboardLabelSectionController.swift in Sources */, - 56C05B7B1E49B4030026DB39 /* UserInfo.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Examples/Examples-iOS/IGListKitExamples/Models/UserInfo.h b/Examples/Examples-iOS/IGListKitExamples/Models/Post.h similarity index 61% rename from Examples/Examples-iOS/IGListKitExamples/Models/UserInfo.h rename to Examples/Examples-iOS/IGListKitExamples/Models/Post.h index 81073d311..b17611789 100644 --- a/Examples/Examples-iOS/IGListKitExamples/Models/UserInfo.h +++ b/Examples/Examples-iOS/IGListKitExamples/Models/Post.h @@ -1,9 +1,9 @@ /** 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 @@ -13,9 +13,18 @@ */ #import -#import -@interface UserInfo : NSObject -@property (nonatomic, copy) NSString *name; -- (instancetype)initWithName:(NSString *)name; +#import + +@interface Post : NSObject + +@property (nonatomic, strong, readonly) NSString *username; +@property (nonatomic, strong, readonly) NSArray *comments; + +- (instancetype)initWithUsername:(NSString *)username + comments:(NSArray *)comments NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + @end diff --git a/Examples/Examples-iOS/IGListKitExamples/Models/UserInfo.m b/Examples/Examples-iOS/IGListKitExamples/Models/Post.m similarity index 64% rename from Examples/Examples-iOS/IGListKitExamples/Models/UserInfo.m rename to Examples/Examples-iOS/IGListKitExamples/Models/Post.m index 3756e9f71..0149ba6c4 100644 --- a/Examples/Examples-iOS/IGListKitExamples/Models/UserInfo.m +++ b/Examples/Examples-iOS/IGListKitExamples/Models/Post.m @@ -1,9 +1,9 @@ /** 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 @@ -12,25 +12,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#import "UserInfo.h" +#import "Post.h" -@implementation UserInfo +@implementation Post -- (instancetype)initWithName:(NSString *)name { +- (instancetype)initWithUsername:(NSString *)username + comments:(NSArray *)comments { if (self = [super init]) { - self.name = name; + _username = [username copy]; + _comments = [comments copy]; } return self; } #pragma mark - IGListDiffable -- (nonnull id)diffIdentifier { +- (id)diffIdentifier { return self; } -- (BOOL)isEqualToDiffableObject:(nullable id)object { - return [self isEqual:object]; +- (BOOL)isEqualToDiffableObject:(id)object { + // since the diff identifier returns self, object should only be compared with same instance + return self == object; } @end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.h b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.h deleted file mode 100644 index 5bd374930..000000000 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - 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 - -@interface CommentSectionController : IGListSectionController - -@end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.m b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.m deleted file mode 100644 index d9dbc7c3b..000000000 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/CommentSectionController.m +++ /dev/null @@ -1,48 +0,0 @@ -/** - 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 "CommentSectionController.h" -#import "CommentCell.h" - -@interface CommentSectionController () -@property (nonatomic, strong) NSString *comment; -@end - -@implementation CommentSectionController - -#pragma mark - IGListSectionType - -- (NSInteger)numberOfItems { - return 1; -} - -- (CGSize)sizeForItemAtIndex:(NSInteger)index { - return CGSizeMake(self.collectionContext.containerSize.width, 25); -} - -- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { - CommentCell *cell = [self.collectionContext dequeueReusableCellOfClass:[CommentCell class] forSectionController:self atIndex:index]; - cell.comment = self.comment; - return cell; -} - -- (void)didUpdateToObject:(id)object { - self.comment = object; -} - -- (void)didSelectItemAtIndex:(NSInteger)index { - -} - -@end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/ImageSectionController.m b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/ImageSectionController.m deleted file mode 100644 index b7fac57f7..000000000 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/ImageSectionController.m +++ /dev/null @@ -1,64 +0,0 @@ -/** - 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 "ImageSectionController.h" -#import "PhotoCell.h" - -@interface ImageSectionController () - -@end - -@implementation ImageSectionController - -#pragma mark - IGListSectionType - -- (NSInteger)numberOfItems { - return 1; -} - -- (CGSize)sizeForItemAtIndex:(NSInteger)index { - return CGSizeMake(self.collectionContext.containerSize.width, self.collectionContext.containerSize.width); -} - -- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { - PhotoCell *cell = [self.collectionContext dequeueReusableCellOfClass:[PhotoCell class] forSectionController:self atIndex:index]; - return cell; -} - -- (void)didUpdateToObject:(id)object { -} - -- (void)didSelectItemAtIndex:(NSInteger)index { - -} - -- (id)supplementaryViewSource { - return self; -} - -- (NSArray *)supportedElementKinds { - return @[UICollectionElementKindSectionFooter]; -} - -- (CGSize)sizeForSupplementaryViewOfKind:(NSString *)elementKind atIndex:(NSInteger)index { - return CGSizeMake(self.collectionContext.containerSize.width, 30); -} - -- (UICollectionReusableView *)viewForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index { - UICollectionReusableView *view = [self.collectionContext dequeueReusableSupplementaryViewOfKind:elementKind forSectionController:self class:[UICollectionReusableView class] atIndex:index]; - view.backgroundColor = [UIColor yellowColor]; - return view; -} - -@end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.h b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.h deleted file mode 100644 index b2b66d95c..000000000 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - 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 - -@interface InteractiveSectionController : IGListSectionController - -@end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.m b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.m deleted file mode 100644 index 394fd872b..000000000 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/InteractiveSectionController.m +++ /dev/null @@ -1,43 +0,0 @@ -/** - 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 "InteractiveSectionController.h" -#import "InteractiveCell.h" - -@implementation InteractiveSectionController - -#pragma mark - IGListSectionType - -- (NSInteger)numberOfItems { - return 1; -} - -- (CGSize)sizeForItemAtIndex:(NSInteger)index { - return CGSizeMake(self.collectionContext.containerSize.width, 41); -} - -- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { - InteractiveCell *cell = [self.collectionContext dequeueReusableCellOfClass:[InteractiveCell class] forSectionController:self atIndex:index]; - return cell; -} - -- (void)didUpdateToObject:(id)object { - -} - -- (void)didSelectItemAtIndex:(NSInteger)index { - -} - -@end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/ImageSectionController.h b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/PostSectionController.h similarity index 89% rename from Examples/Examples-iOS/IGListKitExamples/SectionControllers/ImageSectionController.h rename to Examples/Examples-iOS/IGListKitExamples/SectionControllers/PostSectionController.h index 79d25e033..8420dc377 100644 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/ImageSectionController.h +++ b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/PostSectionController.h @@ -1,9 +1,9 @@ /** 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 @@ -14,6 +14,6 @@ #import -@interface ImageSectionController : IGListSectionController +@interface PostSectionController : IGListSectionController @end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/PostSectionController.m b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/PostSectionController.m new file mode 100644 index 000000000..549cd7218 --- /dev/null +++ b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/PostSectionController.m @@ -0,0 +1,74 @@ +/** + 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 "PostSectionController.h" + +#import "Post.h" +#import "PhotoCell.h" +#import "InteractiveCell.h" +#import "CommentCell.h" +#import "UserInfoCell.h" + +static NSInteger cellsBeforeComments = 3; + +@implementation PostSectionController { + Post *_post; +} + +#pragma mark - IGListSectionType + +- (NSInteger)numberOfItems { + return cellsBeforeComments + _post.comments.count; +} + +- (CGSize)sizeForItemAtIndex:(NSInteger)index { + const CGFloat width = self.collectionContext.containerSize.width; + CGFloat height; + if (index == 0 || index == 2) { + height = 41.0; + } else if (index == 1) { + height = width; // square + } else { + height = 25.0; + } + return CGSizeMake(width, height); +} + +- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { + Class cellClass; + if (index == 0) { + cellClass = [UserInfoCell class]; + } else if (index == 1) { + cellClass = [PhotoCell class]; + } else if (index == 2) { + cellClass = [InteractiveCell class]; + } else { + cellClass = [CommentCell class]; + } + id cell = [self.collectionContext dequeueReusableCellOfClass:cellClass forSectionController:self atIndex:index]; + if ([cell isKindOfClass:[CommentCell class]]) { + [(CommentCell *)cell setComment:_post.comments[index - cellsBeforeComments]]; + } else if ([cell isKindOfClass:[UserInfoCell class]]) { + [(UserInfoCell *)cell setName:_post.username]; + } + return cell; +} + +- (void)didUpdateToObject:(id)object { + _post = object; +} + +- (void)didSelectItemAtIndex:(NSInteger)index {} + +@end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.h b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.h deleted file mode 100644 index 0768a96e1..000000000 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - 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 - -@interface UserInfoSectionController : IGListSectionController - -@end diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.m b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.m deleted file mode 100644 index e4ac9d861..000000000 --- a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/UserInfoSectionController.m +++ /dev/null @@ -1,50 +0,0 @@ -/** - 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 "UserInfoSectionController.h" -#import "UserInfoCell.h" -#import "UserInfo.h" - -@interface UserInfoSectionController () -@property (nonatomic, strong) UserInfo *userInfo; -@end - -@implementation UserInfoSectionController - -#pragma mark - IGListSectionType - -- (NSInteger)numberOfItems { - return 1; -} - -- (CGSize)sizeForItemAtIndex:(NSInteger)index { - return CGSizeMake(self.collectionContext.containerSize.width, 41); -} - -- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { - UserInfoCell *cell = [self.collectionContext dequeueReusableCellOfClass:[UserInfoCell class] forSectionController:self atIndex:index]; - cell.name = self.userInfo.name; - return cell; -} - -- (void)didUpdateToObject:(id)object { - self.userInfo = object; -} - -- (void)didSelectItemAtIndex:(NSInteger)index { - -} - - -@end diff --git a/Examples/Examples-iOS/IGListKitExamples/ViewControllers/ObjcDemoViewController.m b/Examples/Examples-iOS/IGListKitExamples/ViewControllers/ObjcDemoViewController.m index 466f7e18f..6374f7508 100644 --- a/Examples/Examples-iOS/IGListKitExamples/ViewControllers/ObjcDemoViewController.m +++ b/Examples/Examples-iOS/IGListKitExamples/ViewControllers/ObjcDemoViewController.m @@ -16,74 +16,54 @@ #import -#import "UserInfoSectionController.h" -#import "ImageSectionController.h" -#import "InteractiveSectionController.h" -#import "CommentSectionController.h" - -#import "UserInfo.h" -#import "PhotoCell.h" +#import "Post.h" +#import "PostSectionController.h" @interface ObjcDemoViewController () @property (nonatomic, strong) UICollectionView *collectionView; @property (nonatomic, strong) IGListAdapter *adapter; -@property (nonatomic, strong) NSArray *data; +@property (nonatomic, strong) NSArray *data; @end @implementation ObjcDemoViewController -#pragma mark - Setup +- (void)viewDidLoad { + [super viewDidLoad]; -- (void)setupUI { - UICollectionViewLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + self.data = @[ + [[Post alloc] initWithUsername:@"userA" comments:@[ + @"Luminous triangle", + @"Awesome", + @"Super clean", + @"Stunning shot", + ]], + [[Post alloc] initWithUsername:@"userB" comments:@[ + @"The simplicity here is superb", + @"thanks!", + @"That's always so kind of you!", + @"I think you might like this", + ]], + [[Post alloc] initWithUsername:@"userC" comments:@[ + @"So good", + ]], + [[Post alloc] initWithUsername:@"userD" comments:@[ + @"hope she might like it.", + @"I love it." + ]], + ]; + + self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero + collectionViewLayout:[UICollectionViewFlowLayout new]]; [self.view addSubview:self.collectionView]; - self.adapter = [[IGListAdapter alloc] initWithUpdater:[[IGListAdapterUpdater alloc] init] viewController:self workingRangeSize:0]; self.adapter.collectionView = self.collectionView; self.adapter.dataSource = self; - - UserInfo *userA = [[UserInfo alloc] initWithName:@"userA"]; - UserInfo *userB = [[UserInfo alloc] initWithName:@"userB"]; - UserInfo *userC = [[UserInfo alloc] initWithName:@"userC"]; - UserInfo *userD = [[UserInfo alloc] initWithName:@"userD"]; - - self.data = @[ userA, - @"Image-Placeholder-String", - @"", @"Luminous triangle", - @"Awesome", - @"Super clean", - @"Stunning shot", - userB, - @"Image-Placeholder-String", - @"", - @"The simplicity here is superb", - @"thanks!", @"That's always so kind of you!", - @"I think you might like this", - userC, - @"Image-Placeholder-String", - @"", - @"So good comment", - userD, - @"Image-Placeholder-String", - @"", - @"hope she might like it.", - @"I love it." - ]; - -} - -#pragma mark - View lifecycle - -- (void)viewDidLoad { - [super viewDidLoad]; - [self setupUI]; } - (void)viewDidLayoutSubviews { @@ -98,19 +78,7 @@ - (void)viewDidLayoutSubviews { } - (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object { - if ([object isKindOfClass:[NSString class]]) { - if ([object isEqualToString:@"Image-Placeholder-String"]) { - return [[ImageSectionController alloc] init]; - } else if ([object length]) { - return [[CommentSectionController alloc] init]; - } else { - return [[InteractiveSectionController alloc] init]; - } - } else { - return [[UserInfoSectionController alloc] init]; - } - - return nil; + return [PostSectionController new]; } - (UIView *)emptyViewForListAdapter:(IGListAdapter *)listAdapter { From da4ef11f5b20a474aee13d2e7e7bc4a009ac4449 Mon Sep 17 00:00:00 2001 From: Jesse Squires Date: Fri, 7 Apr 2017 15:21:40 -0700 Subject: [PATCH 2/2] Add vision doc Summary: Adding a `VISION.md` doc at the root dir to give collaborators and users guidance about what we will work on and how we will prioritize features/fixes for IGListKit. Issue fixed: #542 Closes https://github.com/Instagram/IGListKit/pull/607 Differential Revision: D4852285 Pulled By: jessesquires fbshipit-source-id: 9588c1ade63d291d60a4ff34c50506c38b51b5b0 --- Guides/VISION.md | 34 ++++++++++++++++++++++++++++++++++ README.md | 4 ++++ 2 files changed, 38 insertions(+) create mode 100644 Guides/VISION.md diff --git a/Guides/VISION.md b/Guides/VISION.md new file mode 100644 index 000000000..2a3f3e505 --- /dev/null +++ b/Guides/VISION.md @@ -0,0 +1,34 @@ +# Vision + +This document serves to outline the long term goals of IGListKit and act as a guidance when making decisions about features and issues. + +## Prioritizing Features & Fixes + +IGListKit is a data-driven, list-building framework built, owned, and maintained by the engineering team at Instagram. Because IGListKit powers parts of the Instagram iOS app, we prioritize features and bugs towards those that effect Instagram. However the team recognizes the wide range of use-cases for IGListKit and wants to serve as broad an audience as possible without sacrificing our own needs. + +## Goals & Scope + +The core goal of IGListKit is to build fast, stable, and data-driven lists in iOS applications. That scope includes things like: + +- `UICollectionView` and `UITableView` integrations +- Data and state management +- Diffing algorithms + +While IGListKit uses specific tools, we do want to limit the reach of how we use those tools. We highly encourage people to explore solutions that fit their needs and will try to assist when possible. Examples of things beyond the scope of IGListKit: + +- Advanced/custom `UICollectionViewLayout`s +- Sizing and layout (e.g. auto layout, estimated sizes) +- Render and display pipelines +- Integration with third-parties + +## Collaboration & Community + +While IGListKit is an Instagram project, we want to give as much ownership and responsibility to the community as possible. We welcome everyone to become a collaborator on the project with whatever level of contribution you feel comfortable with. + +We recognize that maintaining open source projects can be demanding, and often done in addition to other responsibilities. We have no expectation for the amount or frequency of contribution from anyone. + +We also ask that you help keep our community welcoming and open. + +## Communication + +Github Issues serve as the "source of truth" for all communication and decision-making about IGListKit. This keeps everything open and centralized. We will consider other forms of communication (Slack, Facebook Group, etc) once the scale of the project and/or community demands it. \ No newline at end of file diff --git a/README.md b/README.md index 14b0afcfd..ee86085ca 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,10 @@ github "Instagram/IGListKit" ~> 2.0.0 You can find [the docs here](https://instagram.github.io/IGListKit). Documentation is generated with [jazzy](https://github.com/realm/jazzy) and hosted on [GitHub-Pages](https://pages.github.com). +## Vision + +For the long term goals and "vision" of `IGListKit`, please read our [Vision](https://github.com/Instagram/IGListKit/blob/master/Guides/VISION.md) doc. + ## Contributing Please see the [CONTRIBUTING](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md) file for how to help out. At Instagram we sync the open source version of `IGListKit` daily, so we're always testing the latest changes. But that requires all changes be thoroughly tested and follow our style guide.