[iOS微博項目 - 3.0] - 手動刷新微博

A.下拉刷新微博
1.需求
  • 在「首頁」界面,下拉到必定距離的時候刷新微博數據
  • 刷新數據的時候使用控件提示
  • 新數據要加在舊數據的前面
  • 刷新完畢隱藏刷新控件
  • 刷新數據完畢,導航欄下方彈出一個提示框,提示刷新微博數量
 
2.思路
  • 直接使用系統自帶的UIRefreshControl就能夠作出動畫效果
  • 使用微博的獲取微博API參數since_id能夠控制加載的微博從哪一個id開始
  • 使用可變數組來拼接新舊微博數據
  • 建立一個UILabel放在導航控制器view上來提示刷新數據(放在TableView上會被滾走)
 
3.實現
(1)每條微博都有一個id,這個id是隨時間遞進疊加的,id越大越新
Image(115)
 
(2)獲取微博API參數
Image(116)
 
(3)在「首頁」控制器加上下拉刷新代碼
之前的加載微博數據方法"loadWeiboData",也用刷新方法代替
 1 //  HVWHomeViewController.m
 2 - (void)viewDidLoad {
 3     [super viewDidLoad];
 4    
 5     self.tableView.delegate = self;
 6    
 7     // 設置導航欄
 8     [self setupNavigationBar];
 9    
10     // 添加刷新器
11     [self addRefresh];
12 }
13  
14 /** 初始化status */
15 - (NSMutableArray *)statuses {
16     if (nil == _statuses) {
17         _statuses = [NSMutableArray array];
18     }
19     return _statuses;
20 }
21 
22 /** 添加刷新器 */
23 - (void) addRefresh {
24     // 下拉刷新最新微博
25     // 添加刷新控件
26     UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
27     self.refreshControl = refreshControl;
28     [self.view addSubview:refreshControl];
29    
30     // 刷新控件下拉事件
31     [refreshControl addTarget:self action:@selector(refreshLatestWeibo:) forControlEvents:UIControlEventValueChanged];
32    
33     // 開啓的時候自動進入刷新狀態
34     [refreshControl beginRefreshing];
35     // 加載微博數據
36     [self refreshLatestWeibo:refreshControl];
37 }
38  
39 /** 刷新最新微博數據 */
40 - (void) refreshLatestWeibo:(UIRefreshControl *) refreshControl {
41     // 把最新的微博數據加到原來的微博前面
42    
43     // 建立AFNetworking的http操做中管理器
44     AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
45    
46     // 設置參數
47     NSMutableDictionary *param = [NSMutableDictionary dictionary];
48     param[@"access_token"] = [HVWAccountInfoTool accountInfo].access_token;
49    
50     /** 若指定此參數,則返回ID比since_id大的微博(即比since_id時間晚的微博),默認爲0。*/
51     HVWStatus *firstStatus = [self.statuses firstObject];
52     if (firstStatus) {
53         param[@"since_id"] = firstStatus.idstr;
54     }
55    
56     // 發送請求
57     [manager GET:@"https://api.weibo.com/2/statuses/home_timeline.json" parameters:param success:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
58         //        HVWLog(@"獲取微博數據成功-------%@", responseObject);
59        
60         // 保存數據到內存
61         NSArray *dataArray = responseObject[@"statuses"];
62        
63         // 獲得新微博數據
64         // 使用MJExtension直接進行字典-模型轉換
65         NSArray *newStatus = [HVWStatus objectArrayWithKeyValuesArray:dataArray];
66        
67         // 插入到微博數據數組的最前面
68         NSRange newWeiboRange = NSMakeRange(0, newStatus.count);
69         NSIndexSet *newWeiboIndexSet = [NSIndexSet indexSetWithIndexesInRange:newWeiboRange];
70         [self.statuses insertObjects:newStatus atIndexes:newWeiboIndexSet];
71        
72         // 刷新數據
73         [self.tableView reloadData];
74     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
75         HVWLog(@"獲取微博數據失敗------%@", error);
76     }];
77    
78     // 縮回刷新器
79     [refreshControl endRefreshing];
80 }
 
RefreshNewWeiboData
 
(4)添加一個UILabel提示更新微博數量,在請求微博數據成功後顯示
 1 /** 彈出微博更新提示框 */
 2 - (void) showRefreshIndicator:(int) refreshCount {
 3     // 建立UILabel
 4     UILabel *refreshIndicatorLabel = [[UILabel alloc] init];
 5     refreshIndicatorLabel.textAlignment = NSTextAlignmentCenter;
 6    
 7     // 設置文本
 8     refreshIndicatorLabel.text = [NSString stringWithFormat:@"更新了%d條微博", refreshCount];
 9    
10     // 設置背景
11     refreshIndicatorLabel.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithNamed:@"timeline_new_status_background"]];
12    
13     // 設置位置尺寸
14     refreshIndicatorLabel.width = self.navigationController.view.width;
15     refreshIndicatorLabel.height = 35;
16     refreshIndicatorLabel.x = 0;
17     // 由於一開始是藏在導航欄上的,因此要減去自身的高度
18     refreshIndicatorLabel.y = [UIApplication sharedApplication].statusBarFrame.size.height + self.navigationController.navigationBar.height - refreshIndicatorLabel.height;
19    
20     // 添加到導航控制器view,要加載導航器的下面
21     [self.navigationController.view insertSubview:refreshIndicatorLabel belowSubview:self.navigationController.navigationBar];
22    
23     // 使用動畫彈出
24     [UIView animateWithDuration:1.0 animations:^{
25         // 使用更改transform來實現
26         refreshIndicatorLabel.transform = CGAffineTransformMakeTranslation(0, refreshIndicatorLabel.height);
27     } completion:^(BOOL finished) {
28         // 彈出完畢後,再使用動畫縮回
29         [UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
30             // 恢復位置
31             refreshIndicatorLabel.transform = CGAffineTransformIdentity;
32         } completion:^(BOOL finished) {
33             // 從導航view刪除
34             [refreshIndicatorLabel removeFromSuperview];
35         }];
36     }];
37 }
 
RefreshWeiboIndicator
 
 
B.上拉加載舊微博數據
1.需求
當瀏覽到了緩存的全部微博數據底部的時候,上拉加載更多的舊微博數據
也具備一個加載提示器
 
2.思路
跟下拉加載新微博同樣,使用獲取微博API中的「max_id」參數
若是須要加載等待動畫圖標(菊花圖標),可使用代碼或xib建立一個UIView
加載在tableView的footerView上
 
Image(117)
 
3.實現
(1)設計一個「加載更多」控件
 1 //
 2 //  HVWLoadMoreWeiboFooterView.m
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/2/6.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "HVWLoadMoreWeiboFooterView.h"
10 
11 @interface HVWLoadMoreWeiboFooterView()
12 
13 /** 加載更多微博文本 */
14 @property(nonatomic, strong) UILabel *label;
15 
16 /** 加載中活動指示器 */
17 @property(nonatomic, strong) UIActivityIndicatorView *actIndicator;
18 
19 @end
20 
21 @implementation HVWLoadMoreWeiboFooterView
22 
23 - (instancetype)initWithFrame:(CGRect)frame {
24     self = [super initWithFrame:frame];
25 
26     self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithNamed:@"timeline_new_status_background"]];
27    
28     // 設置加載文本
29     UILabel *label = [[UILabel alloc] init];
30     label.textAlignment = NSTextAlignmentCenter;
31     label.text = @"上拉加載更多微博";
32     self.label = label;
33     [self addSubview:label];
34    
35     // 設置加載活動指示器
36     // 不一樣類型的活動指示器大小是不同的,要注意
37     UIActivityIndicatorView *actIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
38     self.actIndicator = actIndicator;
39     [self addSubview:actIndicator];
40    
41     return self;
42 }
43 
44 /** 設置位置尺寸 */
45 - (void)layoutSubviews {
46     [super layoutSubviews];
47    
48     // 設置自己frame
49     self.width = [UIScreen mainScreen].bounds.size.width;
50     self.height = 35;
51    
52     // 設置文本frame
53     self.label.frame = self.bounds;
54    
55     // 設置活動指示器frame
56     CGFloat marginX = 50;
57     self.actIndicator.x = self.width - self.actIndicator.width - marginX;
58     self.actIndicator.y = (self.height - self.actIndicator.height) * 0.5;
59 }
60 
61 @end
 
加在tableView的footerView上,沒有微博數據的時候不須要顯示(app啓動的時候)
 1 //  HVWHomeViewController.m
 2 /** 添加刷新器 */
 3 - (void) addRefresh {
 4     // 下拉刷新最新微博
 5     // 添加刷新控件
 6     UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
 7     self.refreshControl = refreshControl;
 8     [self.view addSubview:refreshControl];
 9    
10     // 刷新控件下拉事件
11     [refreshControl addTarget:self action:@selector(refreshLatestWeibo:) forControlEvents:UIControlEventValueChanged];
12    
13     // 開啓的時候自動進入刷新狀態
14     [refreshControl beginRefreshing];
15     // 加載微博數據
16     [self refreshLatestWeibo:refreshControl];
17    
18     // 添加上拉刷新器
19     HVWLoadMoreWeiboFooterView *loadMoreFooter = [[HVWLoadMoreWeiboFooterView alloc] init];
20     self.loadMoreFooter = loadMoreFooter;
21     self.tableView.tableFooterView = loadMoreFooter;
22   
23 }
24  
25 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
26     // 沒有微博數據的時候,不須要顯示「加載更多微博」控件
27     self.loadMoreFooter.hidden = self.statuses.count==0?YES:NO;
28    
29     return self.statuses.count;
30 }
 
Image(118)
 
 
(2)上拉刷新動做監聽
a.給「上拉刷新」控件增長狀態管理屬性和方法
 1 //
 2 //  HVWLoadMoreWeiboFooterView.h
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/2/6.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface HVWLoadMoreWeiboFooterView : UIView
12 
13 /** 是否正在刷新 */
14 @property(nonatomic, assign, getter=isRefreshing) BOOL refreshing;
15 
16 /** 開始刷新 */
17 - (void) beginRefresh;
18 /** 中止刷新 */
19 - (void) endRefresh;
20 
21 @end
22  
23 //
24 //  HVWLoadMoreWeiboFooterView.m
25 //  HVWWeibo
26 //
27 //  Created by hellovoidworld on 15/2/6.
28 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
29 //
30 
31 #import "HVWLoadMoreWeiboFooterView.h"
32 
33 @interface HVWLoadMoreWeiboFooterView()
34 
35 /** 加載更多微博文本 */
36 @property(nonatomic, strong) UILabel *label;
37 
38 /** 加載中活動指示器 */
39 @property(nonatomic, strong) UIActivityIndicatorView *actIndicator;
40 
41 @end
42 
43 @implementation HVWLoadMoreWeiboFooterView
44 
45 - (instancetype)initWithFrame:(CGRect)frame {
46     self = [super initWithFrame:frame];
47 
48     self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithNamed:@"timeline_new_status_background"]];
49    
50     // 設置加載文本
51     UILabel *label = [[UILabel alloc] init];
52     label.textAlignment = NSTextAlignmentCenter;
53     label.text = @"上拉加載更多微博";
54     self.label = label;
55     [self addSubview:label];
56    
57     // 設置加載活動指示器
58     // 不一樣類型的活動指示器大小是不同的,要注意
59     UIActivityIndicatorView *actIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
60     self.actIndicator = actIndicator;
61     [self addSubview:actIndicator];
62    
63     return self;
64 }
65 
66 /** 設置位置尺寸 */
67 - (void)layoutSubviews {
68     [super layoutSubviews];
69    
70     // 設置自己frame
71     self.width = [UIScreen mainScreen].bounds.size.width;
72     self.height = 35;
73    
74     // 設置文本frame
75     self.label.frame = self.bounds;
76    
77     // 設置活動指示器frame
78     CGFloat marginX = 50;
79     self.actIndicator.x = self.width - self.actIndicator.width - marginX;
80     self.actIndicator.y = (self.height - self.actIndicator.height) * 0.5;
81 }
82 
83 /** 開始刷新 */
84 - (void) beginRefresh {
85     self.label.text = @"正在努力加載更多微博...";
86     [self.actIndicator startAnimating];
87     self.refreshing = YES;
88 }
89 
90 /** 中止刷新 */
91 - (void) endRefresh {
92     self.label.text = @"上拉加載更多微博";
93     [self.actIndicator stopAnimating];
94     self.refreshing = NO;
95 }
96 
97 @end
 
b.在「首頁」控制器中,監聽滾動操做,當「上拉刷新」控件徹底露出的時候啓動刷新
 1 //  HVWHomeViewController.m
 2 /** 加載更多(舊)微博 */
 3 - (void) loadMoreWeiboData {
 4     // 把更多的微博數據加到原來的微博後面
 5    
 6     // 建立AFNetworking的http操做中管理器
 7     AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
 8    
 9     // 設置參數
10     NSMutableDictionary *param = [NSMutableDictionary dictionary];
11     param[@"access_token"] = [HVWAccountInfoTool accountInfo].access_token;
12    
13     /** 若指定此參數,則返回ID小於或等於max_id的微博,默認爲0。*/
14     HVWStatus *lastStatus = [self.statuses lastObject];
15     if (lastStatus) {
16         param[@"max_id"] = @([lastStatus.idstr longLongValue] - 1);
17     }
18    
19     // 發送請求
20     [manager GET:@"https://api.weibo.com/2/statuses/home_timeline.json" parameters:param success:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
21         //        HVWLog(@"獲取微博數據成功-------%@", responseObject);
22        
23         // 保存數據到內存
24         NSArray *dataArray = responseObject[@"statuses"];
25        
26         // 獲得新微博數據
27         // 使用MJExtension直接進行字典-模型轉換
28         NSArray *newStatus = [HVWStatus objectArrayWithKeyValuesArray:dataArray];
29        
30         // 插入到微博數據數組的後面
31         [self.statuses addObjectsFromArray:newStatus];
32        
33         // 刷新數據
34         [self.tableView reloadData];
35     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
36         HVWLog(@"獲取微博數據失敗------%@", error);
37     }];
38    
39     [self.loadMoreFooter endRefresh];
40 }
41  
42 #pragma mark - UIScrollViewDelegate
43 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
44     // 若是正在加載中,不用重複加載
45     if (self.loadMoreFooter.isRefreshing) return;
46    
47     // 滾動時,scrollView處於屏幕頂部下方的內容長度
48     CGFloat scrollingDelta = scrollView.contentSize.height - scrollView.contentOffset.y;
49     // 當scrollView向上滾棟到恰好露出「上拉刷新」控件時,scrollView處於屏幕下方的內容長度
50     CGFloat scrollViewHeighWithFooter = self.tableView.height - self.tabBarController.tabBar.height - self.loadMoreFooter.height;
51    
52     // 當向上滾動至scrollView可以顯示的內容少於恰好露出「上拉刷新」控件時顯示的內容,證實「上拉刷新」控件已經徹底露出,能夠刷新
53     if (scrollingDelta < scrollViewHeighWithFooter) {
54         [self.loadMoreFooter beginRefresh];
55         [self loadMoreWeiboData];
56     }
57 }
 
loadMoreWeibo
相關文章
相關標籤/搜索