cocoa教程1 - HelloWorld !
首先, 使用Xcode来创建一个新的project. 这里假设你已经安装了开发工具. 如果还没有, 可以用开发光盘或者系统光盘安装, 或者在http://connect.apple.com注册免费下载.
- 打开Xcode, 它的默认安装路径是 /Developer/Applications/
- File菜单 : New Project...
- 选择 "Cocoa Application" 这个模板. 一开始常用的两个模板就是这个和 "Cocoa Document-based Application". 后者适用于具有多个相似窗口的应用程序, 比如文本处理器.
- 点击 "Next"
- 输入一个Project名字 (默认的路径是你的用户目录, 这个没什么问题). 输入 "HelloWorld" .
- 点击 "Finish".
- 这时你的 project 窗口就出现了.
- 现在看看产生了哪些文件. 在左边一栏, 点击 "Classes", "Other Sources", 和 "Resources" 左边的小箭头.
Classes 现在应该是空的. 你可以在这里创建新的类文件. 对于大的project, 可以生成更多象这三个这样的组别, 以便于管理, 不过现在这样就好了.
Other Sources 里面是默认的 "main.m" 文件和另一个 "HelloWorld_Prefix.pch". 大多数时候你不用修改这两个文件. "main.m" 里面是应用程序的入口.
Resources 里有三个文件:
Info.plist 应用程序的设置文件, 应用程序名, 版本号, 图标名等可以在这里设置, 现在用默认的就行了.
MainMenu.nib, 是一个 InterfaceBuilder 文件, 用于存储所有界面项目. 后面会说到.
InfoPlist.strings, 含有关于系统信息的字符串, 如果打开看就一目了然了.
后两个左边也有个小箭头, 这是因为本地化的相应的文件要分别加入到这两个组别.
- 现在尝试编译并执行, 可以点击窗口上面的 "build and go", 或者使用 Build 菜单里面对应的命令.
在一阵短暂的时间后会出来一个空的窗口. 现在退出这个新的 Hello World 应用程序.
使用 Interface Builder 来定义用户界面
在这一步, 我们用 Interface builder 来轻微改变一下界面.
- 首先双击 Xcode 里面的 MainMenu.nib . 这就会启动 Interface Builder 并打开这个 .nib 文件.
- 看看这个 "MainMenu.nib" 窗口. 这就是刚刚打开的文件. Interface builder 应该也打开了它的两个项目: "MainMenu", 和 一个空的 window (对应于 MainMenu.nib 里的 Window).
- 现在改一下 MainMenu. 点击第一个菜单, 并将所有的"NewApplication" 改为 "HelloWorld".
你可以更改其他的菜单, 如果需要的话, 或者删除一些, 因为他们在这个教程里用不上, 但是也没有害处, 就保留在那吧.
- 现在在点击窗口 window, 往里添加一些东西. 如果它不在桌面上的话, 双击 "MainMenu.nib" 里面的 "window" 使它出现.
在 "Tools" 菜单里, 选择 "Attributes Inspector" 出来一个新的面板, 叫 "Window Attributes".
- 更改 window 的标题为 "Hello World". 在 "Window Attributes" 的 "Title" 一栏编辑.
- 调整这个窗口的大小, 把它弄小一点.
- 在 "Window Attributes" 里去掉 Resize 左边的勾, 这样程序的用户将不能改变窗口的大小.
- 现在点击 interface builder 一开始打开的一个 library 面板, 点开 Cocoa , 选择 View & Cells.
- 滚动右侧移动条, 使出现 "Label", 将其用鼠标拖到 window 中. 双击这个Label来修改其文本内容.
- 有兴趣的话, 可以在 window 里添加其他的东西.
- 使用 "Command-R" 快捷键可以立刻查看界面的效果
- 输入 "Command-Q" 退出测试模式.
- 存储这个改动并退出 Interface Builder.
Back in Xcode (回到Xcode)
- 现在点击 "Build and Run" 按钮. 你这样就可以看到 MainMenu 里面的改变以及 window 里面的内容.
- 如果退出Xcode, 编译好的程序可以在project目录的build目录里找到.
就这些了吗?
是的, 对这个教程而言, 是这样. 当然, 这个教程并没有展示多少, 但希望能帮你看到使用苹果的工具和Cocoa能很容易的创建真的不错的用户界面.
可以自己熟悉一下用户界面里可以使用的各种控件. 虽然暂时不知道怎么使用, 但是以后会接触到.
下一个教程将增加objective-C代码, 并介绍 Outlets 和 Actions.
cocoa教程2 - Outlets 和 Actions
第一步是连接
- 首先用Xcode生成一个新的 project , 取个名叫 Electricity.
- 双击 project 里的 "MainMenu.nib" , 启动 Interface Builder.
- 从 Library 面板里拖下面的控件到 Window 窗口里, 是一个滑动条和一个文本编辑框.
- 如果现在保存并执行这个应用程序, 会发现这两个部件已经能工作. 不过你肯定想做一些比这更多的, 比如在文本框里显示滑动条的数值.
要做到这个, 在按住Ctrl的同时, 左键点住滑动条, 拖动鼠标到文本框上, 然后放开鼠标. 屏幕上会出现一个连接菜单.
- 在 "Received Actions" 里选择 takeIntValueFrom. 这是告诉文本框从滑动条获得整数值, 就是指针所在位置.
- 保存并测试这个应用程序, 现在文本框显示的是滑动条的指针位置的数值.
一个控制部件
- 现在进一步, 在窗口里添加下面的两个部件, 一个按钮, 一个标签:
- 这里想要做的是让下面的标签显示滑动条的指针位于左边还是右边. 要做到这个, 必须增加一些代码 (哈哈, 终于要动手写了).
- 首先要创建一个控制 "controller" 物件. 象它的名字说的那样, 这个 controller 是用来控制窗口里发生什么的. 如果想知道一些更详细的介绍, 苹果的文档是个好的阅读资料, 读读关于 MVC (Model / View / Controller), (模型 / 视图 / 控制器) 的部分. 本教程暂时不去理会这些.
在 Library 面板里点开 Cocoa 后, 选择 Objects & Controllers. 拖动一个 "NSObject" 到 MainMenu.nib 窗口里. 这是根物件 root object, 我们的 controller 物件只需从它继承一些通用的性质即可.
在 Tool 菜单里选择 Identity Inspector, 在出现的 Identity 面板里在 class 那一栏输入 "ElectricityController"
- 然后添加两个 outlets 和一个 action. Outlets 便于你在代码中访问其他部件, 它相当于函数编程里一个传递数据的指针类型参数. Actions 是一个被某个事件(比如点击一个按钮)激活的方法, 也就是本控制器可以被外界调用的一个函数.
- 添加下面的 outlets 和 actions:
- 接着, 来编写相应的代码. 因为Xcode和interface builder在这方面的同步不是很好, 我们的方法是先到Xcode里, 选择 File 菜单里的 New file, 然后在出来的窗口里选择Cocoa里面的Objective-C Class, 接下来输入 "ElectricityController.m" 作为这个新建立类的文件名, 点击 finish 结束, 在project的class一组可以看到新增加俩个代码文件. 然后回到 interface builder, 点击选择 MainMenu.nib 里的 "ElectricityController", 接着在 File 菜单里选择 write class file, 在出现的窗口里, 默认路径应该是本project的路径, 如果不是, 请选择回来. 然后点击 Save 保存. 下面会提示你要 merge 合并, 还是 replace 替换, 选择 replace.
- 现在回到Xcode, 双击打开新增加的那两个文件, 你会看到下面的代码已经在里面了.
代码:
#import <Cocoa/Cocoa.h>
@interface ElectricityController : NSObject {
IBOutlet id textZone;
IBOutlet id topSlider;
}
- (IBAction)whereButtonAction:(id)sender;
@end
代码:
#import "ElectricityController.h"
@implementation ElectricityController
- (IBAction)whereButtonAction:(id)sender {
}
@end
第一个是头文件, 含有这个类的定义, 第二个含有实现这个类的代码, 现在基本是空的.
- 现在回到 interface builder, 来做必要的连接, 还记得按住ctrl, 然后左键点击并拖动鼠标进行连接吗?
从 ElectricityController 到滑动条 : 选择 topSlider 这个 outlet.
从 ElectricityController 到最下面的文本标签 : 选择 textZone 这个 outlet.
从 按钮 到 ElectricityController : 选择 Received Actions 里的 whereButtonAction.
让我们来修改代码
- 在 interface builder 里点击 File 菜单, 选择 Save 保存. 回到Xcode来修改 ElectricityController.m 双击打开它.
- 我们要修改点击按钮所发生的事件, 这将用到前面建立的 action.
用下面的代码替换 -whereButtonAction
代码:
- (IBAction)whereButtonAction:(id)sender {
if ([topSlider intValue]<50)
[textZone setStringValue:@"Cold"];
else
[textZone setStringValue:@"Hot"];
}
如果还没有, 现在是时候你要认识一下 Objective-C 语言了. 比如去苹果网站阅读一下相关的文档.
那么, 这些代码是做什么呢?
第一行是问滑动条的数值是多少, 并与50进行比较
如果小于 50, 设置文本标签的内容为 Cold. @"Cold" 代表一个 NSString 类型的字符串常数.
否则做同样的事情, 但是显示 "Hot".
试试你的应用程序!
- 点击 Build and Run 按钮测试你的代码!
新Project
先创建一个新的project :
启动 Xcode
File 菜单 : New Project
在对话框里, 选择 "Cocoa Application"
点击 Next
Project 名 : POPreferences
点击 Finish
现在来设置一个 preference 预置文件:
点击 Targets 组别左边的小箭头
双击里面的 POPreferences
点击 Propertities
在 identifier 一栏, 输入 "org.projectomega.popreferences", 或者其他你喜欢的. 应用程序的预置设置将存储在一个名为这个的plist文件中, 该文件的默认路径是 ~/Library/Preferences/
这里使用的是 Java类型的规则来命名这个 preference 预置文件, 这也是苹果推荐的 (某种程度是URL地址反过来写). 这样做主要的一个好处是 preference 文件将会按出品公司归在一起.
使用 Interface Builder 来设计
现在来设计本教程要用到的对话框.
在 Xcode 里展开 "Resources" 组别
双击 MainMenu.nib 启动 Interface Builder 打开它.
把你的窗口改成象下面的样子. 这包括大多数 preferences 要用到的控件. Radio控件默认是2个供选择项, 可以在Attributes Inspector里的Cells一栏改成需要的数目. 另外, 需要在 Radios 每一项的Attributes Inspector里设置它们的tag分别为:0, 1, 2, 3, 对应于 Radio 1, Radio 2, Radio 3, Radio 4, 在后面将用到. 要选中单独的某个 Radio 项, 可能需要点击几次对应项, 直到这一项被高亮显示.
创建 Outlets/Actions
现在要为这个对话框生成一个 controller 物件, 并添加 outlets/actions, 用前一个教程里同样的方法.
点击 Library 面板
拖动一个 NSObject 到 MainMenu.nib 窗口内
在Identity面板里命名class为 " PrefController "
添加5个 outlets (每个控件一个) 和 2个 actions, 并按下图命名:
现在, 创建 PrefController 类:
象上个教程里一样, 先回到Xcode,
File 菜单, New file, 选择 Objective-C Class, 命名为PrefController.m, finish完成, 生成 PrefController.h and PrefController.m.
再回到 Interface Builder, 确认选择 MainMenu.nib 里的 PrefController, 然后
File 菜单, Write class file, 选择project所在路径(如果默认值不是的话), 之后 replace 替换.
现在Xcode里面这两个新文件应为以下内容:
代码:
#import <Cocoa/Cocoa.h>
@interface PrefController : NSObject {
IBOutlet id PrefEdit;
IBOutlet id PrefPopup;
IBOutlet id PrefRadios;
IBOutlet id PrefSlider;
IBOutlet id PrefSwitch;
}
- (IBAction)PrefRestoreAction:(id)sender;
- (IBAction)PrefSaveAction:(id)sender;
@end
代码:
#import "PrefController.h"
@implementation PrefController
- (IBAction)PrefRestoreAction:(id)sender {
}
- (IBAction)PrefSaveAction:(id)sender {
}
@end
连接 Outlets/Actions
回到 Interface Builder 来连接 actions 和 outlets 到不同的部件, 还是使用 ctrl+鼠标拖动.
从 "Restore" 按钮到位于 MainMenu 里的 " PrefController ", 选择Receive Actions里的PrefRestoreAction
同样的, 连接 "Save" 按钮到" PrefController "的 PrefSaveAction
再从 PrefController 连接 outlets 到相应的部件. 最后Connection Inspector面板里应该显示如下:
最后从 "File's Owner" 连接到 " PrefController", 并选择 delegate 委托. 这样关于应用程序开始, 关闭等等的信息就会通知 PrefController, 方便我们使用对应的委托方法去处理这些信息, 比如本project的预置值的读取和存储比较适合于这些时候处理.
头文件
保存并退出 Interface Builder, 回到 Xcode 添加代码 !
将 IBOutlet 的类型id细化为相应的具体类型是一个好习惯, 所以将 " PrefController.h" 文件改成下面的样子:
代码:
#import <Cocoa/Cocoa.h>
@interface PrefController : NSObject
{
IBOutlet NSTextField* PrefEdit;
IBOutlet NSPopUpButton* PrefPopup;
IBOutlet NSMatrix* PrefRadios;
IBOutlet NSSlider* PrefSlider;
IBOutlet NSButton* PrefSwitch;
}
- (IBAction)PrefRestoreAction:(id)sender;
- (IBAction)PrefSaveAction:(id)sender;
@end
现在来编辑 " PrefController.m". 下一节将解释细节.
代码:
#import "PrefController.h"
@implementation PrefController
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
// 自动存储窗口位置
[[PrefEdit window] setFrameAutosaveName:@"PrefWindow"];
// 自动恢复预置值
[self PrefRestoreAction:self];
}
- (IBAction)PrefRestoreAction:(id)sender
{
// 读取 preference 预置文件
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// 文本框
// 获得 preference 预置值, 或者设置默认值
NSString *mystr = [defaults stringForKey:@"EditField"];
// 如果 预置值, 或者设置默认值不存在, 生成一个
if (mystr == nil)
mystr = @"Empty";
// apply the value to the dialog
[PrefEdit setStringValue:mystr];
// 弹出菜单
// 获得 preference 预置值, 或者设置默认值
int pos = [defaults integerForKey:@"Popup"];
// 如果 预置值, 或者设置默认值不存在, 0 会被返回, 也可以做为默认值
// 将这个值应用到对话框
[PrefPopup selectItemAtIndex:pos];
// RADIO 按钮
int posradios = [defaults integerForKey:@"Radios"];
[PrefRadios selectCellWithTag:posradios];
// 滑动条
int slider = [defaults integerForKey:@"Slider"];
[PrefSlider setIntValue:slider];
// SWITCH 按钮
int myvalue = [defaults integerForKey:@"Switch"];
[PrefSwitch setIntValue:myvalue];
}
- (IBAction)PrefSaveAction:(id)sender
{
// 读取 preference 预置文件
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// 文本框
// 从文本框获得文本
NSString* mystr = [PrefEdit stringValue];
// 存储这个文本物件
[defaults setObject:mystr forKey:@"EditField"];
// 弹出菜单
// 获得选项值
int pos = [PrefPopup indexOfSelectedItem];
// 存储这个值
[defaults setInteger:pos forKey:@"Popup"];
// RADIO 按钮
int posradios = [PrefRadios selectedRow];
[defaults setInteger:posradios forKey:@"Radios"];
// 滑动条
int slider = [PrefSlider intValue];
[defaults setInteger:slider forKey:@"Slider"];
// SWITCH 按钮
int myvalue = [PrefSwitch intValue];
[defaults setInteger:myvalue forKey:@"Switch"];
}
@end
代码:
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
// 自动存储窗口位置
[[PrefEdit window] setFrameAutosaveName:@"PrefWindow"];
// 自动恢复预置值
[self PrefRestoreAction:self];
// 显示窗口
[[PrefEdit window] makeKeyAndOrderFront:nil];
}
代码:
[[PrefEdit window] setFrameAutosaveName:@"PrefWindow"];
存储 preference 预置值
- 首先, 你需要读取那个 default 默认文件, 它的名字在一开始就已经确定了:
- 从控件里获得对应的数值 (或者就是一个已经存在的 variable 变量)
- 存储这些值到 default 默认文件. 在这里, 比如把 preference 的 "myvalue" 存到 "Switch" 这个 Key. 恢复 preference 预置值
- 首先, 象前面一样, 你需要读取那个 default 默认文件. - 接着, 下面这行提取 preference 里叫 " Popup" 的值. 如果默认文件里还没有这一项, 返回的值将是 0, 可以接受为最初的默认值. 如果是字符串 string, 对应的key不存在时返回的将是 "nil". - 最后, 恢复的这些值可以恢复到对应的控件上.
检验你的应用程序
如果一切没有问题, 你会得到一个结果.