mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
259 lines
9.5 KiB
Objective-C
Executable file
259 lines
9.5 KiB
Objective-C
Executable file
// AFNetworkActivityIndicatorManager.m
|
||
// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
|
||
//
|
||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
// of this software and associated documentation files (the "Software"), to deal
|
||
// in the Software without restriction, including without limitation the rights
|
||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
// copies of the Software, and to permit persons to whom the Software is
|
||
// furnished to do so, subject to the following conditions:
|
||
//
|
||
// The above copyright notice and this permission notice shall be included in
|
||
// all copies or substantial portions of the Software.
|
||
//
|
||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
// THE SOFTWARE.
|
||
|
||
#import "AFNetworkActivityIndicatorManager.h"
|
||
|
||
#if TARGET_OS_IOS
|
||
#import "AFURLSessionManager.h"
|
||
|
||
typedef NS_ENUM(NSInteger, AFNetworkActivityManagerState) {
|
||
AFNetworkActivityManagerStateNotActive,
|
||
AFNetworkActivityManagerStateDelayingStart,
|
||
AFNetworkActivityManagerStateActive,
|
||
AFNetworkActivityManagerStateDelayingEnd
|
||
};
|
||
|
||
static NSTimeInterval const kDefaultAFNetworkActivityManagerActivationDelay = 1.0;
|
||
static NSTimeInterval const kDefaultAFNetworkActivityManagerCompletionDelay = 0.17;
|
||
|
||
static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notification) {
|
||
if ([[notification object] respondsToSelector:@selector(originalRequest)]) {
|
||
return [(NSURLSessionTask *)[notification object] originalRequest];
|
||
} else {
|
||
return nil;
|
||
}
|
||
}
|
||
|
||
typedef void (^AFNetworkActivityActionBlock)(BOOL networkActivityIndicatorVisible);
|
||
|
||
@interface AFNetworkActivityIndicatorManager ()
|
||
@property (readwrite, nonatomic, assign) NSInteger activityCount;
|
||
@property (readwrite, nonatomic, strong) NSTimer *activationDelayTimer;
|
||
@property (readwrite, nonatomic, strong) NSTimer *completionDelayTimer;
|
||
@property (readonly, nonatomic, getter = isNetworkActivityOccurring) BOOL networkActivityOccurring;
|
||
@property (nonatomic, copy) AFNetworkActivityActionBlock networkActivityActionBlock;
|
||
@property (nonatomic, assign) AFNetworkActivityManagerState currentState;
|
||
@property (nonatomic, assign, getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
|
||
|
||
- (void)updateCurrentStateForNetworkActivityChange;
|
||
@end
|
||
|
||
@implementation AFNetworkActivityIndicatorManager
|
||
|
||
+ (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) {
|
||
return nil;
|
||
}
|
||
self.currentState = AFNetworkActivityManagerStateNotActive;
|
||
[[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];
|
||
self.activationDelay = kDefaultAFNetworkActivityManagerActivationDelay;
|
||
self.completionDelay = kDefaultAFNetworkActivityManagerCompletionDelay;
|
||
|
||
return self;
|
||
}
|
||
|
||
- (void)dealloc {
|
||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||
|
||
[_activationDelayTimer invalidate];
|
||
[_completionDelayTimer invalidate];
|
||
}
|
||
|
||
- (void)setEnabled:(BOOL)enabled {
|
||
_enabled = enabled;
|
||
if (enabled == NO) {
|
||
[self setCurrentState:AFNetworkActivityManagerStateNotActive];
|
||
}
|
||
}
|
||
|
||
- (void)setNetworkingActivityActionWithBlock:(void (^)(BOOL networkActivityIndicatorVisible))block {
|
||
self.networkActivityActionBlock = block;
|
||
}
|
||
|
||
- (BOOL)isNetworkActivityOccurring {
|
||
@synchronized(self) {
|
||
return self.activityCount > 0;
|
||
}
|
||
}
|
||
|
||
- (void)setNetworkActivityIndicatorVisible:(BOOL)networkActivityIndicatorVisible {
|
||
if (_networkActivityIndicatorVisible != networkActivityIndicatorVisible) {
|
||
[self willChangeValueForKey:@"networkActivityIndicatorVisible"];
|
||
@synchronized(self) {
|
||
_networkActivityIndicatorVisible = networkActivityIndicatorVisible;
|
||
}
|
||
[self didChangeValueForKey:@"networkActivityIndicatorVisible"];
|
||
if (self.networkActivityActionBlock) {
|
||
self.networkActivityActionBlock(networkActivityIndicatorVisible);
|
||
} else {
|
||
// [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:networkActivityIndicatorVisible];
|
||
}
|
||
}
|
||
}
|
||
|
||
- (void)setActivityCount:(NSInteger)activityCount {
|
||
@synchronized(self) {
|
||
_activityCount = activityCount;
|
||
}
|
||
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[self updateCurrentStateForNetworkActivityChange];
|
||
});
|
||
}
|
||
|
||
- (void)incrementActivityCount {
|
||
[self willChangeValueForKey:@"activityCount"];
|
||
@synchronized(self) {
|
||
_activityCount++;
|
||
}
|
||
[self didChangeValueForKey:@"activityCount"];
|
||
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[self updateCurrentStateForNetworkActivityChange];
|
||
});
|
||
}
|
||
|
||
- (void)decrementActivityCount {
|
||
[self willChangeValueForKey:@"activityCount"];
|
||
@synchronized(self) {
|
||
_activityCount = MAX(_activityCount - 1, 0);
|
||
}
|
||
[self didChangeValueForKey:@"activityCount"];
|
||
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[self updateCurrentStateForNetworkActivityChange];
|
||
});
|
||
}
|
||
|
||
- (void)networkRequestDidStart:(NSNotification *)notification {
|
||
if ([AFNetworkRequestFromNotification(notification) URL]) {
|
||
[self incrementActivityCount];
|
||
}
|
||
}
|
||
|
||
- (void)networkRequestDidFinish:(NSNotification *)notification {
|
||
if ([AFNetworkRequestFromNotification(notification) URL]) {
|
||
[self decrementActivityCount];
|
||
}
|
||
}
|
||
|
||
#pragma mark - Internal State Management
|
||
- (void)setCurrentState:(AFNetworkActivityManagerState)currentState {
|
||
@synchronized(self) {
|
||
if (_currentState != currentState) {
|
||
[self willChangeValueForKey:@"currentState"];
|
||
_currentState = currentState;
|
||
switch (currentState) {
|
||
case AFNetworkActivityManagerStateNotActive:
|
||
[self cancelActivationDelayTimer];
|
||
[self cancelCompletionDelayTimer];
|
||
[self setNetworkActivityIndicatorVisible:NO];
|
||
break;
|
||
case AFNetworkActivityManagerStateDelayingStart:
|
||
[self startActivationDelayTimer];
|
||
break;
|
||
case AFNetworkActivityManagerStateActive:
|
||
[self cancelCompletionDelayTimer];
|
||
[self setNetworkActivityIndicatorVisible:YES];
|
||
break;
|
||
case AFNetworkActivityManagerStateDelayingEnd:
|
||
[self startCompletionDelayTimer];
|
||
break;
|
||
}
|
||
[self didChangeValueForKey:@"currentState"];
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
- (void)updateCurrentStateForNetworkActivityChange {
|
||
if (self.enabled) {
|
||
switch (self.currentState) {
|
||
case AFNetworkActivityManagerStateNotActive:
|
||
if (self.isNetworkActivityOccurring) {
|
||
[self setCurrentState:AFNetworkActivityManagerStateDelayingStart];
|
||
}
|
||
break;
|
||
case AFNetworkActivityManagerStateDelayingStart:
|
||
//No op. Let the delay timer finish out.
|
||
break;
|
||
case AFNetworkActivityManagerStateActive:
|
||
if (!self.isNetworkActivityOccurring) {
|
||
[self setCurrentState:AFNetworkActivityManagerStateDelayingEnd];
|
||
}
|
||
break;
|
||
case AFNetworkActivityManagerStateDelayingEnd:
|
||
if (self.isNetworkActivityOccurring) {
|
||
[self setCurrentState:AFNetworkActivityManagerStateActive];
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
- (void)startActivationDelayTimer {
|
||
self.activationDelayTimer = [NSTimer
|
||
timerWithTimeInterval:self.activationDelay target:self selector:@selector(activationDelayTimerFired) userInfo:nil repeats:NO];
|
||
[[NSRunLoop mainRunLoop] addTimer:self.activationDelayTimer forMode:NSRunLoopCommonModes];
|
||
}
|
||
|
||
- (void)activationDelayTimerFired {
|
||
if (self.networkActivityOccurring) {
|
||
[self setCurrentState:AFNetworkActivityManagerStateActive];
|
||
} else {
|
||
[self setCurrentState:AFNetworkActivityManagerStateNotActive];
|
||
}
|
||
}
|
||
|
||
- (void)startCompletionDelayTimer {
|
||
[self.completionDelayTimer invalidate];
|
||
self.completionDelayTimer = [NSTimer timerWithTimeInterval:self.completionDelay target:self selector:@selector(completionDelayTimerFired) userInfo:nil repeats:NO];
|
||
[[NSRunLoop mainRunLoop] addTimer:self.completionDelayTimer forMode:NSRunLoopCommonModes];
|
||
}
|
||
|
||
- (void)completionDelayTimerFired {
|
||
[self setCurrentState:AFNetworkActivityManagerStateNotActive];
|
||
}
|
||
|
||
- (void)cancelActivationDelayTimer {
|
||
[self.activationDelayTimer invalidate];
|
||
}
|
||
|
||
- (void)cancelCompletionDelayTimer {
|
||
[self.completionDelayTimer invalidate];
|
||
}
|
||
|
||
@end
|
||
|
||
#endif
|