AFNetworking, as read in this article, is version 3.2.0.
This class is the show and hide of the network activity indicator that rotates in the upper left corner of the status bar during network requests.
1. Interface file
1.1. The macro
NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.")
Copy the code
At the beginning, we can see that there is a macro which, after checking, means that this class is not available in the extension. This extension is a new feature in iOS8 that allows other apps to exchange data with it.
1.2. The attribute
/** Network activity indicator whether to enable */ @property (nonatomic, assign, getter = isEnabled) BOOL enabled; /** Network activity indicator is displayed */ @property (readonly, nonatomic, assign, getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible; @property (nonatomic, assign) NSTimeInterval activationDelay; @property (nonatomic, assign) NSTimeInterval activationDelay; / / @property (nonatomic, assign) NSTimeInterval completionDelay; / / @property (nonatomic, assign) NSTimeInterval completionDelay;Copy the code
Method of 1.3.
/** Get network activity indicator singleton */ + (instanceType)sharedManager; /** Increments the number of active network requests */ - (void)incrementActivityCount; DecrementActivityCount - (void)decrementActivityCount; /** Set a custom event when the network activity indicator is hidden and displayed */ - (void)setNetworkingActivityActionWithBlock:(nullable void (^)(BOOL networkActivityIndicatorVisible))block;
Copy the code
2. Implementation file
2.1. The enumeration
typedef NS_ENUM(NSInteger, AFNetworkActivityManagerState) {
AFNetworkActivityManagerStateNotActive,
AFNetworkActivityManagerStateDelayingStart,
AFNetworkActivityManagerStateActive,
AFNetworkActivityManagerStateDelayingEnd
};
Copy the code
This enumeration defines the state of the network activity indicator:
AFNetworkActivityManagerStateNotActive said the network activity indicator in the inactive state AFNetworkActivityManagerStateDelayingStart said network activity indicator in the delay start state AFNetworkActivityManagerStateActive said the network activity indicator is active AFNetworkActivityManagerStateDelayingEnd said the network activity indicator in the end of the time delay state
2.2. Static constants
/ * * defines the start delay time for 1 second * / static NSTimeInterval const kDefaultAFNetworkActivityManagerActivationDelay = 1.0; / * * defines the end delay time, 0.17 seconds * / static NSTimeInterval const kDefaultAFNetworkActivityManagerCompletionDelay = 0.17;Copy the code
2.3. Static methods
/ * * this method of network users get notification request object * / static NSURLRequest * AFNetworkRequestFromNotification (NSNotification * notification) {if ([[notification object] respondsToSelector:@selector(originalRequest)]) {
return [(NSURLSessionTask *)[notification object] originalRequest];
} else {
returnnil; }}Copy the code
2.4. The alias
/ * * defines the network state changes of the callback block * / typedef void (^ AFNetworkActivityActionBlock) (BOOL networkActivityIndicatorVisible);Copy the code
2.5 class extensions
2.5.1. Properties
/** Number of active requests */ @property (readWrite, Nonatomic, assign) NSInteger activityCount; /** Start delay timer */ @property (readWrite, nonatomic, strong) NSTimer *activationDelayTimer; /** End delay timer */ @property (readwrite, nonatomic, strong) NSTimer *completionDelayTimer; /** Is active */ @property (readonly, nonatomic, getter = isNetworkActivityOccurring) BOOL networkActivityOccurring; / * * network state changes of the callback block * / @ property (nonatomic, copy) AFNetworkActivityActionBlock networkActivityActionBlock; / * * current * / @ property (nonatomic, assign) AFNetworkActivityManagerState currentState; /* / @property (nonatomic, assign, getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;Copy the code
2.5.2. Methods
/ * * according to the current state of the changing state of the network activity indicator * / - (void) updateCurrentStateForNetworkActivityChange;Copy the code
2.6. Method implementation
- Lifecycle approach
+ (instancetype)sharedManager {
static AFNetworkActivityIndicatorManager *_sharedManager = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedManager = [[self alloc] init];
});
return _sharedManager;
}
- (instancetype)init {
self = [super init];
if(! self) {returnnil; } / / records the current state is active self. The currentState = AFNetworkActivityManagerStateNotActive; // listen on AFURLSessionManager Task started, task paused, and task ended [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidStart:) name:AFNetworkingTaskDidResumeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidSuspendNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidCompleteNotification object:nil]; / / for self. The start and end time delay time assignment activationDelay = kDefaultAFNetworkActivityManagerActivationDelay; self.completionDelay = kDefaultAFNetworkActivityManagerCompletionDelay;returnself; } - (void)dealloc {// Remove the observation of the notification [[NSNotificationCenter defaultCenter] removeObserver:self]; // Terminate the timer object [_activationDelayTimer invalidate]; [_completionDelayTimer invalidate]; }Copy the code
- Public methods
- (void)setEnabled:(BOOL)enabled { _enabled = enabled; // If set to NO, the network activity indicator is set to inactiveif (enabled == NO) {
[self setCurrentState:AFNetworkActivityManagerStateNotActive];
}
}
- (void)setNetworkingActivityActionWithBlock (void (^) (BOOL networkActivityIndicatorVisible)) block {/ / record incoming block self.networkActivityActionBlock = block; IsNetworkActivityOccurring {} - (BOOL) / / lock access network request number, is greater than 0 is active @ synchronized (self) {return self.activityCount > 0;
}
}
- (void)setNetworkActivityIndicatorVisible NetworkActivityIndicatorVisible: (BOOL) {/ / if the old and new data inconsistencyif(_networkActivityIndicatorVisible ! = networkActivityIndicatorVisible) {/ / manual implementation networkActivityIndicatorVisible attribute KVO method [self willChangeValueForKey: @"networkActivityIndicatorVisible"]; / / @ synchronized locking assignment (self) {_networkActivityIndicatorVisible = networkActivityIndicatorVisible; } [self didChangeValueForKey:@"networkActivityIndicatorVisible"];
if(self.net workActivityActionBlock) {/ / if set the callback block is called self.net workActivityActionBlock (networkActivityIndicatorVisible); }else[UIApplication sharedApplication] {UIApplication sharedApplication] [UIApplication sharedApplication]setNetworkActivityIndicatorVisible:networkActivityIndicatorVisible];
}
}
}
- (void)setActivityCount:(NSInteger) ActivityCount {@synchronized(self) {_activityCount = ActivityCount; } / / master queue asynchronous call dispatch_async (dispatch_get_main_queue (), ^ {/ / update the current network status [self updateCurrentStateForNetworkActivityChange]; }); } - (void)incrementActivityCount {// Manually implement the KVO method for the activityCount property [self willChangeValueForKey:@]"activityCount"]; @synchronized(self) {_activityCount++; } [self didChangeValueForKey:@"activityCount"]; / / the home side column asynchronous calls to update the current network status dispatch_async (dispatch_get_main_queue (), ^ {[self updateCurrentStateForNetworkActivityChange]; }); DecrementActivityCount - (void)decrementActivityCount {// Manually implement the KVO method on the activityCount property [self willChangeValueForKey:@"activityCount"];
// 加锁赋值
@synchronized(self) {
// 不能小于零
_activityCount = MAX(_activityCount - 1, 0);
}
[self didChangeValueForKey:@"activityCount"]; / / the home side column asynchronous calls to update the current network status dispatch_async (dispatch_get_main_queue (), ^ {[self updateCurrentStateForNetworkActivityChange]; }); }Copy the code
- Private methods
- (void)networkRequestDidStart:(NSNotification *)notification {// increase the number of requests if the request object has a URLif([AFNetworkRequestFromNotification(notification) URL]) { [self incrementActivityCount]; }} - (void)networkRequestDidFinish:(NSNotification *)notificationif ([AFNetworkRequestFromNotification(notification) URL]) {
[self decrementActivityCount];
}
}
- (void)setCurrentState: AFNetworkActivityManagerState CurrentState {/ / lock protect @ synchronized (self) {/ / if the old and new data inconsistencyif(_currentState ! = currentState) {// Manually implement the KVO method of currentState property [self willChangeValueForKey:@"currentState"]; // assign _currentState = currentState; Switch (currentState) {// If no activity is setcaseAFNetworkActivityManagerStateNotActive: / / cancel the start and finish time delay timer [self cancelActivationDelayTimer]; [self cancelCompletionDelayTimer]; // Hide the network activity indicator [selfsetNetworkActivityIndicatorVisible:NO];
break; // If set to delay startcaseAFNetworkActivityManagerStateDelayingStart: / / start delay time [self startActivationDelayTimer];break; // If set to startcaseAFNetworkActivityManagerStateActive: / / cancel complete delay timer [self cancelCompletionDelayTimer]; // Display network activity indicator [selfsetNetworkActivityIndicatorVisible:YES];
break; // If delay end is setcaseAFNetworkActivityManagerStateDelayingEnd: / / completion time delay timing [self startCompletionDelayTimer];break;
}
[self didChangeValueForKey:@"currentState"]; }}} - (void) updateCurrentStateForNetworkActivityChange {/ / if the Settings are availableif(self.enabled) {switch (self.currentstate) {// if the currentState is inactivecaseAFNetworkActivityManagerStateNotActive: / / if the current network activityif(self. IsNetworkActivityOccurring) {/ / sets the status to delay start [the selfsetCurrentState:AFNetworkActivityManagerStateDelayingStart];
}
break; // If the current state is delayed, there is no operationcase AFNetworkActivityManagerStateDelayingStart:
//No op. Let the delay timer finish out.
break; // If the current state is start activitycaseAFNetworkActivityManagerStateActive: / / if the current network activityif(! Self. IsNetworkActivityOccurring) {/ / sets the status to delay the end [of the selfsetCurrentState:AFNetworkActivityManagerStateDelayingEnd];
}
break; // If the current state is delay endcaseAFNetworkActivityManagerStateDelayingEnd: / / if the current network activityif(self. IsNetworkActivityOccurring) {/ / sets the status to start [the selfsetCurrentState:AFNetworkActivityManagerStateActive];
}
break; }}} - (void) startActivationDelayTimer {/ / set the start delay timer and join the running cycle of the self. ActivationDelayTimer = [NSTimer timerWithTimeInterval:self.activationDelay target:self selector:@selector(activationDelayTimerFired) userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:self.activationDelayTimerforMode:NSRunLoopCommonModes]; } - (void) activationDelayTimerFired {/ / if the current network activityif(self.net workActivityOccurring) {/ / set the status to activities [of the selfsetCurrentState:AFNetworkActivityManagerStateActive]; // If there is no network activity}else{// set the state to inactive [self]setCurrentState:AFNetworkActivityManagerStateNotActive]; }} - (void) startCompletionDelayTimer {/ / disable the timer before first [self.com pletionDelayTimer invalidate]; / / to set end delay timer and added to the running cycle of self.com pletionDelayTimer = [NSTimer timerWithTimeInterval:self.com pletionDelay target: the self selector:@selector(completionDelayTimerFired) userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:self.completionDelayTimerforMode:NSRunLoopCommonModes]; } - (void) completionDelayTimerFired {/ / set the status to inactive [the selfsetCurrentState:AFNetworkActivityManagerStateNotActive]; } - (void) cancelActivationDelayTimer {/ / disable start delay timer [self. ActivationDelayTimer invalidate]; } - (void) cancelCompletionDelayTimer {/ / to make complete delay timer is invalid [self.com pletionDelayTimer invalidate]; }Copy the code
3. Summary
After reading the code, we can comb AFNetworkActivityIndicatorManager class work process:
- Displays network activity indicators
1. Notify the start, stop, and end of tasks that listen to AFNetworking by registering them in the initialization method.
2. When the notification is received, the current network request activity is recorded in the callback method of the notification, the KOV is sent manually, and the update status method is called.
3. In the update status method, if the current state is inactive and there is network request activity, the current state is set to the delayed start state.
4. In the setter for currentState property, manually send KVO. If it is found to be in the start delay state, the start delay timer will be started.
5. After 1 second, the timer method is triggered. In the timer method, the current state is set to active if there are still network requests in progress. However, if there are no network requests currently in progress, the state is set to inactive.
6. Now we’re back in the setter for the overridden currentState property, and we’re still sending KVO manually. If we find a start state, we’re going to end the completion timer and display the network activity indicator.
- Hide network activity indicators
7. When receiving a notification of task completion, the current network request activity is recorded in the notification callback method, the KOV is sent manually, and the update status method is called.
8. In the update status method, if the current state is active and there are no network requests in progress, the current state is set to the delayed-end state.
9. In the override currentState property setter, in addition to manually sending KVO, a completion delay timer is turned on if it is found to be set to a delay end state.
10. After 0.17 seconds, the timer method is fired, which sets the state to inactive. In the setter currentState, KVO is sent manually, and inactive ends the start and finish delay timer and hides the network activity indicator
AFNetworking
AFNetworking (A) — Start using it
Source: reading AFNetworking (2) — AFURLRequestSerialization
Source: reading AFNetworking (3) — AFURLResponseSerialization
AFNetworking (4) — AFSecurityPolicy
Source: reading AFNetworking (5) — AFNetworkReachabilityManager
AFNetworking (6) — Afurlssession Manager
AFNetworking (7) — Afhttpssession Manager
AFNetworking (8) – AFAutoPurgingImageCache
AFNetworking (9) — AFImageDownloader
The source code to read: AFNetworking (10) — AFNetworkActivityIndicatorManager
AFNetworking — UIActivityIndicatorView+AFNetworking
AFNetworking (12) — UIButton+AFNetworking
AFNetworking (13) — UIImageView+AFNetworking
UIProgressView+AFNetworking
AFNetworking — UIRefreshControl+AFNetworking
UIWebView+AFNetworking