【问题标题】:ios 13 - Custom SearchBar with UISearchBar _searchField not workingios 13 - 带有 UISearchBar _searchField 的自定义 SearchBar 不起作用
【发布时间】:2019-11-02 04:11:28
【问题描述】:

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

'NSGenericException', reason: '禁止访问 UISearchBar 的 _searchField ivar。这是一个应用程序错误'

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

任何帮助表示赞赏。

【问题讨论】:

  • 永远不要使用valueForKey:来挖掘标准组件的私有子视图结构。它从来都不是有效的,而且它总是在一段时间后结束。使用提供的公共 API 来完成您需要的工作。
  • @rmaddy 感谢您提供宝贵的反馈。但是对于自定义 UISearchBar 已经做到了。那么,现在有什么解决方案。
  • 我怎么理解我们没有唯一的解决方案?

标签: objective-c uisearchbar xcode11 ios13


【解决方案1】:
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
        }
    }

【讨论】:

    【解决方案2】:

    这样做:

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

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

    【讨论】:

      【解决方案3】:

      您可以使用这个答案,在 iOS 13 中运行良好:-

      https://stackoverflow.com/a/60503506/9863222

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          我在取消按钮值 forkey 时崩溃。是否可以在 iOS 13 中自定义取消按钮。

          【讨论】:

          • 您如何访问取消按钮?
          • 让 cancelButton = searchBar.value(forKey: "_cancelButton") as? UIButton @mohsin
          • 通过删除键前的下划线解决了这个问题。 Swift let cancelButton = searchBar.value(forKey: "cancelButton")as? UIButton
          • 是的,从您要访问的任何地方删除“_”。它适用于几乎所有版本
          【解决方案6】:

          对于 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
                      }
                  }
          

          希望对你有帮助

          【讨论】:

            【解决方案7】:

            它仍然适用于我没有下划线的关键“searchField”。斯威夫特 5

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

            【讨论】:

            • 如果您仍在使用 Xcode 10,则必须这样做,因为 SDK 10 UISearchBar 没有“searchTextField”。但是在 iOS 13 下运行时,如果可以。 ` if #available(iOS 13.0, *) { return value(forKey: "searchField") as? UITextField } else { return value(forKey: "_searchField") as? UITextField `
            • 它是私有 API 吗?苹果会拒绝应用商店的应用吗?
            【解决方案8】:
            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
                }
            }
            

            【讨论】:

              【解决方案9】:

              如果你想检查 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
               }
              }
              

              【讨论】:

              • 节省时间的答案!提示:对我来说,它只是没有下划线(self.value(forKey: "searchField") as! UITextField
              【解决方案10】:

              如果我们希望在使用 Xcode 11 编译时也支持 iOS 12 及更早版本,那么我们可以扩展 UISearchBar 以获取文本字段

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

              用法

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

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

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


              适用于 iOS 12 及更早版本

              对于 iOS 13+

              除了UISearchBarBackground,现在我们还有UISearchBarSearchContainerViewUISearchBarScopeContainerView,而UISearchBarTextField 被Apple 在UISearchTextField 类中提供的扩展取代了

              extension UISearchBar {
              
              
                  open var searchTextField: UISearchTextField { get }
              }
              

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

              崩溃会是这样的:

              [UISearchBar searchTextField]: 无法识别的选择器发送到实例

              这是苹果doc

              【讨论】:

              • 当 iOS 部署目标设置为
              • 是的,并且 UISearchTextField 已标记(例如,输入“UISearchTextField * textfield”确实会给我一个警告),但不幸的是,属性“searchBar.searchTextField”并未仅在 SDK 中标记为 iOS13 .
              • 当我调用 becomeFirstResponder 时,iOS 12 崩溃。
              • 上次我检查(在 Xcode 11.6 上)这个属性最终被标记为 iOS 13+。是时候了……
              【解决方案11】:

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

              这是导致崩溃的行:

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

              这就是解决方法:

              let searchField = searchController.searchBar.searchTextField
              

              【讨论】:

              • 您是如何找到导致崩溃的行的?
              • 它有效,但我的问题是以前正常工作的关键方法的值,现在在 xcode 11.2.1 上是什么导致它崩溃?
              • 这对我做了几天的噩梦有帮助
              【解决方案12】:

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

              searchBar.searchTextField.backgroundColor = [UIColor blueColor];
              

              【讨论】:

              • 但现在代码无法在以前的 xcode 上编译...有什么建议吗?
              • 如果您需要支持 iOS 12 及更低版本但您使用 Xcode 11 进行编译?
              • 如果您需要支持早期的 iO​​S 版本,请将其包裹在 if #available(iOS 13.0, *) {} 中。在为 iOS 13 构建时,您将无法使用旧版本的 Xcode。
              • @JordanH 你的回答没问题,但我需要支持 xCode10 也有人可以帮助我
              猜你喜欢
              • 2019-11-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-02-28
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多