重新加载数据时 Tableview 崩溃

Posted

技术标签:

【中文标题】重新加载数据时 Tableview 崩溃【英文标题】:Tableview crashes when reloading data 【发布时间】:2017-02-16 11:54:13 【问题描述】:

我在使用 tableviews 时遇到了意想不到的问题。每次我尝试重新加载表格视图的数据时,应用程序似乎都会退出而没有错误。我知道数组的形成是正确的,所以这些函数有问题:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

        if tableView.tag == 1 

            return latest.count
        
        else if tableView.tag == 2
            return older.count
        
        else 

            return 0 //In case of error
        

    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

        var cell:UITableViewCell?

        if tableView.tag == 1 
            print("Success")
            cell = tableView.dequeueReusableCell(withIdentifier: "latestCell")! as UITableViewCell

            cell = UITableViewCell(style: UITableViewCellStyle.subtitle,
                                   reuseIdentifier: "latestCell")

            cell?.textLabel?.text = latest[indexPath.row]

            cell?.detailTextLabel?.text = latestSub[indexPath.row]

            cell?.accessoryType = .disclosureIndicator

            return cell!

        

        else if tableView.tag == 2 

            cell = tableView.dequeueReusableCell(withIdentifier: "olderCell")! as UITableViewCell

            cell = UITableViewCell(style: UITableViewCellStyle.subtitle,
                                   reuseIdentifier: "olderCell")


            cell?.textLabel?.text = older[indexPath.row]

            cell?.detailTextLabel?.text = olderSub[indexPath.row]

            cell?.accessoryType = .disclosureIndicator

            return cell!
        

        else 
            return cell!
        
    

之前对这类问题的回答是关于忘记设置委托和数据源等等......所以我相信这是一个合适的问题。

提前致谢!

编辑:

var latest = [String]()

var older = [String]()

var latestSub = [String]()

var olderSub = [String]()


override func viewDidAppear(_ animated: Bool) 
    latestTable.reloadData()
    olderTable.reloadData()

完整的日志;

2017-02-16 15:57:28.889 NotebookApp[24985:604704] Firebase 自动屏幕报告已启用。调用 +[FIRAnalytics setScreenName:setScreenClass:] 设置屏幕名称或覆盖默认屏幕类名称。要禁用自动屏幕报告,请在 Info.plist 中将标志 FirebaseAutomaticScreenReportingEnabled 设置为 NO 2017-02-16 15:57:28.997 NotebookApp[24985:] Firebase Analytics v.3600000 开始 2017-02-16 15:57:28.999 NotebookApp[24985:] 要启用调试日志记录,请设置以下应用程序参数:-FIRAnalyticsDebugEnabled 2017-02-16 15:57:29.012:启用 FIRInstanceID AppDelegate 代理,将调整应用程序委托远程通知处理程序。要禁用将“FirebaseAppDelegateProxyEnabled”添加到您的 Info.plist 并将其设置为 NO 2017-02-16 15:57:29.020 NotebookApp[24985:] 自动成功创建 Firebase Analytics App Delegate Proxy。要禁用代理,请在 Info.plist 中将标志 FirebaseAppDelegateProxyEnabled 设置为 NO 2017-02-16 15:57:29.090 NotebookApp[24985:] AdSupport 框架当前未链接。某些功能将无法正常运行。 2017-02-16 15:57:29.180 NotebookApp[24985:] Firebase Analytics 已启用 2017-02-16 15:57:45.703779 NotebookApp[24985:604704] [LayoutConstraints] 无法同时满足约束。 以下列表中的至少一个约束可能是您不想要的。 试试这个: (1)查看每个约束并尝试找出您不期望的; (2) 找到添加了一个或多个不需要的约束的代码并修复它。 (注意:如果您看到不理解的 NSAutoresizingMaskLayoutConstraints,请参阅 UIView 属性 translatesAutoresizingMaskIntoConstraints 的文档) ( "", “” )

将尝试通过打破约束来恢复

在 UIViewAlertForUnsatisfiableConstraints 创建一个符号断点,以便在调试器中捕获它。 中列出的 UIView 上的 UIConstraintBasedLayoutDebugging 类别中的方法也可能会有所帮助。 2017-02-16 16:01:34.316879 NotebookApp[24985:604704] [MC] systemgroup.com.apple.configurationprofiles 路径的系统组容器是 /Users/tuomasnummela/Library/Developer/CoreSimulator/Devices/AA87179A-11E5-4A3A -A63F-B785AA71EC95/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles 2017-02-16 16:01:34.317476 NotebookApp[24985:604704] [MC] 从私人有效用户设置中读取。

我有点不认为这里会有任何有用的东西,因为当应用退出时,它不会将我带到错误页面并突出显示任何代码。

What my project looks like after the app has forcedly closed itself.

【问题讨论】:

分享您的数组值和重新加载表格的方法。 我还将这些数组附加到另​​一个函数中,所以如果这似乎是问题,我也可以发布它。但它包括了 firebase,所以这将永远持续下去。 所以你的应用一加载视图控制器就崩溃了,对吧? @user7356029 错误日志中的错误是什么? 如果发生崩溃,显示错误日志。 【参考方案1】:

这里可能出错的地方是找不到具有您在下一行中传递的重用标识符的单元格

cell = tableView.dequeueReusableCell(withIdentifier: "olderCell")! as UITableViewCell

您所要做的就是在您的 viewDidLoad 中注册带有重用标识符的单元格

<olderTableView>.registerClass(UITableViewCell.self, forCellReuseIdentifier: "olderCell") <latestTableView>.registerClass(UITableViewCell.self, forCellReuseIdentifier: "latestCell")

您可以简单地将出队和初始化行替换为以下内容

if tableView.tag == 1 
        let reuseId = "latestCell" 
        let latestCell = tableView.dequeueReusableCell(withIdentifier: reuseId) ?? UITableViewCell(style: .subtitle, reuseIdentifier: reuseId)

        latestCell.textLabel?.text = latest[indexPath.row]
        latestCell.detailTextLabel?.text = latestSub[indexPath.row]
        latestCell.accessoryType = .disclosureIndicator

        return latestCell

    

【讨论】:

@user7356029 我已经编辑了答案检查应该工作的第二种情况 没错。您发布的第二个案例就像魅力一样。非常感谢! 其实,现在这个很好用,但是单元格上的字幕没有显示出来。知道这可能是什么吗? @user7356029 您可以尝试用let reuseId = "latestCell" let latestCell = tableView.dequeueReusableCell(withIdentifier: reuseId) ?? UITableViewCell(style: .subtitle, reuseIdentifier: reuseId)替换回车线的后卫 @user7356029 我已经编辑了答案。如果这不起作用,那么你的 latestSub 数组应该有一些问题,比如它包含空字符串【参考方案2】:

第一个错误是在viewDidAppear 你必须调用super.viewDidAppear(animated),tableview reload 永远不会触发。

【讨论】:

这好像没什么区别,是不是有第二个错误? 缺少其他信息,您发布的日志仅用于布局。 完整日志现在在主帖中。【参考方案3】:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell 中有许多错误。崩溃可能是由于强制解开 cell 导致的,最后一行中的值为零。

这是我清理它的尝试。请务必使用tableView.register(SubtitleCell.self, forCellReuseIdentifier:"latestCell") 注册UITableViewCell 子类。除非有其他代码不可见,否则您可以对 latestCellolderCell 使用相同的标识符 - 它们似乎与您发布的代码没有什么不同

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    var cell:UITableViewCell //can't be optional

    if tableView.tag == 1 
        print("Success")
       cell = tableView.dequeueReusableCell(withIdentifier: "latestCell", forIndexPath: indexPath) as! SubtitleCell
       //cell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "latestCell") //don't call this here, make a subclass of UITableViewCell to set style

        cell.textLabel?.text = latest[indexPath.row]
        cell.detailTextLabel?.text = latestSub[indexPath.row]
        cell.accessoryType = .disclosureIndicator
        return cell
    

    else if tableView.tag == 2 
        //same comments as above
        cell = tableView.dequeueReusableCell(withIdentifier: "olderCell", for: indexPath) as! SubtitleCell
        cell.textLabel?.text = older[indexPath.row]
        cell.detailTextLabel?.text = olderSub[indexPath.row]
        cell.accessoryType = .disclosureIndicator
        return cell
    

    else 
        cell =  tableView.dequeueReusableCell(withIdentifier: "latestCell", forIndexPath: indexPath)
        return cell //you were returning nil here - need to return a cell
    

这是一个如何初始化正确单元格样式的示例

class SubtitleCell: UITableViewCell 
   override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)

【讨论】:

崩溃不能来自最后一行,因为代码在 else 块中的行数为 0,因此它永远不会到达 cellForRowAtIndexPath 中返回的 nil 情况

以上是关于重新加载数据时 Tableview 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

用tableview重新加载uiviewcontroller的table view subobject的数据

如何在 TableView 中重新加载数据

JSON请求后以编程方式TableView不会重新加载数据

解析查询后在哪里重新加载 UITableView 数据

tableview reloadData在解包可选值时崩溃意外发现的nil

Swift - 第二次加载后 Tableview 无法正确重新加载