AppStore掘金——iPhone SDK应用程序开发
这本书的hello讲的不错摘录下来。
3.2.3 史上最无用的应用程序:HelloView
在能够显示"Hello, World!"之前,要先试验做一个更无用的程序"Hello, View!"。除了创建一对窗口和视图之外,这个应用程序不会做任何事。实际上,由于UIView类只是一个基类,它甚至连显示一些文字都做不到。这个应用程序唯一的用处,就是作为iPhone上任何GUI应用程序都要有的第一行代码。
你可以创建一个基于窗口的应用程序项目,命名为HelloView,加入如例3-1、例3-2和例3-3中所示的代码,就能够用SDK编译这个应用程序了。和本章中的大多数例子一样,你可能也希望从项目中去掉Interface Builder,这样就可以了解各个对象是如何在代码中创建出来的。
例3-1 HelloView应用程序代理的原型(HelloViewAppDelegate.h)
- #import <UIKit/UIKit.h>
- @interface HelloViewAppDelegate : NSObject
<UIApplicationDelegate> {- /* 你的应用程序中的一个窗口,也是唯一的一个 */
- UIWindow *window;
- /* 将要在这个窗口中显示的视图类 */
- UIView *myView;
- }
- @property (nonatomic, retain) IBOutlet UIWindow *window;
- @end
例3-2 HelloView应用程序代理(HelloViewAppDelegate.m)
- #import "HelloViewAppDelegate.h"
- @implementation HelloViewAppDelegate
- @synthesize window;
- - (void)applicationDidFinishLaunching:(UIApplication
*)application {- CGRect screenBounds = [ [ UIScreen mainScreen ]
applicationFrame ];- CGRect windowBounds = screenBounds;
- windowBounds.origin.y = 0.0;
- /* 初始化窗口 */
- self.window = [ [ UIWindow alloc ]
initWithFrame: screenBounds ];- /* 初始化视图 */
- myView = [ [ UIView alloc] initWithFrame:
windowBounds ];- /* 将视图链接到窗口 */
- [ window addSubview: myView ];
- /* 令窗口成为主窗口并显示出来 */
- [ window makeKeyAndVisible ];
- }
- - (void)dealloc {
- [ myView release ];
- [ window release ];
- [ super dealloc ];
- }
- @end
例3-3 HelloView主函数(main.m)
- #import <UIKit/UIKit.h>
- int main(int argc, char *argv[]) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- /* 用应用程序代理类的名字作为参数进行调用 */
- int retVal = UIApplicationMain(argc, argv, nil, @"HelloViewAppDelegate");
- [pool release];
- return retVal;
- }
3.2.4 行为解释
HelloView应用程序从外表上看起来并没做什么事,但也有其内部驱动机制,其行为如下。
1. 当应用程序启动时,其main函数被调用,正如一个通常的C语言程序一样。这个函数转入Objective-C领域,并将应用程序实例化。然后应用程序通知代理HelloView AppDelegate,该代理是在调用UIApplicationMain时指定的。main函数还负责初始化一个自动回收池。自动回收池被广泛用于苹果公司的Cocoa框架中,来处置那些在创建时就已经指明要进行autorelease的对象。这样做就等于告知应用程序,对于这些对象用完之后就不用管了,它们稍后会被回收。
2. 当应用程序对象初始化完毕之后,底层框架会调用HelloViewAppDelegate类的applicationDidFinishLaunching方法。这就是程序的Objective-C部分开始运转的地方。
3. 系统调用UIScreen类的applicationFrame方法,得到应用程序的显示窗口的坐标与大小。这样就可以创建一个新窗口,让应用程序的主视图可以安置在其中。要记住,你稍后对此进行修改,使用整个屏幕区域,好让你的应用程序能在本质上更先进。
4. 应用程序创建主视图类,使用的显示区域从0 × 0位置(窗口的左上角)开始。然后会将视图设置为窗口的内容。
5. 应用程序代理最终会指示窗口来到前端,并显示自身。这样视图就会显示出来,不过并没有呈现任何内容。
3.2.5 从UIView派生
例子HelloView显示了构建并显示一对窗口-视图所需要的最少代码。UIView类自身仅仅是一个基类,实际上它并不能显示任何内容。要创建一个有实际用途的应用程序,你或者需要将一个功能更丰富的对象附着到UIView上,或者派生一个新的UIView类,在其中加入更多功能。iPhone SDK中有许多UIView类的子类,可以提供不同类型的功能。你也可以创建自己的子类,构建一个自定义视图。
要从UIView派生一个子类,需要编写一个新的接口与实现,来声明该子类。下面的代码片段创建了一个名为MainView的类,作为UIView的一个子类:
- @interface MainView : UIView
- {
- }
- - (id)initWithFrame:(CGRect)rect;
- - (void)dealloc;
- @end
MainView类继承自UIView类,所以此时它与UIView的功能相同。为了令这个类更有用处,你需要加入新功能。下面的片段就是之前代码的一个新版本,其中加入了一个变量,其中存有一个名为UITextView的文本框类。实际上,你能够轻易地将一个UITextView对象直接附着到窗口上,因为这个类就是派生自UIView的。在这里,你将其集成到自己的定制类中:
- #import <UIKit/UITextView.h>
- @interface MainView : UIView
- {
- UITextView *textView;
- }
- - (id)initWithFrame:(CGRect) rect;
- - (void)dealloc;
- @end
你可能已经注意到了上面的两个方法initWithFrame和dealloc。这些方法是默认的初始化与析构方法,并将被你的子类MainView重写,从而扩充UIView类的功能。
提示
各种类使用了一个通用构造方法,名为alloc,但是你不必重写这个方法。你可以将自己的自定义初始化代码放在初始化方法中,比如init和initWithFrame。
如你所见,initWithFrame方法会在视图第一次实例化时被调用,对类做初始化操作。一个边框结构体被传递给它,用来定义显示区域。你应该在这个方法中放入对变量或其他对象做初始化的代码。第二个方法dealloc,则在对象被丢弃时调用。在此,你必须释放你的类中之前分配的所有资源,这样当对象被销毁时这些资源也可以被回收。这两个方法都要调用它们的父类方法,这样才能让UIView类对其自身内部的功能进行处理。
下面给出的,是这两个重要方法的模板:
- @implementation MainView
- - (id)initWithFrame:(CGRect)rect {
- /* 首先调用父类的initWithFrame方法,
- * 来初始化UIView对象 */
- self = [ super initWithFrame: rect ];
- /* 如果对象已经被初始化过了,self指针将会是nil */
- if (self != nil) {
- /* 在这里初始化你的类变量 */
- /* 在这里为你的类分配初始资源 */
- }
- return self;
- }
- - (void)dealloc
- {
- /* 在这里释放你的类的资源 */
- /* 调用父类的dealloc方法,
- /* 将UIView持有的资源释放 */
- [ super dealloc ];
- }
- @end