NSString gives "EXC_BAD_ACCESS"

Discussion in 'iPhone/iPad Programming' started by Danneman101, Jul 26, 2010.

  1. macrumors 6502

    Joined:
    Aug 14, 2008
    #1
    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
    Code:
    ...
    @interface RootViewController : UITableViewController {
    	NSString *str_CurrentPlist;
    }
    @property (nonatomic, retain) NSString *str_CurrentPlist;
    ...
    

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

    DetailViewController.m
    Code:
    ...
    @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).
     
  2. macrumors 603

    Joined:
    Aug 9, 2009
    #2
    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.
     
  3. macrumors 603

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #3
    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.
     
  4. thread starter macrumors 6502

    Joined:
    Aug 14, 2008
    #4
    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?
     
  5. macrumors 6502a

    Joined:
    Nov 9, 2007
    #5
    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 ;)
     
  6. thread starter macrumors 6502

    Joined:
    Aug 14, 2008
    #6
    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.
     
  7. macrumors 603

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #7
    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.
    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).
     
  8. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    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:
    Code:
    @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.
     
  9. macrumors 6502a

    Joined:
    Nov 9, 2007
    #9
    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|

     

Share This Page