iOS with Swift:UITableView向下滚动事件导致应用程序崩溃

iOS with Swift:UITableView向下滚动事件导致应用程序崩溃,ios,iphone,swift,uitableview,asynchronous,Ios,Iphone,Swift,Uitableview,Asynchronous,我正在用Swift编写一个iOS应用程序,将API中的数据放入TableView。目标是用户可以向下滚动连续的博客文章列表。发生的情况是,数据很好地填充了第一个屏幕的单元格数量,但当用户向下滚动时,应用程序崩溃,因为其中一个单元格属性,cellImageView变为nil并被展开(因为在单元格类的代码中指定了强制展开): 以下是导致崩溃的代码: override func tableView(_ tableView: UITableView, cellForRowAt indexPath: In

我正在用Swift编写一个iOS应用程序,将API中的数据放入TableView。目标是用户可以向下滚动连续的博客文章列表。发生的情况是,数据很好地填充了第一个屏幕的单元格数量,但当用户向下滚动时,应用程序崩溃,因为其中一个单元格属性,
cellImageView
变为
nil
并被展开(因为在单元格类的代码中指定了强制展开):

以下是导致崩溃的代码:

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

    apiCaller.getAPIDataThroughAsyncCall(id: nextCell, entry: { cellContent in
        DispatchQueue.main.async(execute: {
            cell.cellLabel.text = cellContent.labelText
            cell.cellTextView.text = cellContent.textViewText
            // App crashes at the below line
            cell.initialsImageView = self.createPicture(initials: cellContent.pictureText)
        })
    })

    nextCell += 1

    return cell
}
有趣的是,如果这样做:

    cell.cellLabel?.text = cellContent.labelText
    cell.cellTextView?.text = cellContent.textViewText
    // App does NOT crash at the below line
    cell.initialsImageView? = self.createPicture(initials: cellContent.pictureText)
,应用程序不会崩溃,但数据只是在用户滚动时一次又一次地重复

我在这里尝试了一个类似问题的解决方案,但没有成功。然而,我相信这与异步API调用有关


我认为可能的解决方案可能包括在生成单元格之前填充一组API数据,但在重新思考代码的体系结构之前,我想了解一下这个问题的根源。

您需要在
viewDidLoad
中进行API调用,以了解有多少元素,并在数组中记录它们的ID。然后在
cellForRow
函数中,您可以通过这种方式获取id

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

    apiCaller.getAPIDataThroughAsyncCall(id: array[indexPath.row], entry: { cellContent in
        DispatchQueue.main.async(execute: {
            ...
        })
    })
    return cell
}

nextCell无法工作的原因是,每当表格视图试图显示当前不在屏幕上的单元格时,都会调用此
cellForRow
函数。假设你知道你有10个元素,你的屏幕只能显示其中的5个。当您滚动到底部时,您的下一个单元格将变为10,并且一切正常。但现在,当您向上滚动时,表视图必须再次准备前5个。因此,现在您的下一个单元格变为15,您的API调用中没有相应的元素。

您需要在
viewDidLoad
中进行API调用,以了解有多少元素,并在数组中记录它们的ID。然后在
cellForRow
函数中,您可以通过这种方式获取id

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

    apiCaller.getAPIDataThroughAsyncCall(id: array[indexPath.row], entry: { cellContent in
        DispatchQueue.main.async(execute: {
            ...
        })
    })
    return cell
}

nextCell无法工作的原因是,每当表格视图试图显示当前不在屏幕上的单元格时,都会调用此
cellForRow
函数。假设你知道你有10个元素,你的屏幕只能显示其中的5个。当您滚动到底部时,您的下一个单元格将变为10,并且一切正常。但现在,当您向上滚动时,表视图必须再次准备前5个。现在,您的nextCell变为15,您的API调用中没有相应的元素。

在CellForRow中调用任何API都是不好的做法。indexPath:indexPath,它会产生崩溃,如您所见,请查看MVVM。这就像打赢了一场战争而不必投入战斗,我指的是在cellForRowAt indexPath:indexPath中调用API,并且出口没有初始化。

在cellForRowAt indexPath:indexPath中调用任何API都是不好的做法,它会产生崩溃,如您所见,看看MVVM。这就像赢得了一场战争而不必去战斗,我指的是在cellForRowAt indexPath:indexPath中调用API的实例,并且出口没有初始化。

异常消息是什么?是否在注释为“应用程序在下一行崩溃”的行下方设置了
initialsImageView
outlet。异常消息是
致命错误:在展开可选值时意外发现nil
,这是由于展开
nil
单元格造成的。initialsImageView
您使用
nextCell
是完全不合适的。把它扔掉。可以按任何顺序访问单元格。使用
indepath
确定id。请记住,用户滚动,单元格就会被重用。为什么要为已经看到的单元格重新加载数据?根据需要缓存数据。我正在使用
nextCell
作为API上某个东西的ID,尽管它的名称不同,我不知道这是否会让事情变得更好
nextCell
实际上是一个随机数异常消息是什么?是否在注释为“应用程序在下一行崩溃”的行下方设置了
initialsImageView
outlet。异常消息是
致命错误:在展开可选值时意外发现nil
,这是由于展开
nil
单元格造成的。initialsImageView
您使用
nextCell
是完全不合适的。把它扔掉。可以按任何顺序访问单元格。使用
indepath
确定id。请记住,用户滚动,单元格就会被重用。为什么要为已经看到的单元格重新加载数据?根据需要缓存数据。我正在使用
nextCell
作为API上某个东西的ID,尽管它的名称不同,我不知道这是否会使事情变得更好
nextCell
实际上是一个随机数