*** 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds fo
Posted
技术标签:
【中文标题】*** 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray”【英文标题】:*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray' 【发布时间】:2017-10-18 20:05:01 【问题描述】:我不断收到此错误:
2017-10-18 22:57:52.401421+0300 费用管理器[4213:133067] * 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“* -[__NSArray0 objectAtIndex:] : 索引 0 超出了空 NSArray'的界限
但我不知道我做错了什么。 tableView 在 numberOfSections 为 1 并且它们不按日期排序时工作得很好,但是当我尝试每天做部分时,它应用启动时崩溃。
func userBudgetCount(_ section: Int) -> Int
return fetchedResultsController.sections![section].numberOfObjects
func getUserBudgetAtIndexPath(indexPath : IndexPath) -> Budget
return fetchedResultsController.object(at: indexPath) as Budget
override func viewDidLoad()
super.viewDidLoad()
self.hideKeyboard()
tableView.delegate = self
tableView.dataSource = self
self.tableView.tableFooterView = UIView()
override func viewDidAppear(_ animated: Bool)
super.viewWillAppear(animated)
fetchCoreDataObject()
tableView.reloadData()
func fetchCoreDataObject()
self.fetch (complete) in
if complete
if userBudgetCount(0) >= 1
userBudgetLabel.text = replaceLabel(number: userMoney[userMoney.count - 1].userMoney)
tableView.isHidden = false
plusButton.isHidden = false
moreBtn.isHidden = false
else
tableView.isHidden = true
userBudgetLabel.text = "Bugetul tau"
plusButton.isHidden = true
moreBtn.isHidden = true
var fetchedResultsController: NSFetchedResultsController<Budget>
if _fetchedResultsController != nil
return _fetchedResultsController!
let fetchRequest = NSFetchRequest<Budget>(entityName: "Budget")
// Set the batch size to a suitable number.
fetchRequest.fetchBatchSize = 20
// Edit the sort key as appropriate.
let sortDescriptor = NSSortDescriptor(key: "dateSubmitted" , ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext!, sectionNameKeyPath: "dateSection", cacheName: nil)
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
do
try _fetchedResultsController!.performFetch()
catch
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
return _fetchedResultsController!
var _fetchedResultsController: NSFetchedResultsController<Budget>? = nil
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
tableView.reloadData()
func numberOfSections(in tableView: UITableView) -> Int
return fetchedResultsController.sections!.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
guard let cell = tableView.dequeueReusableCell(withIdentifier: "expenseCell") as? ExpenseCell else return UITableViewCell()
let budget = getUserBudgetAtIndexPath(indexPath: indexPath)
cell.delegate = self
cell.configureCell(budget: budget)
return cell
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool
return true
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle
return UITableViewCellEditingStyle.none
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return userBudgetCount(section)
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
return "Section: \(section)"
【问题讨论】:
哪一行崩溃了?正如错误中提到的,您有一个空数组,并且您正在尝试访问它的第一个索引。 我不知道哪条线路崩溃了,它崩溃时将我带到 AppDelegate。不说台词 添加异常断点 @vadian i.imgur.com/VWWrGqs.png hackingwithswift.com/example-code/xcode/… 【参考方案1】:func numberOfSections(in tableView: UITableView) -> Int guard let count = fetchedResultsController.sections?.count else return 1 返回计数 尝试安全展开:
【讨论】:
【参考方案2】:当您的视图首次加载表视图时,数据源方法开始在结果控制器获取任何数据之前被调用。因此,在任何你强行拆开你可能会崩溃的东西的地方。
要通过强制解包(在使用!
的所有地方)修复此外观,并执行以下操作:
func numberOfSections(in tableView: UITableView) -> Int
return fetchedResultsController.sections?.count ?? 0
这将确保 something 在没有崩溃风险的情况下被退回。在某些地方,您可能很难确定默认返回值应该是什么,但它应该是可行的。
??
运算符称为 nil-coalescing 运算符。语法如下:
let foo = someOptionalThing ?? defaultThing
如果someOptionalThing
有一个值,则将其分配给foo
,否则将defaultThing
分配给foo
。
根据您的 cmets 更新:
看起来你打电话给return fetchedResultsController.object(at: indexPath) as Budget
结果控制器还没有我所期望的对象。
func getUserBudgetAtIndexPath(indexPath : IndexPath) -> Budget
// Make sure the section exists
guard fetchedResultsController.sections?.count > indexPath.section else return Budget()
// Make sure the section has enough objects
guard fetchedResultsController.sections[indexPath.section].objects?.count > indexPath.row else return Budget()
// We made it past both guards, must be safe
return fetchedResultsController.object(at: indexPath) as Budget
【讨论】:
您尝试更改强制展开的每个 位置,还是复制了我上面显示的方法?您提到该特定方法是您从返回硬编码1
更改但不访问数组元素的方法,因此它不太可能是您的问题的实际原因。
我复制了这条线。我尝试对其他强制展开执行相同的操作,但它们对我来说是奇怪的变量,例如 NSFetchedResultsSectionInfo 我不知道应该使用什么默认值
我猜你的问题出在userBudgetCount
或getUserBudgetAtIndexPath
。这些是直接或间接访问数组的方法。为它们中的每一个添加一个断点,当它们被触发时,使用 Step Over 并查看它是否超过了线路或崩溃。如果您遇到崩溃,您将知道问题出在哪里,并添加一个防范措施来防止它发生。
userBudgetCount
可以很好地处理断点,但是当我向getUserBudgetAtIndexPath
函数添加断点时,我会被超出范围的索引抛出,因此代码无法以某种方式调用该函数,否则我的应用程序由于我的断点会停止
Xcode 让我解开其中的一些值,否则代码将无法构建。这就是我打开 guard fetchedResultsController.sections!.count > indexPath.section
和 guard fetchedResultsController.sections![indexPath.section].objects!.count > indexPath.row
的代码仍然给我同样的错误。【参考方案3】:
我解决了!
问题不在于 tableView
填充函数,而是在函数中我尝试检查 我的实体中是否有元素,以便我可以制作我的 tableView 可见
在这段代码中
func fetchCoreDataObject()
self.fetch (complete) in
if complete
if userBudgetCount(0) >= 1
userBudgetLabel.text = replaceLabel(number: userMoney[userMoney.count - 1].userMoney)
tableView.isHidden = false
plusButton.isHidden = false
moreBtn.isHidden = false
else
tableView.isHidden = true
userBudgetLabel.text = "Bugetul tau"
plusButton.isHidden = true
moreBtn.isHidden = true
我尝试检查 userBudgetCount(0) 是否超出范围,因为此时有 NO 部分 0 我尝试检查它是否存在。所以我需要检查我的 fetchedResultsController 是否有任何对象,所以我用if ((fetchedResultsController.fetchedObjects?.count)! > 0)
替换了if userBudgetCount(0) >= 1
,它现在工作正常。谢谢大家的回答!
【讨论】:
不错的尝试。但这并不能保证无崩溃代码。如果您从项目内部的任何地方传递一个大于总节数的数字会发生什么?你可以按照我的回答。谢谢 传递的数字大于总节数是什么意思?我传递的是对象编号,而不是部分【参考方案4】:对不起。实际上问题出在userBudgetCount
方法中。使用 0 参数调用此方法
fetchCoreDataObject
方法中的值抛出异常,因为sections 数组最初是空的。
用下面的代码行替换 uncommentthis 函数。请注意,这些代码行尚未编译。
func userBudgetCount(_ section: Int) -> Int
guard let sections = fetchedResultsController.sections else
fatalError("No sections in fetchedResultsController")
// comment out the above line of and rerun 0 if don’t want to catch exception
// rerun 0;
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
编辑 在我这边编译后,我在下面添加了更新的代码。请使用它而不是上面的。
func userBudgetCount(_ section: Int) -> Int
guard let sections = fetchedResultsController.sections else
return 0;
if sections.count > section
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
return 0;
【讨论】:
我收到Value of type 'NSFetchedResultsSectionInfo' has no member 'object'
@AndreiVataselu 我已经更新了我的答案。 NSFetchResultsSectionInfo 是一个协议,它有一个名为 objects[array] 的属性。从那里获取项目,请参阅我的更新答案。谢谢
现在我收到了Value of type '[Any]?' has no member 'object'
@AndreiVataselu 很抱歉给出错误的答案。请看我的最新回答
别抱歉,我很感激你能帮助我。不幸的是,我仍然遇到同样的错误。以上是关于*** 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds fo的主要内容,如果未能解决你的问题,请参考以下文章
由于未捕获的异常而终止应用程序 [UIImageView _isResizable]
由于未捕获的异常“NSInternalInconsistencyException”错误而终止应用程序