I am trying to build an new iOS app and am using the RxSwift Library and Realm as database.
I build a tableview which shows a list of object from realm and these object should be editable and can be removed. (I don't use the tableview editing capabilities for this.)
Now when I remove an item from the table the table should refresh because i used RxSwift to bind the tableview to the Realm results. But instead of updating it crashes the app.
The error I get when the app crashes is 'RLMException', reason: 'Object has been deleted or invalidated.'
Also I get a stack trace in the output, but I can't find the source / reason why the crash happens.
Output stacktrace:
2018-05-14 00:09:34.660634+0200 RealmTest[65540:4239839] *** Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010f76e1e6 __exceptionPreprocess + 294
1 libobjc.A.dylib 0x000000010ee03031 objc_exception_throw + 48
2 Realm 0x000000010d44abd3 _ZL17RLMVerifyAttachedP13RLMObjectBase + 83
3 Realm 0x000000010d44c89c _ZN12_GLOBAL__N_18getBoxedIN5realm10StringDataEEEP11objc_objectP13RLMObjectBasem + 28
4 Realm 0x000000010d44c877 ___ZN12_GLOBAL__N_115makeBoxedGetterIN5realm10StringDataEEEP11objc_objectm_block_invoke + 39
5 RealmTest 0x000000010cf9c6a9 _T09RealmTest0B9ModelItemV8identitySSvg + 41
6 RealmTest 0x000000010cf9c6f5 _T09RealmTest0B9ModelItemV14Differentiator16IdentifiableTypeAadEP8identity8IdentityQzvgTW + 21
7 Differentiator 0x000000010d29f24e _T014Differentiator4DiffO23calculateAssociatedData33_D199D3FBF4B7CA3AFA95223EE09B4772LLs15ContiguousArrayVyAGyAC04ItemdE0AELLVGG_AKtAGyAGyxGG07initialP5Cache_AM05finalpR0tKAA16IdentifiableTypeRzlFZ + 2094
8 Differentiator 0x000000010d2ac30e _T014Differentiator4DiffO16CommandGenerator33_D199D3FBF4B7CA3AFA95223EE09B4772LLV22calculateItemMovementss15ContiguousArrayVyAIyAC0N14AssociatedDataAELLVGG_AMtAIyAIy0N0QzGG07initialN5Cache_AQ05finalnU0AIyAC07SectionrS0AELLVG0twS0AV0vwS0tKFZ + 334
9 Differentiator 0x000000010d2a1d65 _T014Differentiator4DiffO16CommandGenerator33_D199D3FBF4B7CA3AFA95223EE09B4772LLV27generatorForInitialSectionsAFy_xGSayxG_AI05finalP0tKFZ + 1253
10 Differentiator 0x000000010d2a1395 _T014Differentiator4DiffO27differencesForSectionedViewSayAA9ChangesetVyxGGSayxG15initialSections_AI05finalI0tKAA26AnimatableSectionModelTypeRzlFZ + 277
11 RxDataSources 0x000000010e35ede4 _T013RxDataSources0a26TableViewSectionedAnimatedB6SourceC05tableE0ySo07UITableE0C_0A5Swift5EventOySayxGG08observedL0tFyACyxG_AJtcfU_yycfU_ + 660
12 RxDataSources 0x000000010e360049 _T013RxDataSources0a26TableViewSectionedAnimatedB6SourceC05tableE0ySo07UITableE0C_0A5Swift5EventOySayxGG08observedL0tFyACyxG_AJtcfU_yycfU_TA + 25
13 RxDataSources 0x000000010e35f63d _T0Ieg_IeyB_TR + 45
14 libdispatch.dylib 0x0000000113b5b807 _dispatch_call_block_and_release + 12
15 libdispatch.dylib 0x0000000113b5c848 _dispatch_client_callout + 8
16 libdispatch.dylib 0x0000000113b6792b _dispatch_main_queue_callback_4CF + 628
17 CoreFoundation 0x000000010f730c99 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
18 CoreFoundation 0x000000010f6f4ea6 __CFRunLoopRun + 2342
19 CoreFoundation 0x000000010f6f430b CFRunLoopRunSpecific + 635
20 GraphicsServices 0x0000000117bb5a73 GSEventRunModal + 62
21 UIKit 0x000000010fbeb0b7 UIApplicationMain + 159
22 RealmTest 0x000000010cf9a0a7 main + 55
23 libdyld.dylib 0x0000000113bd9955 start + 1
24 ??? 0x0000000000000001 0x0 + 1
)
My question is if somebody knows what I do wrong and wat the correct way of removing an realm object is using RxSwift and Databinding?
Edit:
I Made a small test project and put it on my github, it errors when you tab the deleteFirst button. https://github.com/Hiiragisan09/ios-example-project-realm-test
I found the solution my self.
When I started using Realm I didn't know that the object mutates if you delete it.
It was a bit of a struggle because when realm crashes on 'realm object has been deleted or invalidated' it doesn't give a stacktrace of where you tried to access a property of the realmobject.
So when you delete an item from Realm it will trigger the table to get new items, and because the table is animated it will try to diff the new data with the old data. And when the Diff tries to access a property in the old data it will crash.
To fix the problem I created structs that represent the data in the table. So that when I delete a Realm object, the table will not crash because the Diff can still access the old data.
The way I use structs with Realm How to save a struct to realm in swift
I had the same issue. Then I read Martyn's answer. I gave him the upvote because triaging the problem was the hardest part for me. But I implemented a different solution than his. Adding a struct-based repository layer on top of my Realm data-model feels heavy given the scope of the problem.
My lighter-weight solution: I added a parameter to my collectionView reload method to control the reload animation. I default the param to true, and then override it & set it to false as needed. The collectionView doesn't try to access old / deleted Realm objects because it's not trying to animate the old elements off the view. Problem solved.
func displayRecipes(_ recipes: [Recipe], withAnimations: Bool = true) {
...
dataSource?.apply(snapshot, animatingDifferences: withAnimations)
}
Related
I originally downloaded the FBSDK's version 4.10 and integrated them into my application by placing them in the frameworks folder. Realizing that these would not get updated over time, I removed them completely and tried to add them as pods to my project. The pods installed successfully, I have imported them correctly in my bridging header file, and there were no other issues. The pods update installed version 4.11 which has caused me some headache.
I am using the FBSDKLoginKit to log a user into their account and retrieve information from that. I am able to get back a dictionary with the users information just fine. I then pass this information to the next ViewController with a segue. At any point after this, if I press the home button on my iPhone or simulator, the app will crash. The error I get is
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]:
attempt to insert nil object from objects[3]'
This exception also occurs if I let the user log in through facebook, segue to the new view controller, unwind to the previous view controller, and then attempt to log in again. I have attempted to log the user out once retrieving their pertinent information on the second screen, but the error still persists.
I have seen a similar question asked where the "solution" was that the FBSDKLoginKit writes the retrieved dictionary to a variable and if the dictionary it has retrieved back has nil values, it throws this error.
Is there anything I can do to catch this before it happens? Has anyone found a work around?
Here is my output from the simulator when I press home:
*** First throw call stack:
(
0 CoreFoundation 0x0000000106f03d85 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010643edeb objc_exception_throw + 48
2 CoreFoundation 0x0000000106e0023e -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 318
3 CoreFoundation 0x0000000106e125bb +[NSDictionary dictionaryWithObjects:forKeys:count:] + 59
4 APPNAME 0x0000000101607a1e -[FBSDKTimeSpentData instanceSuspend] + 622
5 APPNAME 0x000000010160766b +[FBSDKTimeSpentData suspend] + 59
6 APPNAME 0x00000001015b5986 -[FBSDKAppEvents applicationMovingFromActiveStateOrTerminating] + 262
7 CoreFoundation 0x0000000106ecdc8c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
8 CoreFoundation 0x0000000106ecd9cb _CFXRegistrationPost + 427
9 CoreFoundation 0x0000000106ecd732 ___CFXNotificationPost_block_invoke + 50
10 CoreFoundation 0x0000000106f161e2 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1986
11 CoreFoundation 0x0000000106dc5679 _CFXNotificationPost + 633
12 Foundation 0x000000010372ccd9 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
13 UIKit 0x0000000104a685ad -[UIApplication _deactivateForReason:notify:] + 629
14 UIKit 0x0000000104a6f1f1 __61-[UIApplication _sceneSettingsPreLifecycleEventDiffInspector]_block_invoke + 104
15 FrontBoardServices 0x0000000108f88d6c __52-[FBSSettingsDiffInspector inspectDiff:withContext:]_block_invoke27 + 213
16 Foundation 0x000000010377d5bb __NSIndexSetEnumerate + 1016
17 BaseBoard 0x000000010901ba8c -[BSSettingsDiff inspectChangesWithBlock:] + 116
18 FrontBoardServices 0x0000000108f83e4a -[FBSSettingsDiff inspectOtherChangesWithBlock:] + 92
19 FrontBoardServices 0x0000000108f88b2f -[FBSSettingsDiffInspector inspectDiff:withContext:] + 317
20 UIKit 0x0000000104a70880 __70-[UIApplication scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke + 127
21 UIKit 0x0000000104a7052d -[UIApplication scene:didUpdateWithDiff:transitionContext:completion:] + 843
22 FrontBoardServices 0x0000000108f978c8 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
23 FrontBoardServices 0x0000000108f97741 -[FBSSerialQueue _performNext] + 178
24 FrontBoardServices 0x0000000108f97aca -[FBSSerialQueue _performNextFromRunLoopSource] + 45
25 CoreFoundation 0x0000000106e29301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
26 CoreFoundation 0x0000000106e1f22c __CFRunLoopDoSources0 + 556
27 CoreFoundation 0x0000000106e1e6e3 __CFRunLoopRun + 867
28 CoreFoundation 0x0000000106e1e0f8 CFRunLoopRunSpecific + 488
29 GraphicsServices 0x0000000108ae7ad2 GSEventRunModal + 161
30 UIKit 0x0000000104a72f09 UIApplicationMain + 171
31 APPNAME 0x00000001013a26d2 main + 114
32 libdyld.dylib 0x0000000107b0d92d start + 1
33 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Running my code step by step I find that the error occurs during the method:
fbLoginManager.logInWithReadPermissions(permissionsNeeded, fromViewController: self) { (result, error) -> Void in
//crashes before it enters this block
//my code here
}
It crashes before I can even check the error value. I will attempt to check the values by stepping into the fbsdk methods and update
As soon as I press OK on this screen for the second time it crashes. How can I debug this? The action isn't in my app, its in the browser so I'm not sure where to go from here..
I have came across this issues recently, and i solved it by adding this piece of code in Appdelegate.m.
- (void)applicationDidBecomeActive:(UIApplication *)application {
[FBSDKAppEvents activateApp];
}
For Swift 3 version:
func applicationDidBecomeActive(_ application: UIApplication) {
FBSDKAppEvents.activateApp()
}
Update to 4.12, it fixes the issue according to their release notes:
https://developers.facebook.com/docs/ios/change-log-4.x/
The part that says:
Fixed
Fixed cases where AppEvents could crash because of missing session id.
Fixed bug in some cases where access token expiration date was the refresh date.
Although this is not necessarily a comprehensive solution, I have exhausted my debugging methods. I have removed the FBSDK's from my podfile, run pod update to remove them from the project, and reinstalled the version 4.10 FBSDK's in my frameworks folder. I will update this question after trying again when facebook releases an updated version of the FBSDK's.
I am working on an iPhone app in Objective-C (using Xcode 6.1.1, and Parse), and I just got this mysterious NSInternalInconsistencyException:
Caught "NSInternalInconsistencyException" with reason "Tried to save an object with a pointer to a new, unsaved object.":
So my question to the Stack Overflow community is:
How does someone read this stack trace to hunt down the actual source of the problem? I don't see any recognizable filenames, method calls or line numbers anywhere in this stack trace.
Or, if it's not a matter of simply reading the stack trace, and other techniques are involved, then what is the appropriate next step a developer should take to track down the source of this type of error?
Here is the full stack trace that outputs to my console:
2015-07-18 02:01:17.596 testapp[1276:60b] [Error]: Caught "NSInternalInconsistencyException" with reason "Tried to save an object with a pointer to a new, unsaved object.":
(
0 CoreFoundation 0x2f547f9b + 154
1 libobjc.A.dylib 0x39c94ccf objc_exception_throw + 38
2 CoreFoundation 0x2f547ec5 + 0
3 testapp 0x00205a29 -[PFObject(Private) resolveLocalId] + 384
4 testapp 0x00233d6d __32-[PFRESTCommand resolveLocalIds]_block_invoke + 24
5 testapp 0x00233783 +[PFRESTCommand forEachLocalIdIn:doBlock:] + 642
6 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62
7 CoreFoundation 0x2f484043 + 98
8 CoreFoundation 0x2f483f67 + 162
9 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382
10 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62
11 CoreFoundation 0x2f484043 + 98
12 CoreFoundation 0x2f483f67 + 162
13 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382
14 testapp 0x0023373f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 574
15 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62
16 CoreFoundation 0x2f484043 + 98
17 CoreFoundation 0x2f483f67 + 162
18 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382
19 testapp 0x00233ca3 -[PFRESTCommand forEachLocalId:] + 162
20 testapp 0x00233d3f -[PFRESTCommand resolveLocalIds] + 34
21 testapp 0x0023ee2f -[PFRESTCommandRunner _runCommandAsync:withCancellationToken:] + 110
22 testapp 0x0023e8c7 -[PFRESTCommandRunner runCommandAsync:withOptions:cancellationToken:] + 174
23 testapp 0x0023e7d7 -[PFRESTCommandRunner runCommandInBackground:inOperation:] + 42
24 testapp 0x00203667 __65+[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]_block_invoke_3 + 766
25 testapp 0x002854b3 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 + 214
26 libdispatch.dylib 0x3a17c833 + 10
27 libdispatch.dylib 0x3a183ad7 + 222
28 libdispatch.dylib 0x3a183d29 + 56
29 libsystem_pthread.dylib 0x3a2bebd3 _pthread_wqthread + 298
30 libsystem_pthread.dylib 0x3a2bea98 start_wqthread + 8
).
I appreciate any help and insights you can offer me.
This particular example doesn't give the developer much to go on. So, the answer to your question in this case is "Google it." Really, the best clue from the stack trace is the line:
[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]
The line above indicates a failed save using currentUser, combined with the error message "Tried to save an object with a pointer to a new, unsaved object." should be enough to point to a probable cause.
As it turns out, this error is not uncommon and is bewildering why Parse does not fix it. It is generally caused by when your app is using anonymous Parse users and it attempts to save an object prior to the user object having been saved. Since the user object has not been saved, it has no objectId and the save of the other object fails.
The solution is to check to see if the currentUser object has an objectId, and if not, save it first before trying to write to Parse.
// Prevent race condition for unsaved user
// Courtesy of: http://samwize.com/2014/07/15/pitfall-with-using-anonymous-user-in-parse/
if ([PFUser currentUser].objectId == nil) {
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
//do stuff later
}];
} else {
//do stuff now
}
NSInternalInconsistencyException is thrown when a code enters a state which is never supposed to happen. Usually it indicates a bug made by those who wrote it, though sometimes it is possible to cause such condition by mis-using the library (doing something against what the docs say, for instance).
In other words, it's a bug, but if you didn't write the code that throws it, it's probably not yours. From this particular stack trace, the problem has to be in Parse.
Report the bug to the original developers. A good library must never throw that, regardless if you are misusing it or not. Until they fix it, the best you can do is try to workaround it, by doing what you were trying to do in some different way. If you have the sources of that library, you could try to debug and fix the problem yourself.
When you see such kind of errors and Xcode kicks you to AppDelegate, try to put in Xcode 2 kind of breakpoints
Swift Error Breakpoint
Exception Breakpoint ...
You will find these options in the left panel on the top
Breakpoint Navigator -> + (this simbol you'll find at the bottom side) -> Swift Error Breakpoint or/and Exception Breakpoint
Hope this will help you next time
I'm developing a simple game and I am having trouble when a particular UIViewController (called SPSwipes.swift) is loaded. On the screen, there are three buttons: 5, 10, and 25. When one is picked, a variable is set in that scene and the player moves on to the main Game: GameScene.swift.
As far as I am aware, the variables are recognised in the GameScene, but there is a 'NSUnknownKeyException' error when I open up the SPSwipes view in the simulator. This is done by way of a segue. Here is the error in more detail:
2014-11-09 15:32:43.718 Swipe Racer[2644:1620056] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Swipe_Racer.SPSwipes 0x7fbf52d461b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key fiveSwipes.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010c021f35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010dd1bbb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010c021b79 -[NSException raise] + 9
3 Foundation 0x000000010c4397b3 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 259
4 CoreFoundation 0x000000010bf6be80 -[NSArray makeObjectsPerformSelector:] + 224
5 UIKit 0x000000010cd28c7d -[UINib instantiateWithOwner:options:] + 1506
6 UIKit 0x000000010cb87f98 -[UIViewController _loadViewFromNibNamed:bundle:] + 242
7 UIKit 0x000000010cb88588 -[UIViewController loadView] + 109
8 UIKit 0x000000010cb887f9 -[UIViewController loadViewIfRequired] + 75
9 UIKit 0x000000010cb88c8e -[UIViewController view] + 27
10 UIKit 0x000000010caa7ca9 -[UIWindow addRootViewControllerViewIfPossible] + 58
11 UIKit 0x000000010caa8041 -[UIWindow _setHidden:forced:] + 247
12 UIKit 0x000000010cab472c -[UIWindow makeKeyAndVisible] + 42
13 UIKit 0x000000010ca5f061 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2628
14 UIKit 0x000000010ca61d2c -[UIApplication _runWithMainScene:transitionContext:completion:] + 1350
15 UIKit 0x000000010ca60bf2 -[UIApplication workspaceDidEndTransaction:] + 179
16 FrontBoardServices 0x000000011383b2a3 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
17 CoreFoundation 0x000000010bf5753c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
18 CoreFoundation 0x000000010bf4d285 __CFRunLoopDoBlocks + 341
19 CoreFoundation 0x000000010bf4d045 __CFRunLoopRun + 2389
20 CoreFoundation 0x000000010bf4c486 CFRunLoopRunSpecific + 470
21 UIKit 0x000000010ca60669 -[UIApplication _run] + 413
22 UIKit 0x000000010ca63420 UIApplicationMain + 1282
23 Swipe Racer 0x000000010be380de top_level_code + 78
24 Swipe Racer 0x000000010be3811a main + 42
25 libdyld.dylib 0x000000010e507145 start + 1
26 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
As you can see, there is an issue with my first variable, fiveSwipes (and I would imagine that there would be errors with the two others). What does 'this class is not key value coding-compliant for the key fiveSwipes' mean? How should I go about fixing it?
My SPSwipes.swift file:
class SPSwipes: UIViewController {
var no_of_swipes = 0
#IBAction func fiveSwipes(sender: AnyObject) {
no_of_swipes = 5
//and so on
}
Thank you in advance,
Will
The problem was that the button was linked to numerous IBActions - three of which didn't exist. I right clicked on the button in the Interface Builder and removed the old and irrelevant links, fixing the problem.
For me it was because I had multiple views connected to non existent IBOutlets
To get an idea how to find out:
1- Click on the whole view controller
2- go to : Show the connector Inspector
There you will find all the not connected outlets
The exception is happening when attempting to load the view based on what you set up in Interface Builder. It's looking for fiveSwipes and not finding it. This can happen if you edited your code and forgot to update a connection in IB.
Have you made a connection in IB to something called fiveSwipes that isn't this function? Perhaps a variable called fiveSwipes? The way to fix the problem would be to find the element with the bad connection in IB and clear that connection.
This is an old question, the other answers din't help to fix my issue so would like to leave this answer here might help other people.
Our app contains multiple "Targets" now it happens that the ViewController is pointing to specific target and only on that target this ViewController works. When running on other target the app crashes with this error.
So, for those who has multiple "Targets" be sure to check the "Module" in the "Identity Inspector" and make sure that the "Inherit Module From Target" is checked.
Another possible reason for this is if you are initializing your Controller using nibName:bundle: and you pass it the wrong nib name - some other nib that is not for this controller. The end result is the same, you'll likely have a bunch of #IBOutlets that do not match up between the Controller and the nib.
While my one of my NSManagedObjectContext's is running its performBlock the user has chosen to sign out of their account (which will reset all contexts and delete the persistent stores). This reset code is obviously being run at a similar time as the performBlock, and so the app crashes with the exception:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'
The exact location it crashes seems to be when the one context saves in its performBlock, which will then send out the did save notification, and merge into the other context. Here's the stack trace:
0 CoreFoundation 0x03b96df6 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x03820a97 objc_exception_throw + 44
2 CoreData 0x034f7791 _PFRetainedObjectIDCore + 1169
3 CoreData 0x034f72f0 -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:] + 32
4 CoreData 0x034db0f3 -[NSManagedObjectContext objectWithID:] + 595
5 CoreData 0x0352e14e _faultBatchAtIndex + 1102
6 CoreData 0x0352ed02 -[_PFBatchFaultingArray objectAtIndex:] + 50
7 CoreData 0x035dd010 +[NSFetchedResultsController(PrivateMethods) _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 144
8 CoreData 0x035d7ba2 -[NSFetchedResultsController(PrivateMethods) _postprocessInsertedObjects:] + 738
9 CoreData 0x035da3dd __77-[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:]_block_invoke + 2285
10 CoreData 0x034e7454 developerSubmittedBlockToNSManagedObjectContextPerform + 196
11 CoreData 0x034e7337 -[NSManagedObjectContext performBlockAndWait:] + 231
12 CoreData 0x035d9acf -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 127
13 Foundation 0x00eff929 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
14 CoreFoundation 0x03b61974 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
15 CoreFoundation 0x03a4f61b _CFXNotificationPost + 3051
16 Foundation 0x00eeef26 -[NSNotificationCenter postNotificationName:object:userInfo:] + 98
17 CoreData 0x034c84d3 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 83
18 CoreData 0x034d9cbe -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 3934
19 CoreData 0x034d8d40 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 496
20 App 0x00319707 __57-[ContextManager contextDidSavePrivateQueueContext:]_block_invoke + 103
This is iOS 8 only - iOS 7 works fine. What I can't figure out is if this is a bug with iOS 8 that I'm feeling the effects of, or if Apple have introduced "new features" into Core Data that has broken our reset flow. Can anyone shed some light on this?
I fixed the bug by adding a category on NSManagedObjectContext and adding a flag using objc_setAssociatedObject magic. The flag is for whether the context is safe to perform any performBlock that comes its way. For that, I added another method on the category called safePerformBlock which looks at the flag. If it's false, I return out immediately, rather than processing the block that was passed in.
When I delete the persistent store on the contexts, the flag is set to unsafe. When the user then logs back in and the persistent store is recreated, the flag is set to safe.
Essentially, I'm treating this flag on the context as a cancellation token on the performBlocks. Why there is nothing in the API for this I don't know. Under the circumstances, this is the best fix I could find.
Core Data is not thread safe. An NSManagedObjectContext must only be used in the thread where it has been created. And it mustn't be used once the persistent store is gone. It's quite possible that timing is slightly different in iOS 8, but since you can't rely on timing, it's likely that it was always a bug in your code.
You can put the reset operation in the same thread than your performBlock and put the queue in "no conccurency" mode. So the reset will occure only when the performBlock is finished.
So whats happening here is the app has just received the NSPersistentStoreDidImportUbiquitousContentChangesNotification, and I have just called
- (void)storesDidUpdate:(NSNotification*)note {
FLOG(#"storesDidUpdate ");
[_managedObjectContext mergeChangesFromContextDidSaveNotification:note];
// Refresh user Interface
[[NSNotificationCenter defaultCenter] postNotificationName:#"iProjectCoreDataUpdated"
object:self];
[self updateDetails];
}
And now the app is trying to update a UITextView with a fresh copy of text by simply doing the following:
self.detailText.attributedText = [self.detailItem valueForKey:#"scope"];
Where detailItem is a NSManagedObject retrieved prior to receiving the update from iCloud.
Not sure why the textContainer is complaining or what its complaining about, and also not sure why importing logs is happening because I have already received a notification that its done!
Strangely other UITableViews update correctly if I just call reloadData.
Any ideas on whether I am doing something wrong here? Note that if I don't try and update the textView it works fine and if I close the view and go back to it then I get the correct data.
Also when I restart the app all the data is there, no corruptions or anything, in fact the app seems remarkably robust in most respects when it comes to the Core Data store, despite things blowing up on either side of iCloud!
Oh and the reloadFetchedResults is a bit misleading because I don't seem to need to do that, so the method name is a hangover from the past, all I am doing is refreshing values in the UI in this call.
2013-10-09 07:25:53.783 MyApp[4509:510b] OpeningViewController.reloadFetchedResults: called
2013-10-09 07:25:53.786 MyApp[4509:510b] InfoDetailViewController.reloadFetchedResults: called in InfoDetailViewController
2013-10-09 07:25:53.788 MyApp[4509:510b] * Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView *, NSTextContainer *, NSUInteger)(), /SourceCache/UIFoundation/UIFoundation-258/UIFoundation/TextSystem/NSLayoutManager_Private.m:1510
2013-10-09 07:25:53.793 MyApp[4509:510b] -_PFUbiquityRecordImportOperation main: CoreData: Ubiquity: Error importing transaction log:
transactionLogLocation: : /var/mobile/Library/Mobile Documents/HHHHHHNNNN~com~mycompany~MyApp/CoreData/New Document/duncangroenewald~simAABC628E-9D5E-58F7-9B8D-0BC724C6D0C8/New Document/W8MckEJ0x2d~HZZIeUH2be6hs41TEOONzKIrCuLcuP4=/6C953E7C-B2AF-47F7-B828-DD062B96415D.1.cdt
transactionNumber: 5
, exception: Only run on the main thread!
User Info: (null)
2013-10-09 07:25:53.803 MyApp[4509:510b] -_PFUbiquityRecordsImporter operation:failedWithError:: CoreData: Ubiquity: Import operation encountered an error: Error Domain=NSCocoaErrorDomain Code=134060 "The operation couldn’t be completed. (Cocoa error 134060.)" UserInfo=0x16d882c0 {exception=Only run on the main thread!}
userInfo: {
exception = "Only run on the main thread!";
}. While trying to import the log file at the URL:
transactionLogLocation: : /var/mobile/Library/Mobile Documents/HHHHHHNNNN~com~mycompany~MyApp/CoreData/New Document/duncangroenewald~simAABC628E-9D5E-58F7-9B8D-0BC724C6D0C8/New Document/W8MckEJ0x2d~HZZIeUH2be6hs41TEOONzKIrCuLcuP4=/6C953E7C-B2AF-47F7-B828-DD062B96415D.1.cdt
transactionNumber: 5
2013-10-09 07:25:53.809 MyApp[4509:510b] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'
*** First throw call stack:
(0x2ff23f53 0x3a6996af 0x2ff23e2d 0x308cb1df 0x3796643d 0x37966185 0x3798f7bb 0x379926f7 0x37992759 0x379b378b 0x379b331f 0x379b2f0d 0x3273b05d 0x129717 0x2fee6121 0x2fe5a317 0x3083edcd 0x308436ab 0x118263 0x2fee6121 0x2fe5a317 0x2fd8c69f 0x2fd8cc93 0x2fd813dd 0x3085197b 0x308f5b35 0x3ab83297 0x3ab8309b 0x3ab83d15 0x3ab83f8d 0x3acbedbf 0x3acbec84)
libc++abi.dylib: terminating with uncaught exception of type NSException
EDIT:
I have posted some sample Core Data/iCloud apps for iOS and OSX here - they include background threads for loading/deleting data as well as iCloud sync. Hopefully address the issue described here. http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/
OK here is what seems to fix it - I guess I never realised that receiving a notification would run on another thread. Is that normal behaviour, are all Core Data notifications you receive called on a background thread ? If so do you always have to make sure anything you do is then running on the correct thread ?
- (void)storesDidUpdate:(NSNotification*)note {
FLOG(#"storesDidUpdate ");
[_managedObjectContext mergeChangesFromContextDidSaveNotification:note];
[[NSOperationQueue mainQueue] addOperationWithBlock:^ {
//Your code goes in here
LOG(#" Main Thread Code");
// Refresh user Interface
[[NSNotificationCenter defaultCenter] postNotificationName:#"CoreDataUpdatedNotification"
object:self];
}];
}
EDIT:
I have finally gotten around to documenting how I got Core Data and iCloud to work pretty reliably, including handling moving to and from iCloud in response to the use changing their Use iCloud preference settings. I was unable to find a good explanation with working code when I was trying to figure out how to get it working so I hope this proves useful to others. Included is a video of the app working so you can see how it behaves to help you figure out if it's what you are wanting to achieve.
http://ossh.com.au/design-and-technology/software-development/
I got the same problem. It was exactly the issue #John Rogers explained.
I created UITextViews and in the background I called a URL to get some data which should be inserted into my generated UITextViews. But the Problem was the method sendAsynchronousRequest which will be called in background and cause the crash in my case.
I could solve the problem by performing the specific selector on main thread when receiving my data. So maybe you can insert you're method call into another method and call it this way:
[self performSelectorOnMainThread:#selector(received:)
withObject:data
waitUntilDone:YES];
This way you get back to the main thread again.
Reading all the answers+comments (and your fix) - I think it should be noted you MUST update any UI control from the main thread only.
I assume the [self updateDetails]; calls the self.detailText.attributedText = [self.detailItem valueForKey:#"scope"]; code?...which is the actual code that updates the UI?
Assume that, then You could execute the call to -updateDetails using -performSelectorOnMainThread: or in the -updateDetails check that you are executing on the main thread ([NSThread isMainThread]) and wrap the UI update code there so the caller doesn't care what thread they call -updateDetails from.
Yes, I get that but I don't do anything on any threads so something else must be. I am updating a UITextView and I guess its possible something in that is causing a failure. I am not clear on why this would have anything to do with the ubiquityImporter - perhaps someone who can interpret this stuff below can point me in the right direction. Am I somehow running something on the wrong thread ?
First throw call stack:
(
0 CoreFoundation 0x027c55e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x019238b6 objc_exception_throw + 44
2 CoreFoundation 0x027c5448 +[NSException raise:format:arguments:] + 136
3 Foundation 0x01062960 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 101
4 UIFoundation 0x01b33131 -[NSLayoutManager(NSPrivate) _resizeTextViewForTextContainer:] + 419
5 UIFoundation 0x01b32e16 -[NSLayoutManager(NSPrivate) _recalculateUsageForTextContainerAtIndex:] + 2083
6 UIFoundation 0x01b67675 _enableTextViewResizing + 234
7 UIFoundation 0x01b6b275 -[NSLayoutManager textStorage:edited:range:changeInLength:invalidatedRange:] + 688
8 UIFoundation 0x01b6b2fa -[NSLayoutManager processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:] + 82
9 UIFoundation 0x01b93d35 -[NSTextStorage _notifyEdited:range:changeInLength:invalidatedRange:] + 153
10 UIFoundation 0x01b93870 -[NSTextStorage processEditing] + 462
11 UIFoundation 0x01b93419 -[NSTextStorage endEditing] + 80
12 UIFoundation 0x01b934a3 -[NSTextStorage coordinateEditing:] + 66
13 UIKit 0x007f4f48 -[UITextView setAttributedText:] + 254
14 MyApp 0x00027d7a -[WBSDetailViewController displayItem] + 3146
15 MyApp 0x00028c6c -[WBSDetailViewController refreshUI:] + 156
16 Foundation 0x01088e39 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
17 CoreFoundation 0x02821524 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
18 CoreFoundation 0x0277907b _CFXNotificationPost + 2859
19 Foundation 0x00fc2b91 -[NSNotificationCenter postNotificationName:object:userInfo:] + 98
20 Foundation 0x00fd206a -[NSNotificationCenter postNotificationName:object:] + 55
21 MyApp 0x00031095 -[BaseAppDelegate storesDidUpdate:] + 293
22 Foundation 0x01088e39 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
23 CoreFoundation 0x02821524 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
24 CoreFoundation 0x0277907b _CFXNotificationPost + 2859
25 Foundation 0x00fddd7b -[NSNotificationCenter postNotification:] + 121
26 CoreData 0x0173c5f4 -[_PFUbiquityRecordsImporter postImportNotificationForStoreName:andLocalPeerID:withUserInfo:] + 1892
27 CoreData 0x0173cbc2 -[_PFUbiquityRecordsImporter operationDidFinish:] + 706
28 CoreData 0x0172e8ce -[_PFUbiquityRecordImportOperation main] + 15102
29 Foundation 0x0108aa69 -[__NSOperationInternal _start:] + 671
30 Foundation 0x01007798 -[NSOperation start] + 83
31 Foundation 0x0108cd34 __NSOQSchedule_f + 62
32 libdispatch.dylib 0x05b794b0 _dispatch_client_callout + 14
33 libdispatch.dylib 0x05b67088 _dispatch_queue_drain + 450
34 libdispatch.dylib 0x05b66e85 _dispatch_queue_invoke + 126
35 libdispatch.dylib 0x05b67e25 _dispatch_root_queue_drain + 83
36 libdispatch.dylib 0x05b6813d _dispatch_worker_thread2 + 39
37 libsystem_pthread.dylib 0x05f05dab _pthread_wqthread + 336
38 libsystem_pthread.dylib 0x05f09cce start_wqthread + 30
)
libc++abi.dylib: terminating with uncaught exception of type NSException