終於, 不用拼命抓圖了...
多虧了
這個 插件, 雖然還不能正確 Highlight Objective-C, 不過已經很好了...
好的, 第八章 Challenge
In the first edition of this book, readers created the RaiseMan application without using NSArrayController or the bindings mechanism. (These features were added in Mac OS X 10.3.) To do so, readers used the ideas from previous chapters. The challenge, then, is to rewrite the RaiseMan application without using NSArrayController or the bindings mechanism. Bindings often seem rather magical, and it is good to know how to do things without resorting to magic.
實際上, 這個Challenge, 源碼就在書上, 就是讓你打一次, 增強記憶, 然後再加入 column sorting 的功能. 但是, 事實證明, 真的, 看題目要看完...我因為沒有翻到後面的源碼, 導致自己在那邊一邊抓頭, 一邊寫從來不知道該怎麼做的同時更新兩個 column, 書上沒說....不管我怎麼做, 兩個 columns 都在那邊添加一樣的東西, apple dev doc 上面也只是說要拿到 column identifier 什麼的...後來凌晨7點多了, 沒辦法, 又看了一眼書, 差點沒暈死過去...源碼!!!!於是懷著怨恨的心情, 寫了一遍. 原來如此阿..然後它這個challenge實際上是要你熟悉一下不用binding應該怎麼處理這種...雖然我傻傻地分不清楚, 也總算在磕碰的過程中基本明白了 NSTableView 的一些用法.
但問題又來了, 還要求我要給這個 tableView 加上 sorting 的功能, 書上的例子是這樣的(改了一點):
-(void)tableView:(NSTableView *)aTableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
{
[employees sortUsingDescriptors:[aTableView sortDescriptors]];
[tableView reloadData];
}
但不管怎麼說, 當我按下想要排序的表格header的時候, 這個卻不會被 call. 然後我又找阿找, 找啊找. 終於後來給我找到了, 要他媽的在 XCode裡面設定....

要設定好 Sort Key 這裡, 然後上面那個才會被 call, 實在很賤....書上也不說....
不管怎麼說, 總算是完成了.
源碼, 猛擊放大:
Person.h
//
// Person.h
// NewRaiseMan
//
// Created by GANG ZHAO on 3/21/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface Person : NSObject {
NSString *personName;
float expectedRaise;
}
@property (readwrite,copy) NSString *personName;
@property (readwrite) float expectedRaise;
@end
Person.m
//
// Person.m
// NewRaiseMan
//
// Created by GANG ZHAO on 3/21/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "Person.h"
@implementation Person
-(id)init
{
[super init];
expectedRaise = 5.0;
personName = @"New Person";
return self;
}
-(void)dealloc
{
[personName release];
[super dealloc];
}
@synthesize personName;
@synthesize expectedRaise;
- (void)setNilValueForKey:(NSString *)key
{
if([key isEqual:@"expectedRaise"])
{
[self setExpectedRaise:0.0];
}
else
{
[super setNilValueForKey:key];
}
}
@end
MyDocument.h
//
// MyDocument.h
// NewRaiseMan
//
// Created by GANG ZHAO on 3/21/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class Person;
@interface MyDocument : NSDocument
{
IBOutlet NSTableView *tableView;
NSMutableArray *employees;
}
-(IBAction)addPerson:(id)sender;
-(IBAction)delPerson:(id)sender;
@end
MyDocument.m
//
// MyDocument.m
// NewRaiseMan
//
// Created by GANG ZHAO on 3/21/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "MyDocument.h"
#import "Person.h" //import this to avoid a compile time warning.
@implementation MyDocument
- (id)init
{
self = [super init];
employees = [[NSMutableArray alloc]init];
return self;
}
-(void)dealloc
{
[employees release];
[super dealloc];
}
-(IBAction)addPerson:(id)sender
{
Person *newPerson = [[Person alloc]init];
[employees addObject:newPerson];
[newPerson release];
[tableView reloadData];
}
-(IBAction)delPerson:(id)sender
{
NSIndexSet *rows = [tableView selectedRowIndexes];
if ([rows count] == 0) {
NSBeep();
return;
}
[employees removeObjectsAtIndexes:rows];
[tableView reloadData];
}
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [employees count];
}
-(id)tableView:(NSTableView *) tv
objectValueForTableColumn:(NSTableColumn *)tableColumn
row:(int)row
{
NSString *identifier = [tableColumn identifier];
Person *person = [employees objectAtIndex:row];
return [person valueForKey:identifier];
}
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject
forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
NSString *identifier = [aTableColumn identifier];
Person *person = [employees objectAtIndex:rowIndex];
[person setValue:anObject forKey:identifier];
}
//Sorting column
-(void)tableView:(NSTableView *)aTableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
{
[employees sortUsingDescriptors:[aTableView sortDescriptors]];
[tableView reloadData];
}
//Anything below is auto-gen codes.
- (NSString *)windowNibName
{
// Override returning the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
return @"MyDocument";
}
- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
[super windowControllerDidLoadNib:aController];
// Add any code here that needs to be executed once the windowController has loaded the document's window.
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
// Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.
// You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
// For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
}
return nil;
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
// Insert code here to read your document from the given data of the specified type. If the given outError != NULL, ensure that you set *outError when returning NO.
// You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.
if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
}
return YES;
}
@end
Posted by Daddy