带有加载指示器的 UISearchController

UISearchController with loading indicator

我实现了 UISearchController 并且我从 js 回调中获取数据但是当我在 searchbar 中录音时需要一些时间来放置数据所以我想知道如何实现将 indicator 加载到 UISearchController

的 table 查看结果

当您那时开始搜索时,您可以创建一个 activity 指标并使用 addSubView 方法将其添加为 UISearchBarsubview

  UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];

//set your frame for activity indicator

[searchBar addSubview: spinner];

[spinner startAnimating];

完成搜索后,使用 removeFromSuperView 方法将其从搜索栏中删除。

请试试这个。或许对你有帮助

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

在 Swift 3 中写了这个扩展,它似乎工作得很好。

extension UISearchBar {

    private var textField: UITextField? {
        return subviews.first?.subviews.flatMap { [=10=] as? UITextField }.first
    }

    private var activityIndicator: UIActivityIndicatorView? {
        return textField?.leftView?.subviews.flatMap{ [=10=] 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()
            }
        }
    }
}

Loading indicator on search results controller

iOS13 的更新解决方案:

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{ [=10=] 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()
            }
        }
    }
}