Получение сообщения об ошибке «нераспознанный селектор отправлен в экземпляр» при использовании UILocalizedIndexedCollation для создания индексов раздела tableView в Swift 4.2 - PullRequest
0 голосов
/ 25 января 2019

Я пытаюсь создать приложение по образцу приложения контактов iPhone. В этом процессе я пытаюсь поместить индексы разделов в правую часть моего tableView контактов. В Руководстве по программированию Apple View Table для 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)
    }
}

Ожидаемый результат - получить указатели разделов (A ... Z, #) в правой части списка контактов tableView, как в приложении "Контакты iPhone".

1 Ответ

0 голосов
/ 25 января 2019

Селектор, который вы передаете sortedArray(from:collationStringSelector:), должен быть селектором типа сортируемых объектов.У вас нет свойства localizedTitle для объектов в вашем массиве.

Обычно у вас будет массив классов или структур, которые вы хотите отсортировать, и вы передадите селектор некоторого свойства классаили struct.

Но ваш массив - это массив 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, так как это больше не понадобится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...