PDA

View Full Version : NSString gives "EXC_BAD_ACCESS"




Danneman101
Jul 26, 2010, 09:46 PM
I keep getting "EXC_BAD_ACCESS" the second time I set an NSString using the stringByAppendingString-method.

I've tried reading up on this error, and from what I can gather it has to do with the variable not being retained.

So to remedy that I went ahead and declared the string and made it a property (using nonatomic, retain) in the h-file as such:

DetailViewController.h

...
@interface RootViewController : UITableViewController {
NSString *str_CurrentPlist;
}
@property (nonatomic, retain) NSString *str_CurrentPlist;
...



And then synthezized it in the m-file as such:

DetailViewController.m

...
@synthesize str_CurrentPlist;
...
- (void)viewDidLoad
{
...
str_CurrentPlist = @"MENU";
}
...
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([str_CurrentLevel isEqualToString:@"1"]) // Runs first time
{
str_CurrentLevel = @"2";

str_CurrentPlist = [str_CurrentPlist stringByAppendingString:@"_L"];
tempRow = [NSString stringWithFormat: @"%d", (indexPath.row + 1)];
str_CurrentPlist = [str_CurrentPlist stringByAppendingString:tempRow]; // Log p
outputs "MENU_L1", for instance
}

else if ([str_CurrentLevel isEqualToString:@"2"]) // Runs second time
{
str_CurrentLevel = @"3";

// Generates EXC_BAD_ACCESS
str_CurrentPlist = [str_CurrentPlist stringByAppendingString:@"_D"];
}
}


But despite making my string retained, in the second if-else-statment (which is run an iteration after the first if-statement), attempting to append the string results in the error.

Btw, the didSelectRow does NOT pass the scene over to another view, but remains the active view (the table simply reloads with new data from another plist).



chown33
Jul 26, 2010, 10:09 PM
All your uses of str_CurrentPlist are ivar references, not property references. Therefore, you're just assigning or fetching the ivar, not invoking the property methods.

Go back and review the docs on how to access a property from within the defining class. Simple example: self.str_CurrentPlist

My guess is you're doing the same thing with str_CurrentLevel, but you haven't posted any declaration of it, as property or ivar, so I'm just guessing.

firewood
Jul 26, 2010, 11:53 PM
If you knew C, you would know that simply assigning something to a pointer variable has no relationship whatsoever to any Objective C properties or retain counts.

Remember that Objective C syntax is a tiny subset of a much more complete language that will give you so many more ways to screw yourself if you don't learn it first.

Danneman101
Jul 27, 2010, 06:37 AM
Ok, so what I gathered from reading up on properties, it is a way to make a variable have get and set-methods. But instead of using them you can also use the simplified dot-syntax (ie. self.str_CurrentPlist) to both get and set them. In fact, simply replacing all instances of str_CurrentPlist with self.str_CurrentPlist made it work just fine.

A great tutorial on the subject can be found here:
http://www.cocoacast.com/?q=node/103

It seems the great advantage of using the get/set-methods is that they can be overridden, and thus exercise more behavior than just getting and setting the property.

Also, a simple variable can only be set to be private or public, whereas a property can have much more, well, properties like readonly, etc.

What I didnt fully understand was the ivar. Are you referring to a regular variable? Because in the tutorial he uses the name "iVar" for the property, which is a bit confusing if there is a difference between the two :)

Also, how can the compiler even allow the calling of "str_CurrentPlist" when it has been made a property that should be accessed either using dot-syntax or get/set-methods? Does this allow for a different type of use of the property, or is it simply an omission by the compiler?

Luke Redpath
Jul 27, 2010, 08:08 AM
Also, how can the compiler even allow the calling of "str_CurrentPlist" when it has been made a property that should be accessed either using dot-syntax or get/set-methods? Does this allow for a different type of use of the property, or is it simply an omission by the compiler?

Properties are simply synthesized (or dynamic) getters and setters that are backed by an instance variable, in this case, str_CurrentPlist. So when you do 'self.str_CurrentPlist' you are actually calling [self str_CurrentPlist] (the synthesized getter) and when you do 'self.str_CurrentPlist = whatever' you are calling [self setStr_CurrentPlist:whatever].

This doesn't mean you can't assign the instance variable directly; in fact, its often recommended that you do this in your initializer and dealloc methods in case you have a getter/setter that has a side-effect. But whenever you assign a value to an instance variable you must make sure that it is memory managed correctly. Generally, this means if you are assigning an auto-released value, you should make sure you retain it. Read up on Objective-C memory management rules for more on this.

Finally, as a side point, and as a matter of good Objective-C style, please try and drop the pseudo-hungarian notation. This isn't Visual Basic ;)

Danneman101
Jul 27, 2010, 10:01 AM
I see, thanks for the clarification and the suggestion :)

Hehe, yes, Im a C# programmer by day, and dont get me started on how much of a quantum-leap I feel C# is from Obj-C is in terms of intuitive syntax :p

But what is used instead of hungarian-notation in Obj-C? Googling "alternative to hungarian-notation in objective-c" and related strings doesnt result in much of a definite answer, and browsing sample-code provided by apple rather indicates that there is not alternative at all - which of course would be moronic, so I must be missing something.

firewood
Jul 27, 2010, 01:44 PM
Also, how can the compiler even allow the calling of "str_CurrentPlist" when it has been made a property that should be accessed either using dot-syntax or get/set-methods?It doesn't. But you named the property method the same as the C struct variable. And since Objective C is a strict superset of C, you can't hide C language capabilities, such as being able to do an assignment to almost anything.Does this allow for a different type of use of the property, or is it simply an omission by the compiler?
It's certainly not an omission, since that would violate the C specification.

If you don't know C, you can't program in Objective C (without infinitely more opportunities to screw up with absolutely legal syntax).

dejo
Jul 27, 2010, 01:55 PM
Also, how can the compiler even allow the calling of "str_CurrentPlist" when it has been made a property that should be accessed either using dot-syntax or get/set-methods? Does this allow for a different type of use of the property, or is it simply an omission by the compiler?

It doesn't. But you named the property method the same as the C struct variable. And since Objective C is a strict superset of C, you can't hide C language capabilities, such as being able to do an assignment to almost anything.
This is why frequently you will see properties named something like aVariableName with the corresponding ivar named _aVariableName and then "linked" to the property via the synthesizer:
@synthesize aVariableName = _aVariableName;
This way you can't access the property by aVariableName alone; you must include the self. And if you want to reference the ivar, you must use _aVariableName.

Luke Redpath
Jul 27, 2010, 04:39 PM
I see, thanks for the clarification and the suggestion :)

Hehe, yes, Im a C# programmer by day, and dont get me started on how much of a quantum-leap I feel C# is from Obj-C is in terms of intuitive syntax :p

But what is used instead of hungarian-notation in Obj-C? Googling "alternative to hungarian-notation in objective-c" and related strings doesnt result in much of a definite answer, and browsing sample-code provided by apple rather indicates that there is not alternative at all - which of course would be moronic, so I must be missing something.

There is no alternative because one isn't needed. If you have a variable pointing to an instance of a class User, for example, then call the variable 'user' (or something that has a bit more semantic value in your app domain).

I've never needed any kind of hungarian notation in all of my years programming. I don't do it when I write Ruby and I don't do it when I write ObjectiveC. All of the type information is there in the header (or for local variables, where they are declared).

Uncle Bob Martin says it best|


The Hungarian Abhorrence Principle
When you are tempted to encode data structure in a variable name (e.g. Hungarian notation), you need to create an object that hides that structure and exposes behavior.