From 510ce093a5a36977b8edb9f911b1d0dbf672d014 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 20 Dec 2016 14:00:52 +0000 Subject: [PATCH] Update ASDKgram to use a shared base ASViewController --- .../ASDKgram/Sample.xcodeproj/project.pbxproj | 6 + .../ASDKgram/Sample/PhotoFeedBaseController.h | 38 ++++++ .../ASDKgram/Sample/PhotoFeedBaseController.m | 123 ++++++++++++++++++ .../ASDKgram/Sample/PhotoFeedNodeController.h | 5 +- .../ASDKgram/Sample/PhotoFeedNodeController.m | 104 ++------------- .../ASDKgram/Sample/PhotoFeedViewController.h | 4 +- .../ASDKgram/Sample/PhotoFeedViewController.m | 87 ++----------- 7 files changed, 195 insertions(+), 172 deletions(-) create mode 100644 examples/ASDKgram/Sample/PhotoFeedBaseController.h create mode 100644 examples/ASDKgram/Sample/PhotoFeedBaseController.m diff --git a/examples/ASDKgram/Sample.xcodeproj/project.pbxproj b/examples/ASDKgram/Sample.xcodeproj/project.pbxproj index dbbd72d54c..c07075274f 100644 --- a/examples/ASDKgram/Sample.xcodeproj/project.pbxproj +++ b/examples/ASDKgram/Sample.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 768843931CAA37EF00D8629E /* UserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7688437B1CAA37EF00D8629E /* UserModel.m */; }; 768843961CAA37EF00D8629E /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7688437E1CAA37EF00D8629E /* Utilities.m */; }; B13424EE6D36C2EC5D1030B6 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AD5DDA0A29B0F32AA5CC47BA /* libPods-Sample.a */; }; + E5F128F01E09625400B4335F /* PhotoFeedBaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = E5F128EF1E09625400B4335F /* PhotoFeedBaseController.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -81,6 +82,8 @@ 97A9B1BAF4265967672F9EA3 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = ""; }; AD5DDA0A29B0F32AA5CC47BA /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; D09B5DF0BFB37583DE8F3142 /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = ""; }; + E5F128EE1E09612700B4335F /* PhotoFeedBaseController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoFeedBaseController.h; sourceTree = ""; }; + E5F128EF1E09625400B4335F /* PhotoFeedBaseController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoFeedBaseController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -167,6 +170,8 @@ 767A5F141CAA3D8A004CDA8D /* Controller */ = { isa = PBXGroup; children = ( + E5F128EE1E09612700B4335F /* PhotoFeedBaseController.h */, + E5F128EF1E09625400B4335F /* PhotoFeedBaseController.m */, 767A5F161CAA3D96004CDA8D /* UIKit */, 767A5F151CAA3D90004CDA8D /* ASDK */, ); @@ -377,6 +382,7 @@ 768843821CAA37EF00D8629E /* CommentModel.m in Sources */, 768843831CAA37EF00D8629E /* CommentsNode.m in Sources */, 768843961CAA37EF00D8629E /* Utilities.m in Sources */, + E5F128F01E09625400B4335F /* PhotoFeedBaseController.m in Sources */, 768843931CAA37EF00D8629E /* UserModel.m in Sources */, 768843801CAA37EF00D8629E /* AppDelegate.m in Sources */, 768843811CAA37EF00D8629E /* CommentFeedModel.m in Sources */, diff --git a/examples/ASDKgram/Sample/PhotoFeedBaseController.h b/examples/ASDKgram/Sample/PhotoFeedBaseController.h new file mode 100644 index 0000000000..623d961eb7 --- /dev/null +++ b/examples/ASDKgram/Sample/PhotoFeedBaseController.h @@ -0,0 +1,38 @@ +// +// PhotoFeedBaseController.h +// Sample +// +// Created by Huy Nguyen on 20/12/16. +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +#import "AppDelegate.h" + +@class PhotoFeedModel; + +@interface PhotoFeedBaseController : ASViewController + +@property (nonatomic, strong, readonly) PhotoFeedModel *photoFeed; +@property (nonatomic, strong, readonly) UITableView *tableView; + +- (void)refreshFeed; +- (void)insertNewRows:(NSArray *)newPhotos; + +#pragma mark - Subclasses must override these methods + +- (void)loadPage; +- (void)requestCommentsForPhotos:(NSArray *)newPhotos; + +@end diff --git a/examples/ASDKgram/Sample/PhotoFeedBaseController.m b/examples/ASDKgram/Sample/PhotoFeedBaseController.m new file mode 100644 index 0000000000..c901d737e2 --- /dev/null +++ b/examples/ASDKgram/Sample/PhotoFeedBaseController.m @@ -0,0 +1,123 @@ +// +// PhotoFeedBaseController.m +// Sample +// +// Created by Huy Nguyen on 20/12/16. +// Copyright © 2016 Facebook. All rights reserved. +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 "PhotoFeedBaseController.h" +#import "PhotoFeedModel.h" + +@implementation PhotoFeedBaseController +{ + UIActivityIndicatorView *_activityIndicatorView; +} + +// -loadView is guaranteed to be called on the main thread and is the appropriate place to +// set up an UIKit objects you may be using. +- (void)loadView +{ + [super loadView]; + + _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + + _photoFeed = [[PhotoFeedModel alloc] initWithPhotoFeedModelType:PhotoFeedModelTypePopular imageSize:[self imageSizeForScreenWidth]]; + [self refreshFeed]; + + CGSize boundSize = self.view.bounds.size; + [_activityIndicatorView sizeToFit]; + CGRect refreshRect = _activityIndicatorView.frame; + refreshRect.origin = CGPointMake((boundSize.width - _activityIndicatorView.frame.size.width) / 2.0, + (boundSize.height - _activityIndicatorView.frame.size.height) / 2.0); + _activityIndicatorView.frame = refreshRect; + [self.view addSubview:_activityIndicatorView]; + + self.tableView.allowsSelection = NO; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + + self.view.backgroundColor = [UIColor whiteColor]; +} + +- (void)refreshFeed +{ + [_activityIndicatorView startAnimating]; + // small first batch + [_photoFeed refreshFeedWithCompletionBlock:^(NSArray *newPhotos){ + + [_activityIndicatorView stopAnimating]; + + [self insertNewRows:newPhotos]; + [self requestCommentsForPhotos:newPhotos]; + + // immediately start second larger fetch + [self loadPage]; + + } numResultsToReturn:4]; +} + +- (void)insertNewRows:(NSArray *)newPhotos +{ + NSInteger section = 0; + NSMutableArray *indexPaths = [NSMutableArray array]; + + NSInteger newTotalNumberOfPhotos = [_photoFeed numberOfItemsInFeed]; + for (NSInteger row = newTotalNumberOfPhotos - newPhotos.count; row < newTotalNumberOfPhotos; row++) { + NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section]; + [indexPaths addObject:path]; + } + [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone]; +} + +- (UIStatusBarStyle)preferredStatusBarStyle +{ + return UIStatusBarStyleLightContent; +} + +- (CGSize)imageSizeForScreenWidth +{ + CGRect screenRect = [[UIScreen mainScreen] bounds]; + CGFloat screenScale = [[UIScreen mainScreen] scale]; + return CGSizeMake(screenRect.size.width * screenScale, screenRect.size.width * screenScale); +} + +#pragma mark - PhotoFeedViewControllerProtocol + +- (void)resetAllData +{ + [_photoFeed clearFeed]; + [self.tableView reloadData]; + [self refreshFeed]; +} + +#pragma mark - Subclassing + +- (UITableView *)tableView +{ + NSAssert(NO, @"Subclasses must override this method"); + return nil; +} + +- (void)loadPage +{ + NSAssert(NO, @"Subclasses must override this method"); +} + +- (void)requestCommentsForPhotos:(NSArray *)newPhotos +{ + NSAssert(NO, @"Subclasses must override this method"); +} + +@end diff --git a/examples/ASDKgram/Sample/PhotoFeedNodeController.h b/examples/ASDKgram/Sample/PhotoFeedNodeController.h index 04c9aa896c..c97576b7bc 100644 --- a/examples/ASDKgram/Sample/PhotoFeedNodeController.h +++ b/examples/ASDKgram/Sample/PhotoFeedNodeController.h @@ -17,9 +17,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#import -#import "AppDelegate.h" +#import "PhotoFeedBaseController.h" -@interface PhotoFeedNodeController : ASViewController +@interface PhotoFeedNodeController : PhotoFeedBaseController @end diff --git a/examples/ASDKgram/Sample/PhotoFeedNodeController.m b/examples/ASDKgram/Sample/PhotoFeedNodeController.m index 322c9de49a..1e22925e6d 100644 --- a/examples/ASDKgram/Sample/PhotoFeedNodeController.m +++ b/examples/ASDKgram/Sample/PhotoFeedNodeController.m @@ -31,9 +31,7 @@ @interface PhotoFeedNodeController () @implementation PhotoFeedNodeController { - PhotoFeedModel *_photoFeed; - ASTableNode *_tableNode; - UIActivityIndicatorView *_activityIndicatorView; + ASTableNode *_tableNode; } #pragma mark - Lifecycle @@ -51,7 +49,6 @@ - (instancetype)init _tableNode.dataSource = self; _tableNode.delegate = self; - } return self; @@ -63,112 +60,48 @@ - (void)loadView { [super loadView]; - _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - - _photoFeed = [[PhotoFeedModel alloc] initWithPhotoFeedModelType:PhotoFeedModelTypePopular imageSize:[self imageSizeForScreenWidth]]; - [self refreshFeed]; - - CGSize boundSize = self.view.bounds.size; - - [_activityIndicatorView sizeToFit]; - CGRect refreshRect = _activityIndicatorView.frame; - refreshRect.origin = CGPointMake((boundSize.width - _activityIndicatorView.frame.size.width) / 2.0, - (boundSize.height - _activityIndicatorView.frame.size.height) / 2.0); - _activityIndicatorView.frame = refreshRect; - - [self.view addSubview:_activityIndicatorView]; - - self.view.backgroundColor = [UIColor whiteColor]; - _tableNode.view.allowsSelection = NO; - _tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone; _tableNode.view.leadingScreensForBatching = AUTO_TAIL_LOADING_NUM_SCREENFULS; // overriding default of 2.0 } -#pragma mark - helper methods - -- (void)refreshFeed -{ - [_activityIndicatorView startAnimating]; - // small first batch - [_photoFeed refreshFeedWithCompletionBlock:^(NSArray *newPhotos){ - - [_activityIndicatorView stopAnimating]; - - [self insertNewRowsInTableNode:newPhotos]; -// [self requestCommentsForPhotos:newPhotos]; - - // immediately start second larger fetch - [self loadPageWithContext:nil]; - - } numResultsToReturn:4]; -} - - (void)loadPageWithContext:(ASBatchContext *)context { - [_photoFeed requestPageWithCompletionBlock:^(NSArray *newPhotos){ + [self.photoFeed requestPageWithCompletionBlock:^(NSArray *newPhotos){ - [self insertNewRowsInTableNode:newPhotos]; -// [self requestCommentsForPhotos:newPhotos]; + [self insertNewRows:newPhotos]; + [self requestCommentsForPhotos:newPhotos]; if (context) { [context completeBatchFetching:YES]; } } numResultsToReturn:20]; } -//- (void)requestCommentsForPhotos:(NSArray *)newPhotos -//{ -// for (PhotoModel *photo in newPhotos) { -// [photo.commentFeed refreshFeedWithCompletionBlock:^(NSArray *newComments) { -// -// NSInteger rowNum = [_photoFeed indexOfPhotoModel:photo]; -// NSIndexPath *cellPath = [NSIndexPath indexPathForRow:rowNum inSection:0]; -// PhotoCellNode *cell = (PhotoCellNode *)[_tableNode.view nodeForRowAtIndexPath:cellPath]; -// -// if (cell) { -// [cell loadCommentsForPhoto:photo]; -// [_tableNode.view beginUpdates]; -// [_tableNode.view endUpdates]; -// } -// }]; -// } -//} - -- (void)insertNewRowsInTableNode:(NSArray *)newPhotos +#pragma mark - Subclassing + +- (UITableView *)tableView { - NSInteger section = 0; - NSMutableArray *indexPaths = [NSMutableArray array]; - - NSUInteger newTotalNumberOfPhotos = [_photoFeed numberOfItemsInFeed]; - for (NSUInteger row = newTotalNumberOfPhotos - newPhotos.count; row < newTotalNumberOfPhotos; row++) { - NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section]; - [indexPaths addObject:path]; - } - - [_tableNode insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone]; + return _tableNode.view; } -- (UIStatusBarStyle)preferredStatusBarStyle +- (void)loadPage { - return UIStatusBarStyleLightContent; + [self loadPageWithContext:nil]; } -- (CGSize)imageSizeForScreenWidth +- (void)requestCommentsForPhotos:(NSArray *)newPhotos { - CGRect screenRect = [[UIScreen mainScreen] bounds]; - CGFloat screenScale = [[UIScreen mainScreen] scale]; - return CGSizeMake(screenRect.size.width * screenScale, screenRect.size.width * screenScale); + // Do nothing (#1530). } #pragma mark - ASTableDataSource methods - (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { - return [_photoFeed numberOfItemsInFeed]; + return [self.photoFeed numberOfItemsInFeed]; } - (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath { - PhotoModel *photoModel = [_photoFeed objectAtIndex:indexPath.row]; + PhotoModel *photoModel = [self.photoFeed objectAtIndex:indexPath.row]; // this will be executed on a background thread - important to make sure it's thread safe ASCellNode *(^ASCellNodeBlock)() = ^ASCellNode *() { PhotoCellNode *cellNode = [[PhotoCellNode alloc] initWithPhotoObject:photoModel]; @@ -187,13 +120,4 @@ - (void)tableNode:(ASTableNode *)tableNode willBeginBatchFetchWithContext:(ASBat [self loadPageWithContext:context]; } -#pragma mark - PhotoFeedViewControllerProtocol - -- (void)resetAllData -{ - [_photoFeed clearFeed]; - [_tableNode reloadData]; - [self refreshFeed]; -} - @end diff --git a/examples/ASDKgram/Sample/PhotoFeedViewController.h b/examples/ASDKgram/Sample/PhotoFeedViewController.h index 3942ec5c27..3733fde82b 100644 --- a/examples/ASDKgram/Sample/PhotoFeedViewController.h +++ b/examples/ASDKgram/Sample/PhotoFeedViewController.h @@ -17,8 +17,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#import "AppDelegate.h" +#import "PhotoFeedBaseController.h" -@interface PhotoFeedViewController : UIViewController +@interface PhotoFeedViewController : PhotoFeedBaseController @end diff --git a/examples/ASDKgram/Sample/PhotoFeedViewController.m b/examples/ASDKgram/Sample/PhotoFeedViewController.m index ddaf2a7cf9..3a36861e96 100644 --- a/examples/ASDKgram/Sample/PhotoFeedViewController.m +++ b/examples/ASDKgram/Sample/PhotoFeedViewController.m @@ -30,9 +30,7 @@ @interface PhotoFeedViewController ()