NSString not working - iphone

In my code I declared NSString object in .h and synthesized in .m , I m assigning it with string object in array . but its not working .
when I print it on Log it display sometime CAlayer Class , some time shows NSCFString class object .some time shows UIDevicewhitedevicetype class how to solve this ? help...

How are you assigning the string to the NSString object in your code?
Are you doing something like:
NSString* someString = #"My string";
self.myStringProperty = someString;
Where myStringProperty is the NSString declared as a property.

I think your memory is ruined. You maybe release something that should not be released.

The reference is definitely bad. You said you are assigning the string to a property. Does that imply that in your header you have something like:
#property (assign) NSString* myString;
If so, that explicitly states that you are not going to hold onto the string reference, allowing it to be dealloced even if you still hold a pointer (not a reference) to it. You should make it say either:
#property (copy) NSString* myString;
#property (retain) NSString* myString;
If you are pointing your string at a value in an array, as soon as that array is released all of its contents are released. If you aren't holding a retained reference to the string it will be deallocated. Once that has happened the pointer you have stored points to undefined memory that is being reused to hold the object types you listed.

Related

Objective C: Which is changed, property or ivar?

Worrying about duplicates but can not seem to find and answer I can understand in any of the other posts, I just have to ask:
When I have in my .h:
#interface SecondViewController : UIViewController{
NSString *changeName;
}
#property (readwrite, retain) NSString *changeName;
then in my .m
#synthesize changeName;
-(IBAction)changeButton:(id)sender{
changeName = #"changed";
}
Is it the synthesized property or the instance variable that get changed when I press "changeButton" ?
You (and it seems some of the others that answered) are confusing properties with actual variables.
The way properties work is, they create METHODS (called setter and getter) that set or get/return ivars. And the do notation (self.string) actually INVOKES these methods. So a property can't be CHANGED, only the declared iVar is.
When you declare a property like so:
#property (nonatomic, retain) NSString *string;
And #synthesize it the following happens:
An iVar called string (of type NString*) is created
(if you do
#synthesize string = whateverYouWant
the iVar created
is called whateverYouWant - a convention is to name the iVars
the same as the property with preceding underscore (_string))
an accessor method is created like this
-(NSString*) string;
a setter is created like this
-(void) setString: (NSString*) newString;
Now what self.xxxx does is, it actually sends the message xxxx to self
(like [self xxxx]).
It works with ANY method, not just properties, though it should only
Be used with properties.
So when you do self.string = #"hello" it actually comes down to
[self setString: #"hello"];
(Note that the compiler actually knows you are trying to set and so the
setString message is sent instead of just string. If you accessed self.string
it would send [self string])
Thus you don't SET a property, you invoke the (synthesized) setter method that in
itself sets the iVar.
Accessing your iVar directly is ok, if you know what your doing.
Just calling
string = #"something else";
Will produce leaking code, since no memory management is done.
The synthesized accessors and setters actually do this for you, depending
on how you defined th property (retain,copy,assign).
Because the setter (for a retained property) doesn't just do
IVar = newValue
If you declared a retained property it actually looks something like this:
-(void) setString: (NSString*) newString {
if (string) [string release];
string = [newString retain];
}
So the property synthesize takes a bit of work off your hands.
EDIT
Since it still doesn't seem clear, the property that is declared is not to be thought
of like a variable. In the above example, when using
#synthesize string = _string;
there IS NO variable called "string". It's just the way you access the method structures
that set the iVar _string through the setter methods. Since string is no variable/object pointer, you cannot send messages to it ([string doSomething] won't work).
When you just synthesize the property using #synthesize string; the generated iVar gets
the same name as the property.
Calling [string doSomething] will then work, but it has nothing to do with the property. The "string" refers to the iVar. Hence th convention to name the iVars underscored, so
you don't accidentally access the iVar when you meant to use the getter/setter.
Both. Property uses instance variable as its storage. In your code you change the instance variable, but if you access the property (via self.changeName) you'd get the same value as instance variable.
Usually to distinguish between ivars and properties people use _ prefix for ivars. And then synthesizes properties like this:
#synthesize myProperty=_myProperty;
well, the var
it's always the var
in your case the property methods aren't used at all.
now, consider this case:
self.changeName = #"changed";
this way you are using the property, but that just means that you are using the methods "magically" created for you by the compiler, the setter and getter methods, where you, again, change the var (property doesn't exist, in reality, it's just a way to create the setter and getter methods for you)

Memory allocation / release for NSString

I have a class that adopts the MKAnnotation protocol. Along with the two "title and "subtitle" methods to implement, I wanted to add two NSStrings, one to represent each line in a typical US address. For example:
addressLine1 = 123 street
addressline2 = northridge, ca 91326
My subtitle method currently looks like:
- (NSString *)subtitle {
NSMutableString * ret = [NSMutableString stringWithCapacity:kDefaultStringCapacity];
if (streetAddress) {
[ret appendString:streetAddress];
addressLine1 = [[NSString alloc] initWithFormat:streetAddress];
}
... more code
When would I release addressLine1? Because it is a property that I declared with (nonatomic, retain), I already released it in my dealloc method. Or am I to use a class method or autorelease the string? Thanks.
If you autorelease address1, you will lose ownership on the object and without any other owners, it will get deallocated. You would need to autorelease it if you were doing,
self.address1 = [[NSString alloc] initWithString:streetAddress];
which is wrong as you would've taken ownership twice and relinquished it only once in the dealloc method. Right way would've been,
self.address1 = [[[NSString alloc] initWithString:streetAddress] autorelease];
The direct assignment above works only if it were to be assigned a value once. If it is to be assigned again, you would lose the reference to the earlier reference and your application will leak. So it would be good process to use the property accessors here which would ensure that the older values are deallocated.
Another thing with strings is that you would copy them as you wouldn't want them to mutate after assignment so the property should be declared as #property (nonatomic, copy) rather than what it is now.
If your property is (nonatomic, retain), then you're going to leak the addressLine1 resource if you don't explicitly release it. I'd release it as soon as you're done with it. The property should then be released in your dealloc method as you are currently doing.
Somewhat unrelated to the question, but still related, is that anytime you have an object that implements the NSCopying protocol, such as NSString in this case, you should use copy instead of retain. Here's a SO question that provides some great information.

Why aren't my variables persisting between methods? - iPhone

Header file:
NSString *righta;
#property(nonatomic, retain) NSString *righta;
(I don't usually make #property declarations for my variables but thought this might help the variable persist through the class, though it hasn't)
Implementation file:
#synthesize righta;
- (void) function1 {
righta = [NSString stringWithFormat:#"A"];
}
- (IBAction)function2:(id)sender {
NSLog(#"righta is still %#", righta);
}
On trying to access the value of the string in the second function, I receive an "EXC_BAD_ACCESS" and the app crashes.
Any help would be GREATLY appreciated.
Thanks!
stringWithFormat returns an autoreleased object. You must retain it. Note that you are accessing the ivar directy, not the property so the string is not getting retained. Use the property instead:
self.righta = [NSString stringWithFormat:#"A"];
Some programmers prefer to synthesize their properties with a different ivar name to avoid accessing the ivar directly by mistake.
#synthesize righta = righta_;
You must use
self.righta = [NSString stringWithFormat:#"A"];
To assign the variable otherwise the accessor is not used and the value is not retained.
Change function1 to:
self.righta = [NSString stringWithFormat:#"A"];
You were assigning directly to the righta ivar without retaining the string.

Objective-C: Is an autoreleased initialisation followed by a retain wrong in a constructor?

In my #interface theres a NSArray *Monate followed by:
#property (nonatomic, retain) NSArray* Monate;
If i do:
filePath = [[NSBundle mainBundle] pathForResource:#"SomeFile" ofType:#"plist"];
self.Monate = [NSArray arrayWithContentsOfFile:filePath];
in the constructor, it gets set to an autoreleased object (is that correct?).
So should I do a [Monate retain] afterwards?
This code is correct; you should not add a retain call.
+[NSArray arrayWithContentsOfFile:] will return an autoreleased NSArray. Passing that to -[YourClass setMonate:] will retain the object and assign to the backing ivar. After the constructor returns, the new NSArray will have a retain count of 2 and be added once to the current autorelease pool (resulting in a net retain count of 1)
As long as you release the array in your dealloc, this code is correct.
You should NOT do a retain after. By setting a #property of retain, some special things happen when you use the self.Monate setter
1) Anything in the Monate instance variable, if any, will get a release.
2) the new assignment will get a retain.
if you were to use #property of assign, then you would have to retain, but you are fine the way you are.
As a side note, in objective-c, Capitalized words are usually reserved for Class names. I sugges changin it to "monate" instead of "Monate" as this could lead to confusion down the road
[NSArray arrayWithContentsOfFile:]; returns an autoreleased array which will require retaining if you want it to hang around longer than the end of the method.
Notice how your property declaration specifies 'retain'. This means that any self.property = x; calls you do will retain the object you pass in.
So what you are doing there is correct. Just remember to do self.property = nil; in your dealloc method.
Setting a property to nil will release the old object and set the pointer to nil, which is the correct way to do it.

Do I have a leak with this statement?

The statement is:
//Pass the copy onto the child controller
self.childController.theFoodFacilityCopy = [self.theFoodFacility copy];
My property is set to:
#property (nonatomic, retain) FoodFacility *theFoodFacilityCopy;
The reason I think I have a leak is because copy retains the value and then my dot syntax property also retains the value. Doubly retained.
What is the correct way of writing the above statement?
yes, you do have a leak there.
SomeClass *someObj = [self.theFoodFacility copy];
self.childController.theFoodFacilityCopy = someObj;
[someObj release];
This mirrors the recommended approach for initializing an object too:
SomeClass *someObj = [[SomeClass alloc] init];
self.someProperty = someObj;
[someObj release];
In both cases the first line returns an objects with a retain count of 1, and you treat it identically after that.
As mentioned by others, that is indeed a leak. If you expect to be using copies in this way, it’s likely your property should be declared copy instead and the synthesized accessor will do the work for you.
You are right. The cleanest way is something like
id temp = [self.theFoodFacitlity copy];
self.childController.theFoodFacilityCopy = temp;
[temp release]
You want to read the apple site on memory management a lot until these rules become second nature.
What is the advantage of doing this vs just setting the property to copy?
#property (nonatomic, copy) FoodFacility *theFoodFacilityCopy;