用 UIActivityViewController 替换 UISearchBar 放大图标

Posted

技术标签:

【中文标题】用 UIActivityViewController 替换 UISearchBar 放大图标【英文标题】:Replacing UISearchBar magnifying icon with UIActivityViewController 【发布时间】:2019-08-04 10:42:40 【问题描述】:

我已经搜索了一整天,但找不到此代码的修复方法。 此扩展将 UISearchField 放大图标替换为 UIActivityView(为 true 时显示加载图标)

该扩展在 iOS 12Xcode 10.3 上运行良好,但在我更改为 iOS 13Xcode 11 之后Beta 4 停止工作。

我仍然使用这个解决方法:

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

但我无法理解扩展程序停止工作的原因。 我还注意到 .flatMap iOS 13 中已弃用并更改为 .compactMap 但据我所知没有区别,我已经尝试过将 .flatMap 更改为 .compactMap 但仍然无效。

这是扩展名:

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()
            
        
    

【问题讨论】:

请注意,在 ios13 中,如果您将图像设置为 UIImage(),则文本会一直向左移动(包含放大图标的视图会被移除)。然后将“leftViewSize”的初始化设置为 .zero。将空图像设置为“leftViewSize”大小的空/透明图像。 【参考方案1】:

iOS 13 在 UISearchBar 方面发生了一些变化,您可以使用UISearchBar.searchTextField 代替searchBar.value(forKey: "searchField")

searchBar.searchTextField.backgroundColor = .red

或者如果你想让它与扩展一起工作,你可以这样做:

var searchTextField: UITextField? 
    let subViews = self.subviews.first?.subviews.last?.subviews
    return subViews?.first as? UITextField

【讨论】:

感谢您的回答!我已经替换了您的扩展代码,但现在当我运行它时,UIActivityView 超出了 searchField。知道如何解决这个问题吗? 尝试为 UIActivityIndi​​catorView 设置一个框架。 let _activityIndi​​cator = UIActivityIndi​​catorView(frame: CGRect(origin: .zero, size: CGSize(width: 24, height: 24))) 你必须取消设置 UIActivityIndi​​catorView 的中心点,你不能设置框架和中心 let _activityIndi​​cator = UIActivityIndi​​catorView(frame: CGRect(origin: .zero, size: CGSize(width: 24, height: 24))) _activityIndi​​cator.translatesAutoresizingMaskIntoConstraints = true _activityIndi​​cator.style = .medium _activityIndi​​cator.startAnimating () _activityIndi​​cator.backgroundColor = UIColor.clear cutomTextField?.leftViewMode = .always cutomTextField?.leftView = _activityIndi​​cator 非常感谢您的回答!我已经设法用我编写的代码(不是扩展名)获得了相同的结果,问题是当我将 UIActivityIndi​​catorView 设置为 false 时我无法删除它,现在我遇到了同样的问题使用您现在编写的代码。我猜是因为 cutomTextField?.leftView = _activityIndi​​cator

以上是关于用 UIActivityViewController 替换 UISearchBar 放大图标的主要内容,如果未能解决你的问题,请参考以下文章

iOS 8.3:UIActivityViewController 显示无关的行

SwiftUI完美弹出UIActivityViewController(通过微信QQ或隔空投送分享)的应用分享窗口

SwiftUI完美弹出UIActivityViewController(通过微信QQ或隔空投送分享)的应用分享窗口

测试用。

测试用例(功能用例)——完整demo(一千多条测试用例)

校用设备|校用设备课桌椅|校用设备