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

时间:2018-04-26 06:41:57

标签: ios swift xcode uiswitch

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

我剩下的一个问题:每当用户“重新访问”设置VC时,当我的代码“重置”UISwitch时,它会在Xcode 9.2中引发以下警告:

  • UISwitch.on必须在主线程中使用
  • UISwitch.setOn(_:animated :)必须仅在主线程中使用
  • - 必须在主线程中使用[UISwitch setOn:animated:notifyingVisualElement:]

下面的代码“有效” - 但是期望的结果发生得相当缓慢(确实应该“开启”的UISwitch需要花费很长时间才能最终翻转到“on”)。

更多详情: 需要什么:每当VC显示或“重新显示”时,如果用户订阅了给定的组,我需要将自定义单元的UISwitch“重置”为“on”,如果用户是,则需要“关闭”没有订阅。理想情况下,每次显示VC时,都应该触及OneSignal服务器并使用 OneSignal.getTags()函数找出该用户对每个组的“订阅状态”。我有那个部分在工作。这段代码在VC中。但我需要以正确的方式做到这一点,以适应有关线程的正确协议。

  • VC文件,“ViewController_13_Settings.swift”包含一个带有可重复使用的自定义单元格的表视图。
  • 表视图文件名为“CustomTableViewCell.swift”
  • 自定义单元格被称为“customCell”(我知道,我的名字都非常有创意)。

自定义单元格(在XIB中设计)内部只有三个项目:

  1. 标题 - 要订阅或取消订阅的“组”的显示“友好名称”。从远程数据源设置
  2. 字幕 - 上述组的隐藏“数据库名称”。隐藏在用户之外。从远程数据源设置。
  3. UISwitch - 名为“switchMinistryGroupList”
  4. 如何以编程方式正确设置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 :(得分:0)

您的代码正在做什么并不完全清楚,但似乎有一些事情需要整理,这将有助于您解决问题。

1)改进对象的命名。这可以帮助其他人了解在提问时会发生什么。

请勿拨打您的小区CustomTableViewCell - 将其称为MinistryCell或代表其显示数据的内容。而不是textLabelMinistryGroupListtextHiddenUserTagNameministryGroupuserTagName等。

2)让细胞填充自己。在您的单元格IBOutlets中设置private,这样您就无法直接在视图控制器中分配它们。这是一个坏习惯!

3)创建一个对象(例如Ministry),该对象与您分配给单元格的数据相对应。将其分配给单元格并让单元格分配给它的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
}