iPhone开发基础教程笔记(二)--第三章 处理基本交互

来源:互联网 发布:淘宝一元云购在哪里 编辑:程序博客网 时间:2024/06/01 08:02


第三章 处理基本交互

本章将编写一个稍微复杂的应用程序,他有两个按钮和一个标签。当用户按下任一按钮时,标签的文本将随之变化

3.1 模型-视图-控制器泛型

首先,让我们了解一些基本概念。Cocoa Touch设计者们采用模型-视图-控制器(MVC)泛型做为指导原则。MVC是用于拆分GUI应用

程序代码的逻辑方法。目前,几乎所有面向对象框架都对MVC敬畏三分,但很少有像Cocoa Touch这样忠实于MVC的。

1)模型:保存应用程序数据的类。

2)视图:窗口、控件和其他用户可以看到并能与之交互的元素的组成部分。

3)控制器:将模型和视图绑定在一起,确定如何处理用户输入的应用程序逻辑。

MVC可以帮助确保实现最大可重用性。

在编写Cocoa Touch应用程序时,我们将主要使用Interface Builder来创建视图组件,但有时仍然需要在代码中修改界面,或者需

要继承已有的视图和控件。

创建模型的方法是设计一些Obj-C类来保存应用程序数据。在本章的例子中,我们不会创建任何模型对象,因为我们不需要存储或保

留数据。但在后面,随着应用程序变得更加复杂,我们将引入模型对象。

控制器组件通常由开发人员创建的类和特定于应用程序的类组成。控制器可以是完全自定义的类(NSObject子类),但更多情况下

,他们一般是UIKit框架中已有通用控制器类(如UIViewController)的子类。

3.2 创建项目

现在可以开始创建Xcode项目了,使用和上一章相同的模版:基于视图的应用程序。将其保存为Button Fun。

3.3 创建视图控制器

现在,我们先看看这些已经创建的文件。在项目窗口中,展开Classes文件夹,可以看到其中包含4个文件:

Button_FunAppDelegate.h、Button_FunAppDelegate.m、Button_FunViewController.h、Button_FunViewController.m

这4个文件实现了两个类。本章将创建的应用程序仅包含一个视图,且控制器类Button_FunViewController将负责管理该视图。单击

Groups&Files窗格中的Button_FunViewController.h,并查看该文件的内容:

#import <UIKit/UIKit.h>

@interface Button_FunViewController:UIViewController {

}

@end

UIViewController是UIKit的一部分,并未我们免费提供了一些功能。

我们将在Interface Builder中创建2个按钮和一个文本标签。既然我们将编写代码,那么代码必须要通过某种方式与我们在

Interface Builder中创建的元素进行交互。

控制器类可以使用一种特殊的实例变量来引用nib中的对象,这个变量就是“输出口”(outlet)。可以把输出口看成是指向nib中

的对象的指针。另一方面,也可以设置ninb文件中的界面对象触发控制器类中的特殊方法。这些特殊方法称为“操作”方法。

3.31 输出口

使用关键字IBOutlet声明的实例变量。

IBOutlet UIButton *myButton;

IBOutlet关键字的定义如下所示:

#ifndef IBOutlet

#define IBOutlet

#endif

他的唯一作用就是告诉Interface Builder ,此实例变量将被连接到nib中的对象。你创建的任何需要连接到nib文件中的对象的实

例变量都必须以IBOutlet关键字开头。打开IB时,他会在项目头文件中扫描此关键字,并将允许你根据这些变量将代码连接到nib。

3.3.2 操作

通过关键字IBAction声明

- (IBAction)doSomeThing:(id)sender

返回类型必须是IBAction,与声明(void)返回类型相同。这是声明操作方法不返回任何值的另一种方法。通常,操作方法接受一

个参数,该参数通常被定义为id,名称被指定为sender。如果不需要知道哪个控件调用了方法,那么也可以定义无sender参数的操

作方法

- (IBAction)doSomeThing;

3.3.3 将操作和输出口添加到视图控制器

由于Xcode为我们创建的文件已经包含了一些需要的代码,因此我们通常只需在已有文件中插入代码。查看

Button_FunViewController.h的代码清单,可以发现normal typeface类型的任何代码都是文件中的已有代码,

将以下代码添加到Button_FunViewController.h:

#import <UIKit/UIKit.h>

@interface Button_FunViewController:UIViewController {

 IBOutlet UILabel *statusText;

}

@property (retain,nonatomic) UILabel *statusText;

- (IBAction)buttonPressed:(id)sender;

@end

nonatomic将更改访问方法和修改方法的生成方式。简单来说,在默认情况下,这些方法在创建时会具有另外一些代码,用于帮助你

编写多线程程序。这些额外的开销虽然较小,但对于声明指向用户界面对象的指针却没有必要,因此,我们通过声明nonatomic来节

省一些开销。在少数情况下,你不需要为属性指定nonatomic。做为一般规则,大多数情况下,我们在编写iPhone应用程序时都将指

定nonatomic属性。

3.3.4 将操作和输出口添加到实现文件

Button_FunViewController.h的编辑以告一段落,保存他,然后打开Button_FunViewController.m:其内容如下:

 

#import "Button_FunViewController.h"

@implementation Button_FunViewController

- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

 return (interfaceOrientation==UIInterfaceOritationPortrait);

}

- (void) didReceiveMemoryWarning {

 [super didReceiveMemoryWarning];

}

- (void)dealloc {

 [super dealloc];

}

//省略了一大堆注释,注释内容主要是如果你要做某某事情,请覆盖某某方法,和某某函数应该在某种情况下返回某种值

@end

注释的内容现在基本用不到,可以删除,以增加我们的代码的可阅读性。

添加以下代码:

@synthesize statusText;

- (IBAction)buttonPressed:(id)sender

{ NSString *title=[sender titleForState:UIControlStateNormal];//可以获得按下按钮的标题

  NSString *newText=[[NSString alloc] initWithFormat:@"%@ button pressed.",title];

  statusText.text=newText;

  [newText release];

}

- (void) dealloc {

 [statusText release];

 [super dealloc];

}

 

NSString *title=[sender titleForState:UIControlStateNormal];

在请求按钮的标题时,我们需要提供控件状态。4种可能的状态分别为:

正常(normal),表示控制处于活动状态,但当前并未使用;

突出显示(highlighted),表示控件正被按住或正被使用;

禁用(disabled),表示按钮未启用且无法使用

已选中(selected),仅特定控件具有该状态,表示控件当前以被选中。

UIControlStateNormal表示控件的正常状态,并且是最常使用的一种状态。如果未指定其他状态的值,则这些状态将拥有与正常状

态相同的值。

应该指出,我们并没有使用

NSString *newText=[NSString stringWithFormat:@"%@ button pressed",title];

来创建newText,因为这样的对象是使用autorelease释放的,即自动释放对象,使用他们是有代价的。在iPhone上,这些对象会对

应用程序的内存占用造成不利的影响。使用自动释放是可以的,但应该将他们用到有用的地方,而不是仅仅为了少输入几行代码。

继续操作前,一定要保存文件,然后按Cmd+B编译该项目,确保没有输入错误。

3.4 使用应用程序委托

Classes文件夹中的另外两个文件实现了“应用程序委托”。Cocoa Touch广泛使用了委托,他是负责为另一个对象处理特定事情的

类。通过应用程序委托,我们可以在预先定义的时间为UIApplication处理事情。每个iPhone应用程序都有一个且只有一个

UIApplication实例,负责应用程序的运行循环以及处理各种应用程序级功能,如将输入发送给合适的控制器类。

UIApplication是UIKit的标准部分,他主要在后台处理任务,因此一般不需要担心她。但是,在应用程序执行过程中明确指定的时

间,UIApplication将调用特定的委托方法(如果有委托且实现了该方法)。例如,如果需要在程序退出之前触发某段代码,可以在

应用程序委托中实现applicationWillTerminate:方法,并将终止代码置于其中。这种委托可以让应用程序实现常用的应用程序级行

为,而不需要继承UIApplication,或了解他的任何内部机制。

单击Groups&Files窗格中的Button_FunAppDelegate.h,查看应用程序委托的头文件。他应如下所示:

#import <UIKit/UIKit.h>

@class Button_FunViewController;

@interface Button_FunAppDelegate:NSObject <UIApplicationDelegate> {

 IBOutlet UIWindow *window;

 IBOutlet Button_FunViewController *viewController;

}

@property (nonatomic,retain) UIWindow *window;

@property (nonatomic,retain) Button_FunViewController *viewController;

@end

我们不需要对此文件进行任何修改。

可以按下Option键并将光标移动到UIApplicationDelegate上。光标应转变为十字线,然后双击鼠标按钮。这将打开文档浏览器并显

示UIApplicationDelegate协议的文档。此技巧同样适用于类、协议和类别名称,以及编辑器窗格中显示的方法名称。按住Option键

并双击某个单词可以在文档浏览器中搜索该单词。

了解如何快速查找文档中的内容绝对是大有裨益的,但是查看此协议的定义可能更重要。花些时间阅读这些方法的说明是值得的。

单击Button_FunAppDelegate.m,查看应用程序委托的实现:

#import "Button_FunAppDelegate.h"

#import "Button_FunViewController.h"

@implementation Button_FunAppDelegate

@synthesize window;

@synthesize viewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {

 //Override point for customization after app launch

 [window addSubView:viewController.view];

 [window makeKeyAndVisible];

}

- (void)dealloc {

 [viewController release];

 [window release];

 [super dealloc];

}

@end

可以看到应用程序委托实现了协议的一个方法是:applicationDidFinishLaunching:。该方法将在应用程序完成所有设置任务,并

准备好开始与用户交互时触发。

applicationDidFinishLaunching:的委托版本将视图控制器的视图做为子视图添加到应用程序的主窗口中,并将窗口设置为可见,

我们设计的视图就是通过这种方式向用户显示的。

介绍上面的内容,只是希望你了解应用程序委托的一些背景知识,以及其各部分的组成。

3.5 编辑MainWindow.xib

目前,我们已经了解了Classes文件夹下面的4个文件。我们还将探索Resources标签中的3个文件之一。我们在第二章中已经了解了

Info.plist

Resources文件夹内还有另外一个文件夹需要讨论。MainWindow.xib文件的作用是让应用程序委托、主窗口和视图控制器实例在运行

时创建。记住,此文件是做为项目模版的一部分提供的。此外,你不需要做任何修改,或进行任何操作。

展开Groups&Files窗格中的Resources文件夹,然后双击MainWindow.xib。打开Interface Builder之后,注意nib的MainWindow.xib

主窗口。除了Files's Owner和First Responder之外,还有3个图标,他们都是将在nib文件加载时进行实例化的对象。

说明:在默认视图中,nib文件主窗口中的长名称将被截断。如果将光标移到这些图标上,并停留几秒,将会弹出一个工具提示,显

示该项的全名。还需注意,主窗口中的名称不一定表示对象的底层类。新实例的默认名称通常会让你想到底层类,但这些名称可以

(且经常)被修改。

第3个图标是Button_FunAppDelegate的一个实例。第4个图标是应用程序唯一的窗口(UIWindow的实例)。第5个图标是

Button_FunViewController的实例。

3.6 编辑Button_FunViewController.xib

3.6.1 在Interface Builder中创建视图

在Xcode中,双击Groups&Files窗格中的Button_FunViewController.xib。

从库中拖动一个i额标签到视图窗口中。将标签放置到视图的底部,展开他,以占用视图的大部分宽度。使用弹出的蓝色引导线来帮

助放置标签。

蓝色引导线可以帮助你依照Apple Human Interface Guidelines(HIG)来设计界面。与Mac OS X类似,苹果公司提供了iPhone

Human Interface Guidelines来设计iPhone应用程序。HIG将指导你应(或不应)如何设计用户界面,你真的应该读读他,因为其中

包含了iPhone开发人员都需要了解的宝贵信息。其地址为:

http://developer.apple.com/iphone/library/documentation/UserExperience/Conceptual/MobileHIG/

将标签放置在视图底部之后,单击以选中他,按下Cmd+1调出检查器。使用检查器上的文本对齐按钮将文本更改为中间对齐。

将标签放置到所需位置之后,双击标签并删除已有文本。我们不希望在单击按钮之前显示任何文本。

接下来,我们从库中拖动两个Round Rect Button到视图中。

将两个按钮并排排列,放置在视图的中间。其位置是否准确无关紧要。双击左侧的按钮。可以通过此操作编辑按钮的标题,将其文

本更改为“Left”,然后修改右边按钮的标题为“Right”。

3.6.2 连接所有元素

第一步是从Files's Owner连接到View窗口中的标签。为何是Files's Owner呢?

当UIViewController的某个实例或某个子类被实例化时,他将查找相应的nib文件。在我们所使用的模版中,MyViewController将尝

试加载名为MyViewController.xib的nib,后者将由我们选择的项目模版来创建。如果他找到此nib,则将其加载到内存中并成为该

nib文件的所有者。由于MainWindow.xib文件包含一个表示Button_FunViewController的图标,因此应用程序在启动时将自动创建一

个Button_FunViewController实例。此后,该实例会自动将Button_FunViewController.xib加载到内存中并成为该文件的所有者。

现在我们可以使用File's Owner图标将该输出口与标签连接起来。

如果你现在还没有完全理解nib加载过程,也没有关系。这是一个复杂的过程,稍后几章将通过演示来深入讨论此过程。现在,只需

记住控制器类是与之同名的nib文件的所有者。

1,连接输出口

按下Ctrl键,单击nib主窗口中的File's Owner图标,并按钮鼠标按钮,从File's Owner图标拖向View窗口。此时应出现一条蓝色引

导线。继续拖动鼠标,直到鼠标位于View窗口的标签之上。尽管看不到标签,但是当你将光标移到其上时,他就会显示出来。

放开鼠标,此时应弹出一个灰色小菜单。在灰色菜单中选中StatusText

2.指定操作

如果熟悉Mac OS X上的Cocoa编程,那么现在可以采用按住Control键 从按钮拖动到File's Owner图标的方式。说实话,这尽管是一

种可行的方法,但他对于iPhone并不是最佳方法。

iPhone与Mac OS X之间的差异在此处比较明显。在Mac上,控件可以只与一个操作相关,并且此操作通常在使用该控件时触发。这也

存在一些例外,但基本而言,控件将在释放鼠标按钮时触发其相应的操作方法。

Cocoa Touch中的控件可以实现许多功能,因此使用连接检查器而不是点击控件后拖动是最好的方法,可以按下Cmd+2或从Tools菜单中选择Connection Inspector来打开连接检查器。单击Left按钮,然后调出连接检查器。

在Events栏下,可以看到能够潜在地触发操作的所有事件列表。如果愿意,你可以将不同的操作与不同的事件关联在一起。举例来说,可以使用Touch Up Inside来触发某操作,而使用Touch Drag Inside触发不同的操作。我们的情况相对简单和直接。当用户按下那妞时选择哪个操作?答案是Touch Up Inside。当用户的手指离开屏幕时,如果他最后触摸的位置在按钮内部,则用户将触发一个Touch Up Inside事件。试想,在大多数iPhone应用程序中,如果在触摸屏幕时改变了注意,你通常会把手指从按钮处移开,然后再离开屏幕,对吗?如果用户的手指在离开屏幕之前仍然位于按钮上,那么可以放心地假设该按钮单击是故意的。

点击Touch Up Inside右侧的小圆圈并拖动鼠标,这次不需要按下Ctrl键。应该可以看到一条蓝色引导线,将鼠标拖动到File's Owner图标上,从弹出的小菜单中选择buttonPressed:。记住,File's Owner图标代表的是我们正在编辑的nib文件的类。在本例中,File's Owner代表Button_FunViewController类。

对其他按钮执行相同的步骤。然后保存。

3.6.3 测试

保存nib文件之后,返回Xcode并运行应用程序。从Build菜单选择Build and Run。Xcode将编译程序,并且应用程序将出现在iPhone仿真器中。单击左侧按钮时,应出现文本“Left button pressed”等。

3.7 小结

理解本章的所有知识点及其原理非常重要。对于没有完全理解的部分,请回头重新阅读。本章的内容非常重要!

其它信息:广州达内广州it培训广州软件工程师培训广州软件培训


原创粉丝点击