insertNewObjectForEntityForName: inManagedObjectContext: returning NSNumber bug? - iphone

I'm relatively well versed in CoreData and have been using it for several years with little or no difficulty. All of a sudden I'm now dumbfounded by an error. For the life of me, I can't figure out why
insertNewObjectForEntityForName:inManagedObjectContext:
is all of a sudden returning some sort of strange instance of NSNumber. GDB says the returned object is of the correct custom subclass of NSManagedObject, but when I go to print a description of the NSManagedObject itself, I get the following error:
*** -[NSCFNumber objectID]: unrecognized selector sent to instance 0x3f26f50
What's even stranger, is that I'm able to set some relationships and attributes using setValue:forKey: and all is good. But when I try to set once specific relationship, I get this error:
*** -[NSCFNumber entity]: unrecognized selector sent to instance 0x3f26f50
Has anyone ever encountered anything like this before? I've tried clean all targets, restarting everything, even changing the model to the relationship in question is a to-one instead of a to-many. Nothing makes any difference.

I've encountered the "unrecognized selector sent to instance 0x..." error before in a situation where the object I expect to be at the memory address "pointer" has been replaced by something else. Take this situation:
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
NSString *someString = [NSString stringWithString:#"some string"]; // autoreleased object returned
[pool drain];
[pool release];
/*
some other code executes
*/
// since the string behind the someString variable has been autoreleased at this point, the memory that someString points to may be occupied by some other data type. the following may through an EXC_BAD_ACCESS error, or it may try and execute the selector on whatever is occupying that memory space
int stringLength = [someString length];
This example is painfully straightforward and my semantics may be a bit off here, but could it be possible that this is what is happening in your case in a more convoluted way? Maybe try:
[[NSEntityDescription insertNewObjectForEntityForName:#"entityName" inManagedObjectContext:managedObjectContext] retain]
and see what happens?

Related

Xcode 4.3.3 -[__NSArrayM length]: unrecognized selector sent to instance 0x6b6dc60

I have an iPhone application where i download information from the internet and put it into an NSString. It works fine, until i download large files and put it into that one string, then i get the error
-[__NSArrayM length]: unrecognized selector sent to instance 0x6b6dc60
At one point i was getting a EXC_BAD_ACCESS error, but now that's not showing up. I'm guessing that it is a memory problem but i dont know how to fix it. Is there a limit to how large a string variable can be? Any suggestions? I should also mention that the error sometimes doesn't show up, but most of the time it does. Thanks in advance.
Well, it looks like you're trying to get the length of the array by calling a method called length on an array, but to get the length of an array you use the count method like this for example:
NSInteger numberOfElements = [someArray count];
Hope this helps!
P.S. The length method exists but it is used on NSString objects to get the number of characters in the string.
----UPDATE-----
From Ray Wenderlich's "My App Crashed, Now What?" tutorial:
The error message “unrecognized selector sent to instance XXX” means that the app is trying to call a method that doesn’t exist.
So somewhere in your code, you are calling the length method on an object of type NSArray.
You are actually calling the length method on an object of type NSMutableArray, and you know that from the error because __NSArrayM represents an NSMutableArray object; a regular NSArray object would be represented as __NSArrayI (the suffixed "M" stands for "mutable" while the suffixed "I" stands for "immutable").
I even found a very similar question that has a very similar answer to mine:
NSArrayM length : unrecognized selector sent to instance
Heh, I had this before. Somewhere you're doing this: [array length]; but arrays use "count", not "length".
This is happening because you are trying to cast NSMutableArray to NSString, you can remove this error simply by using objectAtIndex:0.
when we use objectAtIndex:0 ,it returns object and in your case that object is your NSString & hence removes error.
e.g.
self.quizTextView.text=[questionTexts objectAtIndex:0];
Try turning on zombies to get a better error message. It's probably something being deallocated before you expect. You can also try running your app in the "Allocations" or "Leaks" instrument to track down why your objects are being released before you expect.

try catch final is not catching exception

While on return to my app from getting phone number from address book, if by mistake i fetch some address or any thing except for phone number, the code in the try catch final gives the following but doesn't catch it, any idea is appreciated in advance:
*** -[CFDictionary length]: message sent to deallocated instance 0x6a4db70
Code:
strContact = (NSString *)phone; CFRelease(phone);
// NSLog(#"%#", strContact);
CFRelease(multi);
name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSRegularExpression *regex = [[[NSRegularExpression alloc] initWithPattern:#"[a-zA-Z]" options:0 error:NULL] autorelease];
// Assuming you have some NSString myString.
NSUInteger matches = [regex numberOfMatchesInString:strContact options:0 range:NSMakeRange(0, [strContact length])];
OK, I think I understand your question now. It just took me a while.
So, I'm assuming you have Zombie Objects enabled (NSZombieEnabled) and you're wondering why you can't catch this error --sending a message to a zombie-- with a #try/#catch structure.
The short answer is NSZombies don't throw an Objective-C exception (one that you can catch this way). There wouldn't really be a point to that, since you wouldn't actually ship an app with NSZombieEnabled anyway. This is meant to be a debugging tool that you use at the debugger or within Instruments.
In your actual app, when you turn off NSZombie's, there still wouldn't be an exception to catch for this, since you would just get an EXE_BAD_ACCESS, which is a UNIX signal (not this type of an exception at this level).
The last point is that Objective-C exceptions (the type that you can #try/#catch) are not recommended for errors that you expect to be able to recover from. Or in other words, this is meant for fatal errors only, where you might do some cleanup and then allow your app to still crash.
The right way to do what you're trying to do is to actually test for different types or different values that you might except to get and then handle each case appropriately. You can do this using normal if/else conditionals or something of that sort. You can test values for nil if you need to and you can see if an object is of a particular class by using [someObj isKindOfClass:[MyExpectedClass class]]
I hope I understood the question correctly?
The problem is probably that you are releasing phone after assigning it to strContact, and then using strContact. The string object is probably getting deallocated when you release phone, so the pointer in strContact is no longer valid.
Are you sure that phone is a string? Looks like you're storing that object in a NSString* pointer 'strContact' that is probably not a string, hence the 'CFDictionary' in the error messages.
Looks like you have two problems to fix:
Getting the object of the right type.
Ensuring that you don't release objects before you need to. Try put the CFRelease after you've finished using the object!

Objective-C release is not called explicitly

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString * str = [[NSString alloc] initWithString:#"test"];
[str release];
int i = 999999999;
while(i-- > 0) {}
NSLog(#"%#", str);
[pool drain];
Output: test
Why didn't release work?
How can I immediately delete the object from memory?
Xcode Version 4.0 iPhone Application
~SOLVED~
Thank's to all for answers.
I've got a lot of useful information about this question. I'm going to use NSString *str = #"text" instead of NSString *str = [[NSString alloc] initWithString:#"text"];
i've understood that release just "marks" memory as "willing to be freed", but not freeing it immediatly
It did work. You have relinquished ownership of that object, and when the system determines that it is no longer owned, it will be marked available for reuse by the system. That may happen immediately, if you were the only owner of the string. It may happen at some later point, if creation of the string caused it to be autoreleased internally. Or, as Dave DeLong points out, the system may optimize it into an object that is never released.
In your case, it's being optimized into a constant string, which will exist for the life of the program. If you were to use an NSMutableString instead of an NSString, you'd see funky behavior that would probably not crash, but wouldn't print what you expected. (See this question for an example.)
If you used an NSArray instead, it would be deallocated when you called release, but you'd still see your NSLog example work correctly until you allocated some other object. Deallocation just marks the memory as available for reuse; it doesn't actually clear it out. So if you passed the array to NSLog, that memory hasn't been changed and thus it still prints correctly.
The key point in all of this, though, is to recognize that calling release will not necessarily cause the object to be deallocated. It may continue to exist for any number of reasons. But once you call release, you have relinquished ownership of the object. If you continue using it after that point, the system is free to do all sorts of weird things at its own will, as demonstrated.
Release does work but what you are attempting to do has undefined behavior, and when using a NSString and a literal you may also get different behavior. What is happening is although your object is released the memory at that location is reclaimable and has not changed and when it goes to print it it is still valid. Since it is a NSString a message to description is not necessarily sent and that is why you are not getting an exception for attempting to message a deallocated object.
This question has some good information about NSString and NSLog.
When you do:
NSString * str = [[NSString alloc] initWithString:#"test"];
This gets optimized into:
NSString * str = #"test";
You can't release a constant string, because it's hardcoded into the application binary.
Proof:
NSString *s = [NSString alloc];
NSLog(#"%p", s);
s = [s initWithString:#"foo"];
NSLog(#"%p", s);
s = #"foo";
NSLog(#"%p", s);
Logs:
2011-04-12 10:17:45.591 EmptyFoundation[6679:a0f] 0x100116370
2011-04-12 10:17:45.599 EmptyFoundation[6679:a0f] 0x100009270
2011-04-12 10:17:45.604 EmptyFoundation[6679:a0f] 0x100009270
You can see that the result of +alloc is different from the result of -initWithString:, and the result of -initWithString: is equivalent to the constant string. Basically, -initWithString: says "aha, i'm going to be an immutable string, and I'm being given an immutable string! I can just take a shortcut, destroy myself, and return the parameter, and everything will still work the same"
You're using a bad pointer in you NSLog(). You happen to be getting lucky in this case, but you should expect code like this to crash or fail in other ways.
There is no need to delete the memory block, this will use up an unneeded cycle.
The memory will be overridden when an new object is allocated an occupy that memory block.

How do I debug a iPhone SDK memory reallocation issue?

I have just been through a client project initially coded by us then abused by them! And we are getting a strange crash, which is consisten on each mac individually but inconsistent between the team or after a reload/restart of Xcode/OSX.
The problem is one I have come across before when I havent been cleaning up objects properly, but I have been through static analyser and am still struggling.
The crashes always seem to occur because objects we have created in the VC are getting overwritten by others therefore changing their type so valid method calls are being thrown as exceptions.
For example:
NSNumber *test1;
-(void)viewDidLoad {
test1 = [NSNumber numberWithInteger:7];
}
-(void)someOtherMethod {
NSLog(#"what was test? %#", [test stringValue]);
}
This is currently throwing an unrecognized selector exception during the NSLog as hovering over test1 tells me is is of type NSURLRequestInternal, if I restart Xcode it will probably be somewhere else!!
How can I debug/solve this!?!?
That should crash every time.
Let's look at the code.
test1 = [NSNumber numberWithInteger:7];
This creates a NSNumber and assigns it to the instance. However, the NSNumber is scheduled for deallocation as soon as the main event loop is run.
NSLog(#"what was test? %#", [test stringValue]);
This, presumably, is being run after the main event loop has had a swing. At this point, test (and I assume this should be test1) is pointing to a dangling pointer. Accessing it will crash.
There is no substitute to reading Apple's documentation on memory management: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
This will explain what you need to know. But basically, you should be using [[NSNumber alloc] initWithInteger:7] or retain it (possibly using property syntax) instead.
But unless you read Apple's documentation on the subject, you're going to be chasing memory bugs forever.
you forgot to retain test1 so it gets autoreleased, hence the crash
try using NSZombieEnabled for debugging this kind of stuff.
test1 = [NSNumber numberWithInteger:7];
should either be
test1 = [[NSNumber numberWithInteger:7] retain];
or (better)
test1 = [[NSNumber alloc] initWithInteger:7];
numberWithInteger: returns an autoreleased object, so by the time someOtherMethod is called, the object that test1 points to has been deallocated.

NSMutableDictionary throws a doesNotRecognizeSelector to objectForKey?

I'm a total noob to iPhone programming, and I've run into an exception being thrown that I just can't wrap my head around.
Background: The error is happening in a custom subview, and occurs immediately upon loading the program. I'm getting an exception thrown in the overridden drawRect method. The code throwing the error follows:
- (void)drawRect:(CGRect)rect{
NSNumber *points = [NSNumber numberWithInt: star.numberOfPoints];
//HERE. Doesn't recognize selector?!
CGPathRef t = (CGPathRef)[starPaths objectForKey:points];
/*snip*/
starPaths is initialized in awakeFromNib as an NSMutableDictionary with capacity 1.
The exception that's getting thrown is -[NSObject doesNotRecognizeSelector:]
starPaths is declared in the header file for the view as
NSMutableDictionary *starPaths;
and is initialized as
- (void)awakeFromNib{
starPaths = [NSMutableDictionary dictionaryWithCapacity: 1];
}
Finally, I haven't been able to get to a point in the code where I successfully add elements to the dictionary, since the code to add an entry relies on receiving a nil response from the dictionary to know that the that specific entry needs to be built.
Any suggestions? Any other information I should provide?
Any help at all would be appreciated, I feel like I'm missing something obvious, but I've been bashing my head against this all day with no luck.
If you do not retain the starPaths variable or explicitly allocate it yourself with [[NSMutableDictionary alloc] initWithCapacity:1] then it will be automatically released on the next iteration of the run loop.
You need to do
starPaths = [[NSMutableDictionary dictionaryWithCapacity:1] retain];
Or
starPaths = [[NSMutableDictionary alloc] initWithCapacity:1];
Just make sure to release it when you no longer need it.
A few things to check:
Is starPaths declared as an NSMutableDictionary* instance variable? You mention that it is initialized. Did you use the dictionaryWithCapacity method (which returns an auto-release object) or initWithCapacity (which needs to be explicitly retained). To be safe, you may want to retain it and release it when done.
Double-check to make sure the header files are properly included so the declaration of starPaths is included in implementation files that make use of it.
Generally speaking if you're getting mystery errors it has to do with corrupted memory. Try putting a breakpoint on the first line of the drawRect method and do a "po starPaths" in the debugger console window to see what's in it and what type of object the runtime thinks it is.