怎样实现代理?这时我们在做iphone程序时会遇到的一个问题,因为,我们希望在我们完成某些操作之后,处理一些数据,但是对这些数据的处具有一定的执行顺序依赖性。这样,我们就可以通过代理来实现了。
我们看一个问题,我们希望设计一个类,这个类在具体的操作完成到一定的程度(不一定是一个函数执行完成,但是我们要求这个执行点是确定的)之后能够执行我们想要的某些操作.
int testNum1;
int testNum2;
-(void)testMethod {
testNum1 = 0;
testNum2 = 0;
}
比如,在上面的代码中,我们希望实现的目标是在testNum1 = 0;执行完成之后在我们如果希望执行我们想要的任意可能的操作,在这些任意的操作执行之后又回过偷来执行testNum2 = 0;但是我们,我们并不想要重写这个函数并在这个函数的testNum1 = 0;和testNum2 = 0;之间加上我们的代码.因为这可能会导致重写大量的代码.我们现在需要避免这个问题,当然可以有很多方法,而代理方法就是其中的一种.下面来探讨代理的实现.
首先我们应该做的是代理的声明其申明格式如下:
@protocol DelegateName <NSObject>
@optional
@required
@end
其中用@optional声明的代理接口方法表示为可选其含义为,我们可以对这些接口实现,也可以不实现,但是@required声明的代理接口方法为如果代理可用则代理实现中必须实现。
声明了,代理我们需要做的就是使用代理,要使用代理我们还得要有方法来设置代理是否启用,这就需要我们在相应的类中定义如下操作来提供接口以保证设置代理是否启用。
@class className : NSObject {
id <DelegateName> delegate;
}
@property(nonatomic, assign)id <DelegateName> delegate;
@synthesize delegate;
只要我们实现了这些之后,我们就可以根据我们的需要来调用delegate属性并根据其设置是否为空来判断代理是否启用,如果不启用,可以设置为nil,也可不设.当然如果设置为使用代理则我们就需要根据各个代理接口的使用要求来实现相应的代理接口.
这里代理接口可以使用了,但是它会执行吗?还不会勒,因为我们并没有设置什么时候使用它,我们必须在某个地方调用这个代理让它在某个时刻能够执行.否则代理是会被执行的.
该怎样做呢?当然是在类中实现了.具体来说就是在我们要在做了某些具体操作这后希望执行我们想要执行的哪个点来通知代理,接下来执行代理.这样我们的程序就跳到代理程序去执行,等到代理执行完毕之后,在回到设置代理的位置继续执行.这和我们一般的程序调用是一样的,只是这里我们调用的程序是在我们需要的时候实时调用的,那么在调用处就需要采取特殊的处理.该怎样处理?
这里我们应当首先熟悉一个函数- (BOOL)respondsToSelector:(SEL)aSelector这个函数将返回一个boolean来判断特定的实现和继承方法是否被响应.其中传入的值是消息的标识.
这样,我们还必需知道另一个操作@selector();只要我们将消息类型放在其中,该操作就产生一个SEL类型的消息标识.这个标识就可以被使用了.
接下来我们就可以根据这些判断来调用代理了.我们可以在条件成立是调用代理.调用方式如下:
- (void)test:(BOOL)b {
SEL aSelector = @selector(test:with:);
if (delegate != nil && [delegate respondsToSelector:aSelector]) {
[delegate test:self with:nil]; //这里调用时我们要传入相应的参数.
}
}
这样我们设置的代理就可以被我们使用使用了.
对helloTest.h文件
#import <UIKit/UIKit.h>
@class helloTest;
@protocol helloTestDelegate <NSObject,UITextViewDelegate>
-(void)test1:(helloTest *)label;
@end
@interface helloTest : UILabel {
id<helloTestDelegate> delegate;
}
@property (nonatomic,retain) id<helloTestDelegate> delegate;
-(void)print;
@end
对helloTest.m文件
#import "helloTest.h"
@implementation helloTest
@synthesize delegate;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
}
return self;
}
- (void)dealloc {
[super dealloc];
}
-(void)print {
for (int i =0; i < 10; i++) {
NSLog(@"delegateTest");
}
if ((delegate != nil) && ([delegate respondsToSelector:@selector(test1:)])) {
[delegate test1:self];
}
}
@end
看到了吗?代理功能我们实现了。
我们来测试看看吧:
RootViewController.h文件
#import <UIKit/UIKit.h>
#import "helloTest.h"
@interface RootViewController : UIViewController <helloTestDelegate> {
helloTest *helloView;
}
@end
RootViewController.m文件
#import "RootViewController.h"
#import "testViewController.h"
@implementation RootViewController
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
helloView = [[helloTest alloc] initWithFrame:CGRectMake(20, 50, 280, 30)];
helloView.delegate = self;
NSLog(@"show");
[self.view addSubview:helloView];
[helloView print];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
-(void)test1:(helloTest *)label {
NSLog(@"show-----");
label.text = [NSString stringWithFormat:@"234r23q5tsdgsd"];
NSLog(@"show-----");
}
运行程序,我们看看结果,如下:
2010-11-17 15:35:37.952 delegateTest[25526:207] show
2010-11-17 15:35:37.953 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.954 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.954 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.955 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.955 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.957 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.958 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.958 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.958 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.959 delegateTest[25526:207] delegateTest
2010-11-17 15:35:37.960 delegateTest[25526:207] show-----
2010-11-17 15:35:37.963 delegateTest[25526:207] show-----
看到了吧,我们设置的代理时在函数print执行之后才执行的。这就是我们要的结果当然。因为我们对代理的响应就是在print中循环结束时才执行 输出 delegateTest。
当然,我们可以把循环放在代理处理的后面,运行程序观察我们的结果,知道代理设置和执行的顺序是怎样的了吧。