Xcode基础:详解Objective-C开发带有图形界⾯的程序
随着知识的积累,我们下⾯将开始讨论如何编写带有图形界⾯的程序。我要承认,Objective-C语⾔是C语⾔的变种。之前我们讨论的很多东西都是纯粹的C语⾔的内容。那么Objective-C语⾔和纯粹的C语⾔有什么不同?区别就在“Objective”上。Objective-C语⾔把抽象的概念当作对象。
直到现在,我们主要在处理数字。如你所知,Objective-C语⾔⾃然⽀持数字的概念。也就是它允许你在内存中创建数,并通过数学公式和数学函数操纵这些数。如果你的程序⽤作处理数字,⽐如计算器程序,那这就很很有⽤了。但是如果你的程序是⼀个⾳乐播放器,⽤来处理歌曲、播放列表、艺术家名单等等,那该怎么办?亦或者你的程序是⼀套航空管制系统,要与飞机、航班、机场打交道,⼜该怎么办?是不是在Objective-C中编写这样的程序如同编写处理数字的程序⼀样容易呢?上⾯这些元素(歌曲、艺术家、飞机、机场等等)都是所谓的“对象”。通过Objective-C语⾔,你可以定义各种你需要处理的对象并为它们编写程序。
通过⼀个例⼦看看Objective-C语⾔编写的程序是如何处理窗⼝的,⽐如Safari浏览器的窗⼝。Mac微机上⼀个打开的Safari窗⼝左上⾓都有三个按钮。红⾊的是关闭按钮。如果点击这个按钮来关闭⼀个窗⼝会发⽣什么?⼀条信息会被发到窗⼝,窗⼝接着运⾏⼀段使⾃⼰关闭的代码来回应这段信息。
窗⼝是⼀个对象,你可以随意的拖放它。三个按钮也是对象,你可以点击它们。这些对象都有⼀个在屏
幕上可以看见的代表物,但并不是所有的对象都有可以被看见的代表物。例如存在于Safari浏览器和Web服务器之间的连接,就是⼀个不可见的对象。
你可以随你的意愿打开任意多的Safari窗⼝。那么你觉得苹果的开发⼈员是a.为每⼀个窗⼝编写代码,绞尽脑汁预测你最多打开多少个窗⼝;还是b.创建⼀个模板使Safari 可以随时创建窗⼝对象?
很显然答案是b。他们编写⼀些代码,被称作“类”(class),这些代码定义⼀个窗⼝的外观和⾏为。当你新建⼀个窗⼝,实际上是这
个“类”为你创建了⼀个窗⼝。这个“类”就代表了窗⼝这个概念,或者说每⼀个窗⼝都是这个“类”的⼀个实例。(就像说76是数这个概念的⼀个实例。)
你创建的窗⼝都在屏幕上有⾃⼰特定的位置。如果你把窗⼝最⼩化到Dock上⼜把它还原,它会回到它在屏幕上原来的位置。这是如何实现的?类定义了专门的变量来记录窗⼝在屏幕上的位置。类的实例,也就是对象,包含有这些变量的值。每个窗⼝有⾃⼰的值,不同的窗⼝也就有不同的值赋给变量。
类不仅仅创建窗⼝对象,⽽且还给它提供⼀系列动作。其中⼀个动作就是关闭。当你点击窗⼝上“close”按钮,按钮就向窗⼝发送⼀条“关闭”信息。能够被对象执⾏的动作叫做⽅法(methods)。它们和函数很相似,所以如果你⼀直跟着我们学到现在,学习它就不会有太多障碍。
当你类创建⼀个窗⼝,它同时在内存(RAM)中留出空间来存放窗⼝的位置信息和其他信息。但是并不包含关闭窗⼝这个程序代码。那样会浪费计算机的内存空间,因为所有的窗⼝都是⽤同样的程序代码执⾏关闭命令。⽤来关闭程序的代码只被需要⼀次,但是每个窗⼝对象都有通向类中相关代码的途径。
像前⾯⼀样,本章下⾯要看到的例⼦依然包含着⼀些涉及内存预留和释放的语句。但是我们仍然要留到后⾯才讨论。抱歉!
下⾯要写的这段程序有两个按钮和⼀个⽂本区域。当按下第⼀个按钮,⼀个值会显⽰在⽂本区域;按下第⼆个按钮另外⼀个值被显⽰在⽂本区域。你可以把它想像成只有两个按钮的计算器,当然它并不能计算。后⾯你学的多了就可以编写⼀个真正的计算器了,我只是举⼀个简单的例⼦。
程序上的任何⼀个按钮被按下,都会传送⼀条信息。这条信息包含要被执⾏的⽅法的名称。那么这样⼀条信息将被发送到什么地⽅?在关闭窗⼝的例⼦中,关闭窗⼝这条信息被发送给了作为窗⼝类的实例的窗⼝对象。这⾥我们同样需要⼀个对象来接收来⾃两个按钮的信息,并且还能告诉⽂本区域显⽰哪个值。
所以,我们要先创建⼀个我们⾃⼰定义的类,并且创建⼀个作为它实例的对象。这个对象会作为来⾃按钮的信息的接收⽅。(参考下⾯的草图。)像窗⼝对象⼀样,我们的类的实例也是⼀个对象,但相
⽐之下我们的类的实例在程序运⾏时并不能像窗⼝对象那样在屏幕上显⽰出来。它只是Mac微机内存中的东西。
当我们的类的实例收到来⾃按钮的信息,相对应的⽅法就会被执⾏。⽅法的代码是包含在类中的⽽不是包含在类的实例中。运⾏时,这个⽅法发送⼀条信息给⽂本区域对象。除了⽂本区域对象的名称,信息还包含⽂本区域类的⼀个⽅法的名称。接收到这条消息,⽂本区域对象就会执⾏⽅法。我们需要⽂本区域对象在我们单击按钮时现实⼀个值。所以这条消息除了包含对象名称、⽅法名称,还会包含⼀个⽅法会使⽤到的参数(值)。
下⾯给出的是Objective-C语⾔信息传递的⼀般格式,[1.1]不带参数,[1.2]是带参数的形式。
例[1]
如你所见,所有的⼯作部分都放在中括号⾥⾯,⽽且要在结尾加上那个永恒不变的分号。在括号⾥,接收对象的名称放在⾸位,紧随其后的是⽅法。如果⽅法要求跟有参数,那么要使⽤[1.2]那样的形式。
具体看看上⾯讲的东西是如何实现的。启动Xcode并创建⼀个新的⼯程。在“Application”标题下选择“Cocoa Application”。给你的⼯程取个名字,按照惯例,图形界⾯程序的名字⼀般以⼤写字母开头。在“Groups & Files”⼀栏打开“Resources”⽂件夹。双击“MainMenu.nib”⼀项。
另⼀个名为界⾯创建器(Interface Builder)的程序就会启动。好多窗⼝同时出现,你可能都想从“⽂件”菜单选择“隐藏其它窗⼝”了。屏幕上应当显⽰出三个窗⼝。⼀个叫做“Window”,你
的程序的使⽤者会看到这个窗⼝。它有点⼉⼤,你可以调整它。“Window”窗⼝的右边是⼀个以“Cocoa-”字样开头的窗⼝。它被称
作“调板”,⾥⾯存放着可以⽤于你的图像界⾯的各种对象。单击调板⼯具栏上第⼆个图标,并且拖拽两个按钮到你的图形界⾯窗
⼝“Window”上。单击调板⼯具栏上第三个图标,把标有“系统字体⽂本(System Font Text)”字样的⽂本区域拖拽到图形界⾯窗⼝。
在后台,从调板上拖拽⼀个按钮实际上是创建了⼀个新的按钮对象并把这个对象放到了你的程序窗⼝中。从调板拖拽⽂本区域或者其它对象情况也是⼀样的。
请注意,当你把光标停留在调板中的图标上,图标的名字就会被显⽰出来,⽐如“NSButton”或者“NST
extView”等等。这都是苹果提供的类的名称。本章的后⾯我们会学习在我们⾃⼰编写的程序需要执⾏某⼀动作时如何从这些类⾥到相关的⽅法。
把“Window”窗⼝中你刚刚拖拽过来的对象排列美观,并把它们的尺⼨调整适当。双击按钮对象可以更改它们的名字,但是要⼀次⼀个。我建议你在我们写完这个程序之后继续探索⼀下调板,掌握其它对象的添加⽅法。
选择⼀个对象,按组合键command-shift-i就可以修改它的属性。这个也要好好探究⼀下。⽐如选择了“Window”窗⼝(你可以在左下⾓的窗⼝的Instances标签页⾥看到它已经被选中),按组合键command-shift-i。如果窗⼝顶部的弹出式菜单上是“Attributes”,你就可以选择勾选“TexturedWindow”⼀项,这个选项使窗⼝呈现⾦属外观。也就是说,不⽤写⼀⾏代码就可以在很多⽅⾯定义你的应⽤程序的外观。
下⾯要编写⼀个类,为此我们还要深⼊的研究⼀下类的⼯作原理。
为了节省编程耗费的精⼒,最好就是能够在已有的东西上创建你的新东西,⽽不是从草稿开始着⼿。举个例⼦,你要写⼀个具有特殊属性(功能)的窗⼝,只要添加那些定义特殊属性的代码就⾜够了。⽽不⽤再去写那些定义其它内容的代码,⽐如最⼩化或者关闭窗⼝。在其他程序员的基础上⼯作,你可免费继承他们已经写好的东西。这也是Objective-C语⾔与C语⾔的不同。
具体的说,这⾥有⼀个窗⼝类(NSWindow),你就能写⼀个继承它功能的类。假如你添加了某些⾏为到你⾃⼰写的窗⼝类中。当你⾃⼰编写的窗⼝接收到⼀条关闭信息时会发⽣什么?你没有写也没有拷贝任何代码到你的类中。很简单,你编写的窗⼝的类如果没有包含常规⾏为的代码时,信息会⾃动地上溯到它所继承功能的原始的类那⾥(称作“⽗类superclass”)。如果有必要会⼀直追溯到⽅法被到(或者追溯到最为原始的那个类为⽌)。
如果⽅法没有被到,那就意味着你发送了⼀条⽆法被处理的信息。这好⽐你到汽车修理⼚修理雪橇,他们却爱莫能助。这个时
候,Objective-C语⾔会报错。
如何去执⾏你⾃⼰定义的⾏为⽽不是从⽗类那⾥继承来的⽅法?很容易你就可以跳过个别⽅法。例如你可以写⼀段这样的代码:点击关闭按钮只是把窗⼝隐藏⽽不真正关闭它。你⾃⼰编写的⽅法要使⽤和苹果定义的关闭窗⼝⽅法⼀样的⽅法名称。这样你⾃⼰写的窗⼝收到关闭信息时就会执⾏你定义的⽅法,⽽不是苹果定义的那个。所以这个窗⼝只会移出你的视线⽽不是真正关闭。
嘿!真正关闭的⽅法苹果已经写好了。除了我们写的⾃⼰的关闭⽅法,我们还可以援引⽗类中提供的关闭⽅法,这就需要另⼀个不同的调⽤语句来确保我们写的关闭⽅法没有被先使⽤。
例[2]
这些内容对于这本⼊门级⼩册⼦来讲都是些进阶内容,我们可不指望你凭此寥寥数语就学会。
所有类⾥⾯,顶级的是被称作“对象类”(NSObject)的类。⼏乎所有的你创建或使⽤的类都直接或间接的是对象类的“⼦
类”(subclass)。⽐如类NSWindow是类NSResponder的⼦类,类
NSResponder⼜是类NSObject的⼦类。类NSObject定义了适⽤所有对象的⼀般⽅法。(⽐如产⽣⼀段对对象的⽂本描述,询问对象是否能理解所给信息等等。)
在这些长篇⼤论的理论是你厌烦之前,看看如何创建⼀个类。
回到“MainMeni.nib”窗⼝,选择“Classes”标签页。在第⼀栏中你会看到“NSObject”。选择它,并在“Classes”菜单中选
择“Subclass NSObject”。回到“MainMeni.nib”窗⼝,给你创建的类取个名字。我叫它“MAFoo”。
“MAFoo”这个名字中前⾯两个⼤写字母是My Application的缩写。你可以随意给你的类起名字。⼀旦你开始写程序了,我们建议你使⽤相似的⽅法取名(也就是说选择两到三个⼤写字母作为所有你编写的类的名称的固定的前缀,以免与现有的类发⽣冲突)。但是不要使
⽤“NS”做前缀,以免引起混淆。NS是苹果⾃有的类专⽤的,它代表NeXTStep。Mac OSX就是在NeXTStep操作系统的基础上发展起来的,苹果公司收购了NeXT公司,此举使乔布斯(Steve Jobs)重返苹果并重坐第⼀把交椅。
当你创建⼀个类的时候,你应当给它取⼀个能够传达有效信息的名称。例如在Cocoa中,描绘窗⼝的类叫做NSWindow。另⼀个例⼦是描绘颜⾊的类叫做NSColor。在我们的例⼦中,类MAFoo是⽤来说明对象在应⽤程序中是怎样互相通讯的。所以我们给他取了⼀个没什么特殊含义的名字。
回到界⾯编辑器中在Classes菜单选择“InstantiateMAFoo”⼀项。就像你现在在“Instances”标签页中看到的⼀样,你有了⼀个新的叫做MAFoo的图标。这个图标代表了我们刚刚创建的类的实例。
我们下⾯要作的就是把发送信息的的按钮和我们创建的对象MAFoo关联起来。此外,我们还要创建⼀个对象MAFoo和⽂本区域之间的连接,因为还有⼀条信息回被传送给⽂本区域对象。如果没有索引,⼀个对象⽆法发送信息给其它对象。在按钮和对象MAFoo之间创建关联就是为按钮提供⼀个通向对象MAFoo的索引。使⽤这个索引按钮就可以向对象MAFoo发送信息。同样的,建⽴对象MAFoo与⽂本区
域的关联可以让前者给后者发送信息。
再从新⾛⼀遍程序的⼯作流程。按钮被单击时发送⼀条定义具体动作的信息。这个信息包含将被执⾏的类MAFoo中的⽅法的名称。信息被送到我们创建的类MAFoo的实例——对象MAFoo那⾥。对象MAFoo本⾝并不包含执⾏动作的代码,但类MAFoo中有。所以发送到对象MAFoo的信息转向请求类MAFoo中的⽅法去做事情:在这个例⼦中是向⽂本区域发送内容。像所有的信息⼀样,这条信息包含着⽅法的名称。本例中⽂本区域对象的⽅法的任务是显⽰⼀个值。这个值被作为信息内容的⼀部分和⽅法的名称⼀起被⽂本区域援引。
我们的类需要两个动作(⽅法),这两个⽅法会被两个按钮分别调⽤。类还需要⼀个出⼝,通过⼀个变量来记录信息被发向哪个对象。
在“Mainfile.nib”窗⼝的“Classes”标签页中选中MAFoo。在键盘上按下组合键command-shift-i来调出检视窗⼝。在检视窗⼝中选择“Action”标签页并点击“Add”按钮来给类MAFoo添加⼀个动作(也就是⼀个⽅法)。重新命名由界⾯编辑器默认的名称使名字富有含义。(⽐如可以叫做“setTo5:”,因为我们会通过这个⽅法在⽂本区域显⽰数字5。)添加其它⽅法并命名。(⽐如叫“reset:”,我们会⽤这个⽅法在⽂本区域中显⽰数字0。)注意⽅法的名称后⾯以冒号“:”结尾,后⾯我们再详细讨论。xcode怎么打开
现在在检视窗⼝中选择“Outlet”标签页,添加出⼝并命名(⽐如叫“textField”)。
在对象之间建⽴起关联之前,我们还要给两个按钮取名。第⼀个按钮要在⽂本区域显⽰数字5,所以叫“Set to 5”(⽅法是双击并按钮并键⼊新名字)。同样,第⼆个按钮改叫“Reset”。注意,上⾯给按钮改名这些步骤并不是程序正确运⾏的要求,⽽只是想让我们的⽤户界⾯看起来尽可能像是⾯对最终⽤户的。
现在我们已经可以创建下⾯这些关联了:
a)按钮“Reset”和MAFoo的实例之间的关联;
b)按钮“Set to 5”和MAFoo的实例之间的关联;
c)MAFoo的实例和⽂本区域之间的关联。
在“MainFile.nib”窗⼝中单击“Instances”标签页。按住键盘上的Ctrl键并⽤⿏标将“Reset”按钮拖拽到MAFoo的实例上。(千万不要使⽤别的⽅法创建关联!)⼀条代表关联关系的线会显⽰
在屏幕上,确认这条线是从按钮连到了MAFoo的实例上就可以松开⿏标了。
当松开⿏标,检视窗⼝会显⽰关联调板,调板中列出了对象MAFoo中可⽤的⽅法。选择正确的⽅法并单击“Connect”按钮来完成关联过程。
现在按钮已经有了通到对象MAFoo的索引,任何时候被单击都会发送包含“reset:”这⼀⽅法名称的信息。
⽤同样的⽅法创建“Set to 5”按钮和对象MAFoo的关联。
创建对象MAFoo和⽂本区域之间的关联时要按住Ctrl键并将对象MAFoo拖拽到⽂本区域上,再单击“Connect”按钮。
上⾯你做的就是没有写⼀⾏代码就创建了关联。
在“MainMenu.nib”窗⼝选中MAFoo的实例,切换到“Classes”标签页,你会看到在列表中类MAFoo被选中。在“Classes”菜单中选择“Create Files for MAFoo”。界⾯编辑器会接着询问⽣成
的⽂件的保存路径。默认情况下,这些⽂件会保存到我们保存程序⼯程的⽂件夹中,这也正是我们需要的。
现在返回到Xcode中,你可以在⼯程窗⼝中看到你创建的⽂件,这些⽂件放在“Other Sources”组中。如果需要,你可以把他们拖拽到“Classes”组中,因为你创建的⽂件本⾝就代表类。
现在我们要回顾⼀下第四章的内容,我们在那⼀章讨论的是函数。你还记得例[11.1]讲到的函数使⽤时,
你必须在使⽤函数前告诉编译器引⼊⼀些东西。在我们刚刚⽣成的两个⽂件中有⼀个叫“MAFoo.h”,它是⼀个头⽂件:包含关于我们的类的信息。⽐如,下⾯第[3.5]⾏有NSObject字样,表明我们的的类继承⾃类NSObject。
例[3]
在第[3.7]⾏,这⾥有⼀个去往⽂本区域的出⼝。“id”指⽰对象。“IB”代表界你⽤来创建代码的⾯编辑器。
第[3.9,3.10]⾏中“IBAction”在这⾥是⽆效的。没有信息会返回给作为信息发送⽅的对象:我们程序中的这些按钮不会从对象MAFoo那⾥得到回应信息。
你还会看到这⾥有两个界⾯编辑器动作(Interface Builder Actions)。
前⾯我们见过和第[3.3]⾏相似的内容:#import <Foundation/Foundation.h>。尖括号中的内容前者是⽤于⾮图形界⾯程序的,后者⽤于图形界⾯程序。
让我们看看第⼆个⽂件:MAFoo.m。⼜是⼀些免费代码。
例[4]
⾸先,头⽂件MAFoo.h被输⼊,所以编译器知道要做什么。两个⽅法“reset:”和“setTo5:”将可以被识别。它们是我们的类的⽅法。它们和函数类似,所以你需要把代码写在⼤括号中。在我们的程序中,当你按下⼀个按钮,按钮会发送⼀条信息到对象MAFoo,要求执⾏⼀个⽅法。但我们并没有写相关的代码,我们做的仅仅是在界⾯编辑器中把按钮和对象MAFoo连接起来了。尽管如此,我们必须写出从对象MAFoo发送到⽂本区域对象的信息的代码。我们在第[5.7,5.12]⾏给出了这些代码。
例[5]
如你所见,我们发送了⼀条消息以出⼝名称“textField”为参数的信息。因为我们已经在界⾯编辑器中关联了这个出⼝到真正的⽂本区域,所以信息会被发送到正确的对象。这条信息包含⽅法的名字“setIntValue:”,同时还有⼀个整数值作为参数。⽅法setIntValue:能在⽂本区域对象上显⽰⼀个整数值。下⾯⼀章我们会讨论如何创建这样的⽅法。
你现在已经可以编译程序并启动它了。按下Xcode⼯具条上的“Build and Go”按钮。Xcode可能需要⼏秒中时间来创建并且运⾏你编写的程序。最后,程序会出现在屏幕上,你可以试试了。
简单的说,我们创建了⼀个(很基本的)程序,你仅仅为它写了两⾏代码。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。