use*_*096 9 iphone objective-c nsurlconnection
我正在尝试将代码从UITableViewController类移动到"helper"类.
该代码利用NSURLConnection来获取和解析JSON,然后填充NSMutableArray.
我想要做的是在我的助手类中调用一个返回NSMutableArray的方法.我不明白的是如何从NSURLConnection的connectionDidFinishLoading委托类(实际构建数组)返回数组,就像它来自最初调用的启动连接的方法一样.换句话说,调用NSURLConnection的方法如何获得控制权,以便它可以从整个操作中返回一个值?
以下是帮助程序类的相关方法.如何让getMovies方法返回在connectionDidFinishLoading委托类中构建的listOfMovies?
-(NSMutableArray)getMovies:(NSURL*)url {
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//NSURLRequest* request = [NSURLRequest requestWithURL: url cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval: 30.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//TODO error handling for connection
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//---initialize the array---
listOfMovies = [[NSMutableArray alloc] init];
tmdbMovies = [[NSArray alloc] init];
posters = [[NSArray alloc] init];
thumbs = [[NSDictionary alloc] init];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
SBJsonParser *json = [[SBJsonParser new] autorelease];
tmdbMovies = [json objectWithString:responseString];
// loop through all the top level elements in JSON
for (id movie in tmdbMovies) {
// 0 - Name
// 1 - Meta
// 2 - Url
if ((NSNull *)[movie objectForKey:@"name"] != [NSNull null]) {
if (![[movie objectForKey:@"name"] isEqualToString:@""]) {
name = [movie objectForKey:@"name"];
}
}
if ((NSNull *)[movie objectForKey:@"info"] != [NSNull null]) {
if (![[movie objectForKey:@"info"] isEqualToString:@""]) {
meta = [movie objectForKey:@"info"];
}
}
if ((NSNull *)[movie objectForKey:@"thumb"] != [NSNull null]) {
if (![[movie objectForKey:@"thumb"] isEqualToString:@""]) {
thumbUrl = [movie objectForKey:@"thumb"];
}
}
NSLog(@"Name: %@", name);
NSLog(@"Info: %@", meta);
NSLog(@"Thumb: %@", thumbUrl);
NSMutableArray *movieData = [[NSMutableArray alloc] initWithObjects:name,meta,thumbUrl,nil];
// add movieData array to listOfJMovies array
[listOfMovies addObject:movieData];
[movieData release];
}
//FIXME: Connection warning
if (connection!=nil) {
[connection release];
}
[responseData release];
[responseString release];
}
Run Code Online (Sandbox Code Playgroud)
dre*_*ful 13
你真正需要做的是创建一个@protocol为你的助手类创建一个委托.然后-(NSMutableArray)getMovies:(NSURL*)url改为-(void)getMovies:(NSURL*)url
调用helper方法的类需要实现helper方法的委托.
然后- (void)connectionDidFinishLoading:(NSURLConnection *)connection调用委托方法.最好有一个成功,一个成功.
=更新Begin =
您还需要id delegate在helper文件中定义一个调用类在init之后但在调用之前设置为self的文件-(void)getMovies:(NSURL*)url.这样,帮助文件知道回调的位置.
getMovies *movieListCall = [[getMovies alloc] init];
movieListCall.delegate = self;
[movieListCall getMovies:<your NSURL goes here>];
Run Code Online (Sandbox Code Playgroud)
您将delegate在getMovies.h和getMovies.m文件中看到一些其他行以包含a .
=更新结束=
在你的getMovies.h文件中添加:
@protocol getMoviesDelegate
@required
- (void)getMoviesSucceeded:(NSMutableArray *)movieArray;
- (void)getMoviesFailed:(NSString *)failedMessage;
@end
@interface getMovies : NSOBject {
id delegate;
}
@property (nonatomic, assign) id delegate;
Run Code Online (Sandbox Code Playgroud)
在你的getMovies.m文件中添加:
@synthesize delegate;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//TODO error handling for connection
if ([delegate respondsToSelector:@selector(getMoviesFailed:)]) {
[delegate getMoviesFailed:[error localizedDescription]];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//finishes with
if ([delegate respondsToSelector:@selector(getMoviesSucceeded:)]) {
[delegate getMoviesSucceeded:listOfMovies];
}
}
Run Code Online (Sandbox Code Playgroud)
更新你的调用类.h文件使用getMoviesDelegate:
@interface MoviesView : UIViewController <getMoviesDelegate>{
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
将getMoviesDelegate方法添加到您的调用类.m文件中
- (void)getMoviesSucceeded:(NSMutableArray *)movieArray {
//deal with movieArray here
}
- (void)getMoviesFailed:(NSString *)failedMessage {
//deal with failure here
}
Run Code Online (Sandbox Code Playgroud)
这未经过测试,但希望能为您提供合作路线图.
协议很好,因为你可以同时制作必需和可选的委托方法,它有助于改进你的帮助方法,使其在各个项目中变得非常可重用.如果您已实现协议但未实现协议所需的委托方法,编译器也会发出警告.如果您遵循此路径,请务必使用conformsToProtocol:和respondsToSelector:
从根本上说,正在发生的是你正在启动异步网络负载(异步是正确的方法,几乎可以肯定),然后你需要一些方法来恢复在加载开始之前你正在做的任何操作.你有几个选择:
创建自己的委托协议.然后,您的UITableViewController将自己设置为帮助程序的委托,并且帮助程序将调用helperDidLoad或者您为该方法命名的任何内容.有关在Cocoa编程指南中编写代理的更多信息.
使用块和继续传递样式.这有点先进,但我喜欢它.在你的UITableViewController中你会写这样的东西:
[helper doSomething:^ (id loaded) {
[modelObject refresh:loaded]; // or whatever you need to do
}];
Run Code Online (Sandbox Code Playgroud)
然后在你的助手中写下:
- (void)doSomething:(void ^ (id))continuation {
_continuation = continuation;
//kick off network load
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
_continuation(_data);
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
3089 次 |
| 最近记录: |