Converting from ASOC to ObjC

I have an ASOC program that has a table and graph where the data can be changed on the fly via 2 sliders, but it’s a little slow, so I’m converting some of it to ObjC. I need help figuring out how to get the data to show up in the table. The Obj C code I have is :

+(NSMutableArray *)makeArray {
    NSMutableArray *theData = [NSMutableArray arrayWithContentsOfURL:[NSURL URLWithString:@"file:///Users/johndoe/documents/Grades/gradeExample.plist"]];
    NSLog(@"%@",theData);
    return theData;
}

-(IBAction)addData:(id)sender{
    NSLog(@"%@",theData);
    NSMutableDictionary *dict;
    dict=[NSMutableDictionary dictionaryWithObjectsAndKeys:newScore,@"rawScore",nil];
    [theData addObject:dict];
    NSLog(@"%@",theData);
}

I call makeArray: from the AS, and the NSLog statement shows the correct data, but nothing shows up in the table. (the content array of the array controller is bound to theData). Also, when I try to add new data via addData: both NSLogs in that method show theData to be NULL. I’m sure I’m missing something simple here, as I have little experience in Obj C coding.

Ric

Hi,

the scope of variables is almost the same as in AppleScript.
local variables (like theData in your example) are visible only in the method where they are created in.
instance variables are globals, which are declared in the interface file. They are visible everywhere in the class.

To populate a table view in Objective-C you can use a NSArrayController via bindings or
you must implement the basic table view data source delegate methods numberOfRowsInTableView: and
tableView:objectValueForTableColumn:row:

It’s not recommended to use class methods +(returnClass)method for this purpose.
Here is a simple example, you have to specify the table column identifer “rawScore” in Interface Builder,


@interface MyClass : NSObject {
	NSMutableArray *theData;
}

- (IBAction)addData:(id)sender;
@end

@implementation MyClass

- (void)awakeFromNib
{
	theData = [[NSMutableArray alloc] init];
}

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

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
	return [theData count];
}

- (id)tableView:(NSTableView *)aTableView 
objectValueForTableColumn:(NSTableColumn *)aTableColumn
			row:(NSInteger)rowIndex
{
	NSString *columnKey = [aTableColumn identifier];
	return [[theData objectAtIndex] valueForKey:columnKey];
}

- (IBAction)addData:(id)sender
{
	NSMutableDictionary *dict;
	dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"test", @"rawScore",nil];
	[theData addObject:dict];
}

@end


I’m afraid we’ll need the full interface and implementarion. What’s the tables data source?

Sorry, here is the whole code so far. I was trying to populate the table through bindings to theData like I do in ASOC (the content of the array controller is bound to controller.theData and the column is bound to Array Controller.arrangedObjects.rawScore). Is that possible in Obj C?

@interface Controller : NSObject {
    NSMutableArray *theData;
    NSNumber *maxScore;
    NSNumber *minScore;
    NSNumber *avgScore;
    NSNumber *scoreCount;
    NSNumber *minCrvdAvg;
    NSNumber *maxCrvdAvg;
    NSNumber *minCrvdStdDev;
    NSNumber *maxCrvdStdDev;
    NSNumber *newScore;
    NSNumber *curvedStdDev;
    NSNumber *curvedAvg;
}

@property (retain) NSMutableArray *theData;
@property (retain) NSNumber *maxScore;
@property (retain) NSNumber *minScore;
@property (retain) NSNumber *avgScore;
@property (retain) NSNumber *scoreCount;
@property (retain) NSNumber *minCrvdAvg;
@property (retain) NSNumber *maxCrvdAvg;
@property (retain) NSNumber *minCrvdStdDev;
@property (retain) NSNumber *maxCrvdStdDev;
@property (retain) NSNumber *newScore;
@property (retain) NSNumber *curvedStdDev;
@property (retain) NSNumber *curvedAvg;

-(IBAction)addData:(id)sender;
-(IBAction)setupValues:(id)sender;
-(IBAction)moreSetup:(id)sender;
-(IBAction)getCurved:(id)sender;
-(IBAction)writeToFile:(id)sender;
+(NSMutableArray *)makeArray;

#import "Controller.h"


@implementation Controller

@synthesize theData;
@synthesize maxScore;
@synthesize minScore;
@synthesize avgScore;
@synthesize scoreCount;
@synthesize minCrvdAvg;
@synthesize maxCrvdAvg;
@synthesize minCrvdStdDev;
@synthesize maxCrvdStdDev;
@synthesize newScore;
@synthesize curvedStdDev;
@synthesize curvedAvg;

+(NSMutableArray *)makeArray {
    NSMutableArray *theData = [NSMutableArray arrayWithContentsOfURL:[NSURL URLWithString:@"file:///Users/johndoe/documents/Grades/gradeExample.plist"]];
    NSLog(@"%@",theData);
    return theData;
}

-(IBAction)addData:(id)sender{
    NSLog(@"%@",theData);
    NSMutableDictionary *dict;
    dict=[NSMutableDictionary dictionaryWithObjectsAndKeys:newScore,@"rawScore",nil];
    [theData addObject:dict];
    NSLog(@"%@",theData);
}
-(IBAction)setupValues:(id)sender{}
-(IBAction)moreSetup:(id)sender{}
-(IBAction)getCurved:(id)sender{}
-(IBAction)writeToFile:(id)sender{}

@end

Ric

As Stefan suggested, using a class method like that won’t work. theData is an instance variable; you can’t use it in a class method.

Ok, I’ve changed the first method to the following, which I call from my app delegate:

-(void)doStartup {
    theData = [NSMutableArray arrayWithContentsOfURL:[NSURL URLWithString:@"file:///Users/johndoe/documents/Grades/gradeExample.plist"]];
    NSLog(@"%@",theData);
}

However, I still have the same problem --still no connection to the table, and I still can’t see theData outside that method.

Ric

You should be using setTheData if you want it key-value observable for bindings.

Bindings require Key Value Coding, that means variables must be get/set by their accessor methods,
in case of a property this is sufficient

self.theData = . 

PS: the root object of a standard plist file is a dictionary, not an array

I tried setTheData:the Data and I tried self.theData =, and I still get the same result.

-(void)doStartup {
    self.theData = [NSMutableArray arrayWithContentsOfURL:[NSURL URLWithString:@"file:///Users/janicedelmar/documents/Grades/gradeExample.plist"]];
    NSLog(@"%@",theData);

Ric

I found out that having my AS (which is the app delegate) be a subclass of my objective c class was somehow screwing things up. I changed the parent back to NSObject and changed some theDatas to self.thedatas and now the table gets populated, and the addData method works as well.

#import "Controller.h"

@implementation Controller

@synthesize theData;
@synthesize maxScore;
@synthesize minScore;
@synthesize avgScore;
@synthesize scoreCount;
@synthesize minCrvdAvg;
@synthesize maxCrvdAvg;
@synthesize minCrvdStdDev;
@synthesize maxCrvdStdDev;
@synthesize newScore;
@synthesize curvedStdDev;
@synthesize curvedAvg;

-(void)doStartup {
    self.theData=[NSMutableArray arrayWithContentsOfURL:[NSURL URLWithString:@"file:///Users/janicedelmar/documents/Grades/gradeExample.plist"]];
}

-(IBAction)addData:(id)sender{
    NSMutableDictionary *dict;
    dict=[NSMutableDictionary dictionaryWithObjectsAndKeys:newScore,@"rawScore",nil];
    [theData addObject:dict];
    self.theData=theData;
}

I don’t know if the “self.theData=theData;” statement is the right way to go, but it works.

Ric

And we seem to have answered tellboy’s question from the other thread,too :smiley:

I am still pondering.:smiley: