SWIFT Тема 1: Неустранимая ошибка: Индекс вне диапазона: Разделы и строки - PullRequest
0 голосов
/ 09 июня 2019

нужна небольшая помощь в получении сгруппированных строк для заполнения их соответствующих разделов. Я работал на секунду, но попытался настроить код, чтобы избавиться от дубликатов и пропущенных строк. С тех пор я получаю «Фатальную ошибку»

Это для тренировочного проекта. Каталог пользователей, сгруппированных по их отделам. Использование Firebase, чтобы вытащить список пользователей. Группировка их по отделам и заполнение таблицы.

//MARK: - CELLS
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "directoryCell", for: indexPath) as! TableViewCell

    let departmentSections = Dictionary(grouping: directoryArray) { (user) -> String in
        return user.department
    }

    //ROW & SECTION SETUP
    let rowsInSection = Array(departmentSections.values)
    //let usersInRowData = rowsInSection[indexPath.section]
    let users = rowsInSection[indexPath.section][indexPath.row]

    //USER CELL INFO
    let profilePic = users.profilePic // PROFILE PHOTO GET AND DISPLAY
    let url = URL(string: profilePic); URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
        if error != nil {
            print(error!)
            return
        }
        DispatchQueue.main.async {
            cell.profilePicView.image = UIImage(data: data!)
            cell.layoutSubviews()
        }
    }).resume()

    //CELL LABELS
    cell.displayNameLabel.text = users.displayName
    cell.emailLabel.text =       users.email
    cell.officeLabel.text =      users.office
    cell.titleLabel.text =       users.title
    cell.profilePicView.layer.masksToBounds = true;
    //cell.profilePicView.contentMode = UIView.ContentMode.scaleAspectFill;
    //cell.departmentLabel.text = users.department
    //cell.reportsToLabel.text = users.directReports
    //cell.extLabel.text = users.ext

    cell.layoutSubviews()

    return cell
}

Я ожидаю, что пользователи будут сгруппированы по отделам. Все, что я получаю, это: «Тема 1: Неустранимая ошибка: индекс выходит за пределы диапазона»

1 Ответ

1 голос
/ 09 июня 2019

Несколько баллов:

В табличном или коллекционном представлении должен отображаться массив (одно или двухмерный) данных. Словарь неупорядочен, поэтому он не подходит ни для одной модели данных.

Ваш текущий код выполняет интенсивную вычислительную реконструкцию вашей модели данных при каждом проходе через cellForRowAt. Вы используете Dictionary(grouping:) для создания словаря, а затем создаете массивы из этих словарей на каждый проход через tableView(_:cellForRowAt:). И вы делаете это, сначала создав словарь, поэтому порядок разделов может каждый раз отличаться. Не делай этого. (Это является возможной причиной ваших сбоев, поскольку при каждом проходе через tableView (_: cellForRowAt :) ваш массив отделов может быть в другом порядке, поэтому число пользователей в каждом разделе может быть разным.

Кроме того, нет смысла строить вашу модель данных в tableView(_:cellForRowAt:), поскольку система сначала вызывает numberOfSections(in:), затем вызывает tableView(_:numberOfRowsInSection:), а затем начинает вызывать заголовки разделов и ячейки. Вы не показываете свои методы numberOfSections(in:) или tableView(_:numberOfRowsInSection:), но я не понимаю, как они могли бы вернуть правильную информацию, поскольку их модели данных не настраиваются при первом вызове.

Я бы предложил определить массив структур сечений и заполнить их один раз при первой настройке табличного представления.

struct SectionStruct: {
  let sectionTitle: String //Department name?
  let sectionItems: [User]
}

var sections = [SectionStruct]() //populate this as described below

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

Теперь в вашем методе numberOfSections будет возвращено sections.count.

rowsInSection вернется sections[section].count

Вы можете поместить код для построения вашей модели данных в метод didSet для вашего directoryArray:

var directoryArray: [User] {
  didSet {
    //Code to group your users by department, build the section structures, and sort them

    tableView?.reloadData()  //Tell the table view to reload
  }

Примечание. Приведенный выше код больше похож на псевдокод, чем на реальный код, который вы можете скопировать в свой проект. Он предназначен, чтобы указать вам в правильном направлении. Не пытайтесь скопировать его в свой проект и пожаловаться, если (когда) он не скомпилируется.

Если вам нужна дополнительная помощь по рефакторингу вашего кода, вам придется опубликовать свои структуры данных (например, тип directoryArray) и код для ваших numberOfSections(in:), tableView(_:numberOfRowsInSection:) и tableView(_:titleForHeaderInSection:) данных. исходные методы. Отредактируйте свой вопрос, чтобы добавить измененный код внизу. Не пытайтесь размещать код в комментариях. Он не отформатирован и поэтому не читается.

...