使用 UILocalizedIndexedCollation 在 Swift 4.2 中创建 tableView 部分索引时出现错误“无法识别的选择器发送到实例”
Posted
技术标签:
【中文标题】使用 UILocalizedIndexedCollation 在 Swift 4.2 中创建 tableView 部分索引时出现错误“无法识别的选择器发送到实例”【英文标题】:Getting error "unrecognized selector sent to instance" while using UILocalizedIndexedCollation to create tableView section Indexes in Swift 4.2 【发布时间】:2019-01-25 04:52:50 【问题描述】:我正在尝试构建一个仿照 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 的联系人应用程序中一样。
【问题讨论】:
【参考方案1】:您传递给sortedArray(from:collationStringSelector:)
的选择器必须是在被排序的对象类型上找到的选择器。您的数组中的对象没有 localizedTitle
属性。
通常,您会拥有一个要排序的类或结构数组,并且您会传递类或结构的某些属性的选择器。
但是您的数组是String
的数组。所以你需要一个String
的属性来返回用于排序的字符串。
而且由于选择器的这种使用基于旧的 Objective-C 框架,因此该属性需要暴露给 Objective-C。
使用String
数组的一件事是使用选择器NSString.description
。这是因为 Swift String
可以桥接到 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
的其他代码,因为不再需要它。
【讨论】:
感谢您的帮助 rmaddy!你真的帮助我理解了选择器。无论如何要对多个键进行排序?我一直在使用 CNContact,想先按 familyName 排序,然后按 givenName 排序? 你应该把它作为一个新问题发布。以上是关于使用 UILocalizedIndexedCollation 在 Swift 4.2 中创建 tableView 部分索引时出现错误“无法识别的选择器发送到实例”的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)