------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1. 应用界面的结构
(1) 每一个应用的界面一般有状态栏和该应用程序自己的UIWindow( UIWindow 继承与 UIView )
(2) UIWindow上面有可以放置很多UIView
(3) 跟用户进行交互的是UIWindow
2. 程序的主体构架
从上面图片我们很容易想到以下问题 :
(1) 谁来管理UIView的生命周期?
(2) 谁来管理UIView之间的切换?
(3) 谁来给UIView装配数据?
(4) 谁来监听UIView的事件?
以上答案都是UIViewController,每一个UIViewController.那么 UIViewController Model(数据源) UIView 三者之间的关系如下 :
这就是经典的 MVC 构架 : UIViewController相当于一个中介者,用来负责管理UIView 和 Model的通信.这种设计模式很好地把各类代码分离,降低了代码维护的难度。
3. 应用程序运行的原理
从一个简单地singleViewApplication来看,程序的入口为main函数:
(1) 执行 int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName); 函数 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// main.m
#import <UIKit/UIKit.h>
#import
"MJAppDelegate.h"
int
main(
int
argc,
char
*argv[])
{
@autoreleasepool {
/*
* 参数 1 和 参数 2接受了main函数的两个参数
* 参数 3 : 接受一个 继承与 UIApplication 的类的名称字符串,如果为空,则默认使用 NSStringFromClass( [UIApplication class] )
* 参数 4 : 接收一个应用程序的代理类的名称的字符串
*/
return
UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate
class
]));
}
}
|
(2) 通过这个函数首先会创建一个 UIApplication 的单例对象,然后开启一个main loop 消息循环
(3) 然后根据传入的类名创建和设置UIApplication代理,通过给代理对象发送消息来监听 UIApplication 的生命周期
(4) 在UIApplication加载完毕后发送消息给代理完成UIWindow的初始化工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
// MyAppDelegate.m
#import
"MyAppDelegate.h"
#import
"MyViewController.h"
@implementation MyAppDelegate
- (
void
)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
- (
BOOL
)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// 在应用程序加载完毕之后调用
{
NSLog(@
"didFinishLaunchingWithOptions-加载完毕"
);
// 初始化一个窗口
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// 传入xib文件名来初始化一个控制器
self.viewController = [[[MJViewController alloc] initWithNibName:@
"MJViewController"
bundle:nil] autorelease];
// 设置窗口的根控制器
self.window.rootViewController = self.viewController;
// 上面的代码内部执行了下面代码的操作
// [self.window addSubview:self.viewController.view];
// 窗口不会默认显示,需要调用方法来显示
// keyWindow是主窗口,只有主窗口才能跟用户正常交互
[self.window makeKeyAndVisible];
// self.window.hidden = NO;
return
YES;
}
- (
void
)applicationWillResignActive:(UIApplication *)application
// 程序失去焦点的时候调用(不能跟用户进行交互了)
{
NSLog(@
"applicationWillResignActive-失去焦点"
);
}
- (
void
)applicationDidEnterBackground:(UIApplication *)application
// 当应用程序进入后台的时候调用(点击HOME键)
{
NSLog(@
"applicationDidEnterBackground-进入后台"
);
}
- (
void
)applicationWillEnterForeground:(UIApplication *)application
// 当应用程序进入前台的时候调用
{
NSLog(@
"applicationWillEnterForeground-进入前台"
);
}
// 获取焦点之后才可以跟用户进行交互
- (
void
)applicationDidBecomeActive:(UIApplication *)application
// 当应用程序获取焦点的时候调用
{
NSLog(@
"applicationDidBecomeActive-获取焦点"
);
}
- (
void
)applicationWillTerminate:(UIApplication *)application
// 程序在某些情况下被终结时会调用这个方法
{
NSLog(@
"applicationWillTerminate-被关闭"
);
}
@end
|
4. UIView事件的绑定
由于UIView的事件处理是由 UIViewController 来负责处理的,因此成员变量的设定在UIViewController上:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// MJViewController.h
#import <UIKit/UIKit.h>
@interface MJViewController : UIViewController
// UI元素一般用assign即可
/*
这些UI元素声明周期已经被UIView很好地管理了,
而UIView已经作为UIViewController的成员变量它的生命周期已经得到很好地管理了
因此管理了UIView的声明周期相当于管理了UIView的子元素的生命周期
因此这里无须额外增加管理生命周期的工作量,使用assign即可
*/
// IBOutlet 可以让子元素成员变量显示到xib文件中
@property (nonatomic, assign) IBOutlet UITextField *qq;
@property (nonatomic, assign) IBOutlet UITextField *pwd;
// IBAction其实就是void
// IBAction可以让方法名,显示到xib文件右击列表中
- (IBAction)login;
@end
|
a. UIViewController的UIView的赋值
b. 获得UIView子元素的引用
c. UIView点击事件绑定
5. 点击事件处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#import "MJViewController.h"
@interface MJViewController ()
@end
@implementation MJViewController
#pragma mark 登录
- (
void
)login {
// 获取文本输入框的内容
NSString *qqText = _qq.text;
NSString *pwdText = _pwd.text;
NSLog(@
"QQ=%@,密码=%@"
, qqText, pwdText);
// 暂时理解:叫出键盘的那个视图就是第一个响应者(FirstResponder)
// resignFirstResponder代表这个视图不想当第一响应者了,于是键盘就会退出
//[_qq resignFirstResponder];
//[_pwd resignFirstResponder];
// 如果第一响应者存在于self.view里面,就可以退出键盘
[self.view endEditing:YES];
}
- (
void
)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (
void
)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
|
6. 总结
(1) 应用程序基本构架是 M(数据源),V(视图,UIView),C(UIViewController),UIViewController包含UIView,和数据源,当UIView需要数据来更新界面时候通过UIViewController来收集用户的数据,然后UIViewController把处理好的数据发送给UIView并控制其更新。
(2) 应用程序启动过程大概经历以下步骤 :
1) 执行 UIApplicationMain 函数,传入UIApplication的类名,和UIApplication代理的类名
2) 开启 main loop 消息循环,创建 UIApplication 对象,并创建代理来监听 UIApplication 的生命周期
3) 当 UIApplication 加载完毕时候会发送 - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 消息给代理
4) 这时在此方法中完成界面初始化工作 :
a. 初始化UIWindow对象
b. 根据xib文件创建UIViewController
c. 把窗口的控制器成为UIWindow的根控制器(里面至少执行了把 UIViewController 的UIView添加到 UIWindow上 : [self.window addSubview:self.viewController.view];)
d. 让该 UIWindow 对象成为keyWindow来完成与用户之间的交互。
(4) 对于事件处理 首先给相应地方法绑定IBAction标志,然后在xib文件中进行绑定
(5) 要处理UIView元素的数据首先获得其引用(assign策略),然后使用IBOutlet来在xib绑定引用.