学习一门新的语言,好的方法非常重要,特别是入门阶段,好的开始是成功的一半嘛。Hello World作为一个精典的开篇例程,主要在于它的简单易学,易于掌握。麻雀虽小,但五脏俱全,开篇我将以一个简单的Hello World例子来展现iPhone开发最基础的各个方面,通过这些基础的学习,我们再一步一步的向高级应用展开,从而挖掘iPhone开发的精髓。
(1) 头文件:HelloWorld.h
#import <UIKit/UIKit.h> @interface HelloWorld : UIApplication { UIWindow *window; } @end
iPhone主要以Objective-C 语言为主要开发语言,它继承了C语言的所有特性,可以说是C语言的一个超集,它与C一样,通过.h头文件声明函数,变量等, 同时它也有许多C++的特性,主要是面向对象方面的支持, 下面为大家分析这个头文件:
1) #import
通过#import引入其它头文件,这与C或C++的#include有一些类似,同时与Java的import也有些类似,C, C++或Java程序员需要注意一下。
2) @interface ... @end
声明类以
@interface 开始,@end结束, 紧接着@interface是类名HelloWorld
3) HelloWorld : UIApplication - 类名:父类名
继承以
类名:父类名 的方式表示,如果大家有过C#或Java经验,肯定会问:为什么没有限定符?是的,没有,所有声明类都是公开的(public), 继承也是公开的(public), 类似于C++的class ClassName : public ParentClass,
当然, 此处的public在Objective-C中是没有的。C#和Java的程序员需要注意,此处类似C#的public class ClassName : ParentClass, 类似于Java的public class ClassName extends ParentClass.
4) 单继承
单继承,ObjC (Objective-C的简称, 通用的简称,并不是我创造的,呵呵)与Java, C#有点类似,ObjC中也有接口的概念,在接下来的章节中会为您揭晓。
5) 成员变量
成员变量,在{}中声明变量,它与其它语言用作包含类函数及变量声明不同,此处声明的是成员变量,并且全部是私有的,类似于C++, C#, Java中的private。
好,到此,我们算是揭开了iPhone开发的一角,当然,头文件并不是这么简单,还有更多的特性我们在以后的章节中慢慢道来!
接下来我们看看它的实现:
(2) 实现文件:HelloWorld.m
#import "HelloWorld.h" #import <CoreFoundation/CoreFoundation.h> #import <UIKit/UIKit.h> #import <UIKit/UITextView.h> #import <UIKit/UIFont.h> @implementation HelloWorld - (void)applicationDidFinishLaunching: (UIApplication *) application { window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; CGRect windowRect = [ [ UIScreen mainScreen ] applicationFrame ]; windowRect.origin.x = windowRect.origin.y = 0.0f; window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; window.backgroundColor = [UIColor whiteColor]; CGRect txtFrame = CGRectMake(50,150,150,150); UITextView *txtView = [[UITextView alloc] initWithFrame:txtFrame]; txtView.text = @"HelloWorld"; UIFont *font = [UIFont boldSystemFontOfSize:18.0]; txtView.font = font; [ window addSubview: txtView ]; [txtView release]; [window makeKeyAndVisible]; } @end
1) #import
头文件的导入, 这里不赘述,与头文件中的#import相同
2) 实现体
实现文件以 @implementation 开始,紧接着的是类名:HelloWorld,中间是实现体,最后以@end接尾.
在实现体中有个函数体: applicationDidFinishLaunching, 实际上这个函数已不被推荐使用,在iOS 3.0之后就使用application:didFinishLaunchingWithOptions:了,新的函数完成声明如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
所以将函数体中的函数 - (void)applicationDidFinishLaunching: (UIApplication *) application换成上面的声明后,结果是一样的,当然你的iOS必须是3.0或之后的版本。
看到这,我想你一定晕头了,如果你有其它语言的开发经验,估计会更晕,这就是为什么我不在HelloWorld.h中声明任何函数的原因,下面我们就以这个复杂的新函数来说明。
3) 函数范围
首先,最前面的 '-' 表示此函数的范围,是类的成员函数,与之对应的有 '+', 表示静态函数,我们可以通过函数的调用来加以区别:
- [类名 函数名称]
这种方式的语法是调用'+'函数,即调用静态函数,静态函数的概念在其它高级语言中都有详细说明,这里就不介绍了,原理是一样的。
- [类实例 函数名称]
这种方式对应的是调用成员函数,即以'-'声明的函数。
4) 函数类型声明 -(参数类型)
紧下来是 (BOOL), ObjC中将类型放在括号中,此处表示函数返回类型是BOOL型,即 YES 或 NO (YES, NO与其它高级语言的 true, false等同).
5) 函数名
紧接着出场的是函数名,不过注意,此处的函数名是 "application:" 而非 "application", 注意它的区别了吗?其实为什么这样写,我们还是以函数的调用方式来加以理解:
- [类实例 : (类型)变量 参数名:(类型)变量]
回过头来我们再看一下application:函数的声明:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
看到没?"application:", 如果此处我们是"application",那紧接着的第一个参数是不是很不好表示了,为了统一调用方式,只有第一个参数没有参数名,后面的参数都是以参数名:(类型)参数变量 的方式来声明参数的。你现在应该知道它为什么以参数名:(参数类型)参数变量的方式来声明参数了,记住:第一个参数没有参数名。
至于函数体中的代码,主要是操作UI的,我会在以后的章节中单独介绍基本控件的使用,以及自定义控件的开发的章节中介绍。
(3) Info.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleDisplayName</key> <string>${PRODUCT_NAME}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIconFile</key> <string></string> <key>CFBundleIdentifier</key> <string>${PRODUCT_NAME:rfc1034identifier}</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>${PRODUCT_NAME}</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>1.0</string> <key>LSRequiresIPhoneOS</key> <true/> </dict> </plist>
info.plist (Information Property List), 程序信息属性表,此表是创建程序时由XCode自动创建的,也是 苹果 对iOS开发的推荐属性表,下面列出推荐属性与常用属性:
推荐属性:
-
CFBundleDevelopmentRegion
-
CFBundleDisplayName
-
CFBundleExecutable
-
CFBundleIconFiles
-
CFBundleIdentifier
-
CFBundleInfoDictionaryVersion
-
CFBundlePackageType
-
CFBundleVersion
-
LSRequiresIPhoneOS
-
NSMainNibFile
常用属性:
-
UIStatusBarStyle
-
UIInterfaceOrientation
-
UIRequiredDeviceCapabilities
-
UIRequiresPersistentWiFi
属性表有下面五种类型的系统内嵌关键字:
-
Core Foundation 基础框架关键字.
-
Launch Services 启动服务关键字,主要有两项是针对iOS的,一项是“是否是iPhone程序“,另一个是”执行该程序的最iOS版本号“,其它主要是针对MAC OS的。
-
Cocoa Cocoa和Cocoa Touch关键字.
-
Mac OS X 苹果系统程序关键字.
-
UIKit iOS 应用程序关键字.
具体细项在苹果网站有详细说明,请查阅Information Property List Key Reference
下面我将一些iPhone开发的基础概念以我的理解在此说明:
[Cocoa], 是MAC OS X的开发环境,包括Foundation 和 AppKit, 这个概念相当于 .Net 或 Java平台的概念,它是针对普通PC操作系统的开发环境。
[Cocoa Touch], 即手持设备开发环境,包括Foundation 和 UIKit, 相当于.Net的精简平台 或 J2ME,主要针对手机,PDA,IPad等平台的开发环境。
[MAC OS X],我们都知道是苹果操作系统,它相当于Liux, Windows等操作系统。
[iOS], 手持设备操作系统,与Windows CE, ARM linux, Andrio等系统一样,操供手机操作系统支持。
[Objective-C],是Cocoa平台的实现语言,相当于C# 和 Java语言,前者实现了.Net框架,后者实现了Java平台, 而ObjC实现了Cocoa框架。
[Foundation], 框架,类似于.Net 的.Net Framework 以及 Java 的JDK。
[UIKit和AppKit], 前者是实现iOS下的界面元素开发,后者是实现MAC OS X下的应用程序界面。
在此我们可以回顾一下HelloWorld.h头文件中的HelloWorld类继承自UIApplication, 同时包含(#import)了UIKit, 它说明我们的程序是基于iOS平台的界面开发。
(4) 入口文件 main.m
#import <UIKit/UIKit.h> int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, @"HelloWorld", @"HelloWorld"); [pool release]; return retVal; }
现在我们开始回到程序开始的地方,所有开发语言开发出来的程序总会有个入口,连Windows下的动态库都有DllMain, 关于iOS开发下“库”的概念,我会单独以一章来介绍。此处的入口与C语言相同, argc是参数个数,argv是参数值组, argc决定了参数值组的大小。
ObjC的Foundation库与COM和Corba一样,对创建的对象进行管理,与JVM以及.Net虚拟机的内存管理有一些类似,我们知道所有的ObjC对象都是继承自NSObject, 它就是用来对类实例引用进行计数的,当某一对像的引用计数为0时,会调用该对象的dealloc以释放该对象, 对象创建时,引用计数为1, 以后给对象发送retain消息时,计数加1,而对象接收到release消息时,引用计数减1。
入口函数的第一行创建了一个NSAutoreleasePool类型的pool对象,同时调用了init函数,此处的alloc和init函数都是NSObject类的成员函数,NSAutoreleasePool类继承自它。NSAutoreleasePool就是对象引用计数的自动处理器。
NSAutoreleasePool是一个栈,可以有多个NSAutoreleasePool对象,通过发送drain来销毁栈顶的pool对象,同时弹出,这样下一个pool就为当前pool。
注意,对象需要发送autorelease消息以加入到当前pool中进行管理, 当NSAutoreleasePool栈接收到drain消息时,它就对当前pool管理的所有对象发送release消息,你可能会想,如果pool所管理的对象的引用计数不为0,而当前pool已经销毁,该怎么办?很遗憾,你的程序有bug了,这一切表明,你得小心的管理你的对象,以免臭虫的产生。
接下来通过UIApplicationMain调用HelloWorld对象进行界面的显示,直到界面退出,才执行下面的程序代码。
[pool release] 对NSAutoreleasePool实例进行释放。
return retVal; 返回界面执行的结果。
到此,一个基本的HelloWorld例子终于完成了,当然你一定还有许多疑问,我在以后的章节中逐步的加入一些概念以阐明ObjC更多的特性。