Use lightweight locking for activityCount
Also exposes isNetworkActivityIndicatorVisible which now is KVO observable.
This commit is contained in:
parent
0470f4b29f
commit
069615a20d
2 changed files with 27 additions and 26 deletions
|
|
@ -30,12 +30,7 @@
|
||||||
/**
|
/**
|
||||||
`AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When enabled, it will listen for notifications indicating that a network request operation has started or finished, and start or stop animating the indicator accordingly. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero.
|
`AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When enabled, it will listen for notifications indicating that a network request operation has started or finished, and start or stop animating the indicator accordingly. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero.
|
||||||
*/
|
*/
|
||||||
@interface AFNetworkActivityIndicatorManager : NSObject {
|
@interface AFNetworkActivityIndicatorManager : NSObject;
|
||||||
@private
|
|
||||||
NSInteger _activityCount;
|
|
||||||
BOOL _enabled;
|
|
||||||
NSTimer *_activityIndicatorVisibilityTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A Boolean value indicating whether the manager is enabled.
|
A Boolean value indicating whether the manager is enabled.
|
||||||
|
|
@ -61,6 +56,11 @@
|
||||||
*/
|
*/
|
||||||
- (void)decrementActivityCount;
|
- (void)decrementActivityCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the network indicator visibility. This is more excact than polling [UIApplication sharedApplication] isNetworkActivityIndicatorVisible] since we add a slight delay while updating the indicator to avoid flickering. You can observe this via KVO.
|
||||||
|
*/
|
||||||
|
- (BOOL)isNetworkActivityIndicatorVisible;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#import "AFNetworkActivityIndicatorManager.h"
|
#import "AFNetworkActivityIndicatorManager.h"
|
||||||
|
|
||||||
#import "AFHTTPRequestOperation.h"
|
#import "AFHTTPRequestOperation.h"
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
|
|
@ -30,7 +31,6 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
@interface AFNetworkActivityIndicatorManager ()
|
@interface AFNetworkActivityIndicatorManager ()
|
||||||
@property (readwrite, nonatomic, assign) NSInteger activityCount;
|
@property (readwrite, nonatomic, assign) NSInteger activityCount;
|
||||||
@property (readwrite, nonatomic, retain) NSTimer *activityIndicatorVisibilityTimer;
|
@property (readwrite, nonatomic, retain) NSTimer *activityIndicatorVisibilityTimer;
|
||||||
@property (readwrite, nonatomic, retain) NSRecursiveLock *lock;
|
|
||||||
@property (readonly, getter = isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
|
@property (readonly, getter = isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
|
||||||
|
|
||||||
- (void)updateNetworkActivityIndicatorVisibility;
|
- (void)updateNetworkActivityIndicatorVisibility;
|
||||||
|
|
@ -39,7 +39,6 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
@implementation AFNetworkActivityIndicatorManager
|
@implementation AFNetworkActivityIndicatorManager
|
||||||
@synthesize activityCount = _activityCount;
|
@synthesize activityCount = _activityCount;
|
||||||
@synthesize activityIndicatorVisibilityTimer = _activityIndicatorVisibilityTimer;
|
@synthesize activityIndicatorVisibilityTimer = _activityIndicatorVisibilityTimer;
|
||||||
@synthesize lock = _lock;
|
|
||||||
@synthesize enabled = _enabled;
|
@synthesize enabled = _enabled;
|
||||||
@dynamic networkActivityIndicatorVisible;
|
@dynamic networkActivityIndicatorVisible;
|
||||||
|
|
||||||
|
|
@ -59,8 +58,6 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lock = [[[NSRecursiveLock alloc] init] autorelease];
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(incrementActivityCount) name:AFNetworkingOperationDidStartNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(incrementActivityCount) name:AFNetworkingOperationDidStartNotification object:nil];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(decrementActivityCount) name:AFNetworkingOperationDidFinishNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(decrementActivityCount) name:AFNetworkingOperationDidFinishNotification object:nil];
|
||||||
|
|
||||||
|
|
@ -73,17 +70,10 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
[_activityIndicatorVisibilityTimer invalidate];
|
[_activityIndicatorVisibilityTimer invalidate];
|
||||||
[_activityIndicatorVisibilityTimer release]; _activityIndicatorVisibilityTimer = nil;
|
[_activityIndicatorVisibilityTimer release]; _activityIndicatorVisibilityTimer = nil;
|
||||||
|
|
||||||
[_lock release];
|
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setActivityCount:(NSInteger)activityCount {
|
- (void)updateNetworkActivityIndicatorVisibilityDelayed {
|
||||||
[self.lock lock];
|
|
||||||
[self willChangeValueForKey:@"activityCount"];
|
|
||||||
_activityCount = MAX(activityCount, 0);
|
|
||||||
[self didChangeValueForKey:@"activityCount"];
|
|
||||||
|
|
||||||
if (self.enabled) {
|
if (self.enabled) {
|
||||||
// Delay hiding of activity indicator for a short interval, to avoid flickering
|
// Delay hiding of activity indicator for a short interval, to avoid flickering
|
||||||
if (![self isNetworkActivityIndicatorVisible]) {
|
if (![self isNetworkActivityIndicatorVisible]) {
|
||||||
|
|
@ -94,11 +84,10 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
[self updateNetworkActivityIndicatorVisibility];
|
[self updateNetworkActivityIndicatorVisibility];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[self.lock unlock];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isNetworkActivityIndicatorVisible {
|
- (BOOL)isNetworkActivityIndicatorVisible {
|
||||||
return self.activityCount > 0;
|
return _activityCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateNetworkActivityIndicatorVisibility {
|
- (void)updateNetworkActivityIndicatorVisibility {
|
||||||
|
|
@ -107,16 +96,28 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not actually exposed, but will be used if someone tries to set activityCount via KVC.
|
||||||
|
- (void)setActivityCount:(NSInteger)activityCount {
|
||||||
|
__sync_swap(&_activityCount, activityCount);
|
||||||
|
[self updateNetworkActivityIndicatorVisibilityDelayed];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)incrementActivityCount {
|
- (void)incrementActivityCount {
|
||||||
[self.lock lock];
|
[self willChangeValueForKey:@"activityCount"];
|
||||||
self.activityCount += 1;
|
OSAtomicIncrement32((int32_t*)&_activityCount);
|
||||||
[self.lock unlock];
|
[self didChangeValueForKey:@"activityCount"];
|
||||||
|
[self updateNetworkActivityIndicatorVisibilityDelayed];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)decrementActivityCount {
|
- (void)decrementActivityCount {
|
||||||
[self.lock lock];
|
[self willChangeValueForKey:@"activityCount"];
|
||||||
self.activityCount -= 1;
|
OSAtomicDecrement32((int32_t*)&_activityCount);
|
||||||
[self.lock unlock];
|
[self didChangeValueForKey:@"activityCount"];
|
||||||
|
[self updateNetworkActivityIndicatorVisibilityDelayed];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSSet *)keyPathsForValuesAffectingIsNetworkActivityIndicatorVisible {
|
||||||
|
return [NSSet setWithObject:@"activityCount"];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue