Nsstring objects changing its data type - iphone

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.

Related

attempt to mutate immutable object randomly thrown

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.

Setter failing selectively in NSManagedObject

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.

Iphone TextField.text

i have this code in my app where i put the text field text in my NSString property.
iname = textField.text;
after that at some point im doing this to make sure that the string is not empty
[iname isEqualToString:#""]
the problem is that if the textfield contain one word without space it works great
if there is space it crashes! and i cant understand why ?
please help! thank you so much
iname = textField.text;
iname is an instance variable, right? If so, you need to take co-ownership of this string, so that the string doesn't die when the text field stops owning it (which will happen if anything, including the user, replaces the text field's value for text with a new value—a new string). Simply assigning the string's pointer to one of your instance variables does not take ownership of the string. See the Memory Management Programming Guide for Cocoa Touch for more information.
If you don't do that, then your program will crash when you try to send a message to the now-dead object whose pointer you have in iname.
after that at some point im doing this to make sure that the string is not empty
[iname isEqualToString:#""]
…for example.
the problem is that if the textfield contain one word without space it works great if there is space it crashes!
Sometimes there can be an element of randomness to whether the crash manifests.
The way to prove my theory would be to run your app under Instruments's Zombies instrument. That instrument causes objects with no owners to not die (be deallocated), but instead become zombies. When you send a message to a zombie, you'll get a flag in the Instruments timeline, which you can use to examine the object and its history to find out why it died before it should have/why you're still holding onto it after it died.
Using the getter properly solve the problem
self.iname = textField.text;

Error:Variable is not CFString

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.

Which iPhone OS memory management rules and how-to's do you know?

Currently I am jumping into the ice cold water called "memory management in iPhone OS".
Here's one rule i've learned:
Every time I see an alloc in my method, I will release that corresponding variable at the bottom of the method.
Every time I create an #property(...) in my header file which says copy or retain, I put a release message on that variable into the dealloc method.
Every time I have an IBOutlet, I do the same thing. Only exception: If the IBOutlet has something like #property(... assign), or in other words: If it has the assign keyword at all. Then I don't care about releasing it in the dealloc method.
I feel that there are many more good rules to know! Just write down what you have. Let's scrape them all together. Links to great descriptions are welcome, too.
Actually, any time you initialize an object and the method name includes "init" you are responsible for releasing it. If you create an object using a Class method that does not include the word "init" then you don't.
For example:
NSString *person = [NSString stringWithFormat:"My name is %#", name];
does not need a release. But:
Person *person = [[Person alloc] init];
needs a release (as you stated in your question). Likewise:
Person *person = [[Person alloc] initWithName:#"Matt"]];
also needs a release.
This is a convention, not a rule of the language, but you will find that it is true for all Apple-supplied APIs.
The rules I use
Release all objects you create using a method whose name begins "alloc" or "new" or contains "copy".
Release all objects you retain.
Do not release objects created using a +className convenience constructor. (The class creates it and is responsible for releasing it.)
Do not release objects you receive in other ways E.g.
mySprockets = [widget sprockets];
If you store an object you receive in an instance variable, retain it or copy it. (Unless it's a weak reference - just a pointer to another object, usually to avoid cyclical references.)
Received objects are valid within the method they are received in (generally) and are also valid if passed back to the invoker.
Some good links:
http://www.gehacktes.net/2009/02/iphone-programming-part-2-objective-c-memory-management/
http://mauvilasoftware.com/iphone_software_development/2008/01/iphone-memory-management-a-bri.html
Memory management can seem daunting when you're seeing segfaults spring from every seeming innocent line of code, but it's actually pretty easy once you get the hang of it. Spend a little time reading this page and then Apple's documentation, and you should be writing bug-free code in no time.
I tend to create only autoreleased objects, either by using a class method or by autoreleasing it immediately after creation, unless I can state a reason not to. For example:
I am assigning it to a member variable because I intend to hold onto it for a while.
I am only creating it to pass it on immediately to another method, and I send it a release message right after that method call.
For performance reasons, I need to free that memory before the nearest NSAutoreleasePool will be released, such as creating a large number of objects inside a loop or the objects are holding onto a large amount of data (e.g., images).
That way, I am less likely to leak objects. By default, I create them autoreleased, and when I make the deliberate decision not to autorelease them, I am immediately faced with the question of where they will be released.
For object properties, rather than releasing them in my dealloc method, I like to assign nil to them. That way, retained or copied properties are sent a release, while assigned properties are simply overwritten, and I don't have to update my dealloc method if I change the property to/from retained.