Debugging NSManagedObjectContext - ios

At debugging time, if I have an NSManagedObjectContext, is there a way to look inside to see what objects are in it.
Basically I'm having a save error since there's a CGColor being saved which is not NSCoding compliant. But I have no idea where this CGColor comes from.

Well, step back for a second and think about where your error is stemming from.
You're trying to encode a CGColorRef via the NSCoding mechanism. This is obviously not supported and will cause an exception to be thrown. You should add an exception breakpoint in your debugger to introspect where this faulty assignment is being executed. You should then be able to figure out your issue.
If you find that this is somehow unrelated to your problem, then you can indeed introspect the objects which are laying around in your context via the -registeredObjects method.

I agree with JR (below) that you should set an exception breakpoint to get a stack trace at the point of failure.
One other thought: although autosaving is convenient, it doesn't always happen at the best time for debugging. You might find it helpful to put in a debugging operation that forces an explicit save when you want to validate your object:
[self.document closeWithCompletionHandler:^(BOOL success) {
if (!success) NSLog(#“failed to close document %#”, self.document.localizedName);
}];
With this, or something like it, you can initiate saving at various points to see when your object becomes corrupted. Do keep in mind that saving is asynchronous.

Related

Method mysteriously exits execution in the middle to resume the rest of the program?

So i've got this code that tries to find an unused upload name, using the user's email and a number at its end. It does this with a list of uploaded objects we've already collected, the user's email.(upload_name), and the
current number that might be open (it is incremented when a match is found).
The list is not sorted, and it's pretty tricky to sort for a few reasons, so I'm having the method read through the list again if it reaches the end and the upload_number has changed.
- (NSString*)findUnusedUploadNameWithPreviousUploads:(NSMutableArray*)objects withBaseUploadName:(NSString*)upload_name {
previous_upload_number = upload_number;
for (NSString *key in objects) {
// the component of the object name before the first / is the upload name.
NSLog([key componentsSeparatedByString:#"/"][1]);
if ([[key componentsSeparatedByString:#"/"][1]
isEqualToString:([NSString stringWithFormat:#"%#_%ld", S3KeyUploadName1, upload_number])]) {
upload_number++;
NSLog([NSString stringWithFormat:#"upload name: %#_%ld", S3KeyUploadName1, upload_number]);
}
NSLog(#"pang");
}
NSLog(#"ping");
if (previous_upload_number == upload_number) {
return [NSString stringWithFormat:#"%#%ld", upload_name, upload_number];
}
return [self findUnusedUploadNameWithPreviousUploads:objects withBaseUploadName:upload_name];
}
The problem is, the program never reads the "ping". it just leaves the method after the first for loop is done.
Edit: No the NSlogs are fine, you can do simple string OR StringWithFormat.
Edit: Don't mind the unnecessary use of recursion, I did this because the simple way was having the same problem and i wanted to see if a different (albeit unnecessarily recursive) way would share that problem. It does.
Edit: I set a breakpoint in the for loop, and I set a break point at the "ping". It does not reach the ping. It completes the for loop and the ditches the whole thing.
Edit: Please try to help me figure out why it's exiting the the method immediately after the for loop. I'm aware this is stylistically meh, and I promise I'll make it shiny and spotless when it works. =]
Edit: to be clear, the method DOES exit. it does so early I know this because the rest of the program following this method (which is not threaded such that it wouldn't have to wait for it) runs AFTER this for loop, consistently.
There are a couple of possible explanations for the described behavior:
The method never exits. For some reason it blocks or performs infinitely somewhere in the loop. Make sure this is not the case by setting a breakpoint after the place where the message is called (i.e. the place to where it should return).
The method, or some method it calls, throws an exception. While seldom and unsupported in productive Cocoa code it could be some misbehaving 3rd party library or just a simple programmer error, where Cocoa actually does throw. Make sure this does not happen by setting an exception breakpoint in Xcode.
Undefined behavior. This is, sadly, part of official C and heavily exploited by modern compilers. It basically means: Anything can happen, if there's something in your code, where the standard says that the behavior is not defined. One example would be accessing a deallocated object. Another fine reason of undefined behavior can be threads accessing common data in an unsynchronized way.
Other than exceptions there's no explanation for a method to "exit early". If you still can't find the reason I suggest you invest some time to learn the debugger. Single stepping, like Aris suggested, might be a way to find out what's going on.

isKindOfClass returning nil inside PromiseKit?

My colleague and I are building an async data layer heavily based on PromiseKit v1.5.3. We've noticed in certain circumstances, when returning a promise (call it X) from a block passed to then, the next then block actually passes Promse X as the argument to the block, rather than what the former promise actually resolved to. Chaining thenable promises is a pretty important feature for most Promise implementations, so we were pretty surprised.
After some pretty lengthy debug sessions, we've found the problem to be within PromiseKit. During the resolution process, an IsPromise call fails to identify the object as a promise, which is really a simple call to
[result isKindOfClass:[PMKPromise class]]
This call returns nil, and an incorrect branch is executed. Here's the source
The baffling thing about this, is that I don't see any reason for this to happen. I don't think this is a bug in PromiseKit since their code appears to be sound. I've confirmed the underlying object is indeed a PMKPromise since it responds to promise methods such as value and fulfilled. I've even pushed it through the correct branch using the debugger and it executes correctly from there!
Here's an interesting log from some tests while halted at the given line.
Given that isKindOfClass is returning nil, it sounds like that object isn't responding to the message... but it's certainly an NSObject. I'm curious if this may be a weird compiler setting or something. I currently have my optimizations set to none if that's relevant. Has anyone ever seen anything like this or know what's going on? What should I check?
isKindOfClass returns unexpected results when you manage to have the same class twice in your project. So you may have an object of class PMKPromise, but it is a different class (with exactly the same class name, exactly the same behaviour, just a second class). Maybe that's what happens. Obviously setting a breakpoint and checking what the object is would help.

message sent to deallocated instance error

Im constantly being given an error that reads *** -[NSKeyValueObservance retain]: message sent to deallocated instance 0x86c75f10. I have tried running the Zombies template and here is the screenshot of what it provides.
It points to a managedObject, and I'm having trouble figuring out where the object is being deallocated. Here is the block of code that the compiler takes me to after each crash.
- (void)setIsFavourite:(BOOL)isFavourite shouldPostToAnalytics:(BOOL)shouldPostToAnalytics;
{
// check whether we need to generate preferences objects just in time
if(!self.preferences && !self.series.preferences /*&& isFavourite*/)
{
if(self.series)
{
[self.series addPreferencesObject];
}
else
{
[self addPreferencesObject];
}
}
//Crash In here
self.preferences.isFavourite = #(isFavourite);
self.series.preferences.isFavourite = #(isFavourite);
EDIT: If you need to see a larger size of the image here is a larger resolution link.
OK, I hit something similar and found a way to debug this kind of issue with NSKeyValueObservance. To debug, do the following:
In Xcode, open the "Breakpoint Navigator".
Add a new symbolic breakpoint with:
-[NSKeyValueObservance _initWithObserver:property:options:context:originalObservable:]
To that breakpoint, add an action and set it to "Debugger Command".
Set the following command: expr (void)NSLog(#"observer <0x%p>: %# <%p>, property: %#", $arg1, (id)NSStringFromClass((id)[(id)$arg3 class]), $arg3, (id)$arg4)
Click the "Automatically continue after evaluating expression".
Now you can run your application and take the steps necessary to reproduce your crash. And yes, you'll want NSZombies enabled. Note: it's going to run slow and you're going to get a ton of debug output, but just be patient. It'll get there eventually.
When you hit the crash when trying to message a deallocated NSKeyValueObservance, you'll be presented with the address of the original object. Highlight the address and hit cmd-e to enter the text in the search buffer. Then hit cmd-g find the next occurrence of the string in the debugger output. You're going to potentially find the address a couple of times, so look for the address that follows the observer <0x?????> output. The output on that line should tell you what object is being observed and for which property.
In my case, when I figured this all out, it turned out that I was observing a synthesized property that depended on an object in array and during a certain operation, the order of the objects in the array changed without doing the correct KVO notifications, and that caused my crash.
Are you using manual reference counting? If so, why? Convert your app to ARC. Manual reference counting is painful at best, and ARC is much better.
I am an experienced iOS and Mac OS developer and can do either, but I far prefer ARC. It's much less fussy and error-prone.
There is a feature built into Xcode that will convert your project to ARC for you. You might have to do some cleanup afterwords, but it's worth it.
If you do that your problem will likely go away.
As to the specifics, your screenshot is far too small to be able to read it. You will need to post a full-sized image if you want somebody to try to figure out what's going on.
However, in broad terms it sounds to me like you have an autorelease bug.
in manual reference counted code, lots of system method return objects that are "autoreleased." That means that when you receive them their retain count is positive (usually 1) so they stick around. However, they have been added to the "autorelease pool," which means that they are going to be released on the next pass through the event loop if nobody retains them first.
When you receive an autoreleased object you should either accept that it will be released once your current method returns, or retain it.
If you are trying to write Core Data code using manual reference counting and don't understand this then you are setting yourself up for failure.
Core Data is pretty complex, and you should have a solid understanding of Cocoa memory management before attempting to write a program that uses it, especially if you're using manual reference counting.

Restkit POST ManagedObjectRequestOperation or ObjectRequestOperation?

My application sends a POST request to a server with some parameters, and the server responds with an array of objects. I've been using RKObjectManager's managedObjectRequestOperationWithRequest:managedObjectContext:success:failure: function to do this, but after having some issues with a mysterious intermittent crash that I suspect is related to the underlying restkit code (RestKit Core Data NSError dealloc Crash) I recently did another read through of the docs and came across RKObjectManager's postObject:path:parameters:success:failure function.
Substituting this in place of the managedObjectRequestOperation does not seem to have any negative effects, and everything is operating as expected and thus my main question is are these two functions different in any significant way where given my described use-case I should prefer one to the other?
A secondary question to this is I'm using CocoaLumberjack to handle debug logging to the console/file, and I'd like the raw JSON (prior to being mapped to objects) to be logged for debugging. The only solution I've found to do this is to do something like this:
[operation setWillMapDeserializedResponseBlock:^id(id deserializedResponseBody) {
DDLogInfo(#"%#", deserializedResponseBody);
return deserializedResponseBody;
}];
This worked before when I was doing a managedObjectRequestOperation, as doing so involved creating an instance of it before configuring it further and telling it to start, but using something the object manager's postObject function as described doesn't involve creating/returning an instance of the operation that I can set the willMapDeserializedResponseBlock on... Any ideas?
You should prefer postObject:path:parameters:success:failure because it's the higher level API. The difference is that the operation gives you more access to the underlying system and request, but if you don't need that you should let the manager handle it for you.
For debug purposes you can use
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
or a lower level.

executeFetchRequest exits current method

I'm experiencing a strange problem with Core Data. Target is iOS 5.0
This line of code:
NSArray *results = [self executeFetchRequest:request error:&error];
exits the current method. No code is executed after that line. The app doesn't crash. No exceptions are thrown. This happens occasionally, not every time.
As I step through code and hit that line, it just returns from the current method.
Any hints, clues, etc?
Thank you for your time.
As stated in comment, the fetch is probably executed on a separate thread. That explains why the app doesn't crash.
Without seeing the code, the crash maybe caused by a wrong fetch request, probably in its syntax.
Try to put a breakpoint and at least print the statement, for example with po request in the console, or NSLog(yourStatament) you should be able to see the whole statement. Have a look if something in there is nil.
Also, I see you are using self in your execute fetch. If this is a separate thread I would probably take a strong reference to self to let the main thread release resources. But this just a guess.

Resources