ios 13 - 带有 UISearchBar _searchField 的自定义 SearchBar 不工作

ios 13 - Custom SearchBar with UISearchBar _searchField not working

在 Xcode-11-Beta (ios13) 之前,下面的代码用于自定义搜索栏值的键,以使 textField 正常工作。现在低于崩溃日志。

'NSGenericException', reason: 'Access to UISearchBar's _searchField ivar is prohibited. This is an application bug'

- (UITextField *)textField
{
 return [self valueForKey:@"_searchField"];
}

感谢任何帮助。

SDK 现在提供 UISearchBar.searchTextField,因此您可以简单地将私有 API 实现替换为 public API.

searchBar.searchTextField.backgroundColor = [UIColor blueColor];

我遇到了同样的崩溃,IOS 13 你不再需要 .value(forKey:)

这是导致崩溃的行:

if let searchField = searchController.searchBar.value(forKey: "_searchField") as? UITextField {

这是解决方法:

let searchField = searchController.searchBar.searchTextField

如果我们想在使用 Xcode 11 编译时也支持 iOS 12 和更早版本,那么我们可以对 UISearchBar 进行扩展,我们可以在其中获取文本字段

extension UISearchBar {

    var textField : UITextField? {
        if #available(iOS 13.0, *) {
            return self.searchTextField
        } else { // Fallback on earlier versions
            for subview in subviews.first?.subviews ?? [] {
                if let textField = subview as? UITextField {
                    return textField
                }
            }
        }
        return nil
    }
}

用法

searchBar.textField?.font = UIFont.systemFont(ofSize: 15.0)

在这里我们可以访问所有 textField 的属性并根据我们的需要在 UISearchBar

中进行修改

视图层次结构发生了变化。 所以通过打印 self.subviews[0]).subviews where self in UISearchBar


对于 iOS 12 及更早版本

对于iOS 13+

连同 UISearchBarBackground,现在我们有 UISearchBarSearchContainerViewUISearchBarScopeContainerView,而缺少 UISearchBarTextField,它被 Apple 在 UISearchTextField 中提供的扩展所取代class

extension UISearchBar {

    
    open var searchTextField: UISearchTextField { get }
}

因此我们可以在iOS 13及以上的设备中直接访问searchBar.searchTextField,而如果我们尝试在iOS 12中访问此属性会导致崩溃及以下 OS 台设备。

崩溃会是这样的:

[UISearchBar searchTextField]: unrecognized selector sent to instance

这是 Apple doc

如果你想检查iOS版本!

 if #available(iOS 13.0, *) {
    searchBar.searchTextField.clearButtonMode = .never
 } else {
    searchBar.textField.clearButtonMode = .never
 }

不要忘记扩展名:

extension UISearchBar {

 var textField : UITextField{
    return self.value(forKey: "_searchField") as! UITextField
 }
}
extension UISearchBar {

    var textField : UITextField? {
        if #available(iOS 13.0, *) {
            return self.searchTextField
        } else {
            // Fallback on earlier versions
            return value(forKey: "_searchField") as? UITextField
        }
        return nil
    }
}

它仍然适用于没有下划线的键 "searchField"。 Swift 5

guard let searchField = searchBar.value(forKey: "searchField") as? UITextField else { return }

对于iOS 11 和更早的版本,您可以像这样进行检查:

if #available(iOS 11, *){
            self.searchBar.placeholder = "Search by Name"
            self.searchBar.setSerchFont(textFont: UIFont(name:AppFontLato.Regular, size:14.0 * DeviceInfo.aspectRatio()))
            self.searchBar.setSerchTextcolor(color: Colors.black51)
        }
        else{
            if let searchTextField = self.searchBar.value(forKey: "_searchField") as? UITextField, let clearButton = searchTextField.value(forKey: "_clearButton") as? UIButton {
                searchTextField.placeholder = "Search by Name"
                searchTextField.font = UIFont(name:AppFontLato.Regular, size:14.0 * DeviceInfo.aspectRatio())
                searchTextField.textColor = Colors.black51
            }
        }

希望对您有所帮助

删除了所有地方的“_”下划线(在尝试访问 属性 时),它适用于所有 iOS 版本。

我在为键取消按钮值时崩溃。 iOS 13.

是否可以自定义取消按钮

你可以使用这个答案,在 iOS 13:-

中工作正常

这样做:

 var searchTextField: UITextField?
    if #available(iOS 13.0, *) {
        searchTextField = searchBar.searchTextField
    } else {
        if let searchField = searchBar.value(forKey: "searchField") as? UITextField {
            searchTextField = searchField
        }
    }

这将根据版本检查为您提供适当的搜索栏文本字段。

if #available(iOS 13.0, *) {
        self.searchBar.searchTextField.clearButtonMode = .never
    } else {
        // Fallback on earlier versions
        if let searchField = searchBar.value(forKey: "searchField") as? UITextField {
            searchField.clearButtonMode = .never
        }
    }