歡迎光臨
每天分享高質量文章

iOS afnetworking取消正在進行的網絡請求

作者:cfxiaoxixi鏈接:https://www.jianshu.com/p/e3ee40181baf

簡介

專案開發時,開發人員經常會遇到一種情況,A控制器push進入B控制器,B控制器正在進行網絡請求,請求未結束時,點擊傳回回到A控制器,現在問題出現了,B中網絡請求還在執行,dealloc並未立即呼叫,為什麼會發生這種情況?想在退出當前控制器時取消掉正在進行的請求,怎麼做?

網絡請求的封裝

以AFNetworking為例,上我自己的網絡請求封裝主要代碼:

//單例樣式
+ (HttpManager *)sharedManager
{
    static dispatch_once_t once;
    dispatch_once(&once;, ^{
        httpManager = [[HttpManager alloc] init];
    });
    return httpManager;
}

//網絡類初始化
- (id)init{
    self = [super init];
    if(self)
    {
        manager = [AFHTTPSessionManager manager];
        manager.requestSerializer = [AFJSONRequestSerializer serializer];
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    }
    return self;
}

註意既然封裝為單例,manager在專案運行期間就只用初始化一次,所以我把它宣告為了一個成員變數。現在來看看我的網絡請求呼叫形式:

[[HttpManager sharedManager] dataFromWithBaseURL:BaseURL path:url method:@"POST" timeInterval:10 params:parmas success:^(NSURLRequest *request, NSURLResponse *response, id JSON) {

 } failure:^(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON) {

    } error:^(id JSON) {

    } finish:^(id JSON) {

    }];

相信大部分開發者的封裝格式都是類似的,個別反人類的封裝格式我也沒遇到過。當我在B呼叫網絡請求時,突然傳回到A(此時B中請求還在執行),但是B中dealloc方法並未立即呼叫,等過幾秒種後,B中請求的資料傳回了,然後dealloc才呼叫。相信很多同學都遇到過這種情況,有人會想是否是block裡面有物件產生了迴圈取用,才發生這種情況。我想說的是,如果真是迴圈取用,那就會導致控制器的dealloc方法一直不呼叫,而不是上述情況。

在我看來,應該是使用了這種Block格式發起的網絡請求後,由於還在執行,block裡面並未得到響應,所以該block對當前的控制器,有一種強取用的效果,導致控制器退出後,並未釋放掉,直到請求資料傳回,block裡面得到響應,才算完成,最終呼叫dealloc方法。


當然,這隻是我的見解,有不對的地方請指出來。

取消正在進行的網絡請求

上面講了一大堆廢話,現在來講正題了。由於上述情況的原因,導致我們開發的app在一些非常規操作上,會產生一些不友好的效果。現在要求就是在退出控制器B後,取消還在B中進行的網絡請求。


要求清晰了,那麼要怎麼實現,其實很簡單,貼上我的代碼:

- (void)cancelRequest
{
    if ([manager.tasks count] > 0) {
        NSLog(@"傳回時取消網絡請求");
        [manager.tasks makeObjectsPerformSelector:@selector(cancel)];
        //NSLog(@"tasks = %@",manager.tasks);
    }
}

不要每次請求的時候都去初始化manager(AFHTTPSessionManager)物件,tasks裡面裝的就是正在進行的網絡請求,來一張圖就理解了:

manager裡面的tasks裝的就是正在執行的網絡請求。執行cancel後,tasks就會清空,網絡請求會進入失敗的狀態,然後響應failure block,得到一個error的信息,表示請求已經成功取消了。

至於後臺服務器是否會因為中斷請求受影響,空閑的同學可以去測試下。

最後

還有一些其它取消請求的方法,就不列出來了,因為要不就沒成功,要不就很麻煩,在這就用了一種我認為最簡單的方法。

赞(0)

分享創造快樂