我正在尝试构建一个模仿iPhone的“通讯录”应用程序的应用程序。在这个过程中,我试图将节索引放在联系人的tableView的右侧。 Apple的iOS文档“表格视图编程指南”建议使用UILocalizedIndexedCollation类。问题似乎出在collationStringSelector上。在Swift 4中,选择器需要公开给@objc,无论如何我都找不到,而且我尝试过的所有内容都会出现以下错误消息:
***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'-[NSTaggedPointerString localizedTitle]:无法识别的选择器已发送至实例
我试图将选择器对象放入其自己的类中,以便可以将其公开给@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)
}
}
预期结果是像在iPhone的“联系人”应用程序中那样,使tableView的联系人列表的右侧下方的部分索引(A ... Z,#)
答案 0 :(得分:0)
您传递给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
的代码,因为不再需要这些值。