请选择 进入手机版 | 继续访问电脑版

环信

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: mmap uikit gcc
查看: 510|回复: 4

Object-C 代理设计模式

  [复制链接]

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2015-10-9 23:16:27 | 显示全部楼层 |阅读模式
本帖最后由 cat 于 2015-10-9 23:20 编辑

代理(delegate),也叫委托,委托别人办事,当一个事情发生后,自己不处理,让别人处理。
代理设计模式,作用是为其他对象提供一种代理以控制对这个对象的访问。
在某种情况下,一个类不想或者不能直接引用另外一个对象,而代理对象就可以在该类和目标对象之间起到中介的作用。

使用例子:
1. 代理和被代理要实现同一个接口(ComputerInterface)。
2. 代理(TDelegate)要引用被代理(IBM):
  1. -(instancetype)initWithVector:(id<ComputerInterface>)vector
复制代码
3. 客户找代理([[TDelegate alloc]initWithVector:ibm])。

                             公共接口
     ---------|--------
    |                                                       |
被代理                                                 代理
IBM                                                       |
                                                           客户

  1. ComputerInterface.h

  2. #import <Foundation/Foundation.h>

  3. @protocol ComputerInterface <NSObject>

  4. -(void)designComputer;
  5. -(void)produceComputer;
  6. //sale computer

  7. @end
复制代码
  1. IBM.h

  2. #import <Foundation/Foundation.h>

  3. #import "ComputerInterface.h"

  4. @interface IBM : NSObject <ComputerInterface>

  5. @end
复制代码
  1. IBM.m

  2. #import "IBM.h"

  3. @implementation IBM

  4. -(void)designComputer{
  5.     NSLog(@"IMB designComputer");
  6. }

  7. -(void)produceComputer{
  8.     NSLog(@"IMB produceComputer");
  9. }

  10. @end
复制代码
  1. TDelegate.h

  2. #import <Foundation/Foundation.h>

  3. #import "ComputerInterface.h"

  4. @interface TDelegate : NSObject <ComputerInterface>
  5. {
  6.     id<ComputerInterface> vector;
  7. }

  8. -(void)saleComputer;
  9. -(instancetype)initWithVector:(id<ComputerInterface>)vector;

  10. @end
复制代码
  1. TDelegate.m

  2. #import "TDelegate.h"

  3. @implementation TDelegate

  4. -(instancetype)initWithVector:(id<ComputerInterface>)v{
  5.     self = [super init];
  6.     if(self)
  7.     {
  8.         self->vector = v;
  9.     }
  10.     return self;
  11. }

  12. -(void)designComputer{
  13.     [self->vector designComputer];
  14. }

  15. -(void)produceComputer{
  16.     [self->vector produceComputer];
  17. }

  18. -(void)saleComputer{
  19.     NSLog(@"sale computer");
  20. }

  21. @end
复制代码


  1. main.m调用:

  2. IBM *ibm = [[IBM alloc]init];
  3. Acer *acer = [[Acer alloc]init];
  4. TDelegate *delegate = [[TDelegate alloc]initWithVector:ibm];
  5. TDelegate *delegateA = [[TDelegate alloc]initWithVector:acer];

  6. [delegate designComputer];
  7. [delegate produceComputer];
  8. [delegate saleComputer];

  9. [delegateA designComputer];
  10. [delegateA produceComputer];
  11. [delegateA saleComputer];
复制代码





回复

使用道具 举报

42

主题

68

帖子

229

积分

中级会员

Rank: 3Rank: 3

积分
229
发表于 2015-10-10 01:32:41 | 显示全部楼层
UIApplication类就是一个典型的例子。UIApplication类中定义了一个应用程序应有的行为或者动作。而不是强制让你的UIApplication子类去接受当前应用程序的状态消息并做出相应处理。UIApplication类通过调用特殊的方法,来传递这些消息给它的委托对象。这个委托对象通过实现名为UIApplicationDelegate的协议(Protocol),之后就可以接受到当前应用程序的状态消息并做出相应处理。比如内存不够的错误,应用程序被中断等重要消息。
回复 支持 反对

使用道具 举报

0

主题

5

帖子

71

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
71
发表于 2015-10-10 01:37:04 | 显示全部楼层
UIApplication类及其委托方法 application:didFinishLaunchingWithOptions

UIApplication继承自UIResponder,的主要作用是提供了iOS程序运行期间的控制和协作工作,每个iOS程序运行期间都会有一个UIApplication实例,一般由main函数的UIApplicationMain函数完成,而在代码中可以调用[UIApplication sharedApplication]方法来得到这个实例(有且仅有一个),比如可以利用它判断程序状态:
  1.     if([UIApplication sharedApplication].applicationState ==UIApplicationStateInactive){

  2.             NSLog(@"程序在运行状态");

  3.        }
复制代码

新建一个任意类型的iOS应用工程,在AppDelegate.h中会看到
  1. AppDelegate :UIResponder <UIApplicationDelegate>
复制代码

即本类实现(采纳)了一个名叫UIApplicationDelegate的接口,且表明AppDelegate这个类就是这个工程中UIApplication实例的代理类。
  1. int main(int argc, char *argv[])

  2. {

  3.     @autoreleasepool {

  4.         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

  5.     }

  6. }
复制代码

这里传入了代理类到UIApplicationMain函数中,UIApplicationMain函数在生成唯一一个UIApplication的时候就可以把代理类的实例指针告诉这个单例对象了。
在UIApplicationDelegate中有很多方法,最重要无非就是
  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions。
复制代码

iOS程序启动时总会调用此方法,其中第二个参数launchOptions为NSDictionary类型的对象,里面存储有此程序启动的原因。例如:若用户直接启动,lauchOptions内无数据; 若由其他应用程序通过openURL:启动,则lauchOptions==UIApplicationLaunchOptionsURLKey对应的对象为启动URL(NSURL),lauchOptions==UIApplicationLaunchOptionsSourceApplicationKey对应启动的源应用程序的bundle ID (NSString)。
回复 支持 反对

使用道具 举报

0

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2015-10-10 01:38:57 | 显示全部楼层
UIApplicationDelegate 代理函数调用的时间(应用程序生命周期)

UIApplicationDelegate 包含下面几个函数监控应用程序状态的改变:
  1. – application:didFinishLaunchingWithOptions:
  2. – applicationDidBecomeActive:
  3. – applicationWillResignActive:
  4. – applicationDidEnterBackground:
  5. – applicationWillEnterForeground:
  6. – applicationWillTerminate:
复制代码

当一个应用程序首先运行时,调用函数didFinishLaunchingWithOptions,但此时应用程序还处于inactive状态,所以接着会调用applicationDidBecomeActive函数,此时就进入了应用程序的界面了。

     接着当按下home键时(此时主界面是应用程序主界面),会调用applicationWillResignActive函数,接着调用applicationDidEnterBackground函数,这时手机回到桌面。

     当再按下应用程序图标时,(假设此时应用程序的内存还没有被其他的应用程序挤掉),调用applicationWillEnterForeground函数,接着调用applicationDidBecomeActive函数,此时又会到应用程序主界面。

     在应用程序的主界面,我们双击home键,(出现多任务栏),调用applicationWillResignActive函数,点击上面部分又会回到程序中,调用applicationDidBecomeActive函数,如果点击多任务栏的其他应用程序,则会调用applicationDidEnterBackground函数之后,进入其他应用程序的界面。

  而对于applicationWillTerminate函数,这里要说明一下:对于我们一般的应用程序,当按下home按钮之后,应用程序会处于一个suspended状态,如果现在去运行其他的程序,当内存不足,或者在多任务栏点击“减号”会完全退出应用程序,但是不管是哪一种,都不会去调用applicationWillTerminate函数(针对IOS4以上),因此我们不能在此函数中保存数据。
  那applicationWillTerminate函数在什么时间调用呢?我查了下资料,还在网上找了找,原来这与当应用程序按下home按钮之后,应用程序的状态有关,当状态为suspended时,是永远不会调用此函数的,而当状态为“后台运行”(running in the background)时,当内存不足或者点击“减号”时,才会调用此函数!官方的原话为:
(Even if you develop your application using iPhone SDK 4 and later, you must still be prepared for your application to be terminated. If memory becomes constrained, the system might remove applications from memory in order to make more room. If your application is currently suspended, the system removes your application from memory without any notice. However, if your application is currently running in the background, the system does call the applicationWillTerminate:method of the application delegate. Your application cannot request additional background execution time from this method.)
回复 支持 反对

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
 楼主| 发表于 2015-10-10 01:40:07 | 显示全部楼层
很多时候,我们不需要关心这个类,我们很少继承这个类,偶尔会调用这个类的api来实现一些功能,但是不可否认,这个类是iOS编程中很重要的一个概念。UIApplication的核心作用是提供了iOS程序运行期间的控制和协作工作。

每一个程序在运行期必须有且仅有一个UIApplication(或则其子类)的一个实例。回想一下我在前面的文章“main函数研究”的文章中提到的main函数的代码,可以看出,在程序开始运行的时候,UIApplicationMain函数是程序进入点,这个函数做了很多工作,其中一个重要的工作就是创建一个UIApplication的单例实例。在你的代码中你,你可以通过调用[UIApplication sharedApplication]来得到这个单例实例的指针。

UIApplication的一个主要工作是处理用户事件,它会起一个队列,把所有用户事件都放入队列,逐个处理,在处理的时候,它会发送当前事件 到一个合适的处理事件的目标控件。此外,UIApplication实例还维护一个在本应用中打开的window列表(UIWindow实例),这样它就 可以接触应用中的任何一个UIView对象。UIApplication实例会被赋予一个代理对象,以处理应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警告)等等。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|环信 Glofty.com ( 粤ICP备15084637号 )

GMT+8, 2017-4-27 22:51 , Processed in 0.238528 second(s), 21 queries .

快速回复 返回顶部 返回列表