Нужна помощь в настройке UISwitch в пользовательской ячейке (XIB, Swift 4, Xcode 9) - PullRequest
0 голосов
/ 26 апреля 2018

Успехи на данный момент: У меня есть удаленный источник данных.Данные динамически переносятся в View Controller.Данные используются для именования .title и .subtitle в каждой из многократно используемых пользовательских ячеек.Кроме того, каждая настраиваемая ячейка имеет переключатель UIS, который я смог использовать для отправки как сигнала «подписки» для push-уведомлений (для данной группы, определенной заголовком / субтитром ячейки), так и сигнала «отписаться»,

Моя единственная оставшаяся проблема: Всякий раз, когда пользователь «пересматривает» VC настроек, в то время как мой код «сбрасывает» переключатели UIS, он вызывает следующие предупреждения в Xcode 9.2:

  • UISwitch.on должен использоваться из основного потока
  • UISwitch.setOn (_: animated :) должен использоваться только из основного потока
  • - [UISwitch setOn: animated: notifyingVisualElement:] должен использоваться из основного потока

Код ниже «работает» - однако желаемый результат происходит довольно медленно (переключатели UIS, которые, как предполагается, должны быть включены, требуют некоторого времени, чтобы окончательнопереключиться на «on»).

Подробнее: Что необходимо: всякий раз, когда VC либо отображается, либо «отображается повторно», мне нужно «сбросить» UIS-переключатель пользовательской ячейки на«on», если пользователь подписан на данную группу, и «off», если пользователь не подписан.В идеале, каждый раз, когда отображается VC, что-то должно протянуть руку и коснуться сервера OneSignal и выяснить «состояние подписки» этого пользователя для каждой группы, используя функцию OneSignal.getTags () .У меня эта часть работает.Этот код находится в ВК.Но мне нужно сделать это правильно, чтобы соответствовать надлежащим протоколам, связанным с многопоточностью.

  • VC-файл «ViewController_13_Settings.swift» содержит табличное представление с настраиваемой ячейкой многократного использования.
  • Файл табличного представления называется «CustomTableViewCell.swift»
  • Пользовательская ячейка называется «CustomCell» (я знаю, все мои имена действительно креативны).

ПользовательскаяЯчейка (разработанная в XIB) содержит только три элемента:

  1. Заголовок - Отображаемое «понятное имя» «группы», на которую можно подписаться или отписаться.Установить из удаленного источника данных
  2. Субтитры - скрытое «имя базы данных» вышеупомянутой группы.Скрыто от пользователя.Установить из удаленного источника данных.
  3. UISwitch - с именем "switchMinistryGroupList"

Как правильно установить UISwitch программно?

Вот код в ViewController_13_Settings.swift, который кажется уместным:

    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell  = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell

    // set cell's title and subtitle
    cell.textLabelMinistryGroupList?.text = MinistryGroupArray[indexPath.row]
    cell.textHiddenUserTagName?.text = OneSignalUserTagArray[indexPath.row]

    // set the custom cell's UISwitch.
    OneSignal.getTags({ tags in
        print("tags - \(tags!)")
        self.OneSignalUserTags = String(describing: tags)
        print("OneSignalUserTags, from within the OneSignal func, = \(self.OneSignalUserTags)")

        if self.OneSignalUserTags.range(of: cell.textHiddenUserTagName.text!) != nil {
            print("The \(cell.textHiddenUserTagName.text!) UserTag exists for this device.")
            cell.switchMinistryGroupList.isOn = true
        } else {
            cell.switchMinistryGroupList.isOn = false
        }
    }, onFailure: { error in
        print("Error getting tags - \(String(describing: error?.localizedDescription))")
        // errorWithDomain - OneSignalError
        // code - HTTP error code from the OneSignal server
        // userInfo - JSON OneSignal responded with
    })
    viewWillAppear(true)
    return cell
    }
    }

В приведенной выше части кода VC эта часть (ниже) являетсяфункционирует, но, видимо, не так, как правильно использует потоки:

    if OneSignalUserTags.range(of: cell.textHiddenUserTagName.text!) != nil {
        print("The \(cell.textHiddenUserTagName.text!) UserTag exists for this device.")
        cell.switchMinistryGroupList.isOn = true
    } else {
        cell.switchMinistryGroupList.isOn = false
    }

1 Ответ

0 голосов
/ 26 апреля 2018

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

1) Улучшение именования ваших объектов. Это помогает другим увидеть, что происходит, задавая вопросы.

Не называйте свою ячейку CustomTableViewCell - назовите ее, скажем, MinistryCell или что-то, что представляет данные, которые она отображает. Вместо textLabelMinistryGroupList и textHiddenUserTagName дерева ministryGroup и userTagName и т. Д.

2) Пусть клетка сама заселится. Сделайте ваш IBOutlets в вашей ячейке private, чтобы вы не могли назначить его непосредственно в вашем контроллере представления. Это плохая привычка!

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

4) Никогда Звоните viewWillAppear, или что-нибудь подобное! Они вызываются системой.

В итоге вы получите что-то вроде этого:

На ваш взгляд контроллер

struct Ministry {
    let group: String
    let userTag: String
    var tagExists: Bool?
}

Вы должны создать массив var ministries: [Ministry] и заполнить его в начале, а не иметь дело с MinistryGroupArray и OneSignalUserTagArray по отдельности.

В твоей камере

class MinistryCell: UITableViewCell {

    @IBOutlet private weak var ministryGroup: UILabel!
    @IBOutlet private weak var userTagName: UILabel!
    @IBOutlet private weak var switch: UISwitch!

    var ministry: Ministry? {
        didSet {
            ministryGroup.text = ministry?.group
            userTagName.text = ministry?.userTag
            if let tagExists = ministry?.tagExists {
               switch.isEnabled = false
               switch.isOn = tagExists
            } else {
               // We don't know the current state - disable the switch?
               switch.isEnabled = false
            }
        }
    }
}

Тогда ваш метод источника данных будет выглядеть так: *

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell  = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! MinistryCell

    let ministry = ministries[indexPath.row]
    cell.ministry = ministry

    if ministry.tagExists == nil {
        OneSignal.getTags { tags in

        // Success - so update the corresponding ministry.tagExists
        // then reload the cell at this indexPath

        }, onFailure: { error in
            print("Error")
        })
    }    
    return cell
}
...