Last active
August 29, 2015 14:04
-
-
Save nguyenhuy/a11d15c11200477b05a6 to your computer and use it in GitHub Desktop.
Showing UIActivityIndicatorView on UISearchBar, depending on state of a request operation or session task
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UISearchBar+AFNetworking.h | |
// | |
// Created by Huy Nguyen on 7/15/14. | |
// Copyright (c) 2014 Huy Nguyen. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
#import <Availability.h> | |
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) | |
#import <UIKit/UIKit.h> | |
@class AFURLConnectionOperation; | |
/** | |
This category adds methods to the UIKit framework's `UISearchBar` class. The methods in this category provide support for automatically adding an UIActivityIndicatorView, starting and stopping its animation depending on the loading state of a request operation or session task. | |
The implementation of this category is greatly inspired by UIActivityIndicatorView+AFNetworking. | |
*/ | |
@interface UISearchBar (AFNetworking) | |
///---------------------------------- | |
/// @name Animating for Session Tasks | |
///---------------------------------- | |
/** | |
Binds the animating state to the state of the specified task. | |
@param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. | |
*/ | |
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 | |
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task activityIndicatorStyle:(UIActivityIndicatorViewStyle)style; | |
#endif | |
///--------------------------------------- | |
/// @name Animating for Request Operations | |
///--------------------------------------- | |
/** | |
Binds the animating state to the execution state of the specified operation. | |
@param operation The operation. If `nil`, automatic updating from any previously specified operation will be disabled. | |
*/ | |
- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation activityIndicatorStyle:(UIActivityIndicatorViewStyle)style; | |
@end | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UISearchBar+AFNetworking.m | |
// | |
// Created by Huy Nguyen on 7/15/14. | |
// Copyright (c) 2014 Huy Nguyen. All rights reserved. | |
// | |
#import "UISearchBar+AFNetworking.h" | |
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) | |
#import "AFHTTPRequestOperation.h" | |
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 | |
#import "AFURLSessionManager.h" | |
#endif | |
#import <objc/runtime.h> | |
#import "UIView+SearchSubview.h" | |
@interface UISearchBar () | |
@property(nonatomic, strong) UITextField *textField; | |
@property(nonatomic, strong) UIActivityIndicatorView *activityIndicatorView; | |
@property(nonatomic, strong) UIView *searchIconView; | |
@end | |
@implementation UISearchBar (AFNetworking) | |
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 | |
- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task activityIndicatorStyle:(UIActivityIndicatorViewStyle)style { | |
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]; | |
if (task) { | |
if (task.state != NSURLSessionTaskStateCompleted) { | |
if (task.state == NSURLSessionTaskStateRunning) { | |
[self startAnimating]; | |
} else { | |
[self stopAnimating]; | |
} | |
[notificationCenter addObserver:self selector:@selector(startAnimatingSafely) name:AFNetworkingTaskDidResumeNotification object:task]; | |
[notificationCenter addObserver:self selector:@selector(stopAnimatingSafely) name:AFNetworkingTaskDidCompleteNotification object:task]; | |
[notificationCenter addObserver:self selector:@selector(stopAnimatingSafely) name:AFNetworkingTaskDidSuspendNotification object:task]; | |
} | |
} | |
self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:style]; | |
} | |
#endif | |
#pragma mark - | |
- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation activityIndicatorStyle:(UIActivityIndicatorViewStyle)style { | |
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; | |
[notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil]; | |
[notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; | |
if (operation) { | |
if (![operation isFinished]) { | |
if ([operation isExecuting]) { | |
[self startAnimating]; | |
} else { | |
[self stopAnimating]; | |
} | |
[notificationCenter addObserver:self selector:@selector(startAnimatingSafely) name:AFNetworkingOperationDidStartNotification object:operation]; | |
[notificationCenter addObserver:self selector:@selector(stopAnimatingSafely) name:AFNetworkingOperationDidFinishNotification object:operation]; | |
} | |
} | |
self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:style]; | |
} | |
#pragma mark - | |
- (UITextField *)textField { | |
return objc_getAssociatedObject(self, @selector(textField)); | |
} | |
- (void)setTextField:(UITextField *)textField { | |
objc_setAssociatedObject(self, @selector(textField), textField, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | |
} | |
- (UIActivityIndicatorView *)activityIndicatorView { | |
return objc_getAssociatedObject(self, @selector(activityIndicatorView)); | |
} | |
- (void)setActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView { | |
objc_setAssociatedObject(self, @selector(activityIndicatorView), activityIndicatorView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | |
} | |
- (UIView *)searchIconView { | |
return objc_getAssociatedObject(self, @selector(searchIconView)); | |
} | |
- (void)setSearchIconView:(UIView *)searchIconView { | |
objc_setAssociatedObject(self, @selector(searchIconView), searchIconView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | |
} | |
- (void)startAnimatingSafely { | |
dispatch_async(dispatch_get_main_queue(), ^{ | |
[self startAnimating]; | |
}); | |
} | |
- (void)stopAnimatingSafely { | |
dispatch_async(dispatch_get_main_queue(), ^{ | |
[self stopAnimating]; | |
}); | |
} | |
- (void)startAnimating { | |
[self setUpViews]; | |
self.textField.leftView = self.activityIndicatorView; | |
[self.activityIndicatorView startAnimating]; | |
} | |
- (void)stopAnimating { | |
[self setUpViews]; | |
self.textField.leftView = self.searchIconView; | |
[self.activityIndicatorView stopAnimating]; | |
} | |
- (void)setUpViews { | |
if (self.textField == nil) { | |
self.textField = [self subviewOfClass:[UITextField class]]; | |
self.searchIconView = self.textField.leftView; | |
} | |
} | |
@end | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIView+SearchSubview.h | |
// | |
// Created by Huy Nguyen on 7/15/14. | |
// Copyright (c) 2014 Huy Nguyen. All rights reserved. | |
// | |
#import <UIKit/UIKit.h> | |
@interface UIView (SearchSubview) | |
- (id)subviewOfClass:(Class)class; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIView+SearchSubview.m | |
// | |
// Created by Huy Nguyen on 7/15/14. | |
// Copyright (c) 2014 Huy Nguyen. All rights reserved. | |
// | |
#import "UIView+SearchSubview.h" | |
@implementation UIView (SearchSubview) | |
- (id)subviewOfClass:(Class)class { | |
for (UIView *subview in self.subviews) { | |
if ([subview isKindOfClass:class]) { | |
return subview; | |
} | |
UIView *secondLevelSubview = [subview subviewOfClass:class]; | |
if (secondLevelSubview != nil) { | |
return secondLevelSubview; | |
} | |
} | |
return nil; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment