【问题标题】:Array Index Out of Bounds issue (NSRangeException) in -[NSManagedObjectContext save:]-[NSManagedObjectContext save:] 中的数组索引越界问题 (NSRangeException)
【发布时间】:2015-06-29 21:27:32
【问题描述】:

我的 iOS 应用程序刚刚在 -[NSManagedObjectContext save:] 上出现 NSRangeException 崩溃。在任何地方都找不到其他有用的东西。我该如何解决这个问题?我没有得到任何内存地址或任何我可以使用的东西......

2015-04-22 14:16:38.078 heavenhelp[33559:1734247] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 6 beyond bounds [0 .. 5]'
*** First throw call stack:
(
    0   CoreFoundation                      0x0167f746 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x00f40a97 objc_exception_throw + 44
    2   CoreFoundation                      0x01553b73 -[__NSArrayM objectAtIndex:] + 243
    3   CoreData                            0x00859cf3 -[NSSQLCore recordToManyChangesForObject:inRow:usingTimestamp:inserted:] + 2531
    4   CoreData                            0x00856a0b -[NSSQLCore _populateRow:fromObject:timestamp:inserted:] + 2923
    5   CoreData                            0x00776e24 -[NSSQLCore prepareForSave:] + 1764
    6   CoreData                            0x00775e3d -[NSSQLCore saveChanges:] + 461
    7   CoreData                            0x0073f15e -[NSSQLCore executeRequest:withContext:error:] + 638
    8   CoreData                            0x0083ee75 __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke + 5349
    9   CoreData                            0x008492ff gutsOfBlockToNSPersistentStoreCoordinatorPerform + 191
    10  libdispatch.dylib                   0x035f4bef _dispatch_client_callout + 14
    11  libdispatch.dylib                   0x035d7b0d _dispatch_barrier_sync_f_invoke + 144
    12  libdispatch.dylib                   0x035d723f dispatch_barrier_sync_f + 105
    13  CoreData                            0x008383f7 _perform + 183
    14  CoreData                            0x0073ec8b -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 459
    15  CoreData                            0x0076ee09 -[NSManagedObjectContext save:] + 1529
    16  heavenhelp                          0x000b6834 _TF10heavenhelp11saveContextFT_T_ + 324
    17  heavenhelp                          0x0015368d _TFC10heavenhelp26ConversationViewController17viewWillDisappearfS0_FSbT_ + 701
    18  heavenhelp                          0x001536ef _TToFC10heavenhelp26ConversationViewController17viewWillDisappearfS0_FSbT_ + 63
    19  UIKit                               0x020a4292 -[UIViewController _setViewAppearState:isAnimating:] + 706
    20  UIKit                               0x020a4904 -[UIViewController __viewWillDisappear:] + 106
    21  UIKit                               0x020bcd1d -[UIViewController(UIContainerViewControllerProtectedMethods) beginAppearanceTransition:animated:] + 200
    22  UIKit                               0x020cafec -[UINavigationController _startCustomTransition:] + 1028
    23  UIKit                               0x020d8e00 -[UINavigationController _startDeferredTransitionIfNeeded:] + 712
    24  UIKit                               0x020d9a51 -[UINavigationController __viewWillLayoutSubviews] + 57
    25  UIKit                               0x02253750 -[UILayoutContainerView layoutSubviews] + 213
    26  UIKit                               0x01fce57a -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 668
    27  libobjc.A.dylib                     0x00f56771 -[NSObject performSelector:withObject:] + 70
    28  QuartzCore                          0x01d5ee47 -[CALayer layoutSublayers] + 144
    29  QuartzCore                          0x01d52925 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 403
    30  QuartzCore                          0x01d5277a _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
    31  QuartzCore                          0x01caec52 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 284
    32  QuartzCore                          0x01cb00e5 _ZN2CA11Transaction6commitEv + 487
    33  QuartzCore                          0x01cb07fc _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
    34  CoreFoundation                      0x015a086e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    35  CoreFoundation                      0x015a07b0 __CFRunLoopDoObservers + 400
    36  CoreFoundation                      0x015961ea __CFRunLoopRun + 1226
    37  CoreFoundation                      0x01595a5b CFRunLoopRunSpecific + 443
    38  CoreFoundation                      0x0159588b CFRunLoopRunInMode + 123
    39  GraphicsServices                    0x046cc2c9 GSEventRunModal + 192
    40  GraphicsServices                    0x046cc106 GSEventRun + 104
    41  UIKit                               0x01f3b106 UIApplicationMain + 1526
    42  heavenhelp                          0x000a5c94 main + 180
    43  libdyld.dylib                       0x0361fac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

这是我用来使我的save: 线程安全的代码:

static var onceToken: dispatch_once_t = 0
static var singleton: CoreDataHelper!
static var sharedInstance: CoreDataHelper {
    get {
        dispatch_once(&onceToken, {
            self.singleton = CoreDataHelper()
        })
        return singleton
    }
}

我的xcdatamodeld(相关部分):

编辑:我编辑了代码以反映我的更改,以使我的NSManagedObjectContext 线程安全。我现在所做的一切,都是在我上面初始化的CoreDataHelper 的一个实例上做的。我发现我可以通过进入一个对话、添加一条消息、进入另一个对话并在那里添加一条消息来触发崩溃。我已经添加了我的xcdatamodeld。

【问题讨论】:

  • 模拟器中也会发生这种情况吗?错误消息可能会更明确
  • "index 6 beyond bounds [0 .. 5] " 这意味着您正在尝试从只有 6 个对象的数组中访问第 7 个对象。并添加一个特殊的断点,它会直接告诉你那一行是什么。
  • @Nandu,6 个对象数组中的第 7 个对象。
  • @vib 我现在无法重现该错误,我会在可以重现时查看断点的内容(我希望可以,否则此错误可能会保留在发布版本中)跨度>
  • 这对我来说像是线程问题。 NSManagedObjects 不是线程安全的。您必须在创建它的同一线程中访问一个。我知道您说过您使 save 方法线程安全,但我敢打赌您正在从多个线程访问 NSManagedObject 上下文。最简单的解决方案可能是创建一个单例对象并让它为您完成所有工作。然后在需要时从任何线程访问该单例。

标签: ios xcode swift appdelegate sigabrt


【解决方案1】:

我显然已将对话和消息之间的一对多关系设置为“有序”。这是不正确的...我已经将 NSManagedObject 的类更改为使用 NSMutableSet 而不是 NSMutableOrderedSet。

显然这会导致 save 方法中出现 NSRangeException...

【讨论】:

    【解决方案2】:

    你说你已经保存了你的保存方法线程。可以给我一些代码吗?

    通常我会这样做:

    // create object with concurrency where you need it
    [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    
    
    // wrapper for saving
    - (BOOL)saveContext
    {
        __block BOOL success = NO;
    
        NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
        if (managedObjectContext != nil)
        {
            [managedObjectContext performBlockAndWait:^{
                if([managedObjectContext hasChanges])
                {
                    NSError *error = nil;
                    success = [managedObjectContext save:&error];
    
                    if (success == NO)
                    {
                        NSLog(@"Unresolved error %@", error.localizedDescription);
                    }
                }
            }];
        }
    
        return success;
    }
    

    【讨论】:

    • 我已经添加了我的代码。我使用了一个全局NSLock,我围绕我的save 方法锁定和解锁。
    • 如果您在与创建它的线程不同的线程上使用 MOC,那么该锁将无济于事。 MOCBusters 的一条规则是不要跨线程。你能分享你正在使用的 dispatch_async 代码吗
    • 谢谢。我根本不熟悉NSLock...你可以尝试使用performBlock 或performBlockAndWait,因为同步是这些方法的目的。你可以在这里找到更多信息:developer.apple.com/library/ios/documentation/Cocoa/Reference/…
    • @donmarkusi 我现在在初始化NSManagedObjectContext 时使用NSPrivateQueueConcurrencyType,但这仍然会使我的应用程序崩溃。同样的错误。我开始认为这是 CoreData 中的一个错误。我将尝试创建一个有错误的最小应用程序。
    • 你是否按照苹果的建议使用performBlockAndWait 或performBlock?是的,一个最小的应用程序会很有趣。
    【解决方案3】:

    您正在AppDelegate 的某个地方创建NSArray,

    通过添加异常断点,您可以检查导致错误的行。

    添加异常断点的方法在以下链接中。

    http://blog.manbolo.com/2012/01/23/xcode-tips-1-break-on-exceptions https://developer.apple.com/library/ios/recipes/xcode_help-breakpoint_navigator/articles/adding_an_exception_breakpoint.html

    【讨论】:

    • 我不能接受这个答案,但我可以告诉你我没有在AppDelegate 中创建NSArray。我投票赞成你添加异常断点的建议。
    • 添加异常断点显示错误发生在[NSManagedObjectContext save:]... 现在该怎么办?
    • 好吧,我插入一个新对象后会出现错误,但它并不总是发生,这很奇怪。该错误仅发生在默认 managedObjectContext (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext 上的 .save(&error) 方法上。我不知道我应该分享什么。我在dataTaskWithRequest: 的completionHandler 中创建NSManagedObjects(由dispatch_async(dispatch_get_main_queue()) 发送到主队列),但直到我在此completionHandler 之外创建对象时才会发生错误。
    • 在模拟器中运行应用程序会产生更好的错误;我编辑了我的问题。
    • 在recordToManyChangesForObject:inRow:usingTimestamp:inserted: 方法(访问错误索引的方法)上使用断点运行应用程序时,我感觉我保存在我的完成处理程序中,同时保存在其他完成处理程序中。有没有办法确保方法在执行中不重叠?
    猜你喜欢
    • 1970-01-01
    • 2014-04-27
    • 2013-07-27
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多