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

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
1
Sorry if this is a newbish question, but I have so far got used to make programs only by using very standard features that concern key-value coding. I have this simple piece of code:

Code:
#import <Foundation/Foundation.h>

@interface test:NSObject{
	NSMutableString *simpleValue;
	NSMutableArray *simpleArray;
}


@end


@implementation test:NSObject
- (id) init {
	self = [super init];
	if (self != nil) {
		simpleValue = [NSMutableString stringWithString:@"hello world!"];
		simpleArray = [NSMutableArray arrayWithObjects:@"hello 1", @"hello 2", nil];
	}
	return self;
}

- (void) dealloc {
	[simpleValue release];
	[simpleArray release];
	[super dealloc];
}

@end

int main (int argc, char *argv[])
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	test *t = [[test alloc]init];
	[t takeValue:@"hello again!" forKey:@"simpleValue"];
	NSLog(@"%@",[t valueForKey:@"simpleValue"]);
	
	
	[pool release];
	return 0;
}

When ran, the debugger gives me a runtime error at the "[pool release]" line. Why is that? What is key-value coding in general, and how can I make my classes use it?
 

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
1
What's the error?

Apple have a great guide to Key Value coding.

Basically it's a nice way to provide generic access to an objects properties in a predictable and controllable method. Bindings is built directly on top of this...

Actually, the debugger comes up, and it doesn't tell me what the error is. I guess you must compile and run it to see for yourself.

the following code gives me errors again...
Code:
#import <Foundation/Foundation.h>

@interface test: NSObject
{
	NSString *simpleValue;
	NSArray *simpleArray;
}

-(void)setSimpleValue:(NSString *)newValue;
-(void)setSimpleArray:(NSArray *)newArray;

-(NSArray *)getSimpleArray;
-(NSString *)getSimpleValue;

@end


@implementation test
- (id) init {
	self = [super init];
	if (self != nil) {
		simpleValue = [NSMutableString stringWithString:@"hello world!"];
		simpleArray = [NSMutableArray arrayWithObjects:@"hello 1", @"hello 2", nil];
	}
	return self;
}


-(void)setSimpleValue:(NSString *)newValue
{
	[simpleValue release];
	simpleValue = [newValue retain];
}

-(void)setSimpleArray:(NSArray *)newArray
{
	[simpleArray release];
	simpleArray = [newArray retain];
}


-(NSArray *)getSimpleArray
{
	return simpleArray;
}

-(NSString *)getSimpleValue
{
	return simpleValue;
}

- (void) dealloc {
	[simpleValue release];
	[simpleArray release];
	[super dealloc];
}

@end

int main (int argc, char *argv[])
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	
	test *testClass = [[test alloc]init];
	
	[testClass setValue:@"hello world!" forKey:@"simpleValue"];
	NSLog([testClass getSimpleValue]);
	
	
	[pool release];
	return 0;
}

...but I don't know why
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Bad memory management...

When you create an instance of the test class you create two objects that are autoreleased (simpleValue and simpleArray). When you then call setSimpleValue this autoreleased object is released again. You should never release an object you have not retained...

So when your pool gets released it tries to release all the objects in it. But you've released it and it crashes.

If you retain the two objects it doesn't crash

A better solution to init is to do something like:

Code:
- (id) init {
	self = [super init];
	if (self != nil) {
		[self setSimpleValue:@"hello world!"];
	}
	return self;
}

This will cause any bindings to get triggered: your way does not...
 

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
1
That corrected the problem I was having. Thanks a lot robbieduncan!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.