Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Danneman101

macrumors 6502
Original poster
Aug 14, 2008
361
1
I'm receiving a EXC_BAD_ACCESS-error from trying to manipulate a string, and I'm not sure exactly where it goes wrong.

The string is a property assigned as follows:

.h-file
Code:
#import <Cocoa/Cocoa.h>
@interface TableViewController : NSTableView <NSTableViewDelegate> {
	// other stuff...
	NSString *str_CurrentPlist;  // <-- THE STRING	
}
// other stuff...
@property (assign) NSString *str_CurrentPlist;  // <-- THE STRING
@end

.m-file
Code:
#import "TableViewController.h"
@implementation TableViewController
@synthesize str_CurrentPlist;  // <-- THE STRING
// other stuff...
@end

I'm using it to update the plist currently loaded into the Array Controller which is bound to and thus populates a TableView.

In my .m-file I have a function UpdateCurrentPlistString that updates that string and adds a number to it.

Starting-value is "MENU" (which will read "MENU.plist" when in a later function I use its value to load the plist), and pressing row 1 in my tableview will give the string "MENU_1", and so on.

Code:
- (void)UpdateCurrentPlistString:(NSInteger *)n_row
{
		// IF:	"MENU"
		// -------------------
		if ([self.str_CurrentPlist isEqualToString:@"MENU"])
		{
			// SET:		Current Plist to "MENU_X"
			self.str_CurrentPlist = [self.str_CurrentPlist stringByAppendingString:@"_"];
			NSString *temp = [NSString stringWithFormat:@"%d", n_row];
			self.str_CurrentPlist = [self.str_CurrentPlist stringByAppendingString:temp];			
		}
		
		// ELSE :	"MENU_X"
		// ----------------------
		else
		{	
			// SET:		Current Plist to "MENU_X_Y"
			self.str_CurrentPlist = [self.str_CurrentPlist stringByAppendingString:@"_"];
			NSString *temp = [NSString stringWithFormat:@"%d", n_row];
			self.str_CurrentPlist = [self.str_CurrentPlist stringByAppendingString:temp];			
		}
}

This works fine the first time around, but the second time the function is called I receive the EXC_BAD_ACCESS-error.

Strangely enough, altering the code a little for debugging-purposes, this does NOT give any errors:

Code:
- (void)UpdateCurrentPlistString:(NSInteger *)n_row
{
		// IF:	"MENU"
		// -------------------
		if ([self.str_CurrentPlist isEqualToString:@"MENU"])
		{
			self.str_CurrentPlist = @"MENU_1";			
		}
		
		// ELSE :	"MENU_X"
		// ----------------------
		else
		{	
			self.str_CurrentPlist = @"MENU_1_1";		
		}
}

This leads me to the conclusion that the problem might have to do with the way I concat the string with the row-number. Could it be that the format of the string is altered, or is there something more nefarious lurking inside this code?
 
Your property is set to assign. This means that when you do:

Code:
self.str_CurrentPlist = [self.str_CurrentPlist stringByAppendingString:temp];

you assign the pointer but do not retail the object. As stringByAppendingString: returns an autoreleased string you have an issue. The normal thing to do would be to have the property set to retain, not assign.
 
So once I use the string for the first time it removes itself when set to assign, and when using retain it persists in memory and is accessible multiple times? Am I understanding this correctly?

Anyway, it works flawlessly now - thanks a lot :)

P.S. Nice to see someone supporting the free press.
 
So once I use the string for the first time it removes itself when set to assign, and when using retain it persists in memory and is accessible multiple times? Am I understanding this correctly?

Anyway, it works flawlessly now - thanks a lot :)

P.S. Nice to see someone supporting the free press.

I am making an educated guess by your verbiage that you don't understand retain/release memory management. As such, you should read this:
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/MemoryMgmt.html

Once you understand ownership this will make a lot more sense. With assign you were getting a pointer to an object you didn't own. Trying to utilize an object you don't own is verboten.

-Lee
 
BTW, are you sure you want to be passing n_row as a pointer? Maybe that should not be a pointer and just the value itself, since NSInteger is not an object, you only need to pass by reference when modifying its value.
 
Last edited:
BTW, are you sure you want to be passing n_row as a pointer? Maybe that should not be a pointer and just the value itself, since NSInteger is not an object, you only need to pass by reference when modifying its value.

So the way the code is written, the string will append a number composed from the decimal integer value of the pointer to n_row?
 
I am making an educated guess by your verbiage that you don't understand retain/release memory management. As such, you should read this:
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/MemoryMgmt.html

Once you understand ownership this will make a lot more sense. With assign you were getting a pointer to an object you didn't own. Trying to utilize an object you don't own is verboten.

-Lee

Ok, the fog regarding the topic of memory management is starting to clear (I think):

"copy" : stores a copy of the actual property, but manipulating that copy will not manipulate the actual property (the original).

"retain" : tells the compiler that the calling instance want to claim ownership of that property and retain it in memory for as long as the instance is alive (or until it is released).

"assign" : now why would you use assign when all it seems to do is create a property that you can't manipulate? Is it for read-only data, ie. a way to create constants?


kainjow said:
BTW, are you sure you want to be passing n_row as a pointer? Maybe that should not be a pointer and just the value itself, since NSInteger is not an object, you only need to pass by reference when modifying its value.

Yes, you're probably right - I should only need the value since I only read it in that function and have no intention of manipulating the original.
 
Ok, the fog regarding the topic of memory management is starting to clear (I think):

"copy" : stores a copy of the actual property, but manipulating that copy will not manipulate the actual property (the original).

"retain" : tells the compiler that the calling instance want to claim ownership of that property and retain it in memory for as long as the instance is alive (or until it is released).

"assign" : now why would you use assign when all it seems to do is create a property that you can't manipulate? Is it for read-only data, ie. a way to create constants?

Your verbiage is a little rough (there's a LOT of terminology if you haven't programmed before). The first two attributes you listed only really refers to properties that are pointers to objects.

With copy when you set the property a copy message is sent to the object you pass in. This gives you a new object you own, and you are no longer affected by what happens to the original that was passed in. When you set the property and it has a previous value, release is sent to the old object relinquishing ownership.

With retain, when an object is passed in it is sent a retain message claiming ownership. This is going to result in sharing the object so changes you make will be reflected other places the object is used, and vice versa. When a new value is set release is sent to the old value relinquishing ownership.

Assign is not meant for objects. A few things would work (NSString literals) but for the most part this flies in the face of retain/release memory management. You should use assign for primitives like int, double, NSInteger, etc. For objects you need to pick one of the other options.

-Lee
 
Your verbiage is a little rough (there's a LOT of terminology if you haven't programmed before). The first two attributes you listed only really refers to properties that are pointers to objects.

With copy when you set the property a copy message is sent to the object you pass in. This gives you a new object you own, and you are no longer affected by what happens to the original that was passed in. When you set the property and it has a previous value, release is sent to the old object relinquishing ownership.

With retain, when an object is passed in it is sent a retain message claiming ownership. This is going to result in sharing the object so changes you make will be reflected other places the object is used, and vice versa. When a new value is set release is sent to the old value relinquishing ownership.

Assign is not meant for objects. A few things would work (NSString literals) but for the most part this flies in the face of retain/release memory management. You should use assign for primitives like int, double, NSInteger, etc. For objects you need to pick one of the other options.

-Lee

That clears the last fog from my brain - thanks a lot :)

Well, I've been programming before in C# and Java, and in that case I could easily migrate concepts from one language to another. But Obj-C is an ENTIRELY different creature. Perhaps my problems with wrapping my head around Obj-C (other than being a bit daft ;) ) is a case of "learning an old dog to sit..". Without any previous knowledge of programming I wouldn't have such a hard time redefining in my head how to program, I guess :)
 
Assign is not meant for objects. A few things would work (NSString literals) but for the most part this flies in the face of retain/release memory management. You should use assign for primitives like int, double, NSInteger, etc. For objects you need to pick one of the other options.
I would dispute this point. There are some cases where it would be better for one object not to own another one yet still maintain a reference to it. This is described in reference-counted memory management as a "weak reference". It does seem a lot safer for every object to retain and release all of its object pointers, but I think there are times when using weak references makes sense. Either technique calls for due diligence in object management..
 
I would dispute this point. There are some cases where it would be better for one object not to own another one yet still maintain a reference to it. This is described in reference-counted memory management as a "weak reference". It does seem a lot safer for every object to retain and release all of its object pointers, but I think there are times when using weak references makes sense. Either technique calls for due diligence in object management..

I guess I consider this a case where I'd say "you'll figure it out when you need it". In this very thread an error was made involving using assign for an object. For the OPs current purposes, assign isn't what they are looking for. Sometimes one has to lie for the sake of simplicity, and months or years later apologize when the lie is uncovered because a need for more advanced techniques has arisen.

I don't dispute your point, but my original assumption was a newcomer to programming not just to Objective-C. Maybe the OP has dealt with and understands the need for weak references. I erred on the side of simplicity.

-Lee
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.