1

I've been searching all day but couldn't find out a fix for this code. This extension replaces the UISearchField magnifying icon with UIActivityView (shows the loading icon when is true)

The extension was working fine on iOS 12, Xcode 10.3 but after I've changed into iOS 13, Xcode 11 Beta 4 it stopped working.

I've still made a workaround using this:

if let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField {
      let loadingIcon = UIActivityIndicatorView()
      loadingIcon.style = .medium
      loadingIcon.backgroundColor = UIColor.clear
      loadingIcon.startAnimating()
      textFieldInsideSearchBar.leftView = loadingIcon
}

But I can't understand the reason why the extension stopped working. Also I've noticed that .flatMap was deprecated in iOS 13 and changed to .compactMap but as I understood there were no differences, and I've already tried to change the .flatMap to .compactMap but still didn't work.

Here is the extension:

extension UISearchBar {
    private var textField: UITextField? {
        let subViews = self.subviews.compactMap { $0.subviews }
        return (subViews.filter { $0 is UITextField }).first as? UITextField
    }

    private var searchIcon: UIImage? {
        let subViews = subviews.flatMap { $0.subviews }
        return  ((subViews.filter { $0 is UIImageView }).first as? UIImageView)?.image
    }

    private var activityIndicator: UIActivityIndicatorView? {
        return textField?.leftView?.subviews.compactMap{ $0 as? UIActivityIndicatorView }.first
    }

    var isLoading: Bool {
        get {

            return activityIndicator != nil
        } set {
            let _searchIcon = searchIcon
            if newValue {
                if activityIndicator == nil {
                    let _activityIndicator = UIActivityIndicatorView()
                    _activityIndicator.style = .medium
                    _activityIndicator.startAnimating()
                    _activityIndicator.backgroundColor = UIColor.clear
                    self.setImage(UIImage(), for: .search, state: .normal)
                    textField?.leftView?.addSubview(_activityIndicator)
                    let leftViewSize = textField?.leftView?.frame.size ?? CGSize.zero
                    _activityIndicator.center = CGPoint(x: leftViewSize.width/2, y: leftViewSize.height/2)
                }
            } else {
                self.setImage(_searchIcon, for: .search, state: .normal)
                activityIndicator?.removeFromSuperview()
            }
        }
    }
}
arata
  • 859
  • 1
  • 8
  • 23
  • Please note that in iOS13 if you set the image to UIImage() the text is moved all the way to the left (the view containing the magnifying icon is removed). The initialisation of the 'leftViewSize' is then set to .zero. Set the empty image to an empty/transparent image of 'leftViewSize' size. – Kim Rasmussen Sep 23 '19 at 11:22

1 Answers1

0

There have been some changes with iOS 13 in terms of UISearchBar, And you can use UISearchBar.searchTextField instead of searchBar.value(forKey: "searchField")

searchBar.searchTextField.backgroundColor = .red

Or if you want to keep it work with the extension, You can do this:

var searchTextField: UITextField? {
    let subViews = self.subviews.first?.subviews.last?.subviews
    return subViews?.first as? UITextField
}
Shady Mostafa
  • 815
  • 10
  • 15
  • thx for the answer! I've replace your code for extension but now when I run it the UIActivityView goes outside of the searchField. Any idea how to fix this one? – arata Aug 04 '19 at 14:13
  • Try set a frame to the UIActivityIndicatorView. let _activityIndicator = UIActivityIndicatorView(frame: CGRect(origin: .zero, size: CGSize(width: 24, height: 24))) – Shady Mostafa Aug 04 '19 at 16:57
  • You got to remove setting the center point for the UIActivityIndicatorView, You can't set frame and center – Shady Mostafa Aug 05 '19 at 06:17
  • let _activityIndicator = UIActivityIndicatorView(frame: CGRect(origin: .zero, size: CGSize(width: 24, height: 24))) _activityIndicator.translatesAutoresizingMaskIntoConstraints = true _activityIndicator.style = .medium _activityIndicator.startAnimating() _activityIndicator.backgroundColor = UIColor.clear cutomTextField?.leftViewMode = .always cutomTextField?.leftView = _activityIndicator – Shady Mostafa Aug 05 '19 at 13:47
  • thx a lot for the answer! I've managed to get the same results with the code that I've wrote (not the extension) and the problem with that was that I couldn't remove the UIActivityIndicatorView when I set it to false and now I'm getting same problem with the code you've wrote now. I guess it's because cutomTextField?.leftView = _activityIndicator – arata Aug 05 '19 at 19:32