I implemented UISearchController
and I'm getting the data from a js callback but when I tape in the searchbar
it takes some time to put the data so I wanted to know how to implement a loading indicator
into the table view result of UISearchController
When you start searching at that time you can create an activity indicator and add it as the subview
of UISearchBar
using addSubView
method.
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
//set your frame for activity indicator
[searchBar addSubview: spinner];
[spinner startAnimating];
When you finish the search remove it from the search bar using removeFromSuperView
method.
Wrote this extension in Swift 3, which seems to work pretty well.
extension UISearchBar {
private var textField: UITextField? {
return subviews.first?.subviews.flatMap { $0 as? UITextField }.first
}
private var activityIndicator: UIActivityIndicatorView? {
return textField?.leftView?.subviews.flatMap{ $0 as? UIActivityIndicatorView }.first
}
var isLoading: Bool {
get {
return activityIndicator != nil
} set {
if newValue {
if activityIndicator == nil {
let newActivityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
newActivityIndicator.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
newActivityIndicator.startAnimating()
newActivityIndicator.backgroundColor = UIColor.white
textField?.leftView?.addSubview(newActivityIndicator)
let leftViewSize = textField?.leftView?.frame.size ?? CGSize.zero
newActivityIndicator.center = CGPoint(x: leftViewSize.width/2, y: leftViewSize.height/2)
}
} else {
activityIndicator?.removeFromSuperview()
}
}
}
}
Updated solution for iOS 13:
extension UISearchBar {
var textField: UITextField? {
if #available(iOS 13.0, *) {
return searchTextField
} else {
if let textField = value(forKey: "searchField") as? UITextField {
return textField
}
return nil
}
}
private var activityIndicator: UIActivityIndicatorView? {
return textField?.leftView?.subviews.compactMap{ $0 as? UIActivityIndicatorView }.first
}
var isLoading: Bool {
get {
return activityIndicator != nil
} set {
if newValue {
if activityIndicator == nil {
let newActivityIndicator = UIActivityIndicatorView(style: .gray)
newActivityIndicator.startAnimating()
if #available(iOS 13.0, *) {
newActivityIndicator.backgroundColor = UIColor.systemGroupedBackground
} else {
newActivityIndicator.backgroundColor = UIColor.groupTableViewBackground
}
newActivityIndicator.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
textField?.leftView?.addSubview(newActivityIndicator)
let leftViewSize = textField?.leftView?.frame.size ?? CGSize.zero
newActivityIndicator.center = CGPoint(x: leftViewSize.width/2, y: leftViewSize.height/2)
}
} else {
activityIndicator?.removeFromSuperview()
}
}
}
}
Please try this one. May be its helpfull to you
SearchBarWithloading.h
#import <UIKit/UIKit.h>
@interface SearchBarWithloading : UISearchBar
- (void)startActivity; // increments startCount and shows activity indicator
- (void)finishActivity; // decrements startCount and hides activity indicator if 0
@end
SearchBarWithloading.m
import "SearchBarWithloading.h"
@interface SearchBarWithloading()
@property(nonatomic) UIActivityIndicatorView *activityIndicatorView;
@property(nonatomic) int startCount;
@end
@implementation SearchBarWithloading
- (void)layoutSubviews {
UITextField *searchField = nil;
for(UIView* view in self.subviews){
if([view isKindOfClass:[UITextField class]]){
searchField= (UITextField *)view;
break;
}
}
if(searchField) {
if (!self.activityIndicatorView) {
UIActivityIndicatorView *taiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
taiv.center = CGPointMake(searchField.leftView.bounds.origin.x + searchField.leftView.bounds.size.width/2,
searchField.leftView.bounds.origin.y + searchField.leftView.bounds.size.height/2);
taiv.hidesWhenStopped = YES;
taiv.backgroundColor = [UIColor whiteColor];
self.activityIndicatorView = taiv;
[taiv release];
_startCount = 0;
[searchField.leftView addSubview:self.activityIndicatorView];
}
}
[super layoutSubviews];
}
- (void)startActivity {
self.startCount = self.startCount + 1;
}
- (void)finishActivity {
self.startCount = self.startCount - 1;
}
- (void)setStartCount:(int)startCount {
_startCount = startCount;
if (_startCount > 0)
[self.activityIndicatorView startAnimating];
else {
[self.activityIndicatorView stopAnimating];
}
}
@end
来源:https://stackoverflow.com/questions/37692809/uisearchcontroller-with-loading-indicator