I am using sqlite database to save data from our xib.
When I add first time then its added successfully but when i repeat that process then it shows run time exception and exit from program,and shows variable is not CFString.
Hard to say without looking at the code, but if this thread is any indication:
I believe the issue is that the array enumeration is doing an implicit cast to the enumerator variable type (NSString *, in this case), but the object(s) in the array aren't actually NSString *. When the 'rangeOfString' method is called on the object, the exception is raised.
Even if your code doesn't include that specific problem, it is likely to have some conversion issue related with CFString.
Related
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.
I'ver wondered, why is it that in front of an NSError, such as below, do we put: &error and not error?
E.g.
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
Hope you can explain, also is this always the way or only in certain situations this is needed? Thanks.
You need to take the address of error because the function needs to modify it. error is passed by pointer, so you need the "take address" operator & for it.
C and Objective-C pass parameters by value. If you pass error without an ampersand and the method that you call modifies it, your function that made the call would not see any changes, because the method would operate on its local copy of NSError*.
You know that you need an ampersand in front of the corresponding parameter if you look at the signature of the method and see ** there:
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error
// ^ one ^^ two
The error parameter's type is (NSError **), that is a pointer to a pointer to an NSError. The error variable that you use as the argument is probably declared as NSError *, so in order to get the types to match properly, you have to use the address of operator to get a pointer to a pointer (&error). The reason the method needs a pointer to a pointer in the first place is so that it can modify the value of error and have that new value be available to you, the caller of the method.
Essentially, the root of the issue is a hack for wanting to return a second (optional) object.
How can we do this, as we can only return one thing? Well, we could return some sort of (return_value, error) tuple, but that's a bit unwieldy. We can have as many parameters as we like though, can we do something with those...
So, methods/functions can't modify their parameters (to be precise, they operate with a copy, so any modifications they make are local). That is to say (concurrency issues aside) the value of fetchRequest before the message in your question will be equal to the value of fetchRequest afterwards. Note the object pointed to by fetchRequest might change, but the value of fetchRequest itself won't.
This puts us in a bit of a bind. Except, wait, we know we can happily take the value of a parameter and modify what it points to! If you look at the declaration for executeFetchRequest:error: you'll see it takes an NSError**. That's "a pointer to a pointer to an NSError". So, we can initialise an empty/dangling NSError*, find the address of it (with the unary & operator), and pass that in. The method can then assign to the NSError* pointed to by this.
Voila, we effectively have optional additional return values.
One part of the program takes text from a uitextfield, copies it to a mutable string and then performs
sharedManager.ce_name=name.text
[sharedManager.ce_name replaceOccurrencesOfString:#" " withString:#"%20"
options:NSLiteralSearch range:NSMakeRange(0, [sharedManager.ce_name length])];
At this point it always gave me "attempt to mutate immutable object" - it was not random
The first time I got this error I changed it to
sharedManager.ce_name=(NSMutableString *)name.text
This STILL gave me the attempt to mutate immutable object error, but it would occur randomly - weird right?
I then changed it to
NSMutableString *mutable_name = [NSMutableString stringWithString:name.text];
sharedManager.ce_name=mutable_name;
It has yet to fail on me doing it this way but I am convinced that I have not found the solution.
my questions:
1) Could that fact that it was doing it randomly after the first fix indicate I have some deep seated memory management problem?
2) Why didn't the C-style cast fix it?
3) Will my current fix work?
Thanks for your time :)
The problem here is the way in which you're using casting. When you cast a pointer, it just starts treating the memory at that location as though it were a block of data representing that type.
So if I've got a pointer to a Car class: Car* mycar;, and I cast it to a Person object: (Person*)mycar;, the program will try to access the memory there as though it was pointing at a Person object. However, a car is not a person, except in an old TV sitcom, so when it tries to access members on this or call functions, it's going to try to go to a memory location that contains something other than what it's expecting, and undefined things happen (generally, crashing).
NSMutableString and NSString are incompatible in this regard, and so casting from one to the other will result in terrible times. Your fix ([NSMutableString stringWithString:]) is the correct solution.
If it was doing it randomly, it means that name.text was sometimes a mutable string and some times an immutable string.
Casting between objects like that doesn't change the class of the object. It won't make your immutable object mutable.
That "fix" is probably the best way to do it (at least from what I can see in the code you are showing)
Without seeing at least the declarations of the variables involved, it's difficult to say for certain, but your final solution, creating a new mutable string is likely the correct fix. As for your questions,
Not memory management per se, but it was probably overwriting something it shouldn't have somewhere.
Casts cannot change the fundamental type of an object. You had (presumably) an NSString and all the casting in the world cannot make it into an NSMutableString.
Like I said, probably, but we'd need to see more code to make sure. It's certainly a much better fix.
I have a certain nsstring property declared in a variable, it is used to do store a text string when i am performing a parsing operation. As this parsing operation happens mulitple times, the Nsstring property changes bizzardly to any random data type and crashing my application. This happens when i try to compare the property with other local variable which is also string. But by the time i compare, the appdelegate variable has already changed its data type, and hence crashes my app.
Any one ever come across such issue? If so, please guide me.
It is a sign that your NSString object has been deallocated so you send a message to a deallocated object. That crashes your application. The datatype changes because after an object is deallocated the memory it was placed in is not correct anymore and may contain a trash. You should use Run with Performance tool -> Leaks tool. It helps a lot in such cases. Please keep in mind that you should enable zombie object detection in settings.
I have a NSManagedObject which I'm trying to instantiate with given values. I access the setters like so:
object.couchID = (NSString *)[dictObject objectForKey:#"_id"];
...and this works fine on my machine, but my partner gets this error when he runs it on his machine:
'-[NSCFString type]: unrecognized selector sent to instance 0x4e465e0'
About 90% of the setters (all formatted in the same way) work on my partner's machine, but a good 10% fail with that error. All of them work on my machine.
We're running the exact same code (according to SVN (yes, I know)), and fetching the same data from the same server, so everything seems like it should work.
We've checked the objects being passed, and they're the same. Commenting out the setter allows the code to get through to the next troublesome setter, but of course we need it to actually work. How else should we troubleshoot? Thanks in advance.
Update 1: Unlocked the Tumbleweed badge for that one... guess it's too sticky to touch? Any thoughts or guesses are welcome. And hey, you could earn 50 points.*
Update 2: the mixed-good-news is that checking out a fresh version from source control results in the same problem on my machine, so a) it's definitely something in the code, and b) I can more actively troubleshoot. Thanks for all your suggestions so far, I'm going to go through them all again.
I ran into something similar at work the other day. I suspect that one of you has a stale .momd file inside the app bundle, and that it's not being replaced when it gets upgraded. I suspect this is a bug in Xcode 4, though I haven't totally verified it yet. If your partner deletes the app completely and then installs the app, does the error go away?
You may need to create a temporary variable whose value is object cast to whatever the actual class is, e.g.
MyClass *c = (MyClass *)object; // if object is in fact a MyClass instance
c.couchID = (NSString *)[dictObject objectForKey:#"_id"];
I have seen cases where the compiler cannot make mental leap and realize that your attribute is the class you know it is. The solution for me in these cases has been to be more explicit. Does this make sense? It's worth a shot at least, no? :-)
if this code fails on your partner's machine:
someManagedObject.couchID = #"some hardcoded string";
seems like you have a dangling pointer: i would check that someManagedObject is properly retained and still a valid object when you try to call the -setCouchID method on it.
I have had nearly the same problem when trying to draw a CATiledLayer with data in NSManagedObjects. What should be a valid object barfs with an "unrecognised selector" exception
It nearly always happens because theres no retain on the object external to the point where you are trying to set or get the property. Being in a separate thread seemed to have a relationship too.
After fruitlessly trying to get round this with [NSManagedObjectContext lock] and retain on the context within the new thread I eventually just threw the contents of my fetch into a mutable set to try and keep a grip on it which seems to work on iOS but not on OS X so well.
So a couple of possibilities
Are you doing this not in the main
thread and does the MOC have a retain
within that thread. Check the docs
for [NSManagedObjectContext lock]. But essentially each thread working with the context needs its own retain on the context.
Try throwing it into a container
while you operate on it. Make it a
bit stickier. Sorry if that sounds
like voodoo but it is.