该版本的RaiseMan不用Array Controller,全部手写代码。

要注意的有以下几点:

1.TableView每列的sort设置和AC版的相同,但要手写排序代理方法

2.TableView和add、remove按钮的绑定和一般cocoa程序相同

3.需要添加TableView每列的id

4.需要手写TableView的DataSource和Delegate的相关方法

5.Person类和AppDelegate类方法和AC版的相同

代码如下:

Document.h

//
//  Document.h
//  RaiseMan_No_AC
//
//  Created by kinds on 15/6/29.
//  Copyright (c) 2015年 hopy. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface Document : NSDocument{
    NSMutableArray *employees;
}
@property (weak) IBOutlet NSButton *removeButton;
@property (weak) IBOutlet NSTableView *tableView;
- (IBAction)remove:(id)sender;
- (IBAction)add:(id)sender;

@end

Document.m

//
//  Document.m
//  RaiseMan_No_AC
//
//  Created by kinds on 15/6/29.
//  Copyright (c) 2015年 hopy. All rights reserved.
//

#import "Document.h"
#import "Person.h"

@interface Document ()

@end

@implementation Document

- (instancetype)init {
    self = [super init];
    if (self) {
        // Add your subclass-specific initialization here.
        employees = [NSMutableArray array];
    }
    return self;
}

- (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.
}

+ (BOOL)autosavesInPlace {
    return YES;
}

- (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 @"Document";
}

-(void)awakeFromNib{
    [_removeButton setEnabled:NO];
}

- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
    // Insert code here to write your document to data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning nil.
    // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
    [NSException raise:@"UnimplementedMethod" format:@"%@ is unimplemented", NSStringFromSelector(_cmd)];
    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 outError != NULL, ensure that you create and set an appropriate error when returning NO.
    // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
    // If you override either of these, you should also override -isEntireFileLoaded to return NO if the contents are lazily loaded.
    [NSException raise:@"UnimplementedMethod" format:@"%@ is unimplemented", NSStringFromSelector(_cmd)];
    return YES;
}

-(NSInteger)numberOfRowsInTableView:(NSTableView *)tv{
    return [employees count];
}

/*
-(BOOL)tableView:(NSTableView*)tv shouldSelectRow:(NSInteger)row{
    NSLog(@"%s:selected row is %ld",__func__,row);
    return YES;
}
*/

-(void)tableView:(NSTableView *)tv sortDescriptorsDidChange:(NSArray *)oldDescriptors{
    NSArray *sort_descriptors = [tv sortDescriptors];
    NSLog(@"%s:%@",__func__,sort_descriptors);
    [employees sortUsingDescriptors:sort_descriptors];
    [tv reloadData];
}

-(void)tableViewSelectionDidChange:(NSNotification*)notification{
    NSLog(@"entry %s",__func__);
    if([[_tableView selectedRowIndexes] count] == 0)
        [_removeButton setEnabled:NO];
    else
        [_removeButton setEnabled:YES];

}

-(id)tableView:(NSTableView*)tv objectValueForTableColumn:(NSTableColumn *)tableColumn
        row:(NSInteger)row{
    NSString *col_id = [tableColumn identifier];
    Person *person = [employees objectAtIndex:row];
    return [person valueForKey:col_id];
}

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

}

- (IBAction)remove:(id)sender {
    NSLog(@"entry %s",__func__);
    NSIndexSet *rows = [_tableView selectedRowIndexes];
    //NSLog(@"rows is %@",rows);
    if([rows count] == 0) {
        NSBeep();
        return;
    }
    [employees removeObjectsAtIndexes:rows];
    [_tableView reloadData];
}

- (IBAction)add:(id)sender {
    NSLog(@"entry %s",__func__);
    Person *employee = [Person new];
    [employees addObject:employee];
    [_tableView reloadData];
}
@end

cocoa编程第4版 8.6 挑战2 解答的更多相关文章

  1. cocoa编程第4版 8.5 挑战1 解答

    看似简单,其实也很简单,但开始思路想错了:还上网查了一下,有网友说是将Array Controller的Keys中的personName改为personName.length,好像完全不起作用. 后来 ...

  2. 苹果开发之COCOA编程(第三版)上半部分

    第一章:什么是Cocoa 1.1 历史简介 1.2 开发工具:Xcode.Interface Builder(一个GUI构建工具).在它们内部,使用gcc为编译器来编译代码,并使用gdb来查找错误 1 ...

  3. 苹果开发之COCOA编程(第三版)下半部分

    第十八章:Image和鼠标事件 1.NSResponderNSView继承自NSResponder类.所有的事件处理方法都定义在NSResponder类中.NSResponder申明了如下方法:- ( ...

  4. 《苹果开发之Cocoa编程》挑战2 创建一个数据源 练习

    <苹果开发之Cocoa编程>第4版 P87 创建一个to-do list应用程序,在文本框中输入任务.当用户单击Add按钮时,添加字符串到一个变长队列,新任务就出现在list的末尾. 关键 ...

  5. 《苹果开发之Cocoa编程》挑战1 创建委托 练习

    <苹果开发之Cocoa编程>第4版 P87 新建一个单窗口应用程序,设置某对象为窗口的委托,当用户调整窗口尺寸时,确保窗口高度为宽度的2倍. 需要实现的委托方法为:-(NSSize)win ...

  6. 教孩子学编程 python语言版PDF高清完整版免费下载|百度云盘|Python入门

    百度云盘:教孩子学编程 python语言版PDF高清完整版免费下载 提取码:mnma 内容简介 本书属于no starch的经典系列之一,英文版在美国受到读者欢迎.本书全彩印刷,寓教于乐,易于学习:读 ...

  7. 《UNIX网络编程(第3版)》unp.h等源码文件的编译安装

    操作系统:Mac OS X 10.11.5 1.下载书中的源代码:点击下载 2.切换到解压后的目录 unpv13e,先查看下 README,依次执行: ./configure cd lib make ...

  8. Cocoa编程开发者手册

    Cocoa编程开发者手册(Objective-C权威著作超一流翻译阵容) [美] 奇斯纳尔(Chisnall,D.)  著 霍炬等 译 ISBN 978-7-121-12239-2 2013年7月出版 ...

  9. 【转】apue《UNIX环境高级编程第三版》第一章答案详解

    原文网址:http://blog.csdn.net/hubbybob1/article/details/40859835 大家好,从这周开始学习apue<UNIX环境高级编程第三版>,在此 ...

随机推荐

  1. xlsx批量转为utf8的csv

    xlsx批量转为utf8的csv(金庆的专栏)策划的配置表为 xlsx 表格,可以有注释,公式.服务器和客户端使用的配置文件需要转成 csv 文件.使用 WPS 另存无法批量转换,并且结果不是utf8 ...

  2. Java之equals和==详解

    两者的区别: A:== 基本类型:比较的是值是否相同 引用类型:比较的是地址值是否相同 B:equals() 只能比较引用类型. 默认情况下,比较的是地址值是否相同,因为我们可以看源代码可以看到,在O ...

  3. 电脑hash破解

    我一直在想,到底用什么样的方式才能较长时间地控制已经得到了权限的目标呢?留后门,种木马,甚至是Rootkit?留的Webshell痕迹太明显,哪怕是一句话的Webshell,都极容易被管理员清除.放了 ...

  4. ROS_Kinetic_x 基於ROS和Gazebo的RoboCup中型組仿真系統(多機器人協作)

    國防科學技術大學發布了RoboCup中型組仿真平臺,基於ROS和Gazebo設計. 該平臺可以用於多機器人協作研究.參考資料如下: ROS新聞:1    http://www.ros.org/news ...

  5. 使用Broadcast实现android组件之间的通信

    android组件之间的通信有多种实现方式,Broadcast就是其中一种.在activity和fragment之间的通信,broadcast用的更多本文以一个activity为例. 效果如图: 布局 ...

  6. UNIX网络编程——产生RST

    产生RST的3个条件:1. 建立连接的SYN到达某端口,但是该端口上没有正在监听的服务.   如:IP为192.168.1.33的主机上并没有开启WEB服务(端口号为0x50),这时我们通过IE去访问 ...

  7. ECMAScript 6之Set和Map数据结构

    Set 基本用法 ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set本身是一个构造函数,用来生成Set数据结构. var s = new Set(); [2, ...

  8. JavaScript实现的网页放大镜效果

    今天在观看视频学习的时候,学到了一个小技巧.就拿过来与大家进行分享一下啦. 实现的原理 分析需求:需要两张图,一大一小.然后根据鼠标的动作显示出不同的区域块的图像. 核心:鼠标事件的获取和处理.图片显 ...

  9. 如何在Cocos2D 1.0 中掩饰一个精灵(四)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 为了完成需要的效果,我们将使用如下策略: 我们将首先绘制掩饰精灵 ...

  10. design principle:java 回调与委派/委托机制

    博客 design principle:模拟 android Button 控件点击事件 主要说了一下模拟 android 的 Listener 模式,其实这就是一种委派与回调机制的体现. 委派,也可 ...