Swift:当UITableView滚动太快时,应用程序崩溃

时间:2015-10-29 03:40:05

标签: ios swift uitableview scroll swift2

我正在创建一个页面,用户从UITableView的行业列表中选择他们所在的行业。这是配置文件创建过程的一部分。当用户选择一个行业时,它会被勾选(如果以前没有选择)&未选中标记(如果之前已选中)。

我已经使代码正常工作,并且能够成功构建。一切正常,但当我滚动太快时,应用程序崩溃时出现以下错误:

  

2015-10-29 10:16:40.576Protégé1.0[10867:473794] *由于未捕获的异常'NSRangeException'而终止应用程序,原因:'* - [__ NSArrayM objectAtIndex:]:索引11超出界限[0 .. 10]'

接下来是“First throw call stack”和所有文件的列表。奇怪的是,这似乎只有在我滚动太快时才会发生。经常也会突然发生。

以下是我的代码。在网上搜索了与我得到的错误消息相关的任何内容,似乎没有什么对这种情况有帮助。似乎无法弄清楚什么是错的,并且真的很感激任何帮助。我是Swift的新手,所以如果我的代码中有任何错误,请告诉我!在此先感谢:)

var array = ["Industry 1", "Industry 2", "Industry 3", "Industry 4", "Industry 5"]
var itemsSelected: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()
}

确定有多少行

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return array.count
}

定义每个单元格的内容

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    cell.textLabel?.text = array[indexPath.row]

    for var i = 0; i < selectedCells.count; i++ {
            let indexPath = NSIndexPath(forRow: selectedCells[i], inSection: 0)
            let checkedCell = tableView.cellForRowAtIndexPath(indexPath)
            checkedCell?.accessoryType = UITableViewCellAccessoryType.Checkmark
    }

    return cell
}

创建阵列以存储选定的单元格

var selectedCells: [Int] = []

选择行 - 选中标记&amp;未选中标记

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
    let cell = tableView.cellForRowAtIndexPath(indexPath)

    // Checkmark & un-checkmark cell
    if cell!.accessoryType == UITableViewCellAccessoryType.None {
        cell!.accessoryType = UITableViewCellAccessoryType.Checkmark
    } else {
        cell!.accessoryType = UITableViewCellAccessoryType.None
    }

    // Add cell # to selectedCells array if it's a new selection. Remove if it's a deselection.
    if selectedCells.contains(indexPath.row) {
        selectedCells = selectedCells.filter {$0 != indexPath.row}
    } else {
        selectedCells.append(indexPath.row)
    }

    print(selectedCells)
}

将所选字符串传输到主要配置文件创建视图控制器

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "selectionCompleted" {

        // Get the new view controller using segue.destinationViewController
        let destViewController: CreateProfileViewController = segue.destinationViewController as! CreateProfileViewController

        // Pass the selected object to the new view controller.
        destViewController.displayedSelection = array[0]
    }
}

将segue的速度提升回主要配置文件创建视图控制器

override func performSegueWithIdentifier(identifier: String, sender: AnyObject?) {

    if identifier == "selectionCompleted" {
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.performSegueWithIdentifier("selectionCompleted", sender: nil)
        })
    }
}

1 个答案:

答案 0 :(得分:0)

根据您提供的上下文。我想问题可能是因为你的“内容定义方法”和选择的检查机制。

我的猜测:

在tableView(:UITableView :NSIndexPath)中 - &gt; UITableViewCell函数, 每当代表要求一个单元格时,它就会循环传递selectedArray。

由于NSArray(数组)不是线程安全的,所以任何更改或快速访问selectedCell数组都可能导致各种状态。当“滚动如此之快”会创建许多同时访问同一阵列的循环时,我认为这里可能会发生一些冲突。

让我提一个建议。您可以使用Set而不是数组。使用“包含”“插入”“删除”来控制状态,每个单元只管理自己。

可能是这样的:

let cell = ...
...
if selectedSet.contains(indexPath.row){
    cell.accessoryType = UITableViewCellAccessoryType.Checkmark
}else{
    cell.accessoryType = UITableViewCellAccessoryType.None
}
...
return cell