NSString value nil inside onEnterTransitionDidFinish method - ios

I guess its a very basic memory concept. But couldn't figure it out what happens with below case. Any insight would be helpful.
This could be similar to Problems with NSString inside viewWillDisappear
But I wanted to know why there requires a #property. How can we do it without taking #property. Please provide some inside view.
in .h I have NSString *someString
in .mm (this is my non-ARC cocos2d+box2d game scene)
-(id)initWithString:(NSString *)tempString
{
if(self = [super init])
{
someString = [[NSString allo]init];
someString = tempString;
}
return self;
}
-(void)onEnterTransitionDidfinish
{
[super onEnterTransitionDidfinish];
NSLog("The String is %#",someString);//Becomes nil here
}
-(void)printString
{
NSLog(#"The String is %#",someString);//This works fine
}

If you are not using ARC then you need to learn a lot more about memory management.
The following two lines:
someString = [[NSString allo]init];
someString = tempString;
should be:
someString = [tempString copy]; // or [tempString retain];
And be sure you call [someString release] in your dealloc method.
BTW - you are not using a property. someString is declared as an instance variable, not a property.

Related

NSString : leak when assigning value to a property

Assuming we don't use ARC.
Suppose we have a very simple class in which we declare 2 NSString properties, like this :
#interface Foo : UIView {}
-(id)initWithArguments:(NSString*)mess title:(NSString*)tit;
#property(nonatomic, retain) NSString *message;
#property(nonatomic, retain) NSString *title;
#end
and in implementation :
#implementation Foo
#synthesize message, title;
-(id)initWithArguments:(NSString*)mess title:(NSString*)tit{
if((self = [super init])){
message = mess; // (1)
self.title = tit; // (2)
(...)
}
return self;
}
-(void)dealloc{
message = nil;
title = nil;
[super dealloc];
}
#end
Now if I call a method from another class, in which I create 2 NSString and an instance of Foo , like this :
-(void)someMethod{
NSString *string1 = [NSString stringWithFormat:#"some text with %d things", 5];
NSString *string2 = [NSString stringWithFormat:#"other text with %d things", 5];
Foo *foo = [[Foo alloc] initWithArguments:string1 title:string2];
}
The whole code works fine and doesn't crash, but, if I profile it with instruments,
it doesn't cause a leak when calling (1)("message = mess;")
it cause a leak when calling (2)("self.title = tit;")
It's very confusing, because stringWithFormat is an autoreleased object, isn't it ?
So, how an autoreleased object can cause a leak when assigning to a property ???
I read somewhere that it's almost always better to use the "self.text = value;" form instead of the "text = value;" form, because the second one may cause a leak.
Actually, in this code it's the contrary.
And... If I use a constant NSString like #"some text", instead of the values returned by [NSString stringWithFormat], there is no leak, of course.
Any idea ?
You have forgotten to invoke the (compiler-generated) setter methods in a few cases:
self.message = mess; // in init method
self.message = nil; // in dealloc method
self.title = nil; // ditto
It's crucial that you use the setter/getter methods in non-ARC code.

Objective-C memory leak when returning NSString

I want to be sure that my code is not leaking, since this small snippet is called thousand times in my app. I run the app through Instruments and the initWithBytes seems to be problematic. Is anything wrong in this code?
First [reader readString] is called.
case FirstCase:
{
NSString *string = [reader readString];
[self setPropertyByName:propertyName value:string];
break;
}
...
readString is returns the strings which is autoreleased.
- (NSString*) readString
{
...
NSString *string = [[[[NSString alloc] initWithBytes:cursor length:stringLength encoding:NSUTF8StringEncoding] autorelease];
return string;
}
Is the code OK? Any other better approach to avoid autorelease?
I cannot change my code to ARC. Plain old non-ARC memory management.
What you posted is OK. The only rule at this point is that methods contain "create" or "alloc" will return an object that needs to be explicitly released. In your case that is the string returned in the readString method.
Since the object will be returned you need to retain it till the end of the run loop cycle which the autorelease pool will do. What that means for instance is if this method will be called in a for loop the objects will not be deallocated before the loop has exited.
If you want or need to avoid that I suggest you to do the same pattern with "create" or "alloc" and return an object not being autoreleased:
case FirstCase:
{
NSString *string = [reader createReadString];
[self setPropertyByName:propertyName value:string];
[string release];
break;
}
...
- (NSString*) createReadString
{
...
NSString *string = [[[NSString alloc] initWithBytes:cursor length:stringLength encoding:NSUTF8StringEncoding];
return string;
}

xCode won't allow addObject

absolute beginner here. I'm trying to teach myself Xcode using several different sources. My current lesson, I'm just trying to capitalize each word in a string. For some reason, I'm not given the option of using addObject, even though I've resorted to copying line for line what's in the book! Here's the code I'm using, I'm just typing it into the ViewController.m. I haven't touched the header file.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *myString = #"How much wood could a woodchuck chuck";
NSArray *wordsInSentence = [myString componentsSeparatedByString:#" "];
NSLog(#"%#", wordsInSentence);
NSMutableArray *capitalizedWords = [[NSMutableArray alloc] init];
for (int word =0; word < [wordsInSentence count]; word++)
{
NSString *uncapitalizedWords = [wordsInSentence objectAtIndex:word];
NSString *capitalizedWords = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWords];
}
NSLog(#"%#", capitalizedWords);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
My problem is with
[capitalizedWords addObject:capitalizedWords];
When I begin typing, it doesn't even show addObject in the drop down box as an option, the only option I have is addObserver.
Any and all help would be much appreciated, Thanks
The problem is that you have two variables with the same name, capitalizedWords. One is the mutable array, the other is the string. And, thus, when you use capitalizedWords inside that for loop, it's using the string rendition. I would suggest renaming the string variable, e.g., replace:
NSString *uncapitalizedWords = [wordsInSentence objectAtIndex:word];
NSString *capitalizedWords = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWords];
with
NSString *uncapitalizedWord = [wordsInSentence objectAtIndex:word]; // renaming this isn't critical, but using singular case makes it more clear
NSString *capitalizedWord = [uncapitalizedWord capitalizedString]; // renaming this fixes the problem
[capitalizedWords addObject:capitalizedWord];
The problem is that you are naming the string the same as the array.
Try changing
NSString *capitalizedWords = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWords];
to:
NSString *capitalizedWordsString = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWordsString];
When you're declaring the string with the same name as the array you're shadowing the array and Xcode will see capitalizedWords as a string, not an array. That's why it doesn't present you with the addObject method.

How does ARC deal with local variable within the method?

For example,
- (void) method
{
NSString *string = #"This is a string.";
}
Do I need to add
string = nil;
at the end of the method in order to let ARC release it?
Situation may be different in non-literal object such as
- (void) method
{
NSData *data = [[NSData alloc] init];
}
Do I need to add at the end
data = nil;
to release it?
You don't need to nil it, but ARC doesn't release it either. Since it's a literal, it's statically allocated in the app's binary. It's never released.
- (void)method {
NSString *string = #"I'm never released because I'm statically allocated";
NSString *arcReleasesMeAfterMyLastSourceRef = [NSString stringWithString:string];
}

gettin EXC_BAD_ACCESS while using nsstring

I am getting crazy during 4 hours and I really need help. Here is the code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//check if strGroup has prefix and suffix #
BOOL result;
result = [strGroup hasPrefix: #"#"];
if (result)
{
result = [strGroup hasSuffix: #"#"];
if (result)
{
NSMutableString* string = [NSMutableString stringWithString: strGroup];
str = [strGroup substringWithRange: NSMakeRange (1, [string length]-2)];
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
}
}
NSLog(#"strToHoldAllContact=%#",strToHoldAllContact);
}
I am gettin the value of strToHoldAllContact correctly. But when I try to access strToHoldAllContact from another method I am getting the error:
[CFString respondsToSelector:]: message sent to deallocated instance 0x856f2a0
Use
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
[[strToHoldAllContact retain] autorelease];
and forget about release.
where ever you are initializing or setting the string do this [strToHoldAllContact retain]; and don't forget to release it once you are done using it
Just replace
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
to
strToHoldAllContact = [[NSString alloc] initWithFormat:#"%#",str];
And release it after you don't need it anymore.
with ARC, in .h declare strToHoldAllContact as:
#property(strong) NSString *strToHoldAllContact;
in .m, use it (after #synthesize) as self.strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
this way you will not have problems.
without ARC,in .h declare strToHoldAllContact as:
#property(retain) NSString *strToHoldAllContact;
and use it same ways as with ARC in.m file.

Resources