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

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
I got this error tonight and I have never seen it before, What does it mean? I instantiated an Object that contained NSString instance variables and int variables. It then took the information from NSTextFields put them into the variables and save the object to an NSMutableArray before releasing the object.

But when my TableView tries to crate a new object from the stored object in the array 1 of the NSStrings says 'Variable is not a CFString'.

What would cause that?
 
I got this error tonight and I have never seen it before, What does it mean? I instantiated an Object that contained NSString instance variables and int variables. It then took the information from NSTextFields put them into the variables and save the object to an NSMutableArray before releasing the object.

But when my TableView tries to crate a new object from the stored object in the array 1 of the NSStrings says 'Variable is not a CFString'.

What would cause that?

Code would help. :( Not sure what you mean by "array 1 of the NSString".
 
Just a guess, but as you stated "I instantiated an Object that contained NSString" and "save the object to an NSMutableArray" When the tableview is accessing the array are you assuming that the value is text to be displayed? Seeing the code here might help.
 
Sorry, it is a lot of code so I will edit it down to the problem area. I have not used all of the variables yet since I code a little and then test it for problems
Entry.h
Code:
#import <Foundation/Foundation.h>

@interface Entry : NSObject {
    int xp, level,hp;
    NSString *note; // NSTextField
    NSString *skillUsed; //NSLabel
    NSString *DOA;
@private
    
}
[COLOR="Red"]@property (copy) NSString * note; // this is where I get EXC_BAD_ACCESS and it terminates[/COLOR]
@property (copy) NSString * skillUsed;
@property (copy) NSString * DOA;
@property int xp;
@property int level;
@property int hp;

-(void)DOAEntry: (NSString *) a;
-(void)XpEntry: (int) b;
-(void)levelEntry: (int) c;
-(void)hpEntry: (int) d;
-(void)skillEntry: (NSString *) e;
-(void)noteEntry: (NSString *) f;

@end

Entry.m
Code:
#import "Entry.h"

@implementation Entry
@synthesize xp,level,hp;
@synthesize note;
@synthesize skillUsed;
@synthesize DOA;

-(void)DOAEntry: (NSString *) a{
    DOA = a;   
}
-(void)XpEntry: (int) b{
    xp = b;
}
-(void)levelEntry: (int) c{
    level = c;
}
-(void)hpEntry: (int) d{
    hp = d;
}
-(void)skillEntry: (NSString *) e{
    skillUsed = e;
}
-(void)noteEntry: (NSString *) f{
    note = f;
}
- (void)dealloc
{
    [super dealloc];
}

@end

TableViewController.m
I am editing it down to the 2 methods that are the problems.
Code:
#import "TableViewController.h"
@implementation TableViewController

- (IBAction)endCombatButton:(id)sender {  
    tempString = [DoaTextField stringValue];
    if ([tempString isEqualToString:@"DOA"]) { [COLOR="DarkOrange"]// checks to see if the DOA was changed[/COLOR]
        [errorTextField setTextColor:[NSColor redColor]];
        [errorTextField setStringValue:@"SELECT DOA FIRST"];
        return;
    }
    tempString = [levelTextField stringValue];
    if ([tempString isEqualToString:@"0"]) { [COLOR="DarkOrange"]// Checks to make sure the entered a level that is not 0[/COLOR]
        [errorTextField setTextColor:[NSColor redColor]];
        [errorTextField setStringValue:@"ENTER LEVEL FIRST"];
        return;
    }
    tempString = [DoaTextField stringValue];
    if ([tempString isEqualToString:@"DEAD"]) { [COLOR="DarkOrange"]//Adds the 250 xp points * the level if dead[/COLOR]
        hitpoints = ([levelTextField intValue] * 250) + runningCombatTotal;
    }
    else{
        hitpoints = runningCombatTotal;
    }
    totalXpValue = 0;
    Entry *newRecord = [[Entry alloc] init]; [COLOR="DarkOrange"]// instantiate a new record[/COLOR]

    [newRecord XpEntry: hitpoints]; // add the information from the textFields
    [newRecord skillEntry:[skillUsedTextField stringValue]];
    [newRecord noteEntry:[noteTextField stringValue]];
   
    [list addObject: newRecord]; [COLOR="DarkOrange"]//Adds the newRecord object to the NSMutableArray[/COLOR]
    [viewTable reloadData];
    [newRecord release]; [COLOR="DarkOrange"]// Release the object that I instantiated.[/COLOR]
    
    for (int i = 0; i < [list count]; i++) { [COLOR="DarkOrange"]// I need to add up all the XP points from all the objects in the list for a grand total.[/COLOR]
        Entry *tempEntry = [list objectAtIndex:i];
        totalXpValue = totalXpValue + [tempEntry xp];
    }
    [totalXpTextField setIntValue:totalXpValue]; [COLOR="DarkOrange"]//set the total XP points to the textField[/COLOR]
    
    [currentCombatTotalTextField setStringValue:@"0"];
    [self reset];
}
-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
    Entry *e = [list objectAtIndex:row];
    NSLog(@"skill = %@", [e skillUsed]);
    NSLog(@"xp = %d", [e xp]);
    [COLOR="Red"]NSLog(@"note = %@", [e note]); // here is where the problem starts. Not a CFSTtring Var?[/COLOR]
    NSString *identifier = [tableColumn identifier];
    return [e valueForKey:identifier];
}
Here is the interface
 

Attachments

  • xpTracker.jpg
    xpTracker.jpg
    77.5 KB · Views: 86
Why are you synthesizing properties but then using your own (incorrect) setter methods instead? E.g., to set the note you should just use

Code:
newRecord.note = [noteTextField stringValue];

Your noteEntry method is missing essential memory management code.
 
Those setters are wrong. They definitely won't work in a non-garbage collected environment (or non-ARC if you're using that), and they aren't creating a copy as the @property declaration suggests. Just use the synthesised setters. If you have to have those custom names use @property (copy, setter=aSetterName).
 
The table was a combination of learning to use tables via this tutorial http://www.youtube.com/watch?v=_Qbjwx0hB6A&feature=relmfu and blending it in to my project.

So I will use setters and getters and get rid of the @property and @synthesize

admanimal - You brought up an important point. When I started to learn about Objective C The book said you can use DOT operators or brackets and I should pick one and follow it. If that is the case then these should be the same right? My version is used with setters and getters and your version is used with @property and @synthesize. Am I correct in understanding that?
Code:
[newRecord noteEntry:[noteTextField stringValue]];
newRecord.note = [noteTextField stringValue];
 
Use the synthesised setters and getters unless you have to have custom ones!

Code:
@interface Entry : NSObject {
    NSString *note;
}

@property (copy) NSString * note;

@end 

@implementation Entry

@synthesize note

@end

Means you automatically get:

Code:
// The setter
[entry setNote:newNote];
// Which is the same as:
entry.note = newNote

// and the getter
[entry note];
// or
entry.note

Both setter/getter styles will compile to exactly the same thing.
 
Ok. Due most Obj-C programmers use both DOT operators and [] brackets? I have been trying to just be consistent and use 1 type, the brackets. But what you guys showed me it is impossible to use @properties and @synthesizers without using the DOT.

I should get in the habit of using both?

Thanks again!!!
 
@property and @synthesize gives you both styles.

Code:
[object setProperty:newProperty]

or

Code:
object.property = newProperty

You can mix and match, but (as you've been advised) you should probably choose one and stick with it. It's personal preference which one you decide on!
 
Are you using garbage collection or manual memory management (I know you're not using ARC, because then [super dealloc] would be illegal)?
 
So I will use setters and getters and get rid of the @property and @synthesize

Don't get rid of the synthesized properties. @synthesized properties work and are usually more efficient than the code that you would write yourself. But your noteEntry method is just badly wrong. It stores a pointer into the note variable instead of calling the note accessor.

I recommend having different names for member variables to avoid that kind of confusion. Call it m_note or note_ or whatever you like (in a consistent way) to avoid that kind of mistake so you only access the variable directly when you really want. And using "self" is also useful to see what's going on.

self.note = @"astring"; // Accessor method
self->note_ = @"astring"; // Stores the pointer
note = @"astring"; // Have to look at the @interface, local variables...

BTW. Both "retain" and "copy" properties take ownership of an object, so they need to be released in dealloc or you'll have a memory leak.
 
Thanks. Memory Management is my weakest area so far. I understand that when I use alloc it stays around until I release it, or autorelease which jim showed me. If I create an Object and don't alloc it in a method, I have gotten in the habit of assuming that the system will release it when the method finishes execution.

I also know that if I pass an object that I did not alloc to an NSArray or NSDictionary in a method, The system is now responsible for memory management of that object as the method ends.

Those things are embedded in me pretty good. But I have never used the COPY, RETAIN or NEW in my projects, except for this one. The only reason for this COPY was because I was watching a tutorial on NSTablesViews and he used COPY.

I need to find a project or tutorial that will show example of how and why to use them. Retain? Why retain of I instantiated the object. It's around until I release it, I own that object.

Thanks everyone again for all your help! Last time this year I was trying to understand Functions in C. Slowly but surly I am getting it :)
 
I do read the Doc's. Sometimes it makes perfect sense and other times I am still confused. The only learning tools I have are the books that I read and this forum. By doing small projects with using new code I can see how things work and build my skills.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.