Skip to content

Commit

Permalink
#4. 由于完全异步读取的用户体验差,改回使用批量分页读取。
Browse files Browse the repository at this point in the history
  • Loading branch information
exiaomo committed Jun 21, 2015
1 parent 0d00755 commit 59347b4
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 96 deletions.
2 changes: 1 addition & 1 deletion ARGO_317_2/General/AllBoardsList/TopicListViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ - (void)fetchTotal_topicNumWithBoardName:(NSString *)boardname
// NSLog(@"Post List.");
if (self.boardName && self.boardTitle) {
[[DataManager manager] getBoardByBoardName:boardname success:^(NSDictionary *data){
// NSLog(@"Dictionary: %@", [data description]);
// NSLog(@"Dictionary: %@", [data description]);

total_topicNum=[[[data objectForKey:@"data"] objectForKey:@"total_topic"]integerValue];
//记录下拉刷新时间:
Expand Down
152 changes: 66 additions & 86 deletions ARGO_317_2/General/Home/PostListViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// This contains a 3-stages lazy load:
// 1. No data.
// 2. List ready.
// 3. Rendering cell when visible.
// 3. Rendering cells in page.

#import "PostListViewController.h"
#import "AddPostViewController.h"
Expand All @@ -23,21 +23,38 @@
#define floorTag 4
#define hasPictureTag 5

static long batchCount = 3;
static int pageSize = 10;

static NSString *CellIdentifier = @"postCell";

@implementation PostListViewController
@implementation PostListViewController {
int currentPage;
}
@synthesize boardName,fileName;
@synthesize postTopicList,postList;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

// -------------------------------------------------------------------------------
// viewDidLoad
// -------------------------------------------------------------------------------
- (void)viewDidLoad
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {

}
return self;
[super viewDidLoad];
dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/beijing"];
dateFormatter.dateFormat=@"yyyy/MM/dd, HH:mm";
loadingCell=[[LoadingCell alloc]initWithNormalStr:@"上拉刷新" andLoadingStr:@"数据加载中.." andStartViewStr:@"可下拉刷新.."];
[loadingCell loading];

currentPage = 0;
// Load list asynchously.
[self initTopicList];
UIRefreshControl *refresh=[[UIRefreshControl alloc]init];
refresh.tintColor=[UIColor lightGrayColor];
refresh.attributedTitle=[[NSAttributedString alloc]initWithString:@"下拉刷新"];
[refresh addTarget:self action:@selector(refreshView:) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;

}

-(void) initTopicList {
Expand All @@ -57,41 +74,23 @@ -(void) initTopicList {
[postTopicList addObject:[data objectAtIndex:i]];
}
}
//记录数据加载时间
lastUpdated=[NSString stringWithFormat:@"更新时间 %@", [dateFormatter stringFromDate:[NSDate date]]];
[self fetchInBatch:0 count: batchCount];
[loadingCell normal];
loadingCell.label.text=[NSString stringWithFormat:@"%@",lastUpdated];
[self.refreshControl endRefreshing];
[self loadNextPage];
}
} failure:^(NSString *data, NSError *error) {
// failed?
NSLog(@"Loading failed.");
NSString* errorMsg = NSLocalizedString([error.userInfo objectForKey:@"error"],@"");
[loadingCell normal];
loadingCell.label.text = [NSString stringWithFormat:@"%@%@",NSLocalizedString(@"Reason:", @""), errorMsg];
UIAlertView *av = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"Error",@"") message: [NSString stringWithFormat:@"%@%@",NSLocalizedString(@"Reason:", @""), errorMsg] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[av show];
}
];

}

// -------------------------------------------------------------------------------
// viewDidLoad
// -------------------------------------------------------------------------------
- (void)viewDidLoad
{
[super viewDidLoad];
dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/beijing"];
dateFormatter.dateFormat=@"yyyy/MM/dd, HH:mm";
loadingCell=[[LoadingCell alloc]initWithNormalStr:@"上拉刷新" andLoadingStr:@"数据加载中.." andStartViewStr:@"可下拉刷新.."];
-(void) loadNextPage {
[loadingCell loading];

// Load list asynchously.
[self initTopicList];
UIRefreshControl *refresh=[[UIRefreshControl alloc]init];
refresh.tintColor=[UIColor lightGrayColor];
refresh.attributedTitle=[[NSAttributedString alloc]initWithString:@"下拉刷新"];
[refresh addTarget:self action:@selector(refreshView:) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;

[self fetchInBatch:currentPage*pageSize count:pageSize];
}

//下拉刷新调用的方法
Expand All @@ -110,78 +109,51 @@ - (void)clear
{
[postTopicList removeAllObjects];
[loadingCell loading];
currentPage = 0;
}

// -------------------------------------------------------------------------------
// didReceiveMemoryWarning
// -------------------------------------------------------------------------------
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}

#pragma mark - UITableViewDataSource

// -------------------------------------------------------------------------------
// tableView:numberOfRowsInSection:
// Customize the number of rows in the table view.
// -------------------------------------------------------------------------------
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Always there is a loading cell.
return self.postTopicList.count + 1;
return [self numberOfRows] + 1;
}

-(NSInteger) numberOfRows {
return MIN(currentPage * pageSize, self.postTopicList.count);
}

// -------------------------------------------------------------------------------
// tableView:cellForRowAtIndexPath:
// -------------------------------------------------------------------------------
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;

NSUInteger nodeCount = self.postTopicList.count;

if (nodeCount == indexPath.row) {

if ([self numberOfRows] == indexPath.row) {
// for the last row always return loading cell.
return loadingCell.cell;
}

cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

NSDictionary *post = (self.postList)[indexPath.row];
[self composite:cell at:indexPath with:post];

if(post == (id)[NSNull null]) {
NSLog(@"Going to fetch:%@",[postTopicList objectAtIndex:indexPath.row]);

[[DataManager manager] getPostByBoard:boardName andFile:[postTopicList objectAtIndex:indexPath.row] success:^(NSDictionary *resultDict) {
NSLog(@"On fetching successfully:%@",[[resultDict objectForKey:@"data"] objectForKey:@"filename"]);
if ([resultDict objectForKey:@"data"]&&[[resultDict objectForKey:@"data"]isKindOfClass:[NSDictionary class]]) {
self.postList[indexPath.row]=[resultDict objectForKey:@"data"];
[self composite:cell at:indexPath with:self.postList[indexPath.row]];
}
NSLog(@"TableView rows=%ld",(long)[tableView numberOfRowsInSection:0]);
NSLog(@"Going to reload row=%@",indexPath);
NSLog(@"The cell=%@",[tableView cellForRowAtIndexPath:indexPath]);
if([tableView cellForRowAtIndexPath:indexPath]) { [tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
}


} failure:^(NSString *data, NSError *error) {
NSLog(@"When fetching failed.");
}];
}

NSLog(@"Returning cell=%@",cell);
return cell;
}

-(void) fetchInBatch:(long) from count:(long) count {
-(void) fetchInBatch:(int) from count:(int) count {
assert(postTopicList.count > 0);
assert(count >= 0);
__block int counter = 0;
unsigned long threshold = MIN(count, postTopicList.count - from);
NSLog(@"Going to fetch next %ld from %ld", count, from);
for (int i = 0; i < threshold; ++i) {
int threshold = MIN(count, (int)postTopicList.count - from);
if (threshold < 0) {
// No more data now.
lastUpdated=[NSString stringWithFormat:@"更新时间 %@", [dateFormatter stringFromDate:[NSDate date]]];
[loadingCell normal];
loadingCell.label.text=[NSString stringWithFormat:@"%@",lastUpdated];
}
NSLog(@"Going to fetch next %d from %d", count, from);
for (int i = from; i < from + threshold; ++i) {
NSLog(@"Going to fetch :%@", [postTopicList objectAtIndex:i]);
[[DataManager manager] getPostByBoard:boardName andFile:[postTopicList objectAtIndex:i] success:^(NSDictionary *resultDict) {
NSLog(@"On fetching successfully:%@",[[resultDict objectForKey:@"data"] objectForKey:@"filename"]);
Expand All @@ -190,6 +162,14 @@ -(void) fetchInBatch:(long) from count:(long) count {
}
++counter;
if(counter == threshold) {
currentPage++;
[loadingCell normal];
if (postTopicList.count <= from + threshold) {
lastUpdated=[NSString stringWithFormat:@"更新时间 %@", [dateFormatter stringFromDate:[NSDate date]]];
loadingCell.label.text=[NSString stringWithFormat:@"%@",lastUpdated];
} else {
loadingCell.label.text=[NSString stringWithFormat:@"下面还有%lu贴,轻轻上拉继续看",(unsigned long)postTopicList.count-from-threshold];
}
[self.tableView reloadData];
}
} failure:^(NSString *data, NSError *error) {
Expand Down Expand Up @@ -240,10 +220,10 @@ -(NSString *) formatTime:(double)timeStr {
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
//触发上拉加载更多的条件
if(scrollView.contentSize.height - (scrollView.contentOffset.y + scrollView.bounds.size.height - scrollView.contentInset.bottom) <= -REFRESH_HEADER_HEIGHT && scrollView.contentOffset.y > 0){
if(scrollView.contentSize.height - (scrollView.contentOffset.y + scrollView.bounds.size.height - scrollView.contentInset.bottom) <= -REFRESH_HEADER_HEIGHT && scrollView.contentOffset.y > 0) {
//如果是提醒详情,则不需要上拉加载更多
if ([self.navigationItem.title isEqualToString:@"提醒详情"]==NO) {
// [self performSelector:@selector(loadMorePostFeed) withObject:nil afterDelay:0];
[self loadNextPage];
}
}

Expand All @@ -254,7 +234,7 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa
if (indexPath.row<[postList count] && postList[indexPath.row]!=[NSNull null]) {
return [self getTheHeight:indexPath.row];
} else {
return 100;
return 50;
}
}

Expand All @@ -274,9 +254,9 @@ -(CGFloat) getTheHeight:(NSInteger)row {

// 返回需要的高度,这里的判断不需要那么严格
if ([[postList[row]objectForKey:@"ah"]count]==0) {
return height+58;
return height+28;
} else {
return height+88;
return height+38;
}
}

Expand Down
11 changes: 6 additions & 5 deletions ARGO_317_2/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
Expand Down Expand Up @@ -1193,7 +1194,7 @@
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleAspectFit" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mx9-AR-gJj">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<subviews>
<imageView multipleTouchEnabled="YES" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eUx-Yx-qpj">
<imageView multipleTouchEnabled="YES" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eUx-Yx-qpj">
<constraints>
<constraint firstAttribute="width" constant="320" id="rfZ-ZW-FTc"/>
</constraints>
Expand Down Expand Up @@ -1588,10 +1589,10 @@
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
<inferredMetricsTieBreakers>
<segue reference="EYj-UX-AS2"/>
<segue reference="22l-MZ-9b5"/>
<segue reference="LJV-ft-H5N"/>
<segue reference="EYj-UX-AS2"/>
<segue reference="O0L-GN-udV"/>
<segue reference="owN-Hs-TkM"/>
<segue reference="63l-aH-bEP"/>
</inferredMetricsTieBreakers>
</document>
30 changes: 28 additions & 2 deletions ARGO_317_2/Models/DataManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ @implementation DataManager


NSString * const MSG_NETWORK_FAILURE = @"MSG_NETWORK_FAILURE";
NSString * const MSG_BUSINESS_FAILURE = @"MSG_BUSINESS_FAILURE";

DataManager *manager;

Expand Down Expand Up @@ -59,7 +60,13 @@ - (void)getData:(NSString*) url

[[AFHTTPRequestOperationManager manager] GET:url parameters:param success:^(AFHTTPRequestOperation *operation, id responseObject) {
[self.postCache setObject:responseObject forKey:cacheKey];
success(responseObject);
NSError* error = [self isSuccessfulJsonResponse:responseObject];
if (!error) {
success(responseObject);
} else {
NSError* error = [NSError errorWithDomain:@"" code:123 userInfo:responseObject];
failure(NSLocalizedString(MSG_BUSINESS_FAILURE, MSG_NETWORK_FAILURE_KEY),error);
}
} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
failure(NSLocalizedString(MSG_NETWORK_FAILURE, MSG_NETWORK_FAILURE_KEY),error);
}];
Expand All @@ -71,12 +78,31 @@ - (void)getData:(NSString*) url
success:(void (^)(NSDictionary *resultDict))success
failure:(void (^)(NSString *data, NSError *error))failure; {
[[AFHTTPRequestOperationManager manager] GET:url parameters:param success:^(AFHTTPRequestOperation *operation, id responseObject) {
success(responseObject);
NSError* error = [self isSuccessfulJsonResponse:responseObject];
if (!error) {
success(responseObject);
} else {
failure(NSLocalizedString(MSG_BUSINESS_FAILURE, @""), error);
}
} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
failure(NSLocalizedString(MSG_NETWORK_FAILURE, MSG_NETWORK_FAILURE_KEY),error);
}];
}

-(NSError*) isSuccessfulJsonResponse: (id) responseObject {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSDictionary* jsonDict = (NSDictionary*) responseObject;
if ([[jsonDict objectForKey:@"success"] isEqual:@"1"] ||
[[jsonDict objectForKey:@"success"] isEqual:@(1)] ||
[jsonDict objectForKey:@"data"] ){
return nil;
}
return [NSError errorWithDomain:@"" code:[[jsonDict objectForKey:@"code"] integerValue] userInfo:responseObject];
}
// Should not happen.
return [NSError errorWithDomain:@"" code:404 userInfo:responseObject];
}

- (void)getAllSections:(void (^)(NSDictionary *resultDict)) success
failure:(void (^)(NSString *data, NSError *error)) failure; {
NSString *cacheKey = @"allSection";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@
Copyright (c) 2014 [email protected]. All rights reserved.
*/
"welcome"="Click on the screen to continue...";
"MSG_NETWORK_FAILURE"="网络错误。如果您多次看到此提示,请尝试使用浏览器访问http://argo.sysu.edu.cn/";
"MSG_NETWORK_FAILURE"="网络错误。如果您多次看到此提示,请尝试使用浏览器访问http://argo.sysu.edu.cn/";
"Post not exists."="该贴不存在";
"Error"="出错了";
"Reason:"="错误原因:";
2 changes: 1 addition & 1 deletion xARGO.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@
ORGANIZATIONNAME = "[email protected]";
TargetAttributes = {
B0C3D86518D6F421004B5F9F = {
DevelopmentTeam = FG2DXVNB5P;
DevelopmentTeam = 38A6JF2N52;
};
};
};
Expand Down

0 comments on commit 59347b4

Please sign in to comment.