ios - 使用 UILocalizedIndexedCollation 在 Swift 4.2 中创建 tableView 部分索引时出现错误“无法识别的选择器发送到实例”
问题描述
我正在尝试构建一个以 iPhone 的联系人应用程序为模型的应用程序。在那个过程中,我试图将部分索引放在我的联系人表格视图的右侧。Apple 的 iOS 文档表视图编程指南建议使用 UILocalizedIndexedCollation 类。问题似乎出在 collationStringSelector 上。在 Swift 4 中,选择器需要暴露给@objc,无论如何我都找不到这样做,我尝试过的所有操作都返回此错误消息:
*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[NSTaggedPointerStringlocalizedTitle]:无法识别的选择器发送到实例
我试图将选择器对象放入它自己的类中,以便可以将其公开给@objc,但这不起作用。这是我尝试过的代码:
class SelectorObj: NSObject {
@objc var selector: Selector
init(selector: Selector) {
self.selector = selector
}
}
回到基线代码。这是我正在尝试的示例代码。
class ObjectTableViewController: UITableViewController {
let collation = UILocalizedIndexedCollation.current()
var sections: [[AnyObject]] = []
var objects: [AnyObject] = [] {
didSet {
let selector: Selector = #selector(getter: UIApplicationShortcutItem.localizedTitle)
sections = Array(repeating: [], count: collation.sectionTitles.count)
let sortedObjects = collation.sortedArray(from: objects, collationStringSelector: selector)
for object in sortedObjects {
let sectionNumber = collation.section(for: object, collationStringSelector: selector)
sections[sectionNumber].append(object as AnyObject)
}
self.tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
objects = (["One", "Two", "Three"] as [AnyObject])
}
// MARK: UITableViewDelegate
override func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let cellData = sections[indexPath.section][indexPath.row]
cell.textLabel!.text = (cellData as! String)
return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return collation.sectionTitles[section]
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return collation.sectionIndexTitles
}
override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
return collation.section(forSectionIndexTitle: index)
}
}
预期的结果是在 tableView 联系人列表的右侧获取部分索引 (A...Z, #),就像在 iPhone 的联系人应用程序中一样。
解决方案
您传递给sortedArray(from:collationStringSelector:)
的选择器必须是在被排序的对象类型上找到的选择器。您的数组中的对象没有localizedTitle
属性。
通常,您将拥有一个要排序的类或结构数组,并且您将传递类或结构的某些属性的选择器。
但是你的数组是一个数组String
。因此,您需要一个String
返回用于排序的字符串的属性。
而且由于选择器的这种使用基于旧的 Objective-C 框架,因此需要将属性暴露给 Objective-C。
可以使用数组的一件事String
是使用选择器NSString.description
。这是可行的,因为 SwiftString
可以桥接到NSString
.
您需要做的另一件事是将您的数组类型从AnyObject
它真正的类型更改为 - String
。
var sections: [[String]] = []
var objects: [String] = [] {
didSet {
let selector: Selector = #selector(NSString.description)
sections = Array(repeating: [], count: collation.sectionTitles.count)
let sortedObjects = collation.sortedArray(from: objects, collationStringSelector: selector)
for object in sortedObjects {
let sectionNumber = collation.section(for: object, collationStringSelector: selector)
sections[sectionNumber].append(object)
}
self.tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
objects = ["One", "Two", "Three"]
}
更新您尝试转换这些值的其他代码,as String
因为不再需要这些代码。
推荐阅读
- c# - 如何在没有 Windows 窗体参考的情况下获得屏幕分辨率?
- java - 按分隔符数量拆分字符串
- sql - 将一列中的记录作为table1中的不同行从sql-server中table2的一行中的不同列插入
- python - 列表索引超出范围错误必须有索引指示
- sql - SQL 选择列 BLOB 数据的特定(第 4)部分,由特定模式分隔
- javascript - 使用php和mysql数据库的活动监控流程图
- angular - 在 Angular 6 表单构建器中找不到具有未指定名称属性的控件
- configuration - wso2中的rsync机制都在一个主动-主动
- javascript - Sweatalert2 在表单内无法正常工作
- css - 如何修复Firefox中德语变音符号的显示?