1. 程式人生 > >AFNetworking使用過程中的幾個細節

AFNetworking使用過程中的幾個細節

0.先來看一下AFN如何傳送GET請求的

 // 傳送網路請求
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"a"] = @"category";
params[@"c"] = @"subscribe";

[[AFHTTPSessionManager manager] GET:@"https://api.3w.com/api/api_open.php" parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id
_Nullable responseObject) { } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { }];

1.在實際專案中,我們往往是點選一個按鈕就傳送了GET請求,但如果因為網請求需要時間,在資料沒有還沒有返回來,這個時候我退出了當前控制器返回上一級,應該取消AFN的所有操作。
當前控制器銷燬會呼叫dealloc方法,我們可以在這個方法裡做取消AFN操作的工作。

那麼如何拿到AFN管理者呢?
(1)、用屬性儲存AFN管理者

/**
 *  AFN請求管理者
 */
@property(nonatomic,strong)AFHTTPSessionManager *manager;
- (AFHTTPSessionManager *)manager
{
    if (!_manager) {
        _manager = [AFHTTPSessionManager manager];
    }
    return _manager;
}

這樣我們在GET請求的時候,就應該這樣寫:

[self.manager GET:@"https://api.3w.com/api/api_open.php" parameters:params progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { }];

(2)、

#pragma mark - 控制器的銷燬
- (void)dealloc
{
    // AFN停止所有操作
    [self.manager.operationQueue cancelAllOperations];
}

2.有的時候我們可以會不停的傳送多個請求,但只要最後一次請求返回的資料。
這裡寫圖片描述
比如這個案列中,我們點選左側分類分別請求網路資料,但其實我們只需要處理當前分類的資料。

如何解決這種需求?
(1)、儲存每次請求的引數

/**
 *  請求引數
 */
@property(nonatomic,strong)NSMutableDictionary *params;
// 準備請求引數
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"a"] = @"list";
params[@"c"] = @"subscribe";
params[@"category_id"] = @(c.id);
params[@"page"] = @(c.currentPage);
self.params = params; // 儲存

(2)、在GET返回中判斷屬性params和當前請求的引數是否相同,我們只需要處理當前請求的資料。所以引數不同就return。

[self.manager GET:@"https://api.3w.com/api/api_open.php" parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        if (self.params != params) return; //這裡判斷

        //處理反正資料...(這裡是我們想要的當前分類的資料了)

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         if (self.params != params) return; // 這裡判斷
    }];

3、優化
當用戶依次點選『網紅、精品、搞笑』這些分類,都要做網路請求,在上面我們是判斷了非最後一次請求不處理返回資料,其實這樣不好。因為即使前面請求返回來的資料我們將來還是可以用到,比如使用者從『搞笑』分類又回到『精品』,所以來修改一下我們上面的程式碼,把判斷是否是最後一次請求的程式碼放到 服務區返回資料處理完畢和重新整理表格之間。
本案例中程式碼如下:

// 傳送請求給伺服器,載入右側的資料
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    params[@"a"] = @"list";
    params[@"c"] = @"subscribe";
    params[@"category_id"] = @(c.id);
    params[@"page"] = @(c.currentPage);
    self.params = params;

    [self.manager GET:@"https://api.budejie.com/api/api_open.php" parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        // 字典陣列 -> 模型陣列
        NSArray *users = [RecommendUser mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];

        // 清除以前所有舊資料
        [c.users removeAllObjects];

        // 新增到當前類別對應的使用者陣列中
        [c.users addObjectsFromArray:users];

        // 儲存從伺服器返回資料的總條數
        c.total = [responseObject[@"total"] integerValue];

        // 不是最後一次請求
        if (self.params != params) return;

        // 必須要重新整理表格
        [self.userTableView reloadData];

        // 結束重新整理
        [self.userTableView.mj_header endRefreshing];
        if (c.users.count == c.total) {
            [self.userTableView.mj_footer endRefreshingWithNoMoreData];
        }

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         if (self.params != params) return;

        // 提醒
        [SVProgressHUD showErrorWithStatus:@"載入使用者資料失敗 "];

        // 結束重新整理
        [self.userTableView.mj_header endRefreshing];
    }];