需要帮助在自定义单元格中设置 UISwitch (XIB, Swift 4, Xcode 9)

Need help setting UISwitch in custom cell (XIB, Swift 4, Xcode 9)

到目前为止的成功: 我有一个远程数据源。数据被动态拉入视图控制器。该数据用于在每个可重用自定义单元格上命名 .title 和 .subtitle。此外,每个自定义单元格都有一个 UISwitch,我已经能够使用它发送推送通知的“订阅”信号(对于由单元格的 title/subtitle 标识的给定组)和“取消订阅”信号以及。

我剩下的一个问题:每当用户 "revisits" 设置 VC,而我的代码是 "resetting" UISwitches 时,它会导致Xcode 9.2 中的以下警告:

"works" 下面的代码——但是期望的结果发生得相当慢(确实应该是 "on" 的 UISwitch 需要一段时间才能最终翻转到 "on") .

更多详情: 需要什么:每当显示 VC 或 "re-shown," 我需要 "reset" 自定义单元格的 UISwitch 到 "on" 如果用户订阅了给定的组,并且"off" 如果用户未订阅。理想情况下,每次显示 VC 时,应该有什么东西伸出并触摸 OneSignal 服务器,并使用 OneSignal.getTags()函数。我有那部分工作。此代码在 VC 中。但我需要以正确的方式进行,以适应有关线程的适当协议。

自定义单元格(在 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) 改进对象的命名。这有助于其他人在提问时了解发生了什么。

不要将您的单元格命名为 CustomTableViewCell - 例如,将其命名为 MinistryCell 或代表其显示的数据的名称。而不是 textLabelMinistryGroupListtextHiddenUserTagNameministryGroupuserTagName

2) 让单元格自行填充。在您的单元格 private 中创建您的 IBOutlets 这样您就不能直接在您的视图控制器中分配给它们。这是个坏习惯!

3) 创建一个对象(例如,Ministry),它对应于您要分配给单元格的数据。把这个赋给cell,让cell赋给它的Outlets。

4) 永远不要 调用 viewWillAppear 或任何类似的东西!这些都是系统调用的。

你最终会得到这样的结果:

在你的视图控制器中

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

您应该创建一个数组 var ministries: [Ministry] 并在开始时填充它,而不是分别处理 MinistryGroupArrayOneSignalUserTagArray

在你的手机里

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
            }
        }
    }
}

那么你的 dataSource 方法看起来像...

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
}