Creating and Using Your Own Delegates in Objective-C
来源:互联网 发布:windows recv返回值 编辑:程序博客网 时间:2024/06/09 21:02
Recently, I've been working on a project where I needed to access a series of web services to post and get my data. This is a pretty common thing to do however, if you look at the many examples of how to do this you'll find overly simplistic code that throws everything into a single class/file and completely ignored code reuse or good Object Oriented design.
The Scenario
My scenario was this; I needed to be able to access several web services from several different form/classes in the application. I not only wanted the class to send the data to the web service, but also retrieve it and do something with the data it got back, which in my case was a SOAP response.
The Problem
Calling a SOAP web service with the iPhone relies on using the NSURLConnection which sends an asynchronous call to the server. It relies on it's own delegate to deal with each process of the call. My initial web service impementation looked like this:
01.
#import "UserWebService.h"
02.
03.
@implementation UserWebService
04.
05.
@synthesize users;
06.
07.
-(id)initWithUserData: (User *)user {
08.
// code here to initialize the request with user data
09.
}
10.
11.
-(
void
) send {
12.
NSURLConnection *theConnection = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
13.
[theConnection release];
14.
}
15.
16.
-(
void
)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
17.
NSLog(@
"Received Response"
);
18.
[webData setLength:0];
19.
}
20.
21.
-(
void
)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
22.
NSLog(@
"Got Data"
);
23.
[webData appendData:data];
24.
}
25.
26.
-(
void
)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
27.
[webData release];
28.
[connection release];
29.
}
30.
31.
-(
void
)connectionDidFinishLoading:(NSURLConnection *)connection {
32.
33.
// code here to do something with all the data (XML) that was returned
34.
35.
}
And then to use this I have the following code in another class, a UIViewController subclass where I needed the data
01.
User *user = [[User alloc]init];
02.
[user setUserId:@
"userid"
];
03.
[user setPassword:@
"password"
];
04.
05.
ws = [[UserWebService alloc ]initWithUserData:user];
06.
[user release];
07.
[ws send];
08.
09.
NSArray *users = [ws users];
But here's the problem. When we call [ws users] to get the array of users back from the web service there is no way to know if that web service has completed yet. I kept getting zero users back even though I knew, by stepping through my code, it was getting 3 users back.
The Solution
I needed to find a way to notify my UIViewController subclass that the web service had completed. This is where our custom delegate comes to play. First, you define a protocol for your delegate in a header file:
1.
@protocol WsCompleteDelegate
2.
-(
void
) finished;
3.
@end
Next, we modify our web service to notify the delegate when it has completed. In the web service class header file we define a delegate property like so:
01.
@interface UserWebService : NSObject {
02.
03.
id <WsCompleteDelegate> delegate;
04.
05.
}
06.
07.
@property (retain, nonatomic) id <WsCompleteDelegate> delegate;
08.
09.
@end
Then in our web service class' connectionDidFinishLoading method, we simply call our delegate method:
1.
-(
void
)connectionDidFinishLoading:(NSURLConnection *)connection {
2.
3.
// do all necessary wrap up work
4.
[delegate finished];
5.
6.
}
The next step is to use this delegate in our UIViewController subclass. First, we modify the header file like so:
1.
@interface LoginViewController : UIViewController <WsCompleteDelegate> {
2.
// other code here
3.
}
Then in the implementation file we have to do two things. First, we tell the web service instance what it's delegate is, which is the LoginViewController, or in Objective-C, 'self' and then we impement the delegate's 'finish' method.
01.
-(IBAction)submit {
02.
User *user = [[User alloc]init];
03.
[user setUserId:@
"username"
];
04.
[user setPassword:@
"password"
];
05.
06.
ws = [[UserWebService alloc ]initWithUserData:user];
07.
08.
ws.delegate = self;
09.
10.
[user release];
11.
[ws send];
12.
}
13.
14.
-(
void
) finished {
15.
NSArray *users = [ws users];
16.
}
When the web service class calls [delegate finished] it notifies all classes listening to that delegate and the 'finished' method is called. We now know the web service has completed and can safely get the array of users from it. Then we just do whatever we need to do with them.
Conclusion
There are lots of possibilites for the delegation pattern and this is just one of them. But it proved to be very simple to implement and an elegant solution to a possibly combersome problem.
- Creating and Using Your Own Delegates in Objective-C
- Using JavaScript in PeopleSoft: Creating your own dialog boxes
- Creating Your Own Widgets using SWT
- Using Your Own Model in train
- Creating Your Own Procedures
- Creating Your Own Validation
- objective-c protocols and delegates 基础
- Using MC.exe, message resources and the NT event log in your own projects
- Reporting Crashes in IMVU: Creating Your Very Own Symbol Server
- Creating Protected and Private Variables in Objective-C Class
- Model View Controller (MVC) Using C#, Delegates and Events in .NET
- Embed an HTML control in your own window using plain C
- Embed an HTML control in your own window using plain C
- Embed an HTML control in your own window using plain C
- Embed an HTML control in your own window using plain C
- Creating your own JavaScript Library
- Creating Your Own Java Annotations
- Using your own SQLite database in Android applications
- 2011年软考系统架构设计师学习笔记第八章
- java网络编程入门到精通
- C语言嵌入式系统编程修炼之软件架构篇 3
- KMP算法
- 让百万级数据瞬间导入SQL Server
- Creating and Using Your Own Delegates in Objective-C
- 在IT界取得成功应该知道的10件事
- 惠普收入高利润低 webOS携手Palm死去
- JDBC API
- 设计模式--工厂模式
- C#:WQL查询LIKE子句中反斜杠字符引发的血案及解决之道
- 关于内联函数
- 高级查询和表连接
- SQL语句中的内连接,左链接,右链接和全链接