您的位置:首页 > 移动开发 > Objective-C

【IOS 开发学习总结-OC-21】★★★objective-c面向对象——委托/代理(delegate)

2015-09-27 19:59 651 查看
本文建议结合上篇博文一起学习: 【IOS 开发学习总结-OC-20】★★★objective-c面向对象——协议(protocol)

delegate 是什么

协议和委托/代理关系很密切,代理是种设计模式。delegate是委托/代理模式.委托/代理模式是将一件属于委托者做的事情,交给另外一个被委托者来处理. 为了便于理解,这里都成为统一称为委托(delegate)。

一个标准的委托由如下内容组成:

1.协议的声明——用来声明哪些方法被委托出去

#import <Foundation/Foundation.h>

@protocol SecDelegate <NSObject>

-(void)phone;//打电话
-(void)payoff;//发工资
@end


2.委托者声明一个属性——用于代表被委托者,一般建议用id类型。注意:这个属性是弱引用——为什么是弱引用,会在后面说明。

@property (weak,nonatomic)id<SecDelegate>delegate;


3.被委托者声明实现了委托里的协议

@interface HXYSec : NSObject<SecDelegate>


4.设置委托——在被委托者里设置自身是委托者的被委托者。

boss.delegate=sec;
//将被委托者自己的实例作为被委托对象

5委托事件——在被委托者里调用委托的方法

[boss.delegate phone];
[boss.delegate payoff];
//或者是
[sec phone];
[sec payoff];


示例代码:

SecDelegate.h

#import <Foundation/Foundation.h>

@protocol SecDelegate <NSObject>

-(void)phone;//打电话
-(void)payoff;//发工资
@end


HXYBoss.h

#import <Foundation/Foundation.h>
#import "SecDelegate.h"

@interface HXYBoss : NSObject

@property (strong,nonatomic)NSString * name;
@property (weak,nonatomic)id<SecDelegate>delegate;
// 一般建议用id类型
-(void)talk;//谈心

@end


HXYBoss.m

#import "HXYBoss.h"

@implementation HXYBoss
@synthesize name;

-(void)talk
{
    NSLog(@"%@在谈话!",name);
}

@end


HXYSec.h

#import <Foundation/Foundation.h>
#import "HXYBoss.h"

@interface HXYSec : NSObject<SecDelegate>
@property (strong,nonatomic)NSString * name;

@end


HXYSec.m

#import "HXYSec.h"

@implementation HXYSec
@synthesize name;

-(void)phone
{
    NSLog(@"%@在打电话!",name);
}

-(void)payoff
{
    NSLog(@"%@在发工资!",name);
}

@end


main.m

#import <Foundation/Foundation.h>
#import "HXYBoss.h"
#import "HXYSec.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        HXYBoss *boss=[[HXYBoss alloc]init];
        boss.name=@"韩新源";
        HXYSec *sec=[[HXYSec alloc]init];
        sec.name=@"李秘书";
        [boss talk];
        boss.delegate=sec;
        [boss.delegate phone];
        [boss.delegate payoff];
        //或者是
        [sec phone];
        [sec payoff];

    }
    return 0;
}


编译运行结果:

2015-09-28 09:48:15.022 代理[1312:34897] 韩新源在谈话!
2015-09-28 09:48:15.023 代理[1312:34897] 李秘书在打电话!
2015-09-28 09:48:15.023 代理[1312:34897] 李秘书在发工资!
2015-09-28 09:48:15.024 代理[1312:34897] 李秘书在打电话!
2015-09-28 09:48:15.024 代理[1312:34897] 李秘书在发工资!


delegate为什么用弱引用

答案是:为了避免retain cycle。

即:有A,B两个Object, A中有一个B的实例变量,B中又有一个A的实例变量,要release A就必须releaseA中的B,而要release B有必须release B中的A,这样就产生了一个Retain Circle,A B都不能被dealloc.解决Retain Circle的方法就是使用弱引用(weak reference),弱引用没有被引用的那个Object的所有权,也就不需要release它,从而解决了Retain Circle问题.为了防止Retain Circle的发生, delegate通常都是弱引用的, 因此我们一般不应该retain一个delegate。

NSURLConnection是个例外。

delegate 的3个用途

委托一般可以分成3种

1.传递事件

传递事件就是A发生了什么事情, 希望B知道下, 然后B在自己的类里面要做出某些反应.典型的如

tableView:didSelectRowAtIndexPath:
, 就是UITableView点击了某个cell的时候, 希望其它类(通常是ViewController)响应这个点击, 在点击的时候跳转到其他viewController之类的.

2.确定事件可执行

确定事件可执行是当A需要执行某个事件的时候, A不确定到底可执行, 这个时候希望B能回应下. 如
tableView:shouldHighlightRowAtIndexPath:
是UITableView询问其它类要不要高亮显示某个cell, 当返回NO的时候, 就UITableView就不会执行cell的高亮方法.

3.传递值

传递值是当A需要某个数据的时候, 由B来提供. 例子还是UITableView里的,
tableView:cellForRowAtIndexPath:
是需要某个cell的时候由其他类提供这个cell.

委托命

委托

通常的委托用delegate做后缀.如
<UIScrollViewDelegate>


@protocol <#class#>Delegate


数据源

当你的委托的方法过多, 可以拆分数据部分和其他逻辑部分, 数据部分用dataSource做后缀. 如
<UITableViewDataSource, UITableViewDelegate>


@protocol <#class#>DataSource


多播委托

多播委托

通常的委托只支持一对一的委托, 但是在某些场景下, 我们希望有多个被委托者. 这种场景下可以考虑使用多播委托.

多播委托的实现类在XYMulticastDelegate, https://github.com/uxyheaven/XYQuick/tree/master/XYQuick/event/modules.

他是copy form XMPP的GCDMulticastDelegate.

每个多播委托的委托者类建议有以下的基本描述

// .h
// 多播委托, 建议加上你的协议修饰: -(id <InAppPurchasesServiceProtocol>)multicastDelggate;
- (id)multicastDelggate;
- (void)addDelegate:(id)delegate;
- (void)removeDelegate:(id)delegate;
- (void)removeAllDelegates;


实现文件里, 你需要这么写

// .m
- (void)addDelegate:(id)delegate
{
    [_multicastDelggate addDelegate:delegate delegateQueue:dispatch_get_main_queue()];
}

- (void)removeDelegate:(id)delegate
{
    [_multicastDelggate removeDelegate:delegate];
}

- (void)removeAllDelegates
{
    [_multicastDelggate removeAllDelegates];
}


其他的用法和普通的delegate类似

// 协议
@protocol InAppPurchasesServiceProtocol <NSObject>
@optional
/**
 * @brief callback for update product list succeed
 */
-(void)inAppPurchasesService:(InAppPurchasesService *)service didUpdatedProducts:(NSArray *)array;

// 用的时候
[self.multicastDelggate inAppPurchasesService:self didUpdatedProductsFailed:error];


本文建议结合上篇博文一起学习: 【IOS 开发学习总结-OC-20】★★★objective-c面向对象——协议(protocol)

参考资料:

1./article/1822252.html

2.http://www.jianshu.com/p/b6434c2997d1

3.http://leopard168.blog.163.com/blog/static4./168471844201306114533858/

4.https://github.com/robbiehanson/XMPPFramework
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: