NSString Append EXC_BAD_ACCESS Url Connection - objective-c

I am new to Objective-C however I am slowly making progress. All I would like to do is append a new string to a current string. I need to do this for my NSURLConnection so that I can put all the data into one string. I currently have something like this, however it does work and I don't fully understand why and what I need to do to fix it.
NSString *temp = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
html = [htmlTemp stringByAppendingString:temp];
htmlTemp = html;
Thanks For any help I am sure its something to do with the memory however I don't fully understand that either.

StringByAppendingString is a convenience method that does not start with "new" or contains "alloc" or "copy", the returned string will be autoreleased most likely in the next run cycle, which is why when you try to read it again from html, it has already been released. To fix this you can send a copy message like this:
htmlTemp = [html copy];
I would recommend making htmlTemp a property like this:
#property (nonatomic, copy) NSString *htmlTemp;
This way when you assign a new value to it, using the setter, the old value will get released, before pointing to the new value that way you can do:
self.htmlTemp = [htmlTemp stringByAppendingString:temp];

Related

When not to alloc and init an NSString

Whenever I need to create a new NSString variable I always alloc and init it. It seems that there are times when you don't want to do this. How do you know when to alloc and init an NSString and when not to?
Whenever I need to create a new NSString variable I always alloc and init it.
No, that doesn't make sense.
The variable exists from the moment the program encounters the point where you declare it:
NSString *myString;
This variable is not an NSString. It is storage for a pointer to an NSString. That's what the * indicates: That this variable holds a pointer.
The NSString object exists only from the moment you create one:
[[NSString alloc] init];
and the pointer to that object is only in the variable from the moment you assign it there:
myString = [[NSString alloc] init];
//Or, initializing the variable in its declaration:
NSString *myString = [[NSString alloc] init];
Thus, if you're going to get a string object from somewhere else (e.g., substringWithRange:), you can skip creating a new, empty one, because you're just going to replace the pointer to the empty string with the pointer to the other one.
Sometimes you do want to create an empty string; for example, if you're going to obtain a bunch of strings one at a time (e.g., from an NSScanner) and want to concatenate some or all of them into one big string, you can create an empty mutable string (using alloc and init) and send it appendString: messages to do the concatenations.
You also need to release any object you create by alloc. This is one of the rules in the Memory Management Programming Guide.
If you want to initialise it to a known value, there is little point in using alloc, you can just use a string literal:
NSString* myStr = #"Some value";
If you want to initialise it with a format or whatever, but don't need it to stick around beyond the current autorelease pool lifetime, it's a bit neater to use the class convenience methods:
NSString* myTempStr = [NSString stringWithFormat:#"%d", myIntVar];
If you need its lifetime to go beyond that, either alloc/init or else add a retain to the previous call. I tend to slightly prefer the latter, but the two are pretty much equivalent. Either way you will need a balancing release later.
Note that, since NSString is not mutable, this sort of thing is not only unnecessary but actively wrong:
// don't do this!
NSString* myStr = [[NSString alloc] initWithString:#""];
myStr = someOtherStr;
since it leaks the initial placeholder value.
It seems that there are times when you don't want to do this.
I can't think of any time when I would want to alloc/init a NSString. Since NSStringgs are immutable, you pretty much always create new strings by one of:
convenience class method e.g.
NSString* foo = [NSString stringWithFormat:...];
literal
NSString* foo = #"literal";
NSString instance method
NSString* foo = [bar uppercaseString];
copy from mutable string
NSString* foo = [mutableBar copy]; // foo needs to be released or autoreleased in this case
I'm guessing that you are referring to using StringWithString or similar instead of initWithString? StringWithString alloc and inits for you under the hood and then returns an autoreleased string.
If you don't need to do any string manipulation other than to have the string, you can use NSString *str = #"string";
In general with iOS, the tighter you manage your memory the better. This means that if you don't need to return a string from a method, you should alloc init and then release it.
If you need to return a string, of course you'll need to return an autoreleased string. I don't think its any more complicated than that.

In Obj-C How to update an existing NSString variable with a new formatted string?

How do i update an existing NSString variable with a new formatted string?
for example i have a variable like this:
String1 = [NSString new];
I want this string object to be updated from time to time with new formatted contents using the standard printf format.
I can initialise a new NSString using the initWithFormat: message but this is unavailable to already instantiated objects.
Any ideas? I'm thinking i can destroy the NSString each time and re-initialise a new one but is this the correct solution each time i need to update it?
Two options:
Create a new string every time with [[NSString alloc] initWithFormat:#"whatever"] and assign it to the variable. (Make sure you follow the memory management rules, which includes making sure the string's previous value is released. Of course, you'll need to follow those rules no matter how you tackle this problem.)
Create an NSMutableString and update the string with the mutating methods (appendFormat:, setString:, deleteCharactersInRange:, etc.). In this case, you're not just updating the variable, but the string itself.
Personally, I would use method 1, creating a new NSString every time. That way I don't have to fiddle with mutation and can just create a string with the precise value I want.
Strings in Cocoa are immutable objects.
This means that you won't change the same string but you will just free the old one and allocate a new NString with your updated content.
Of course this is not a problem since you will have a NSString* reference that will point to the last updated string.
NSString myString = [NSString stringWithFormat:...];
// do whatever
myString = [NSString stringWithFormat:..]
There is an NSMutableString which can be modified after the initialization. You can add a formatted string using appendStringWithFormat:. But if you want to replace the entire string, just create another. It doesn't cost much time and resources.
It depends on the taste, but I am against re-using a variable as Jack suggested. It often just confuses me, I prefer to create a new variable name whenever I create a new string, as in
NSString* myString = [NSString stringWithFormat:...];
// do whatever
NSString*myString2 = [NSString stringWithFormat:...];
Another thing is that new is not widely-used in Objective-C world. If you use that because it sounds familiar from your C++ background etc., consider using [[Class alloc] initWith...] instead.
The simplest thing to do is just always use "factory" methods that give you an autoreleased immutable object. In fact, you basically do that whenever you create an NSString that holds some static text.
For example:
NSString *myString = #"myString";
myString = [NSString stringWithFormat:#"myStringWithFormat"]; // Update it to something else
myString = [NSString stringWithFormat:#"The current date is: %#", [NSDate now]]; // Update it again
All three of the above examples are immutable strings that have a collective ref count of 0. You do not need to worry about releasing or allocating them.

Objective-C NSString Assignment Problem

In my Cocoa application, in the header file, I declare a NSString ivar:
NSString *gSdkPath;
Then, in awakeFromNib, I assign it to a value:
gSdkPath = #"hello";
Later, it's value is changed in the code:
gSdkPath = [NSString stringWithString:[folderNames objectAtIndex:0]];
(the object returned from objectAtIndex is an NSString)
However, after this point, in another method when I try to NSLog() (or do anything with) the gSdkPath variable, the app crashes. I'm sure this has something to do with memory management, but I'm beginning with Cocoa and not sure exactly how this all works.
Thanks for any help in advance.
EDIT: This was solved by retaining the string [gSdkPath retain].
(the object returned from
objectAtIndex is an NSString)
Are you sure? I suggest putting this in it's own temporary variable and double checking that it's not nil or invalid in some way.
Edit: If that is OK so far, do note that stringWithString returns an autoreleased object. You need to retain it if you want to use it "later".
gSdkPath = [NSString stringWithString:[folderNames objectAtIndex:0]];
[gSdkPath retain];

Crashing Strings.... :(

I have in the .h file :
NSString *dataHML;
NSString *dataHML2;
NSString *dataHML3;
NSString *dataHML4;
NSString *dataHML5;
NSString *dataHML6;
NSString *dataHMLtotal;
in the .m file I merge them with :
NSString *dataHtmlTotal = [NSString stringWithFormat:#"%#%#%#%#%#%#", dataHtml, dataHtml2, dataHtml3, dataHtml4,dataHtml5,dataHtml6];
But unfortunately it crashes at some point because of this.
Could anyone give me a other solution and post it please, because I already tried nsuserdefault or a nsarray, but without I couldn't get it working.
If you really do have 6 variables numerically named like that, you could be better off with an array.
NSMutableArray *dataHMLStrings = [NSMutableArray array];
[dataHMLStrings addObject:#"String1"];
[dataHMLStrings addObject:#"String2"];
.
.
.
[dataHMLStrings addObject:#"String100"]; // or however many you have.
NSString *dataHMLTotal = [dataHMLStrings componentsJoinedByString:#""];
You can give the componentsJoinedByString: method a different string (I passed an empty string here because you didn't want anything to appear between each dataHML string).
Please make sure your strings are all allocated and initialized (neither points of which you mention in your question.) If you do not do so then you run the risk of manipulating data at the location of the garbage pointers, and your application will very likely crash.

Do I need to release NSString generated using #"..."?

If I make an NSString using the code below, do I need to need to release someString?
NSString *someString = #"somestring";
No, it's a compile time constant string object, so it doesn't need releasing. It's the moral equiv of char *c = "hello world" -- where the string hello world is in global data, and you're assigning the address of this data to the pointer c.
If you created an object via a method call that contains alloc, retain, or copy, or starts with new (N-A-R-C = "narc"), then you are responsible for releasing the object. If this is not the case, then you can ignore the object.
So in the case of strings:
NSString * myString = #"This is a string";
I don't see a call there to a NARC method, so you are not responsible for releasing it. It's really that simple.
No, since it's a compile-time constant string, you do not need to release it. In fact, doing so will likely cause a run-time error.
I checked this case is different from NSString *someThing = #"someThing";
they should release urlString because of
[[NSString alloc] initWithFormat:#"%#%#", baseURLString, queryTerm];
Anywhere you use alloc/init you release it no mater what.
If it's a compile-time constant string, there wouldn't be a need to retain it as well. Is it correct?
So, please check what Apple does under the section "Insert Data Using a POST Request" at the following link:
I see a [urlString release];, why?