Monday, July 15, 2013

MapKit Test


Just a simple test of MapKit Framework, including MKMapView navigation, adding pins via annotation and overlay :)


Sunday, July 7, 2013

Cocoa MVC




In order to help myself understand how Cocoa MVC works, I wrote a very simple program with implementations including Target-Action, delegate, datasource and KVO mechanism. What it does is to simply allow user to add/remove data in/from the tableview. It also allows editing of contents. When value in the tableview is edited, it would pop up a window displaying "Database Updated!!!". Each row has different color based on salary amount (red if >= 1000, otherwise green).

Here is the code snippet:

controller conforms to datasource and delegate protocol. Properly connections between controller and xib.

@interface TableController : NSObject <NSTableViewDataSource, NSTableViewDelegate> {
    IBOutlet NSTableView *tableview;
    NSMutableArray *database;
}

-(IBAction)add:(id)sender;
-(IBAction)remove:(id)sender;

@end


Target-Action setting for Add button; for each data, add an observer for KVO(Key-Value Observing). reloadData to enforce viewer to update itself via methods from datasource protocol. 

-(IBAction)add:(id)sender {
    Person *person = [[Person alloc]init];
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    [person addObserver:self forKeyPath:@"salary" options:NSKeyValueObservingOptionNew context:nil];
    [database addObject:person];
    [tableview reloadData];
}


For remove button, before removing takes place, remove its observer.

[person removeObserver:self forKeyPath:@"name"];
[person removeObserver:self forKeyPath:@"salary"];


Due to controller being the observer for person object, when user edits values in tableview which in turn changes values of person object, it would notify controller about the changes, here I just simply make it pop up a window.

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSAlert *alert = [[NSAlert alloc]init];
    [alert setMessageText:@"Database Updated!!!"];
    [alert addButtonWithTitle:@"OK"];
    [alert runModal];
}


Implement few methods from datasource protocol, when viewer needs to be updated or user enter new values, it would call these methods for setup.

-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {

    return [database count];
}

-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

    Person *person = [database objectAtIndex:row];
    NSString *identifier = [tableColumn identifier];
    return [person valueForKey:identifier];
}

-(void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    Person *person = [database objectAtIndex:row];
    NSString *identifier = [tableColumn identifier];
    [person setValue:object forKey:identifier];
}


Use delegate protocol to colorize cell based on salary amount

-(void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

    Person *person = [database objectAtIndex:row];
    if(person.salary >= 1000)
    {
        [cell setBackgroundColor:[NSColor redColor]];
        [cell setDrawsBackground:YES];
    }
    else {
        [cell setBackgroundColor:[NSColor greenColor]];
        [cell setDrawsBackground:YES];

    }
}