Getting a "This application is modifying the autolayout engine from a background thread" error? - swift

Been encountering this error a lot in my OS X using swift:
"This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release."
I have a my NSWindow and I'm swapping in views to the contentView of the window. I get the error when I try and do a NSApp.beginSheet on the window, or when I add a subview to the window. Tried disabling autoresize stuff, and I don't have anything using auto layout. Any thoughts?
Sometimes it's fine and nothing happens, other times it totally breaks my UI and nothing loads

It needs to be placed inside a different thread that allows the UI to update as soon as execution of thread function completes:
Modern Swift:
DispatchQueue.main.async {
// Update UI
}
Older versions of Swift, pre Swift 3.
dispatch_async(dispatch_get_main_queue(){
// code here
})
Objective-C:
dispatch_async(dispatch_get_main_queue(), ^{
// code here
});

You get similar error message while debugging with print statements without using 'dispatch_async'
So when you get that error message, its time to use
Swift 4
DispatchQueue.main.async { //code }
Swift 3
DispatchQueue.main.async(){ //code }
Earlier Swift versions
dispatch_async(dispatch_get_main_queue()){ //code }

The "this application is modifying the autolayout engine from a background thread" error is logged in the console long after the actual problem occured, so debugging this can be hard without using a breakpoint.
I used #markussvensson's answer to detect my problem and found it using this Symbolic Breakpoint (Debug > Breakpoints > Create Symbolic Breakpoint):
Symbols: [UIView layoutIfNeeded] or [UIView updateConstraintsIfNeeded]
Condition: !(BOOL)[NSThread isMainThread]
Build and run the app on the emulator and replicate the steps that lead to the error message being thrown (the app will be slower than usual!). Xcode will then stop the app and mark the line of code (e.g. the call of a func) that's accessing the UI from a background thread.

When you try to update a text field value or adding a subview inside a background thread, you can get this problem. For that reason, you should put this kind of code in the main thread.
You need to wrap methods that call UI updates with dispatch_asynch to get the main queue. For example:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.friendLabel.text = "You are following \(friendCount) accounts"
})
EDITED - SWIFT 3:
Now, we can do that following the next code:
// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
// Do long running task here
// Bounce back to the main thread to update the UI
DispatchQueue.main.async {
self.friendLabel.text = "You are following \(friendCount) accounts"
}
}

For me, this error message originated from a banner from Admob SDK.
I was able to track the origin to "WebThread" by setting a conditional breakpoint.
Then I was able to get rid of the issue by encapsulating the Banner creation with:
dispatch_async(dispatch_get_main_queue(), ^{
_bannerForTableFooter = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait];
...
}
I don't know why this helped as I cannot see how this code was called from a non-main-thread.
Hope it can help anyone.

I had this problem since updating to the iOS 9 SDK when I was calling a block that did UI updates within an NSURLConnection async request completion handler. Putting the block call in a dispatch_async using dispatch_main_queue solved the issue.
It worked fine in iOS 8.

Had the same problem because I was using performSelectorInBackground.

Main problem with "This application is modifying the autolayout engine from a background thread" is that it seem to be logged a long time after the actual problem occurs, this can make it very hard to troubleshoot.
I managed to solve the issue by creating three symbolic breakpoints.
Debug > Breakpoints > Create Symbolic Breakpoint...
Breakpoint 1:
Symbol: -[UIView setNeedsLayout]
Condition: !(BOOL)[NSThread isMainThread]
Breakpoint 2:
Symbol: -[UIView layoutIfNeeded]
Condition: !(BOOL)[NSThread isMainThread]
Breakpoint 3:
Symbol: -[UIView updateConstraintsIfNeeded]
Condition: !(BOOL)[NSThread isMainThread]
With these breakpoints, you can easily get a break on the actual line where you incorrectly call UI methods on non-main thread.

You must not change the UI offside the main thread! UIKit is not thread safe, so that above problem and also some other weird problems will arise if you do that. The app can even crash.
So, to do the UIKit operations, you need to define block and let it be executed on the main queue: such as,
NSOperationQueue.mainQueue().addOperationWithBlock {
}

Obviously you are doing some UI update on back ground thread. Cant predict exactly where, without seeing your code.
These are some situations it might happen:-
you might be doing something on background thread and not using. Being in the same function this code is easier to spot.
DispatchQueue.main.async { // do UI update here }
calling a func doing web request call on background thread and its completion handler calling other func doing ui update.
to solve this try checking code where you have updated the UI after webrequest call.
// Do something on background thread
DispatchQueue.global(qos: .userInitiated).async {
// update UI on main thread
DispatchQueue.main.async {
// Updating whole table view
self.myTableview.reloadData()
}
}

I had this issue while reloading data in UITableView. Simply dispatching reload as follows fixed the issue for me.
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})

I had the same problem. Turns out I was using UIAlerts that needed the main queue. But, they've been deprecated.
When I changed the UIAlerts to the UIAlertController, I no longer had the problem and did not have to use any dispatch_async code. The lesson - pay attention to warnings. They help even when you don't expect it.

You already have the correct code answer from #Mark but, just to share my findings:
The issue is that you are requesting a change in the view and assuming that it will happen instantly. In reality, the loading of a view depends on the available resources. If everything loads quickly enough and there are no delays then you don't notice anything. In scenarios, where there is any delay due to the process thread being busy etc, the application runs into a situation where it is supposed to display something even though its not ready yet. Hence, it is advisable to dispatch these requests in a asynchronous queues so, they get executed based on the load.

I had this issue when I was using TouchID if that helps anyone else, wrap your success logic which likely does something with the UI in the main queue.

It could be something as simple as setting a text field / label value or adding a subview inside a background thread, which may cause a field's layout to change. Make sure anything you do with the interface only happens in the main thread.
Check this link: https://forums.developer.apple.com/thread/7399

I had the same issue when trying to update error message in UILabel in the same ViewController (it takes a little while to update data when trying to do that with normal coding). I used DispatchQueue in Swift 3 Xcode 8 and it works.

If you want to hunt this error, use the main thread checker pause on issues checkbox.
Fixing it is easy most of the times, dispatching the problematic line in the main queue.

For me the issue was the following.
Make sure performSegueWithIdentifier: is performed on the main thread:
dispatch_async (dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"ViewController" sender:nil];
});

Swift 4,
Suppose, if you are calling some method using operation queue
operationQueue.addOperation({
self.searchFavourites()
})
And suppose function searchFavourites is like,
func searchFavourites() {
DispatchQueue.main.async {
//Your code
}
}
if you call, all code inside the method "searchFavourites" on the main thread, it will still give an error if you are updating some UI in it.
This application is modifying the autolayout engine from a background
thread after the engine was accessed from the main thread.
So use solution,
operationQueue.addOperation({
DispatchQueue.main.async {
self.searchFavourites()
}
})
For this kind of scenario.

Here check out this line from the logs
$S12AppName18ViewControllerC11Func()ySS_S2StF + 4420
you can check that which function calling from the either background thread or where you are calling api method you need to call your function from the main thread like this.
DispatchQueue.main.async { func()}
func() is that function you want to call in the result of api call
success or else.
Logs Here
This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.
Stack:(
0 Foundation 0x00000001c570ce50 <redacted> + 96
1 Foundation 0x00000001c5501868 <redacted> + 32
2 Foundation 0x00000001c5544370 <redacted> + 540
3 Foundation 0x00000001c5543840 <redacted> + 396
4 Foundation 0x00000001c554358c <redacted> + 272
5 Foundation 0x00000001c5542e10 <redacted> + 264
6 UIKitCore 0x00000001f20d62e4 <redacted> + 488
7 UIKitCore 0x00000001f20d67b0 <redacted> + 36
8 UIKitCore 0x00000001f20d6eb0 <redacted> + 84
9 Foundation 0x00000001c571d124 <redacted> + 76
10 Foundation 0x00000001c54ff30c <redacted> + 108
11 Foundation 0x00000001c54fe304 <redacted> + 328
12 UIKitCore 0x00000001f151dc0c <redacted> + 156
13 UIKitCore 0x00000001f151e0c0 <redacted> + 152
14 UIKitCore 0x00000001f1514834 <redacted> + 868
15 UIKitCore 0x00000001f1518760 <redacted> + 104
16 UIKitCore 0x00000001f1543370 <redacted> + 1772
17 UIKitCore 0x00000001f1546598 <redacted> + 120
18 UIKitCore 0x00000001f14fc850 <redacted> + 1452
19 UIKitCore 0x00000001f168f318 <redacted> + 196
20 UIKitCore 0x00000001f168d330 <redacted> + 144
21 AppName 0x0000000100b8ed00 $S12AppName18ViewControllerC11Func()ySS_S2StF + 4420
22 AppName 0x0000000100b8d9f4 $S12CcfU0_y10Foundation4DataVSg_So13NSURLResponseCSgs5Error_pSgtcfU_ + 2384
23 App NAme 0x0000000100a98f3c $S10Foundation4DataVSgSo13NSURLResponseCSgs5Error_pSgIegggg_So6NSDataCSgAGSo7NSErrorCSgIeyByyy_TR + 316
24 CFNetwork 0x00000001c513aa00 <redacted> + 32
25 CFNetwork 0x00000001c514f1a0 <redacted> + 176
26 Foundation 0x00000001c55ed8bc <redacted> + 16
27 Foundation 0x00000001c54f5ab8 <redacted> + 72
28 Foundation 0x00000001c54f4f8c <redacted> + 740
29 Foundation 0x00000001c55ef790 <redacted> + 272
30 libdispatch.dylib 0x000000010286f824 _dispatch_call_block_and_release + 24
31 libdispatch.dylib 0x0000000102870dc8 _dispatch_client_callout + 16
32 libdispatch.dylib 0x00000001028741c4 _dispatch_continuation_pop + 528
33 libdispatch.dylib 0x0000000102873604 _dispatch_async_redirect_invoke + 632
34 libdispatch.dylib 0x00000001028821dc _dispatch_root_queue_drain + 376
35 libdispatch.dylib 0x0000000102882bc8 _dispatch_worker_thread2 + 156
36 libsystem_pthread.dylib 0x00000001c477917c _pthread_wqthread + 472
37 libsystem_pthread.dylib 0x00000001c477bcec start_wqthread + 4
)

I also encountered this problem, seeing a ton of these messages and stack traces being printed in the output, when I resized the window to a smaller size than its initial value. Spending a long time figuring out the problem, I thought I'd share the rather simple solution. I had once enabled Can Draw Concurrently on an NSTextView through IB. That tells AppKit that it can call the view's draw(_:) method from another thread. After disabling it, I no longer got any error messages. I didn't experience any problems before updating to macOS 10.14 Beta, but at the same time, I also started modifying the code to perform work with the text view.

Related

Issues with RxSwift and AVKit

I am building what I hope to be a simple macOS application that will locally stored videos selected from a popUP button.
The application is two windows 1) the AVPlayerView and 2) a simple control panel that allows the user to select and play the flagged videos on the other window.
All of this works very well in XCode. When the saved URL is selected, it is made into an AVAsset which is it turn made into an AVPlayerItem. The next process I have tried successfully(in Xcode) two ways: create a 1) PublishSubect or a 2) PublishSubject. In the view controller for the AVPlayerview window, I subscribe to the control panel's publish subject and either update the AVplayerView's player with the AVPlayerItem
destinationVC.videoSubject.subscribe(
onNext: { [weak self] item in
self?.player.replaceCurrentItem(with: item)
}
).disposed(by: bag)
or I inject the player in a similar fashion. Either of these options works flawlessly when I run the application in XCode. The issue that I have is when I archive it to run the app on my computer, when I select the video to be played, the app crashes.
I isolated this task to a background thread with the hopes of better sniffing out an error but the resulting crash report does not make much sense to me:
Thread 2 Crashed:: Dispatch queue: Background
0 [myinfo].STSVideoPlayer 0x000000010e655476 closure #1 in closure #1 in VideoViewController.prepare(for:sender:) + 134 (VideoViewController.swift:40)
1 [myinfo].STSVideoPlayer 0x000000010e655499 thunk for #escaping #callee_guaranteed () -> () + 25
2 libdispatch.dylib 0x00007fff6e6d56c4 _dispatch_call_block_and_release + 12
3 libdispatch.dylib 0x00007fff6e6d6658 _dispatch_client_callout + 8
4 libdispatch.dylib 0x00007fff6e6dbc44 _dispatch_lane_serial_drain + 597
5 libdispatch.dylib 0x00007fff6e6dc5d6 _dispatch_lane_invoke + 363
6 libdispatch.dylib 0x00007fff6e6e5c09 _dispatch_workloop_worker_thread + 596
7 libsystem_pthread.dylib 0x00007fff6e930a3d _pthread_wqthread + 290
8 libsystem_pthread.dylib 0x00007fff6e92fb77 start_wqthread + 15
I am, obviously, over my head here. Any insight that you may have would be much appreciated!
I found a more detailed crash report, and it turns out that I was force-unwrapping some nils. I am not sure how that got through in XCode, but now everything is working swimmingly.

How to know where crash for postNotificationName:object:userInfo

Is there some method to know crash reason in Xcode 4.6?
The crash stack is :
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0xd9f2c061
Crashed Thread: 0
Thread 0 Crashed:
0 libobjc.A.dylib 0x3a74f5aa objc_msgSend + 10
1 Foundation 0x33157599 -[NSNotificationCenter postNotificationName:object:userInfo:] + 73
2 UIKit 0x347830cd -[UIApplication _handleApplicationSuspend:eventInfo:] + 733
3 UIKit 0x346f91e7 -[UIApplication handleEvent:withNewEvent:] + 2459
4 UIKit 0x346f86cd -[UIApplication sendEvent:] + 73
5 UIKit 0x346f811b _UIApplicationHandleEvent + 6155
6 GraphicsServices 0x363ee5a3 _PurpleEventCallback + 591
When you add an observer to the notification centre you have to remove it when the object is being dealloced/destroyed. Otherwise Notification Centre would send the notification to the destroyed object resulting in crash.
1 - check if you properly handle the removing from notification centre. (typically you do this on dealloc method)
2 - If step 1 doesn't help, profile your application with instruments & zombies. it would point out which object is destroyed but still receiving messages.
Almost certainly an object registered with the notification centre to receive that notification and then failed to deregister before deallocation.
The easiest way to catch the problem would be to enable NSZombies — see e.g. this tutorial. If you run with zombies enabled then objects that should have been deallocated remain in memory but raise an exception if anyone attempts to call them. So you can figure out exactly what type of object the notification centre is attempting to call and therefore which object is probably making the mistake.
Given the name of the origin of the notification — _handleApplicationSuspend:eventInfo: — you might also want to have a quick check of anyone registering for UIApplicationWillResignActiveNotification, UIApplicationDidEnterBackgroundNotification and the others related to application suspension.
Might be an useful information that it appears to crash only on ios7, as my project ran perfectly on ios6.
Maybe userInfo is has nil value....
[[NSNotificationCenter defaultCenter] postNotificationName:SayLoggedInNotification object:wSelf userInfo:#{#"from": wSelf.from}];
# wSelf.form is nil

Why do i get exc bad access in cases when object is not nil?

I have an app that receives remote notifications. My view controller that is shown after push has a tableview. App crashes very randomly (1 in 20 tries) at line setting frame:
if (!myTableView) {
NSLog(#"self.myTableView is nil");
}
myTableView.frame=CGRectMake(0, 70, 320, 376);
This only happens when i open the app, then open some other apps and then receive the push notification. I guess it has something to do with memory. I use ARC (ios 5). The strange thing is that nslog is not displayed, so tableview is not nil.
Crash log:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x522d580c
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x352b1f7e objc_msgSend + 22
1 Foundation 0x37dc174c NSKVOPendingNotificationCreate + 216
2 Foundation 0x37dc1652 NSKeyValuePushPendingNotificationPerThread + 62
3 Foundation 0x37db3744 NSKeyValueWillChange + 408
4 Foundation 0x37d8a848 -[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:] + 176
5 Foundation 0x37e0ca14 _NSSetPointValueAndNotify + 76
6 UIKit 0x312af25a -[UIScrollView(Static) _adjustContentOffsetIfNecessary] + 1890
7 UIKit 0x312cca54 -[UIScrollView setFrame:] + 548
8 UIKit 0x312cc802 -[UITableView setFrame:] + 182
9 POViO 0x000913cc -[FeedVC viewWillAppear:] (FeedVC.m:303)
Dealloc is not called because it is not logged:
- (void)dealloc {
NSLog(#"dealloc");
}
You are having memory issues. Your tableView is reaching a retain count of zero; so although a pointer to the tableView still exists, the system has trashed the object at that actual address, hence the EXC_BAD_ACCESS.
It's possible that your UI that showed the tableView is hidden and therefore unloaded, but you've left some logic that assumes the table view still exists when it doesn't.
It's hard to debug what's going on without seeing more of the project. The best thing for you to do is have a careful look at the design of your application and UI flow. What would be causing the UI to be be released? How are you entering the code that assumes that part of the UI is still there?
N.B. Sending messages to a nil reference would not generate any errors; this is by language design.
I found the solution here:
Using ARC and UITableViewController is throwing Observation info was leaked, and may even become mistakenly attached to some other object
Seems pull to refresh (subview to tableview) was causing problems.
Do not change frame directly,do something like this.
CGRect frame = self. myTableView.frame;
frame.x =something;
frame.y=something;
myTableView.frame=frame;
and let me know.

iPhone Crash stack trace VS Crash report

Just spent some time... on a crash, without understanding it. That's a classic:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000010
Which leads me to a memory issue, addressing the invalid adress 0x10
What bothers me is that I have crash report and stack trace, which differ:
The crash report, sent by user (symbolicated successfully, that happens) :
Thread 0 Crashed:
0 libobjc.A.dylib 0x000027d8 objc_msgSend + 16
1 UIKit 0x0005e9d2 -[UIViewAnimationState animationDidStop:finished:] + 54
2 QuartzCore 0x0002d8c2 run_animation_callbacks(double, void*) + 286
3 QuartzCore 0x0002d764 CA::timer_callback(__CFRunLoopTimer*, void*) + 116
4 CoreFoundation 0x000567f4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 8
5 CoreFoundation 0x000562a6 __CFRunLoopDoTimer + 854
6 CoreFoundation 0x0002779e __CFRunLoopRun + 1082
7 CoreFoundation 0x00027270 CFRunLoopRunSpecific + 224
8 CoreFoundation 0x00027178 CFRunLoopRunInMode + 52
9 GraphicsServices 0x000045ec GSEventRunModal + 108
10 GraphicsServices 0x00004698 GSEventRun + 56
11 UIKit 0x0000411c -[UIApplication _run] + 396
12 UIKit 0x00002128 UIApplicationMain + 664
13 MyApp 0x00003158 main (main.m:13)
14 MyApp 0x00003120 0x1000 + 8480
The crash stack trace (catched live by an Exception Handler)
0 MyApp 0x000d79c3 0x0 + 883139
1 MyApp 0x000d790b 0x0 + 882955
2 libSystem.B.dylib 0x302765d3 _sigtramp + 42
3 UIKit 0x31eab9d9 -[UIViewAnimationState animationDidStop:finished:] + 60
4 QuartzCore 0x33a178c9 _ZL23run_animation_callbacksdPv + 292
5 QuartzCore 0x33a1776b _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv + 122
6 CoreFoundation 0x3084e7fb __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
7 CoreFoundation 0x3084e2ad __CFRunLoopDoTimer + 860
8 CoreFoundation 0x3081f7a5 __CFRunLoopRun + 1088
9 CoreFoundation 0x3081f277 CFRunLoopRunSpecific + 230
10 CoreFoundation 0x3081f17f CFRunLoopRunInMode + 58
11 GraphicsServices 0x31e445f3 GSEventRunModal + 114
12 GraphicsServices 0x31e4469f GSEventRun + 62
13 UIKit 0x31e51123 -[UIApplication _run] + 402
14 UIKit 0x31e4f12f UIApplicationMain + 670
15 MyApp 0x0000315f 0x0 + 12639
16 MyApp 0x00003128 0x0 + 12584
Both differ, and the stack trace points to the crash in my code, but at addresses I can neither symbolicate nor identify. I think the crash report indicates that a message was sent to a released instance... Probably related to the use of :
+ (void)setAnimationDelegate:(id)delegate
+ (void)setAnimationDidStopSelector:(SEL)selector
So here (finally!) are my questions:
What explains the differences between logs? (libobjc.A vs libSystem.B ??)
Does the SIGBUS comes from my code or from UIKit?
How can I decipher the stack trace upper addresses (0x000d79??, which atos doesn't resolve)
Is that what I think, an issue related to an animation failing to end? similar to this > How to unset delegate on UIView setAnimationDelegate: call?
AFAIK, setAnimationDelegate is supposed to retain delegate... Someone to confirm?
EDIT: I can't use NSZombiesEnabled, this is a crash report from a published app, a crash that I didn't manage to reproduce on development environment. I just have these logs to diagnose.
Whenever I see objc_msgSend at the top, my trust of the remaining stack is low, as the error that gives this tends to do bad things to the stack.
GuardMalloc is good for this since the attempt to do anything with deallocated space will crash the app immediately in the debugger. The stack will be intact. (This makes the app very slow, but it is a very powerful tool.)
The two stacks are the same up to the UIViewAnimationState method call. The version that came from your exception handler is showing C++ mangled names instead of the regular names shown in the crash log.
(As I understand it) _sigtramp is the system's method of calling your signal handler and is short for Signal Trampoline. The stack entries beyond that are probably your signal-handler code.
Answering my own question, weeks laters, since I had no relevant answers, most are guesses, I wished I had more precise answers, but I guess my question was unclear :
Difference is coming from the origin of the log, a sighandler vs CrashReporter service, which are happening at different times, then the stack traces are slightly different.
SIGBUS comes from UIKit, but chances are big that's on a callback initiated from my code that ends on a released object. These kind of stack traces are a pain to debug when you can't reproduce the issue, since it basically tells you "I'm crashing somewhere because of an animation", which one, where... I still didn't figured precisely. Could be anywhere, and also could be an Apple iOS bug.
The first addresses in the stack are just a dead-end where any SIGBUS stack-trace ends when a released object is called. They differs across compilations (versions), but are the same on any device, That's why they can't be symbolicated. (I would love to have a technical explanation of this, instead of my guess)
& 5. I guess I solved this bug byt being more "agressive" on canceling animations in certain cases like on deallocation of some Views...
Hope that helps someone.
You should try NSZombie, to get information about what object you've released. This is a very useful tool when you get EXC_BAD_ACCESS.
To activate NSZombie do the following:
Get info of the executable.
Go to the arguments tab.
In the "Variables to be set in the environment:" section add:
Name: NSZombieEnabled
Value: YES
Then run your app as usual and when it crashes it should tell you which deallocated object received the message.
1. I'm not 100% sure but I think the discrepancy is due to how the application is being run. In the second log it looks like you're running the application via XCode in debug mode, a sigtramp signal has been sent to indicate a EXC_BAD_ACCESS error.
2. Your code - the error may come from the UIKit library but it's a result of a problem with your usage.
3. This is where NSZombieEnabled will make your life a lot easier! If you run your application with the NSZombieEnabled flag set XCode will keep 'zombie' objects in place of deallocated objects. When a zombie object is sent a message the process will trap the error and let you know exactly what object was sent the message.
If you're using XCode 4 enable NSZombieEnabled using the following instructions...
How do I set up NSZombieEnabled in Xcode 4?
For older versions follow these instructions...
http://www.cocoadev.com/index.pl?NSZombieEnabled
4. It does indeed appear that your animation delegate has been deallocated prior to the animation completing.

Core Data background thread NSManagedObjectContext merging error

I'm writing an Ipad app that shows articles and downloads new articles in a separate NSOperation on a queue and inserts them into core data. Currently I have a separate context for the operation, created in the main method of the operation and using the same coordinator as the main context. I use the same pattern that has been suggested alot of listening in that operation for NSManagedObjectContextDidSaveNotification and then calling mergeChangesFromContextDidSaveNotification on the main thread context. The problem is I'm getting this error:
2011-01-27 07:26:02.574 Zagazine[12298:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'
*** Call stack at first throw:
(
0 CoreFoundation 0x3284b987 __exceptionPreprocess + 114
1 libobjc.A.dylib 0x31aca49d objc_exception_throw + 24
2 CoreData 0x3549d07b _PFRetainedObjectIDCore + 638
3 CoreData 0x3549cdfb - [NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:] + 14
4 CoreData 0x354bf85b -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 2170
5 CoreFoundation 0x327e9bbf -[NSObject(NSObject) performSelector:withObject:] + 22
6 Foundation 0x320fd795 __NSThreadPerformPerform + 268
7 CoreFoundation 0x328017dd __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
8 CoreFoundation 0x327d34fb __CFRunLoopDoSources0 + 194
9 CoreFoundation 0x327d2e5b __CFRunLoopRun + 230
10 CoreFoundation 0x327d2c87 CFRunLoopRunSpecific + 230
11 CoreFoundation 0x327d2b8f CFRunLoopRunInMode + 58
12 GraphicsServices 0x3094a4ab GSEventRunModal + 114
13 GraphicsServices 0x3094a557 GSEventRun + 62
14 UIKit 0x32c14329 -[UIApplication _run] + 412
15 UIKit 0x32c11e93 UIApplicationMain + 670
16 ArticleApp 0x0000233f main + 70
17 ArticleApp 0x000022f4 start + 40
)
terminate called after throwing an instance of 'NSException'
Program received signal: “SIGABRT”.
This interesting part is that this error only occurs the first time I launch the app after installing it. All subsequent launches after it's installed work fine. Does anyone know why this error is happening and why it would only happen on initial install.
Also, this is how I'm merging the context, this is called on background thread when it receives notification:
- (void)mergeChanges:(NSNotification *)notification {
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *mainContext = [appDelegate managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:#selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
This interesting part is that this error only occurs the first time I launch the app after installing it. All subsequent launches after it's installed work fine. Does anyone know why this error is happening and why it would only happen on initial install.
My guess then is that the persistent store is not correctly associated to the file on the disk correctly at the first launch. The file backing the Core Data store does not materialize when you assign its URL to the persistent store coordinator. It only materializes when it is first saved.
And merging changes without having a backed file ready causes a lot of problems.
Try saving the context once from the main thread at the first launch very early in the execution, when the Core Data context is still empty, before creating the background thread. Hopefully that will solve your issue.
Did you have any other mergeChangesFromContextDidSaveNotification notification being observed by any other context? If so, it might be the order you're notifying. It might be notifying to a context who doesn't know about the schema the changes are affecting to (aka, 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator').