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

klaxamazoo

macrumors 6502
Original poster
Sep 8, 2006
438
0
I am having an odd problem that I can't figure out. I am trying to fill a table with values parsed from some file names.

I am trying to fill up a tableView using the standard:
Code:
tableView:(NSTableView *)aTableView	
    objectValueForTableColumn: (NSTableColumn *) tableColumn 
                          row: (int) row
method.

However, I get an error when I return the value depending on how I set the value eblTestname in rowEblTest.eblTestName.

Code:
-(id)               tableView:(NSTableView *)aTableView	
    objectValueForTableColumn: (NSTableColumn *) tableColumn 
                          row: (int) row 

NSLog(@"CALLED - AppDelegate: objectValueForTableColumn");
    NSLog(@"FOR: tableColumn = %@", [tableColumn identifier]);
    
    NSString *tableIdentifier = [tableColumn identifier];
    NSLog(@"tableIdentifier = %@", tableIdentifier);
    
    //eblTest Table
    if (aTableView == tableView_eblTest) {
        NSLog(@"Tableview == EBL Test");
        NSLog(@"row = %i, ebltTestArray count = %lu",row, [eblTestArray count]);
        if (row <= ([eblTestArray count])) {
            NSLog(@"passEBLTestArray size check with:");
            // create local EBLTest to handle variables
            EBLTest *rowEblTest = [eblTestArray objectAtIndex: row];


            // This is where I have the error depending on how eblTestName is defined:
            NSLog(@"%@", rowEblTest.eblTestName);
            return [rowEblTest valueForKey: tableIdentifier];
        }
    }

The problem I have is when I set the eblTestName. The TableView loads just fine if I set the eblTestName directly with an arbitrary testString1 I made directly; however, but I have a memory problem is I use testString2 which comes from a custom NSObject, ImageTag, which I use to parse the filename and then pass the values between my different objects.

Code:
// initialize EBLTest object
-(id) initWithBlank {
	self = [super init];
    NSLog(@"CALLED: EBLTest - initWithBlank");
    ImageTagging *newImageTag = [[ImageTagging alloc] init];  // Initializes default ImageTag
    
    
// testString1 is hard-coded, arbitrary string
    NSString *testString1 = [NSString stringWithString: @"EBL-TA1"];
    NSLog(@"TESTSTRING = %@", testString1);         // This outputs fine
  
// testString2 is taken from a newImageTag
    NSString *testString2 = [newImageTag valueForKey:@"eblTestName"];
    NSLog(@"TESTSTRING2 = %@", testString2);        // This outputs fine
    
    // testString1 sets eblTestName correctly
    // testString2 results in a memory error once eblTestName is called from my AppDelegate
	eblTestName = [NSString stringWithString: testString2];
    
    NSLog(@"eblTestName = %@", eblTestName);        // This outputs fine
    
    dosage = 680;
    
    sampleGroupArray = [[NSMutableArray alloc] init];
	
	return self;
}

I think I have a problem with pointers or something but I can't figure it out.
 

chown33

Moderator
Staff member
Aug 9, 2009
10,751
8,425
A sea of green
Code:
// initialize EBLTest object
-(id) initWithBlank {
	self = [super init];
    NSLog(@"CALLED: EBLTest - initWithBlank");
    ImageTagging *newImageTag = [[ImageTagging alloc] init];  // Initializes default ImageTag
    
    
// testString1 is hard-coded, arbitrary string
    NSString *testString1 = [NSString stringWithString: @"EBL-TA1"];
    NSLog(@"TESTSTRING = %@", testString1);         // This outputs fine
  
// testString2 is taken from a newImageTag
    NSString *testString2 = [newImageTag valueForKey:@"eblTestName"];
    NSLog(@"TESTSTRING2 = %@", testString2);        // This outputs fine
    
    // testString1 sets eblTestName correctly
    // testString2 results in a memory error once eblTestName is called from my AppDelegate
	[COLOR="Red"]eblTestName = [NSString stringWithString: testString2];[/COLOR]
    
    NSLog(@"eblTestName = %@", eblTestName);        // This outputs fine
    
    dosage = 680;
    
    sampleGroupArray = [[NSMutableArray alloc] init];
	
	return self;
}

You have a memory management bug. Specifically, you have a "lack of ownership" bug.

The red-hilited code is almost certainly the problem. I say "almost" only because you didn't show any headers, so I can only guess that eblTestName is an instance variable.

The problem is you're storing a reference to an object you don't own. Since you didn't claim ownership, then at some later time the object will dealloc'ed, but your eblTestName still has a pointer to it. That is, eblTestName will eventually point to a dealloc'ed object. Grave disorder ensues.

http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

The solution is to claim ownership for as long as your class needs that object to exist. You must also relinquish ownership when you don't need that object in that specific class.


Your other option on Mac OS is to enable garbage collection (GC) for your app.
 

klaxamazoo

macrumors 6502
Original poster
Sep 8, 2006
438
0
You have a memory management bug. Specifically, you have a "lack of ownership" bug.

The red-hilited code is almost certainly the problem. I say "almost" only because you didn't show any headers, so I can only guess that eblTestName is an instance variable.

The problem is you're storing a reference to an object you don't own. Since you didn't claim ownership, then at some later time the object will dealloc'ed, but your eblTestName still has a pointer to it. That is, eblTestName will eventually point to a dealloc'ed object. Grave disorder ensues.

http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

The solution is to claim ownership for as long as your class needs that object to exist. You must also relinquish ownership when you don't need that object in that specific class.

Thanks you so much. I added a [testString2 retain] and it worked just fine. I thought that @property (copy) NSString would give me a copy of eblTestName when I set its value. I'm going to review the memory management and then make a few small, test programs to double-check my understanding.

Thanks,
Bob
 
Last edited:

chown33

Moderator
Staff member
Aug 9, 2009
10,751
8,425
A sea of green
I thought that @property (copy) NSString would give me a copy of eblTestName when I set its value.

It will only do that when you use property syntax:
Code:
self.eblTestName = someString;
or when you use setter-method syntax:
Code:
[self setEblTestName:someString];

The syntax you used was this:
Code:
eblTestName = someString;
which always and only means direct variable access. Direct variable access provides none of the property's declared attributes.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Thanks you so much. I added a [testString2 retain] and it worked just fine. I thought that @property (copy) NSString would give me a copy of eblTestName when I set its value. I'm going to review the memory management and then make a few small, test programs to double-check my understanding.

Thanks a lot,
Owen

I've made a habit of using setters and getters in init methods to maintain the encapsulation, even though you're already in code for the object. This way when you have properties the attributes you've given them will still be used. Those attributes are meaningless if you assign directly to an ivar with = instead of self.myProperty = or [self setMyProperty:...].

You should still review the memory management guide, but if you did things this way you would be able to depend on copy behaving as you expected.

-Lee

EDIT: Beaten to the punch.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.