Variable is not a CFString?

Discussion in 'Mac Programming' started by larswik, Aug 19, 2011.

  1. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    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?
     
  2. Sykte macrumors regular

    Joined:
    Aug 26, 2010
    #2
    Code would help. :( Not sure what you mean by "array 1 of the NSString".
     
  3. cMacSW macrumors regular

    Joined:
    Mar 20, 2006
    #3
    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.
     
  4. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #4
    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
     

    Attached Files:

  5. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #5
    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.
     
  6. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #6
    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).
     
  7. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #7
    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];
     
  8. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #8
    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.
     
  9. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #9
    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!!!
     
  10. JoshDC macrumors regular

    Joined:
    Apr 8, 2009
    #10
    @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!
     
  11. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #11
    Are you using garbage collection or manual memory management (I know you're not using ARC, because then [super dealloc] would be illegal)?
     
  12. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #12
    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.
     
  13. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #13
    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 :)
     
  14. LostSoul80 macrumors 68020

    LostSoul80

    Joined:
    Jan 25, 2009
    #14
  15. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #15
    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.
     

Share This Page