Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios FRC内容更改时的UITableView异常_Ios_Swift_Uitableview_Nsfetchedresultscontroller - Fatal编程技术网

Ios FRC内容更改时的UITableView异常

Ios FRC内容更改时的UITableView异常,ios,swift,uitableview,nsfetchedresultscontroller,Ios,Swift,Uitableview,Nsfetchedresultscontroller,我有一个UITableView,它显示来自NSFetchedResultsController的数据。FRC中显示的数据量各不相同,从一次提取约20条记录到最大一次提取约14k条记录。我遇到的问题是,如果我在tableView滚动大的fetch时执行fetch,我会得到一个异常。调用cellforrowatinexpath时,FRC已经更新,并且那里没有数据,导致异常 我发现,这听起来像我遇到的,尽管我无法通过这种方法解决它 func tableView(_ tableView: UITab

我有一个
UITableView
,它显示来自
NSFetchedResultsController的数据。FRC中显示的数据量各不相同,从一次提取约20条记录到最大一次提取约14k条记录。我遇到的问题是,如果我在tableView滚动大的fetch时执行fetch,我会得到一个异常。调用
cellforrowatinexpath
时,FRC已经更新,并且那里没有数据,导致异常

我发现,这听起来像我遇到的,尽管我无法通过这种方法解决它

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseID, for: indexPath) as! CustomTableViewCell
    // Exception occurs here
    let myObject = fetchedResultsController.object(at: indexPath)
    cell.myObject = myObject

    return cell
  }
以下是堆栈跟踪:

0   CoreFoundation                      0x0000000110b241e6 __exceptionPreprocess + 294
1   libobjc.A.dylib                     0x000000010b820031 objc_exception_throw + 48
2   CoreData                            0x000000010c2458fd -[NSFetchedResultsController objectAtIndexPath:] + 685
3   MyApp                         0x000000010aaf36c5 _T011MyApp0B14ViewControllerC05tableC0So07UITableC4CellCSo0fC0C_10Foundation9IndexPathV12cellForRowAttF + 437
4   MyApp                         0x000000010aaf39ec _T011MyApp0B14ViewControllerC05tableC0So07UITableC4CellCSo0fC0C_10Foundation9IndexPathV12cellForRowAttFTo + 92
5   UIKit                               0x000000010cf45567 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 783
6   UIKit                               0x000000010cf45ae4 -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
7   UIKit                               0x000000010cf0ceaa -[UITableView _updateVisibleCellsNow:isRecursive:] + 3168
8   UIKit                               0x000000010cf2d7e0 -[UITableView layoutSubviews] + 176
9   UIKit                               0x000000010ceb77a8 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1515
10  QuartzCore                          0x000000010cc21456 -[CALayer layoutSublayers] + 177
11  QuartzCore                          0x000000010cc25667 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 395
12  QuartzCore                          0x000000010cbac0fb _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 343
13  QuartzCore                          0x000000010cbd979c _ZN2CA11Transaction6commitEv + 568
14  UIKit                               0x000000010cde22ef _UIApplicationFlushRunLoopCATransactionIfTooLate + 167
15  UIKit                               0x000000010d747662 __handleEventQueueInternal + 6875
16  CoreFoundation                      0x0000000110ac6bb1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
17  CoreFoundation                      0x0000000110aab4af __CFRunLoopDoSources0 + 271
18  CoreFoundation                      0x0000000110aaaa6f __CFRunLoopRun + 1263
19  CoreFoundation                      0x0000000110aaa30b CFRunLoopRunSpecific + 635
20  GraphicsServices                    0x0000000115c2fa73 GSEventRunModal + 62
21  UIKit                               0x000000010cde8057 UIApplicationMain + 159
22  MyApp                         0x000000010aacd427 main + 55
23  libdyld.dylib                       0x0000000111c5b955 start + 1
我欢迎关于解决这一问题的建议。在
tableview
完成之前,我希望避免做一些像禁用新抓取这样的黑客行为。谢谢你的阅读

更新

下面是我对
UIFetchedResultsControllerDelegate
的实现。这是苹果公司的代码:

更新2

作为对注释的响应,这是我用来更新谓词的代码。我有一个
startDate
endDate
的观察者,它调用
updatePredicate()
<按下分段控件时,会更新代码>开始日期
结束日期

  // This is used to set values for searching via segmentedControl
  @objc dynamic var startDate: Date?
  @objc dynamic var endDate: Date?

  func updatePredicate() {
    // you need a start date or stop executing
    guard let startDate = startDate else { return }

    var predicateArray: [NSPredicate] = []

    if let endDate = endDate {
      let startEndPredicate = NSPredicate(format: "time >= %@ AND time <= %@", argumentArray: [startDate, endDate])
      predicateArray.append(startEndPredicate)
    } else {
      // use the startDate's end of day if endDate is nil
      let startPredicate = NSPredicate(format: "time >= %@ AND time <= %@", argumentArray: [startDate, startDate.endOfDay!])
      predicateArray.append(startPredicate)
    }

    let sliderPredicate = NSPredicate(format: "magnitude >= %f", argumentArray: [magSlider.value])
    predicateArray.append(sliderPredicate)

    currentPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicateArray)

    fetchResults()
  }
更新3

针对另一项评论,以下是FRC声明:

  private lazy var fetchedResultsController: NSFetchedResultsController<EarthquakeEntity> = {
    let managedObjectContext = appDelegate.persistentContainer.viewContext
    let fetchRequest: NSFetchRequest<EarthquakeEntity> = EarthquakeEntity.fetchRequest()
    let dateSortDescriptor = NSSortDescriptor(key: #keyPath(EarthquakeEntity.time), ascending: false)
    fetchRequest.sortDescriptors = [dateSortDescriptor]
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: frcKeyPath, cacheName: nil)
    frc.delegate = self

    return frc
  }()
private lazy var fetchedResultsController:NSFetchedResultsController={
让managedObjectContext=appDelegate.persistentContainer.viewContext
let fetchRequest:NSFetchRequest=EarthquakeEntity.fetchRequest()
让dateSortDescriptor=NSSortDescriptor(键:#键路径(EarthQuantity.time),升序:false)
fetchRequest.sortDescriptors=[dateSortDescriptor]
设frc=NSFetchedResultsController(fetchRequest:fetchRequest,managedObjectContext:managedObjectContext,sectionNameKeyPath:frcKeyPath,cacheName:nil)
frc.delegate=self
返回frc
}()

我最终玩了
fetchLimit
,这似乎解决了我的问题

在执行提取时,我按如下方式使用它:

fetchedResultsController.fetchRequest.fetchLimit = 2_500

2500大约是我在不破坏应用程序的情况下所能得到的最大值。

当FRC与
fetchBatchSize
一起使用时,FRC操作的数据集是一个代理数组。如果在访问批次元素时尚未获取批次数据,则在访问时获取该数据

代理阵列的线程安全性与您操作的托管对象的线程安全性相同-必须从底层MOC的专用队列访问它。您可以检查线程安全性是否是本文后面的问题:。理想情况下,访问必须采用以下方式:

var myObject;
fetchedResultsController.managedObjectContext.performBlockAndWait({
    myObject = fetchedResultsController.object(at: indexPath) 
})
cell.myObject = myObject
此外,在崩溃时,请检查这些陈述是否属实:

1) fetchedResultsController.sections.first.numberOfObjects <= 
                                         fetchedResultsController.fetchRequest.fetchLimit

2) fetchedResultsController.sections.first.numberOfObjects == 
                                         tableView.numberOfRows(inSection: 0)

1)fetchedResultsController.sections.first.numberOfObjects您能提供如何实现
nsFetchedResultsController委托
方法吗?@TarasChernyshenko更新。查看它时,我看到强制展开的
newIndexPath/indexPath
,这可能是我的问题。您能提供创建获取请求的代码吗?您是否在将取回限制更改为2500之前设置了取回限制?@DisableR感谢您的阅读。我用你要求的代码更新了帖子。在fetch中更改fetchLimit后,你的问题解决了吗?
fetchedResultsController.fetchRequest.fetchLimit = 2_500
var myObject;
fetchedResultsController.managedObjectContext.performBlockAndWait({
    myObject = fetchedResultsController.object(at: indexPath) 
})
cell.myObject = myObject
1) fetchedResultsController.sections.first.numberOfObjects <= 
                                         fetchedResultsController.fetchRequest.fetchLimit

2) fetchedResultsController.sections.first.numberOfObjects == 
                                         tableView.numberOfRows(inSection: 0)