原始碼閱讀:AFNetworking(十一)——UIActivityIndicatorView+AFNetworking

堯少羽發表於2018-03-15

該文章閱讀的AFNetworking的版本為3.2.0。

這是一個UIActivityIndicatorView類的分類,這個類提供了一個根據task的載入狀態自動控制載入菊花顯示和隱藏的方法。

1.介面檔案

1.1.方法

介面檔案只向外部暴露了一個方法:

/**
 為一個指定的task繫結一個載入菊花控制元件
 */
- (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task;
複製程式碼

2.實現檔案

2.1.AFActivityIndicatorViewNotificationObserver私有類

2.1.1.介面

2.1.1.1.屬性

/**
 載入菊花控制元件
 */
@property (readonly, nonatomic, weak) UIActivityIndicatorView *activityIndicatorView;
複製程式碼

2.1.1.2.方法

/**
 以指定的載入菊花控制元件初始化
 */
- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView;

/**
 設定要繫結的task
 */
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task;
複製程式碼

2.1.2.實現

  • 介面方法
- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView
{
    self = [super init];
    if (self) {
        // 儲存傳入的載入菊花控制元件
        _activityIndicatorView = activityIndicatorView;
    }
    return self;
}

- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task {
    // 建立通知中心物件
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    
    // 先移除掉之前新增通知
    [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil];
    [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil];
    [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
    
    // 如果傳入的task不為nil
    if (task) {
        // 如果task的狀態不是已經執行完成
        if (task.state != NSURLSessionTaskStateCompleted) {
            // 如果task的狀態是執行中就顯示載入菊花控制元件,否則就隱藏
            UIActivityIndicatorView *activityIndicatorView = self.activityIndicatorView;
            if (task.state == NSURLSessionTaskStateRunning) {
                [activityIndicatorView startAnimating];
            } else {
                [activityIndicatorView stopAnimating];
            }

            // 註冊通知監聽task的開始、完成和暫停
            [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task];
            [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task];
            [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidSuspendNotification object:task];
        }
    }
}
複製程式碼
  • 通知回撥方法
- (void)af_startAnimating {
    // 如果接收到了task啟動的通知,就在主佇列非同步回撥中顯示載入菊花控制元件
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.activityIndicatorView startAnimating];
    });
}

- (void)af_stopAnimating {
    // 如果接收到了task完成或暫停的通知,就在主佇列非同步回撥中隱藏載入菊花控制元件
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.activityIndicatorView stopAnimating];
    });
}
複製程式碼
  • 宣告週期方法
- (void)dealloc {
    // 移除掉新增通知
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    
    [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
    [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil];
    [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil];
}
複製程式碼

2.2.方法實現

- (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver {
    // 通過執行時的關聯物件為UIActivityIndicatorView新增了一個屬性:af_notificationObserver,這個屬性儲存的就是上面看過的那個私有類
    AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver));
    if (notificationObserver == nil) {
        notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self];
        objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return notificationObserver;
}

- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task {
    // 生成AFActivityIndicatorViewNotificationObserver物件,並通過關聯物件儲存在擴充套件的屬性af_notificationObserver中,然後呼叫這個物件的繫結task的方法
    [[self af_notificationObserver] setAnimatingWithStateOfTask:task];
}
複製程式碼

3.總結

可以看到當我們使用這個分類時,只需要通過介面暴露的方法傳入想要繫結載入菊花控制元件的task,在方法內部就會生成一個負責管理載入菊花控制元件的物件,並通過關聯物件儲存。

負責管理載入菊花控制元件的物件,會通過新增通知監聽task的開始與停止,來控制空間的展示與隱藏。

原始碼閱讀系列:AFNetworking

原始碼閱讀:AFNetworking(一)——從使用入手

原始碼閱讀:AFNetworking(二)——AFURLRequestSerialization

原始碼閱讀:AFNetworking(三)——AFURLResponseSerialization

原始碼閱讀:AFNetworking(四)——AFSecurityPolicy

原始碼閱讀:AFNetworking(五)——AFNetworkReachabilityManager

原始碼閱讀:AFNetworking(六)——AFURLSessionManager

原始碼閱讀:AFNetworking(七)——AFHTTPSessionManager

原始碼閱讀:AFNetworking(八)——AFAutoPurgingImageCache

原始碼閱讀:AFNetworking(九)——AFImageDownloader

原始碼閱讀:AFNetworking(十)——AFNetworkActivityIndicatorManager

原始碼閱讀:AFNetworking(十一)——UIActivityIndicatorView+AFNetworking

原始碼閱讀:AFNetworking(十二)——UIButton+AFNetworking

原始碼閱讀:AFNetworking(十三)——UIImageView+AFNetworking

原始碼閱讀:AFNetworking(十四)——UIProgressView+AFNetworking

原始碼閱讀:AFNetworking(十五)——UIRefreshControl+AFNetworking

原始碼閱讀:AFNetworking(十六)——UIWebView+AFNetworking

相關文章