仅在将对象添加到 CoreData 后无法在捆绑包中找到 NIB?

Unable to find NIB in bundle only after adding an object to CoreData?

这个问题困扰了我几个小时,看了各种相关问题,我似乎找不到答案。

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

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

我已经通读了我能找到的所有相关问题,下面是我已经尝试但未成功的事情的快速列表:

漂亮 确定它与 CoreData 相关,因为这似乎是视图控制器何时工作和不工作之间的唯一区别,但我对 Swift 和 iOS dev,所以我可能偏离目标。

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

堆栈跟踪:

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 Class with subclass of UITableViewCell and a single出口链接到情节提要中的 nameLabel

一些快速的事后想法...如果您需要任何我没有包含在此处的信息,请告诉我。我正在使用 Core Data Stack Class 和一个教授改编的扩展 iOS dev class 我一年前使用它提供了易于使用的 .items() 功能... 我也可以 post 如果您认为这会导致任何问题。这太奇怪了,因为我有另一个核心数据实体(产品而不是计数)使用几乎完全相同的代码完美运行。我似乎无法弄清楚这种情况有什么不同...

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

总结一下,希望以后能对某人有所帮助,问题似乎出在 CountTableViewController.swift:

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

像往常一样,这似乎是重用旧代码和 copy/pasting 的混合体。奇怪的是,这段代码似乎在与同一项目中的 Product 实体几乎相同的场景中工作正常。不过,我删除了上面的最后两行,只剩下:

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

果然,NSInternalInconsistencyException 错误消失了!

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

感谢@pbasdf comment/answer!