Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1779
  • 博文数量: 1
  • 博客积分: 55
  • 博客等级: 民兵
  • 技术积分: 15
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-29 11:19
文章分类
文章存档

2011年(1)

我的朋友
最近访客

分类: 系统运维

2011-08-29 11:31:56

1.1 iPad概览
 
    关于iPad,有一些参数是首先需要了解的,包括它的重量、大小、屏幕尺寸、容量、操作系统特性、通信接口、传感器等。有了这些知识,才能知道这款设备的潜能,以及设计的应用所能包含的功能。下面所介绍的参数以第一代iPad的Wi-Fi型号为例。
    iPad高为24.28厘米,宽为18.97厘米,比报亭陈列的A4尺寸杂志略小,厚为1.34厘米,与一般杂志厚度相似。iPad的重量为0.68千克,约等于5个iPhone的重量。这样的尺寸和重量,使得iPad适合于双手持握或者平放于膝盖上操作,易于旋转方向。但由于它不适合于长时间单手持握,因此,在设计应用时,不应加入甩动之类让用户吃力的操作。同时,iPad适合于放在公文包中携带,而不是像iPhone那样能够放在口袋里(除非口袋足够大)带到野炊场所的。因此,当考虑iPad用户需求时应当想到,很多iPad用户是携带公文包的白领或中产阶级,而非每天在街边嬉戏的年轻学生。
    iPad有着9.7英寸的电容式多点触摸屏,屏幕分辨率为1024×768像素,像素大小为132DPI(Dots Per Inch)。相对于iPhone的480×320像素的屏幕分辨率,iPad屏幕可以显示更多的信息和内容。比如一款含有地图的游戏,在iPhone上,用户需要不停卷动屏幕来浏览地图,而在iPad上,用户的地图翻动操作将会少得多,因此这类游戏更适合于在iPad上开发。iPad容量为16GB,但这将不会成为你的限制。它有着16GHz的苹果A4处理器,能够保证大多数应用流畅运行。但是它的DRAM(Dynamic Random-Access Memory,动态随机存取存储器)容量仅为256MB,因此在开发中需要执行严格的内存管理。iPad下载应用的方式主要为Wi-Fi和3G,而不便于下载大容量的应用,所以应当控制所开发的应用的大小,最好不要超过100MB,否则用户会不乐意去下载你的应用。
    当前,iPad运行的操作系统为iOS 3.2.1。这个版本的操作系统不支持多任务功能,因此你的应用应当能够随时保存状态,防止用户突然退出应用。即便未来iPad所运行的操作系统支持多任务功能了,仍然需要加入这样的考虑,以确保信息安全。
    传感器方面,iPad上有加速度传感器和环境光传感器,其中加速度传感器是这款设备的核心设计之一,它使得在iPad上的任何一款应用都能够支持四个设备方向,也使得一些需要感应设备倾斜的应用成为可能。在设计iPad应用时,还需要考虑到对不同设备方向的支持,这也是苹果官方对所有iPad应用的建议。iPad上可供使用的输入方式有触摸、软件键盘、声音、加速度传感器,输出方式则包括屏幕和声音。这些输入/输出方式应当在应用开发当中多加使用,以丰富用户使用乐趣。
 
1.2 从PC到iPad
 
    如果要从PC(Mac)平台转向iPad开发,那么需要了解PC开发与iPad开发的几点区别。
    iPad的交互方式以触摸为主,而其他类电脑的交互方式以鼠标和键盘为主。iPad适合用于查看E-mail、上网冲浪、做简单的笔记。完成这些工作不需要大量的键盘输入,人们又希望能够随时随地做这些工作,iPad的携带比任何电脑和笔记本方便很多,所以iPad非常实用。相反地,iPad不适合于文本输入工作,因为人们在软件键盘上的输入速度会比在硬件键盘上慢很多。
    iPad的用户会总是期望无论设备处于何种方向,他们都能够使用各种应用程序。他们会从各种设备方向打开应用,然后将设备在手中反复翻转,期望应用能做出响应。相反地,用户不会去尝试翻转他们的台式机或者笔记本来让应用做出响应。
    还需要考虑到iPad有限的计算和存储能力。iPad上的应用不应当过于消耗计算能力,那样用户会体验到很“卡”的感觉,会给你的应用评“一星”(很低)!在iPad上,应当执行更为严格的内存控制,保证不用的对象得到及时释放,否则应用会因为内存耗尽而崩溃。
    iPad和其他类电脑也有交互。iPad玩家需要用其他类电脑上的iTunes软件来向iPad同步歌曲、电影、书籍,乃至其他更多应用。有一些应用本身也通过Wi-Fi将iPad和其他类电脑连接起来,实现更多的功能。比如iPad应用Brushes,可以在iPad上面用这款应用绘制图形,然后将文件通过Wi-Fi传至其他类电脑上,再通过电脑上的应用程序来重现在iPad上一步一步完成作品的过程!

1.3 从iPhone到iPad
 
    很多iPad开发者可能来自iPhone开发阵营。相对于其他类电脑,iPad和iPhone的差异较为微妙,如若不能理解这些微妙的差异,开发出的应用将无法吸引感兴趣的用户。
    先来看看两者的相似之处:它们都有着电容式触摸屏,同样运行着iOS,但在版本和功能上会略有不同;它们都通过同一个App Store来下载应用,iPad甚至可以兼容绝大多数的iPhone应用。那么,为什么不能简单地改动一下iPhone应用使之成为iPad应用呢?为什么还要来专门研究iPad开发呢?
    答案在于那块大了一倍以上的屏幕,它多了三倍以上的像素数量。如果只是将iPhone应用中元素的尺寸简单扩大一倍,那么无异于浪费了iPad的高分辨率,有些元素也会显得很怪异。如果不放大iPhone应用中的元素,而是将它们重新组合在iPad屏幕上,那么你会发现,屏幕上多出了很多空白,空间被浪费了。面对iPad的高分辨率屏幕,每一个iPhone开发者都应当静下心来思考如何重新设计界面元素,重新定义和用户的交互方式,花时间重塑应用,而不要寻找捷径来牺牲用户体验。这也是苹果官方为iPad设计UISplitViewController和UIPopoverViewController的核心思想,我们会在后面的章节中讲到。
1.4 iPad开发的必备知识
 
    如果你是一名iPhone开发者,那么相信已经掌握了iPad开发的基础知识和工具,可以直接跳至第2章,去学习视图和视图控件的使用。对于初次接触iOS开发的读者,可以从这里开始搜集所需的资料和工具。
    作为一名iPad开发者,首先需要掌握Objective-C语言。Objective-C是一门面向对象的语言,可以看做是C或者C++的超集。Objective-C编译器不仅能编译Objective-C源码,也可以编译C或者C++源码。一个纯Objective-C的源文件的后缀名应当为.m,而一个包含C++代码的源文件的后缀名应当为.mm。本书将在后面的实例中帮助读者逐步熟悉Objective-C的具体语法。
    仅仅掌握Objective-C是不够的,因为如果要想从零开始,一行一行写代码来完成一个应用,将需要很长的时间,这样不仅效率低下,也没有必要。苹果已经为开发者提供了一个很高的起点,只需站在这个起点之上,就能事半功倍。这个起点就是Cocoa—iOS应用程序的框架。事实上,它也是Mac OS X应用程序的框架。Cocoa在iOS操作系统中运行在应用框架(Application Frameworks)层和核心框架(Core Frameworks)层之中。它为开发者提供了基本的应用程序框架、用户界面元素、绘画和图像显示功能、系统交互功能、多线程和内存管理功能、软件国际化功能、文本、网络等。熟悉Cocoa的这些知识,便能调用这些API来快速、高质量地完成你的应用。
    如果是从零开始学Objective-C和Cocoa,本书当中的例子将是最好的参考。书中会对每一个应用的结构做出分析,也会对每一个新出现的语法做出详细的解释。

1.5 iPad开发的必备工具
 
    要掌握的开发工具主要包括:一个集成开发环境—XCode IDE,一个iPad/iPhone界面创建软件—Interface Builder(书中简称为IB),以及一个性能分析仪器—Instruments。这三件工具也统称为XCode。这些工具可以在苹果官方的iPhone开发中心(iPhone Dev Center)的网站上获取,网址是http://developer.apple.com/iphone/index.action(注意,苹果可能会更新这个网站的网址,因此如果上述网址失效,请在Google上搜索iPhone Dev Center。本书中提到的其他网址也可能会失效,请使用Google搜索找到最新网址)。你需要注册一个Apple ID,用这个ID登录,然后在下载区域下载iOS SDK。iOS SDK里面包含了你所需要的全部工具。
    以上只是做iPad开发所必需的工具。如果想下载最新的iOS SDK,并且希望将所开发出来的应用放在App Store上销售,就需要在上述网站中申请加入iPhone开发者项目(iPhone Developer Program,iDP)。申请获得通过后,将需要支付一定费用来获取为期一年的开发资质(个人为一年99美元,企业为一年299美元)。关于iDP申请和之后的操作,将在本书的最后一章专门叙述。
XCode IDE是苹果公司开发的一个集成开发环境,主要用于iPad、iPhone和Mac开发。它提供了项目模板,你可以直接从模板开始创建iPad应用。它提供了一个方便的界面让你设置编译目标,还提供了一键编译执行功能。它提供了一个模拟器(Simulator),这有两个好处:如果你没有iPad,依然可以在模拟器中来查看你的应用运行情况;你有iPad,通过模拟器来观察代码运行情况会更快捷。但是,模拟器也缺少真机的很多功能,比如它无法模拟重力传感器,不能连接App Store,而且模拟器的运算能力会比iPad强大,因此一些潜在问题可能反映不出来。XCode IDE还提供了良好的调试环境,让你能方便地查找代码中的漏洞。
    Interface Builder能够帮助你快速并且直观地创建用户界面。它有着一个包含了大量界面元素的库,可以直接从库中拖拽界面元素到iPad界面,进行可视化编程。对于初学者来说,IB和XCode IDE的结合会令人头疼,但是一旦跟着本书完成了一两个应用之后,将会很快掌握IB用法。
    Instruments可以帮助了解应用运行过程中的内存使用状况,也可以查出内存的泄露情况。前面强调过,内存管理在iPad开发中至关重要,内存泄露小则导致程序运行效率降低(对于游戏来说,是FPS(Frame per Second,每秒帧率)的降低),大则引起程序崩溃。所以,在代码中需要执行内存管理的思想,在写完代码之后,还要通过Instruments来查漏补缺,确保iPad应用能高效运行。
 
1.6 第一个iPad应用—Hello World
 
    下面,将开始实现第一个iPad应用—Hello World。这个应用的主界面非常简单,只有一个按钮,上面显示“Hello World Mail”。点击这个按钮后,将弹出一个邮件发送界面,界面上预先写好发送者的邮件地址、邮件主题和邮件正文。通过这个例子,将学习到如何新建iPad应用,如何通过IB来添加界面元素,如何与用户交互,以及如何调用邮件发送界面。


1.6.1   建立工程:HelloWorldMail
    首先,打开XCode,在菜单中选择“File”→“New Project”。选择View-based Application选项,在Product下拉菜单中选中iPad,然后单击Choose按钮,将应用命名为HelloWorldMail,这样就创建好了一个基于视图的应用,如图1-1所示。              
    下面来看一看XCode IDE的界面,如图1-2所示。界面上方是工具条,左侧是工程文件浏览区,中间是源码浏览区。
    工具条左侧的Overview下拉菜单很重要,我们要在这里选择:
1)真机还是模拟器?在此我们选择模拟器,以方便调试。
2)调试模式还是发布模式?调试模式会包含很多调试符号,发布模式则没有。因此,如果应用在发布模式下崩溃了,那么会得到一些十六进制地址,而非有意义的文字。在调试模式下,编译器不对可执行文件进行优化,但这样也使得调试更为方便。通常情况下,在开发阶段使用调试模式,只有在最后发布时使用发布模式。Dverview的相关设置如图1-3所示。
    工具条上最常用的一个按钮是Build and Run,如图1-4所示。单击这个按钮,XCode会对工程进行编译,生成iPad模拟器的可执行文件,并在模拟器上运行HelloWorldMail这个应用。此时,会出现一个空白的屏幕,因为还没有为应用加入任何按钮和功能。          
                               图1-2   XCode IDE的界面
 
1.6.2 工程概览
 
在左侧工程文件浏览区,可以看到如图1-5所示的内容,下面一一解释这些文件的用途。 如果是首次接触Objective-C,那么这一小节内容至关重要,在这一小节,我们会介绍很多Objective-C编程的基本概念和方法。

1. main.m
这个文件中的主函数main(见代码清单1-1)是整个应用执行的起点。其中第一句建立了一个自动释放池;第二句调用UIApplicationMain函数建立起应用对象(application object)和事件循环(event cycle),事实上这个函数永远不会返回,因为它将一直运行,直到用户按下Home按钮为止;第三句释放了前面建立起来的自动释放池,同时也会释放池中的所有变量,这严格执行了内存管理机制。
代码清单1-1   Main函数
int main(int argc, char *argv[]) {
   
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}
作为iPad开发者,不需要修改这个主文件,但是为了帮助你更好地理解程序执行的流程,下面简单介绍程序进入UIApplicationMain函数后如何找到其他文件的入口。
值得注意的是,UIApplicationMain函数的第三个参数指定了该应用从哪个类初始化,它的值为nil,因此程序会默认通过UIApplication来初始化应用对象。UIApplicationMain函数的第四个参数指定了应用的代理从哪个类初始化,它的值为nil,因此程序会默认在HelloWorldMail-Info.plist文件中寻找一个叫做“Main nib file base name”的项,打开这个.plist文件,会发现这个键值为“MainWindow”,因此程序会从MainWindow.xib文件中去寻找应用的代理所属的类。
小知识:对象(object)
Objective-C是面向对象的编程语言,因此对象也是该语言的核心内容。对象中包括了一些相关数据,这些是其成员变量(member variable或者instance variable),除非特别做出声明,否则这些变量只有其所属对象能够操作(读、写、复制等)。对象也提供了一些操作成员变量的方法(method),类似于C++中的函数(function)。
在Objective-C中,永远只需要通过一个对象的指针来操作该对象。空指针是一个特殊的指针,用nil表示(类似于C++中的NULL)。
小知识:消息机制(messaging)
可以给任何一个对象传递一个消息,告诉它去执行某个方法,这个操作叫做消息机制,类似于C++中的函数调用。消息传递的格式为:
[receiver message]
其中receiver为一个对象,而message在源代码中就是一个方法的名称和相应的参数。例如:
[NSAutoreleasePool alloc]
NSAutoreleasePool是一个类,定义了一个自动释放库,在这里就是receiver。alloc是一个方法,在这里就是message。

                                                                                                                                                                                                                                 2. HelloWorldMail-Info.plist
plist指的是属性列表(Property List),包含以XML格式组织起来的数据,每一个数据都有其自己的命名。通常情况下不需要修改plist文件,但有例外,比如想在iPhone上隐藏状态条或指定应用的图标文件。

 

3. HelloWorldMailAppDelegate.h和HelloWorldMailViewController.h
这是两个头文件。以HelloWorldMailAppDelegate.h为例(见代码清单1-2)来简单看一下Objective-C的头文件结构。在学习过程中,可以将Objective-C和C++的语法做出类比,以辅助记忆。
代码清单1-2   HelloWorldMailViewController.h
#import

@class HelloWorldMailViewController;

@interface HelloWorldMailAppDelegate : NSObject {
    UIWindow *window;
    HelloWorldMailViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet HelloWorldMailViewController *viewController;

@end
第一句#import,是用于包含头文件的语句,类似于C++中的#include。紧随其后,系统文件往往用<>括号括起来,而自己写的文件用""引起来。
第二句@class,是一个指令语句,作用是对一个类做出前向声明,能最小化编译器和连接器所看到的代码的数量。这类似于C++中的前向声明指令class。
从@interface到@end之间,是类的声明。HelloWorldMailAppDelegate是类的名称,而冒号后面的NSObject是其父类名称。声明了一个代理机制:尽管HelloWorldMailAppDelegate没有继承UIApplication类,但是它依然可以调用UIApplication类的一些代理方法。
HelloWorldMailAppDelegate类有两个成员变量,是两个指针,指针所指向的对象分别属于UIWindow类和HelloWorldMailViewController类。UIWindow是一个窗口类,绝大部分的应用都会用到这个类。HelloWorldMailViewController则是在另一个头文件HelloWorldMailViewController.h中定义的一个类。需要注意的是,在Objective-C中,只使用对象的指针,而不是对象本身。这一点可以从这两个成员变量的定义中看出。
再往下面,@property为两个成员变量提供了属性,使得我们可以通过点语法(dot syntax)来对这两个成员变量进行读写操作(access)。关于这一点,在后面还会做出详细说明。

 

4. HelloWorldMailAppDelegate.m和HelloWorldMailViewController.m
这两个文件包含了类的实现。以HelloWorldMailAppDelegate.m为例(见代码清单1-3)来简单说明其中语法和功能。
代码清单1-3   HelloWorldMailAppDelegate.m
#import "HelloWorldMailAppDelegate.h"
#import "HelloWorldMailViewController.h"

@implementation HelloWorldMailAppDelegate

@synthesize window;
@synthesize viewController;

#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
   
    // 这个方法通常是这个应用的编程起点
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    /*
     当有来电或短消息时,应用进入Inactive状态
     在这个方法中,通常停止计时器、降低OpenGL ES的帧率、暂停游戏
     */
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
     重新启动所有暂停了的任务
     */
}

- (void)applicationWillTerminate:(UIApplication *)application {
    /*
     应用即将彻底结束,所谓彻底结束,是和进入后台相对应的
     */
}

#pragma mark -
#pragma mark Memory management

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /*
     应用收到内存警告时,应当尽量多地释放内存,以缓解内存紧张状况
     */
}

- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

@end
两个#import用于包含头文件。前面提过了,包含非系统性头文件用""引起来。
在@implementation和@end之间,是对HelloWorldMailAppDelegate类的实现。其中@synthesize和头文件中的@property成对出现。#pragma mark只是用于分隔源代码的,不对代码运行产生影响。下面来看一看每一个方法(类似于C++中的函数)的作用。
小知识:Objective-C中的方法(Method)
以HelloWorldMailAppDelegate.m的第一个方法为例。
-(BOOL)application:(UIApplicaiton*)application
   didFinishLaunchingWithOptions: (NSDictionary*)launchOptions
其中application和didFinishLaunchingWithOptions是这个方法的签名(signature),application和launchOptions是这个方法的参数,这两个参数的类型分别为UIApplication*和NSDicitonary*。
可以看出,Objective-C方法的签名和参数可以交互出现,一个签名后面跟随一个参数(在C++中,函数的参数都在括号之中,和函数名是分开的)。Objective-C中这样做的好处是,每个参数的类型和意义非常明确,代码可读性很强。
方法开头的(BOOL)表示这个方法的返回值是BOOL类型的。方法开头的减号(-)表明这是一个实例方法(instance method),意思是这个方法的调用者必须是一个类的实例(instance),而不能是一个类(class)本身。相反地,方法开头如果有加号(+),则表明这是一个类方法(class method),意思是这个方法的调用者必须是一个类。
第一个方法的签名为application: didFinishLaunchingWithOptions:,在应用启动后自动被调用。第二个方法的签名为applicationWillResignActive:,在应用即将从活动状态转入非活动状态时被调用。第三个方法的签名为applicationDidBecomeActive:,在应用刚刚转入活动状态后被调用。第四个方法的签名为applicationWillTerminate:,在应用即将退出时被调用。第五个方法的签名为applicationDidReceiveMemoryWarning:,在应用得到内存警告后被调用。以上5个方法都是代理方法(delegate method)。需要注意的是第一个方法中的
[window addSubview:viewController.view];
这一句的作用就是将viewController的视图作为子视图加在window上面。程序启动后,用户所看到的也是viewController.view。因此,如果要修改呈献给用户的内容,就需要修改viewController所属的类HelloWorldMailViewController。
小知识:代理(Delegation)与协议(Protocol)
代理是iPhone开发中一个很重要的设计模式。简单地说,在代理模式中,一个对象(在例子当中就是UIApplication)给其代理(HelloWorldMailAppDelegate的实例)发送消息,向它要求输入或者通知它一个事件即将或者刚刚发生。代理模式的好处是,即使HelloWorldMailAppDelegate不继承UIApplication,它依然可以使用UIApplication的一些方法。在C++中,继承(Inheritance)是重复利用代码的主要方法;而代理则提供了另一种方法,很多时候会比继承更方便。
由于人们希望一些方法能够经常为代理所使用,于是将这些方法合在一块,组成协议。HelloWorldMailAppDelegate采用(Adopt)了UIApplication协议,也就是说它能够执行UIApplication的一些代理方法。
最后一个方法的签名是dealloc。这个方法继承自NSObject类。它非常重要,只有正确地实现它才能够确保无内存泄露。在dealloc中,需要释放所有为HelloWorldMailAppDelegate所拥有的对象。

5. HelloWorldMailViewController.xib和MainWindow.xib
xib文件中包含了视图的信息。如果双击一个xib文件,就会启动IB,可以进行“所见即所得”的操作。

6. HelloWorldMail_Prefix.pch
这是一个包含文件,会和其他文件分开编译,因此不需要在其他文件之中包含它。

7. UIKit.framework, Foundation.framework和CoreGraphics.framework
这是三个最常用的框架(framework),类似于C++中的库(library)。

8. HelloWorldMail.app
这就是在iPhone上的可执行文件了!

1.6.3   添加按钮
这一小节中,我们要让用户能够在应用启动后,看到一个按钮,上面写着“Say Hello World through Mail!”。上一节中提到了,我们需要修改HelloWorldMailViewController这个类,包括其xib文件、h文件和mm文件。为了达成这一目标,需要修改界面文件、修改源文件以及给两者建立起连接。
我们先来修改xib文件。双击HelloWorldMailViewController.xib文件,能看到IB启动,并且呈现出一个大大的白色视图—这就是用户在程序启动后将看到的视图。下面请选择Interface Builder→Tools→Library,将看到一个包含大量界面元素的库(如图1-6所示)—将从这里开始熟悉可用于装饰界面并呈现信息的元素。请找到一个叫做Round Rect Button的按钮元素,将其拖到视图中央。双击这个按钮,可以输入这个按钮上将要显示的文字;本程序中输入的是“Say Hello World through Mail!”(如图1-7所示)。

此时,可以单击工具条中的Build and Run按钮,查看含有按钮的iPad界面,如图1-8所示。这时的按钮还不具备任何功能,因此下面我们所要做的是为按钮添加一点功能—当单击时在调试区域显示“Hello World!”。我们通过修改源文件来添加一个在调试区域显示字符串的方法。请打开HelloWorldMailViewController.h,在@end前面加入以下方法声明:
-(IBAction) didClickButton;
然后打开HelloWorldMailViewController.m,为我们刚刚声明的方法添加实现:
-(IBAction) didClickButton {
    NSLog(@"Hello World!");
}
NSLog是做开发调试的最好伙伴,可以用它在程序运行时显示想查看的参数内容,也可以用它来检测代码流程。上面这句的参数@"Hello World!"是要显示的字符串。
至此,我们在xib文件中添加了按钮,也在源文件中添加了按钮按下后要实现的方法,但两者之间的连接尚未建立—这个很简单,请打开HelloWorldMailViewController.xib文件,按住Control键不要松开,同时将鼠标从视图上的按钮拖向File誷 Owner。这时可以看到一个弹出框,如图1-8所示。单击didClickButton,这样连接就建立好了。

此时,请再次单击Build and Run按钮,运行iPad模拟器。按下界面上的按钮,看看调试区域是否显示出了“Hello World!”,如果显示出来了,那么按钮已经具备了基本功能。但只和自己说Hello World是不够的,我们将在下一小节讲解怎么使用邮件编辑器,向全世界任何一个在使用互联网的人说Hello World!

1.6.4 邮件编辑器

 

使用邮件编辑器,需要完成以下步骤:添加框架(framework),包含头文件,设置代理,完成代理方法。本小节将讲解如何一步一步完成这些工作。当今后学习如何播放音乐、视频,如何调用系统图片库时,将需要完成同样的步骤。

首先,你需要向工程中添加框架MessageUI.framework。在工程文件浏览区域,找到Frameworks组,右键单击后,选择Add→Existing Frameworks,然后在弹出框中选中MessageUI.framework

接下来,打开HelloWorldMailViewController.h文件,用下面这句来包含所必需的头文件:
#import
然后是将HelloWorldMailViewController设置为MFMailComposeViewController的代理。需要添加,使得文件成为:

#import
#import

@interface HelloWorldMailViewController : UIViewController {

}

-(IBAction) didClickButton;

@end

 

最后打开HelloWorldMailViewController.m,如代码清单1-4所示的修改didClickButton方法,并添加签名为mailComposeController:   didFinishWithResult: error:的代理方法。在didClickButton中,我们首先通过[MFMailComposeViewController canSendMail]判断设备的邮件发送功能是否已经设置好。如果设置好了,我们就初始化一个MFMailComposeViewController的实例picker,并且将其代理设置为self—也就是这个消息的接收对象。接下来,我们用setSubject:setMessageBody: isHTML:两个方法来预设邮件编辑器的主题和正文。此时,邮件编辑器已经设置好了,我们用presentModalViewController: animated:方法来显示邮件接收器。最后,由于我们使用了alloc来创建picker,并且它已经呈现在屏幕上了,因此我们需要release掉。再看看这个代理方法,它在用户发送完邮件或者点击cancel(取消)按钮后被触发。这时,我们需要移除掉picker,方法是dismissModalViewControllerAnimated:

代码清单1-4   HelloWorldMailViewController.m中两个需要修改的方法

-(IBAction) didClickButton {
    if ([MFMailComposeViewController canSendMail]) {
        MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
        picker.mailComposeDelegate = self;

        [picker setSubject:@"Hello World from my iPad app!"];

        NSString *emailBody = @"Hey,

\
        this is from my first iPad app!";
        [picker setMessageBody:emailBody isHTML:YES];

        [self presentModalViewController:picker animated:YES];
        [picker release];
    }
}

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
    [self dismissModalViewControllerAnimated:YES];
}
此时,再运行iPad应用,你可以打开邮件编辑器了(如图1-9所示)。你可以试着用这款应用给朋友发送邮件,看看他们能不能收到你的问候呢?

                               1-2   XCode IDE的界面

 

1.6.2 工程概览

 

在左侧工程文件浏览区,可以看到如图1-5所示的内容,下面一一解释这些文件的用途。 如果是首次接触Objective-C,那么这一小节内容至关重要,在这一小节,我们会介绍很多Objective-C编程的基本概念和方法。

1.      main.m

这个文件中的主函数main(见代码清单1-1)是整个应用执行的起点。其中第一句建立了一个自动释放池;第二句调用UIApplicationMain函数建立起应用对象(application object)和事件循环(event cycle),事实上这个函数永远不会返回,因为它将一直运行,直到用户按下Home按钮为止;第三句释放了前面建立起来的自动释放池,同时也会释放池中的所有变量,这严格执行了内存管理机制。

代码清单1-1   Main函数
int main(int argc, char *argv[]) {
   
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}
作为iPad开发者,不需要修改这个主文件,但是为了帮助你更好地理解程序执行的流程,下面简单介绍程序进入UIApplicationMain函数后如何找到其他文件的入口。
值得注意的是,UIApplicationMain函数的第三个参数指定了该应用从哪个类初始化,它的值为nil,因此程序会默认通过UIApplication来初始化应用对象。UIApplicationMain函数的第四个参数指定了应用的代理从哪个类初始化,它的值为nil,因此程序会默认在HelloWorldMail-Info.plist文件中寻找一个叫做“Main nib file base name”的项,打开这个.plist文件,会发现这个键值为“MainWindow”,因此程序会从MainWindow.xib文件中去寻找应用的代理所属的类。
小知识:对象(object
Objective-C
是面向对象的编程语言,因此对象也是该语言的核心内容。对象中包括了一些相关数据,这些是其成员变量(member variable或者instance variable),除非特别做出声明,否则这些变量只有其所属对象能够操作(读、写、复制等)。对象也提供了一些操作成员变量的方法(method),类似于C++中的函数(function)。
Objective-C中,永远只需要通过一个对象的指针来操作该对象。空指针是一个特殊的指针,用nil表示(类似于C++中的NULL)。
小知识:消息机制(messaging
可以给任何一个对象传递一个消息,告诉它去执行某个方法,这个操作叫做消息机制,类似于C++中的函数调用。消息传递的格式为:
[receiver message]
其中receiver为一个对象,而message在源代码中就是一个方法的名称和相应的参数。例如:
[NSAutoreleasePool alloc]
NSAutoreleasePool
是一个类,定义了一个自动释放库,在这里就是receiveralloc是一个方法,在这里就是message

                                                                                            2. HelloWorldMail-Info.plist
plist
指的是属性列表(Property List),包含以XML格式组织起来的数据,每一个数据都有其自己的命名。通常情况下不需要修改plist文件,但有例外,比如想在iPhone上隐藏状态条或指定应用的图标文件。

 

3. HelloWorldMailAppDelegate.hHelloWorldMailViewController.h
这是两个头文件。以HelloWorldMailAppDelegate.h为例(见代码清单1-2)来简单看一下Objective-C的头文件结构。在学习过程中,可以将Objective-CC++的语法做出类比,以辅助记忆。

代码清单1-2   HelloWorldMailViewController.h
#import

@class HelloWorldMailViewController;

@interface HelloWorldMailAppDelegate : NSObject {
    UIWindow *window;
    HelloWorldMailViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet HelloWorldMailViewController *viewController;

@end
第一句#import,是用于包含头文件的语句,类似于C++中的#include。紧随其后,系统文件往往用<>括号括起来,而自己写的文件用""引起来。

第二句@class,是一个指令语句,作用是对一个类做出前向声明,能最小化编译器和连接器所看到的代码的数量。这类似于C++中的前向声明指令class
@interface@end之间,是类的声明。HelloWorldMailAppDelegate是类的名称,而冒号后面的NSObject是其父类名称。声明了一个代理机制:尽管HelloWorldMailAppDelegate没有继承UIApplication类,但是它依然可以调用UIApplication类的一些代理方法。
HelloWorldMailAppDelegate
类有两个成员变量,是两个指针,指针所指向的对象分别属于UIWindow类和HelloWorldMailViewController类。UIWindow是一个窗口类,绝大部分的应用都会用到这个类。HelloWorldMailViewController则是在另一个头文件HelloWorldMailViewController.h中定义的一个类。需要注意的是,在Objective-C中,只使用对象的指针,而不是对象本身。这一点可以从这两个成员变量的定义中看出。
再往下面,@property为两个成员变量提供了属性,使得我们可以通过点语法(dot syntax)来对这两个成员变量进行读写操作(access)。关于这一点,在后面还会做出详细说明。

 

4. HelloWorldMailAppDelegate.mHelloWorldMailViewController.m
这两个文件包含了类的实现。以HelloWorldMailAppDelegate.m为例(见代码清单1-3)来简单说明其中语法和功能。

代码清单1-3   HelloWorldMailAppDelegate.m
#import "HelloWorldMailAppDelegate.h"
#import "HelloWorldMailViewController.h"

@implementation HelloWorldMailAppDelegate

@synthesize window;
@synthesize viewController;

#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
   
    //
这个方法通常是这个应用的编程起点

    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    /*
    
当有来电或短消息时,应用进入Inactive状态

    
在这个方法中,通常停止计时器、降低OpenGL ES的帧率、暂停游戏
     */
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
    
重新启动所有暂停了的任务
     */
}

- (void)applicationWillTerminate:(UIApplication *)application {
    /*
    
应用即将彻底结束,所谓彻底结束,是和进入后台相对应的
     */
}

#pragma mark -
#pragma mark Memory management

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /*
    
应用收到内存警告时,应当尽量多地释放内存,以缓解内存紧张状况
     */
}

- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

@end
两个#import用于包含头文件。前面提过了,包含非系统性头文件用""引起来。
@implementation@end之间,是对HelloWorldMailAppDelegate类的实现。其中@synthesize和头文件中的@property成对出现。#pragma mark只是用于分隔源代码的,不对代码运行产生影响。下面来看一看每一个方法(类似于C++中的函数)的作用。
小知识:Objective-C中的方法(Method
HelloWorldMailAppDelegate.m的第一个方法为例。
-(BOOL)application:(UIApplicaiton*)application
   didFinishLaunchingWithOptions: (NSDictionary*)launchOptions
其中applicationdidFinishLaunchingWithOptions是这个方法的签名(signature),applicationlaunchOptions是这个方法的参数,这两个参数的类型分别为UIApplication*NSDicitonary*
可以看出,Objective-C方法的签名和参数可以交互出现,一个签名后面跟随一个参数(在C++中,函数的参数都在括号之中,和函数名是分开的)。Objective-C中这样做的好处是,每个参数的类型和意义非常明确,代码可读性很强。
方法开头的(BOOL)表示这个方法的返回值是BOOL类型的。方法开头的减号(-)表明这是一个实例方法(instance method),意思是这个方法的调用者必须是一个类的实例(instance),而不能是一个类(class)本身。相反地,方法开头如果有加号(+),则表明这是一个类方法(class method),意思是这个方法的调用者必须是一个类。
第一个方法的签名为application: didFinishLaunchingWithOptions:,在应用启动后自动被调用。第二个方法的签名为applicationWillResignActive:,在应用即将从活动状态转入非活动状态时被调用。第三个方法的签名为applicationDidBecomeActive:,在应用刚刚转入活动状态后被调用。第四个方法的签名为applicationWillTerminate:,在应用即将退出时被调用。第五个方法的签名为applicationDidReceiveMemoryWarning:,在应用得到内存警告后被调用。以上5个方法都是代理方法(delegate method)。需要注意的是第一个方法中的
[window addSubview:viewController.view];
这一句的作用就是将viewController的视图作为子视图加在window上面。程序启动后,用户所看到的也是viewController.view。因此,如果要修改呈献给用户的内容,就需要修改viewController所属的类HelloWorldMailViewController
小知识:代理(Delegation)与协议(Protocol
代理是iPhone开发中一个很重要的设计模式。简单地说,在代理模式中,一个对象(在例子当中就是UIApplication)给其代理(HelloWorldMailAppDelegate的实例)发送消息,向它要求输入或者通知它一个事件即将或者刚刚发生。代理模式的好处是,即使HelloWorldMailAppDelegate不继承UIApplication,它依然可以使用UIApplication的一些方法。在C++中,继承(Inheritance)是重复利用代码的主要方法;而代理则提供了另一种方法,很多时候会比继承更方便。
由于人们希望一些方法能够经常为代理所使用,于是将这些方法合在一块,组成协议。HelloWorldMailAppDelegate采用(Adopt)了UIApplication协议,也就是说它能够执行UIApplication的一些代理方法。
最后一个方法的签名是dealloc。这个方法继承自NSObject类。它非常重要,只有正确地实现它才能够确保无内存泄露。在dealloc中,需要释放所有为HelloWorldMailAppDelegate所拥有的对象。

5. HelloWorldMailViewController.xibMainWindow.xib
xib
文件中包含了视图的信息。如果双击一个xib文件,就会启动IB,可以进行所见即所得的操作。

6. HelloWorldMail_Prefix.pch
这是一个包含文件,会和其他文件分开编译,因此不需要在其他文件之中包含它。

7. UIKit.framework, Foundation.frameworkCoreGraphics.framework
这是三个最常用的框架(framework),类似于C++中的库(library)。

8. HelloWorldMail.app
这就是在iPhone上的可执行文件了!


1.6.3  
添加按钮
这一小节中,我们要让用户能够在应用启动后,看到一个按钮,上面写着“Say Hello World through Mail。上一节中提到了,我们需要修改HelloWorldMailViewController这个类,包括其xib文件、h文件和mm文件。为了达成这一目标,需要修改界面文件、修改源文件以及给两者建立起连接。
我们先来修改xib文件。双击HelloWorldMailViewController.xib文件,能看到IB启动,并且呈现出一个大大的白色视图这就是用户在程序启动后将看到的视图。下面请选择Interface Builder→Tools→Library,将看到一个包含大量界面元素的库(如图1-6所示)将从这里开始熟悉可用于装饰界面并呈现信息的元素。请找到一个叫做Round Rect Button的按钮元素,将其拖到视图中央。双击这个按钮,可以输入这个按钮上将要显示的文字;本程序中输入的是“Say Hello World through Mail(如图1-7所示)。

此时,可以单击工具条中的Build and Run按钮,查看含有按钮的iPad界面,如图1-8所示。这时的按钮还不具备任何功能,因此下面我们所要做的是为按钮添加一点功能当单击时在调试区域显示“Hello World!”。我们通过修改源文件来添加一个在调试区域显示字符串的方法。请打开HelloWorldMailViewController.h,在@end前面加入以下方法声明:
-(IBAction) didClickButton;
然后打开HelloWorldMailViewController.m,为我们刚刚声明的方法添加实现:
-(IBAction) didClickButton {
    NSLog(@"Hello World!");
}
NSLog
是做开发调试的最好伙伴,可以用它在程序运行时显示想查看的参数内容,也可以用它来检测代码流程。上面这句的参数@"Hello World!"是要显示的字符串。
至此,我们在xib文件中添加了按钮,也在源文件中添加了按钮按下后要实现的方法,但两者之间的连接尚未建立这个很简单,请打开HelloWorldMailViewController.xib文件,按住Control键不要松开,同时将鼠标从视图上的按钮拖向File Owner。这时可以看到一个弹出框,如图1-8所示。单击didClickButton,这样连接就建立好了。
   
此时,请再次单击Build and Run按钮,运行iPad模拟器。按下界面上的按钮,看看调试区域是否显示出了“Hello World!”,如果显示出来了,那么按钮已经具备了基本功能。但只和自己说Hello World是不够的,我们将在下一小节讲解怎么使用邮件编辑器,向全世界任何一个在使用互联网的人说Hello World

 

1.7   小结

在这一章中,我们简要地介绍了iPad性能,并与电脑和iPhone做了比较,以强调其主要特性:高分辨率的屏幕、触摸式交互以及不错的移动性能。通过这些比较,我们为iPad应用的设计提供了建议。接下来,我们谈到了iPad开发所必需的知识(Objective-CCocoa)和工具(XCode IDE)。最后,我们通过一个邮件编辑器实例,来帮助完成你的第一个iPad应用。在例子当中,我们介绍了最基本的Objective-C语法以及XCode IDE使用方法。有了这一章的基础,你可以开始学习更多的iPad开发技术了!

 

 



 

阅读(746) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~