只有在向CoreData添加对象后才能在bundle中找到NIB?

问题描述 投票:1回答:1

这一直困扰我几个小时,在查看了各种相关问题之后,我似乎无法找到答案。

我收到一个奇怪的NSInternalInconsistencyException错误。该错误表明它无法加载名为CountTableViewController的NIB。但是,当我第一次运行应用程序时(在模拟器和物理设备中),我可以很好地转向该视图控制器。它加载和查看就像在Main.storyboard文件中一样。然后,当我向后导航并激活另一个视图控制器,将一些测试数据加载到我正在使用的核心数据堆栈时,事情就变得非常糟糕。使用断点和控制台日志,我可以看到单个对象已成功添加到核心数据堆栈中。但是,当我再次单击CountTableViewController时,应用程序崩溃并出现以下错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Could not load NIB in bundle: 'NSBundle <FILEPATH> (loaded)' with name 
'CountTableViewController''

我已经阅读了我能找到的每个相关问题,这里是我已经尝试过的不成功的快速列表:

  • 检查相关文件的拼写/大小写以及它们被引用的任何位置 (CountTableViewController.swift,CountTableViewCell.swift,CountReuseCell [重用id])
  • 删除对相关文件的引用,重新拖入Xcode
  • 删除对Main.storyboard和LaunchScreen.storyboard的引用,重新拖入Xcode
  • 验证项目的“构建阶段”中的“编译源”下是否正确列出了每个文件
  • 验证故事板是否在项目的“构建阶段”中的“复制捆绑资源”下正确列出
  • 从头开始重写为一个全新的视图控制器(仍然有相同的错误)

我很确定它的CoreData是相关的,因为这似乎是视图控制器执行和不工作之间的唯一区别,但我对Swift和iOS开发人员来说是新手,所以我可能会偏离目标。

我有堆栈跟踪,我将在下面发布。我将尝试发布一些我认为有用的代码的简洁部分。预先感谢您的帮助!

StackTrace:

0   CoreFoundation                      0x000000010721912b __exceptionPreprocess + 171
1   libobjc.A.dylib                     0x0000000102a78f41 objc_exception_throw + 48
2   CoreFoundation                      0x000000010728e245 +[NSException raise:format:] + 197
3   UIKit                               0x00000001043fd098 -[UINib instantiateWithOwner:options:] + 501
4   UIKit                               0x00000001040b2687 -[UITableView _dequeueReusableViewOfType:withIdentifier:] + 590
5   UIKit                               0x0000000120c4f79d -[UITableViewAccessibility dequeueReusableCellWithIdentifier:] + 147
6   UIKit                               0x00000001040b2b6b -[UITableView _dequeueReusableCellWithIdentifier:forIndexPath:usingPresentationValues:] + 148
7   UIKit                               0x00000001040b2aa3 -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:] + 89
8   UIKit                               0x0000000120c4f8e0 -[UITableViewAccessibility dequeueReusableCellWithIdentifier:forIndexPath:] + 285
9   BSA Inventory Control               0x00000001018d35d6 _T021BSA_Inventory_Control24CountTableViewControllerC05tableF0So07UITableF4CellCSo0iF0C_10Foundation9IndexPathV12cellForRowAttF + 774
10  BSA Inventory Control               0x00000001018d3c4c _T021BSA_Inventory_Control24CountTableViewControllerC05tableF0So07UITableF4CellCSo0iF0C_10Foundation9IndexPathV12cellForRowAttFTo + 92
11  UIKit                               0x00000001040ce484 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 778
12  UIKit                               0x00000001040cea2a -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
13  UIKit                               0x00000001040941f6 -[UITableView _updateVisibleCellsNow:isRecursive:] + 3031
14  UIKit                               0x00000001040b62e6 -[UITableView layoutSubviews] + 176
15  UIKit                               0x000000010403ea6d -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439

CountTableViewController.swift

import UIKit
import CoreData
class CountTableViewController: UITableViewController {
    let coreDataStack = CoreDataStack.shared
    var moc: NSManagedObjectContext! = nil
    var counts: [Count] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        moc = coreDataStack.viewContext

        tableView.register(CountTableViewCell.self, forCellReuseIdentifier: "CountReuseCell")
        let nib = UINib(nibName: "CountTableViewController", bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: "CountReuseCell")
    }
    func reload() {
        counts = Count.items(for: moc, matching: nil, sortedBy: nil)
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        reload()
        tableView.reloadData()
    }
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return counts.count
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "CountReuseCell", for: indexPath) as? CountTableViewCell else  {
            fatalError("The dequeued cell is not an instance of CountTableViewCell")
        }
        let count = counts[indexPath.row]
        cell.nameLabel.text = count.name       
        return cell
    }
}

CountTableViewCell.swift文件只是一个默认的Cocoa Touch类,其子类为UITableViewCell,单个出口链接到storyboard中的nameLabel

几个快速的事后...请告诉我,如果你需要的任何信息,我没有在这里包括。我正在使用核心数据堆栈类和一个由我在一年前开发的iOS开发类教授改编的扩展,它提供了易于使用的.items()功能......如果您认为这会导致任何问题,我也可以发布。这很奇怪,因为我有另一个核心数据实体(Product而不是Count)使用几乎完全相同的完全相同的代码。我似乎无法弄清楚这种情况有什么不同......

Xcode版本9.2(9C40b),iOS版本11.2(15C107)

swift core-data nib
1个回答
1
投票

只是为了把事情包起来并希望将来帮助某个人,问题似乎已经出现在Count TableViewController.swift中的这些行中:

tableView.register(CountTableViewCell.self, forCellReuseIdentifier: "CountReuseCell")
let nib = UINib(nibName: "CountTableViewController", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "CountReuseCell")

像往常一样,这似乎是重用旧代码和复制/粘贴的混合物。奇怪的是,这个代码似乎在与同一个项目中的Product实体几乎完全相同的情况下工作正常。尽管如此,我删除了上面的最后两行,只留下我:

tableView.register(CountTableViewCell.self, forCellReuseIdentifier: "CountReuseCell")

果然,NSInternalInconsistencyException错误消失了!

昨晚,我能够以编程方式完全重写CountTableViewController并且它正常工作,所以我打算暂时使用它。但是,知道将来导致此错误的原因是很好的。

感谢@pbasdf的评论/回答!

© www.soinside.com 2019 - 2024. All rights reserved.