Ios 在swift上频繁更新表视图失败

Ios 在swift上频繁更新表视图失败,ios,swift,uitableview,Ios,Swift,Uitableview,我有一个tableview需要立即更新。代码如下。我将headerview设计为具有下拉功能,当显示标题点击其余部分时。当我试图点击头部时,代码将崩溃,线程停止,xcode没有给出任何关于如何和为什么的提示 func didListOfBLEDevicesUpdate(newDevice: BLEDevice) { println("receivedDevice from scanner every second: \(newDevice.deviceName)") self.dev

我有一个tableview需要立即更新。代码如下。我将headerview设计为具有下拉功能,当显示标题点击其余部分时。当我试图点击头部时,代码将崩溃,线程停止,xcode没有给出任何关于如何和为什么的提示

func didListOfBLEDevicesUpdate(newDevice: BLEDevice)
{
  println("receivedDevice from scanner every second: \(newDevice.deviceName)")
    self.deviceTableView.reloadData()
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return BLEDevice.listOfDevices.items.count
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1;
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return BLEDevice.listOfDevices.items[section].deviceName
}

func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return 1
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if(IsExpandedMode[indexPath.section] == true){
        return 400
    }
    return 70;
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let headerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 40))
    headerView.backgroundColor = UIColor.grayColor()
    headerView.tag = section

    let headerString = UILabel(frame: CGRect(x: 10, y: 10, width: tableView.frame.size.width-10, height: 30)) as UILabel
    headerString.text = BLEDevice.listOfDevices.items[section].deviceName
    headerView .addSubview(headerString)
    let headerTapped = UITapGestureRecognizer (target: self, action:"sectionHeaderTapped:")
    headerView .addGestureRecognizer(headerTapped)
    return headerView
}

func sectionHeaderTapped(recognizer: UITapGestureRecognizer) {
    println("Tapping working")
    println(recognizer.view?.tag)


    var indexPath : NSIndexPath = NSIndexPath(forRow: 0, inSection:(recognizer.view?.tag as Int!)!)
    if (indexPath.row == 0) {

        var collapsed = self.IsExpandedMode [indexPath.section]
        collapsed = !collapsed;

        self.IsExpandedMode[indexPath.section] = collapsed
        //reload specific section animated
        var range = NSMakeRange(indexPath.section, 1)
        var sectionToReload = NSIndexSet(indexesInRange: range)
        self.deviceTableView.reloadSections(sectionToReload, withRowAnimation:UITableViewRowAnimation.Fade)
    }
 }

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell : DeviceTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! DeviceTableViewCell

      let row = indexPath.row
    cell.deviceName!.text = BLEDevice.listOfDevices.items[row].deviceName
    cell.connectionStatus.text = BLEDevice.listOfDevices.items[row].connectionStatus
    cell.deviceSignalStrengthen.text = BLEDevice.listOfDevices.items[row].RSSI
    cell.manufacturerData.text = BLEDevice.listOfDevices.items[row].advertisementPackage.cBAdvertisementDataManufacturerData
    cell.serviceUUID.text = BLEDevice.listOfDevices.items[row].advertisementPackage.cBAdvertisementDataServiceUUIDs
    cell.serviceData.text = DataConvertHelper.getNSDictionary(BLEDevice.listOfDevices.items[row].advertisementPackage.cBAdvertisementDataServiceData)
    cell.TxPowerLevel.text = BLEDevice.listOfDevices.items[row].advertisementPackage.cBAdvertisementDataTxPowerLevel
    cell.IsConnectable.text = DataConvertHelper.getBool(BLEDevice.listOfDevices.items[row].advertisementPackage.cBAdvertisementDataIsConnectable)
    cell.solicitedServiceUUID.text = BLEDevice.listOfDevices.items[row].advertisementPackage.cBAdvertisementDataSolicitedServiceUUIDs
    cell.shortenedLocalName.text = BLEDevice.listOfDevices.items[row].advertisementPackage.cBAdvertisementDataLocalName
      return cell
}

使用重新加载节和重新加载行而不是重新加载数据

使用重新加载节和重新加载行而不是重新加载数据

用于处理表的方法似乎相当复杂。备选方案如下:

1) 代码中的假设是每个设备都与一个节相关联。如评论中所述,您的
cellforratindexpath
方法似乎使用
[row]
索引数据模型,但该模型基于
[section]
,因为您总是将每个节的行数返回为1,节数是设备数

2) 不必为每个部分使用标题视图,也不必添加手势识别器,只需创建一个自定义单元格来表示设备,并将该部分的这一行设为0

3) 因此,每个设备都与一个部分相关联,每个部分的第0行是标题信息单元,而不是标题视图。使标题视图为零。可以使用收割台高度在节之间留出间隙

4) 添加代码以检测单元格的选择。当单元格行为0时,其为标题单元格。如果设备已折叠,请将其设置为展开,反之亦然,然后重新加载节

5) 为下拉列表信息创建新的自定义单元格。这将是显示信息的任何部分的第1行

6) 更新节中的行数,如果展开则返回2,如果折叠则返回1

7) 更新
cellforrowatinexpath
以返回第0行的标题单元格和第1行的详细信息单元格。确保将
[row]
索引修复为
[section]
索引

这将为您提供一个设备标题单元格表,单击时在下面插入详细信息单元格,再次单击时将其删除,无需手势识别器


您需要确保数据模型更新工作正常。从错误中可以看出,您没有正确更新数据模型:特别是删除设备。

您用于处理表的方法似乎相当复杂。备选方案如下:

1) 代码中的假设是每个设备都与一个节相关联。如评论中所述,您的
cellforratindexpath
方法似乎使用
[row]
索引数据模型,但该模型基于
[section]
,因为您总是将每个节的行数返回为1,节数是设备数

2) 不必为每个部分使用标题视图,也不必添加手势识别器,只需创建一个自定义单元格来表示设备,并将该部分的这一行设为0

3) 因此,每个设备都与一个部分相关联,每个部分的第0行是标题信息单元,而不是标题视图。使标题视图为零。可以使用收割台高度在节之间留出间隙

4) 添加代码以检测单元格的选择。当单元格行为0时,其为标题单元格。如果设备已折叠,请将其设置为展开,反之亦然,然后重新加载节

5) 为下拉列表信息创建新的自定义单元格。这将是显示信息的任何部分的第1行

6) 更新节中的行数,如果展开则返回2,如果折叠则返回1

7) 更新
cellforrowatinexpath
以返回第0行的标题单元格和第1行的详细信息单元格。确保将
[row]
索引修复为
[section]
索引

这将为您提供一个设备标题单元格表,单击时在下面插入详细信息单元格,再次单击时将其删除,无需手势识别器


您需要确保数据模型更新工作正常。从错误中可以看出,您没有正确更新数据模型:特别是删除设备。

是否在计时器上调用了
DidListofBledDevicesUpdate
,是否在主线程上?你说的线头是什么意思?你说过表每秒钟更新一次。如果这种情况发生在后台线程中,那么您可以在尝试重新加载表时更改模型。我认为您需要在问题中添加更多关于发生了什么以及您看到了什么的详细信息:例如,点击手势代码是否完成或中途崩溃代码:如果是,在何处等…计时器上调用DidListofBledDevicesUpdate。我的目标是制作一个tableview来显示一个设备列表,每一行都应该有一个标题,当点击标题时,该行会下降并显示设备的详细信息。计时器是在主线程上还是在后台线程上?我还认为这个计时器在调用这个方法之前找到了新的设备?也值得您展示该代码。计时器设置和计时器方法。与其尝试检测节标题上的点击,不如始终将给定节的第0行设置为自定义标题单元格。然后,您可以使用标准单元格选择和
didSelectRowAtIndexPath
。还想知道为什么在
cellforrowatinexpath
中从未使用
?似乎您只使用了
,这对于基于分区的表来说是奇数?这是错误:“由于未捕获的异常而终止应用程序'nsInternalInconsistencException',原因:'无效更新:分区数无效。更新后表视图中包含的分区数(14)必须等于更新前表视图中包含的节数(13),加上或减去插入或删除的节数(1个插入,1个删除)。“***第一次抛出调用堆栈:此列表可能已更新bcz新设备添加到