Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/43.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何从使用NSURLConnection及其';什么是代表课?_Iphone_Objective C_Nsurlconnection - Fatal编程技术网

Iphone 如何从使用NSURLConnection及其';什么是代表课?

Iphone 如何从使用NSURLConnection及其';什么是代表课?,iphone,objective-c,nsurlconnection,Iphone,Objective C,Nsurlconnection,我正在尝试将代码从UITableViewController类移动到“helper”类 代码利用NSURLConnection获取和解析JSON,然后填充NSMUTABLEARRY 我想做的是在我的助手类中调用一个返回NSMutableArray的方法。我不明白的是,如何从NSURLConnection的ConnectionIDFinishLoading委托类(实际构建数组的地方)返回数组,就好像它是从启动连接的最初调用的方法返回一样。换句话说,调用NSURLConnection的方法如何获得控

我正在尝试将代码从UITableViewController类移动到“helper”类

代码利用NSURLConnection获取和解析JSON,然后填充NSMUTABLEARRY

我想做的是在我的助手类中调用一个返回NSMutableArray的方法。我不明白的是,如何从NSURLConnection的ConnectionIDFinishLoading委托类(实际构建数组的地方)返回数组,就好像它是从启动连接的最初调用的方法返回一样。换句话说,调用NSURLConnection的方法如何获得控制权,以便能够从整个操作返回值

下面是helper类中的相关方法。如何让getMovies方法返回ConnectionDiFinishLoading委托类中构建的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];



}
如何让getMovies方法返回ConnectionDiFinishLoading委托类中构建的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];



}
我要说的是你不应该那样做

网络请求应异步进行。如果您的
getMovies
要发出一个同步请求,并且仅当它有数据时才返回,那么在等待网络连接完成时,您将阻塞整个线程。如果您的主线程正在调用
getMovies
,这通常是一个坏主意,也是一个糟糕的主意。阻止主线程将阻止您响应触摸或更新UI,您的应用程序将显示为冻结状态,如果您的用户没有在沮丧中首先退出,操作系统将终止它


相反,当数据可用时(或检索数据失败时),让helper类通过委托回调、通知、KVO或您喜欢的任何机制通知调用方。

以下是类似伪代码的步骤:

  • [helperInstance setDelegate:self];//其中self是UITableViewController类

  • 在助手类中,在ConnectionIDFinishLoading中执行以下操作:

     [helper doSomething:^ (id loaded) { 
         [modelObject refresh:loaded]; // or whatever you need to do
     }];
    
    [代表完成加载数据:JSONData]

  • 此外,您还可以为委托定义协议,并在助手类中按如下方式声明委托:

    @property (nonatomic, assign) id<YourProtocol> delegate;
    
    @属性(非原子,赋值)id委托;
    
    希望这有帮助,
    Moszi

    从根本上说,现在发生的是您正在启动一个异步网络负载(异步是这样做的正确方法,几乎可以肯定),然后您需要某种方法来恢复负载开始之前正在执行的任何操作。您有几个选择:

    • 创建自己的代理协议。然后,UITableViewController将自身设置为帮助者的委托,帮助者将调用
      helperIDLoad
      或您命名的任何方法。Cocoa编程指南中有关于编写委托的更多信息

    • 使用块和连续传递样式。这是一个有点先进,但我喜欢它。在UITableViewController中,您可以编写如下内容:

       [helper doSomething:^ (id loaded) { 
           [modelObject refresh:loaded]; // or whatever you need to do
       }];
      
      然后在助手中写下:

       - (void)doSomething:(void ^ (id))continuation {
           _continuation = continuation;
           //kick off network load
       }
      
      
       - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
           _continuation(_data);
       }
      
    • 使用通知。阅读NSNotificationCenter文档
    • 使用KVO。《KVO编程指南》中有很多关于键值的好信息

    这里真正需要做的是创建一个
    @protocol
    ,为助手类创建一个委托。然后将
    -(NSMutableArray)getMovies:(NSURL*)url更改为
    -(void)getMovies:(NSURL*)url

    调用助手方法的类需要实现助手方法的委托

    然后
    -(void)connectionIDFinishLoading:(NSURLConnection*)connection
    调用委托方法。最好有一个是成功的,一个是失败的

    =更新开始=

    您还需要在助手文件中定义一个
    id委托
    ,调用类在init之后调用
    -(void)getMovies:(NSURL*)url
    之前将其设置为self。这样,助手文件就知道在哪里回叫

    getMovies *movieListCall = [[getMovies alloc] init];
    movieListCall.delegate = self;
    [movieListCall getMovies:<your NSURL goes here>];
    
    在getMovies.m文件中添加:

    @protocol getMoviesDelegate
    
    @required
    - (void)getMoviesSucceeded:(NSMutableArray *)movieArray;
    - (void)getMoviesFailed:(NSString *)failedMessage;
    
    @end
    
    @interface getMovies : NSOBject {
    id delegate;
    }
    
    @property (nonatomic, assign) id delegate;
    
    @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];
        }
    }
    
    更新调用class.h文件以使用
    getMoviesDelegate

    @interface MoviesView : UIViewController <getMoviesDelegate>{
    .
    .
    .
    }
    
    这是没有测试,但希望给你一个路线图工作


    协议很好,因为您可以创建必需的和可选的委托方法,并且它有助于改进您的助手方法,使其在项目中变得非常可重用。如果您已实现协议,但未实现协议所需的委托方法,编译器也会发出警告。如果您遵循此路径,请确保使用
    conformsToProtocol:
    respondsToSelector:

    使用协议或NSNotificationCenter这看起来是一个不错的方法。我会给它一个机会,然后报告。谢谢大家的输入。我在调用[delegate GetMoviesSuccessed:listOfMovies]时收到一个未声明的代理错误;顺便问一下,有没有办法在评论中发布代码?想发布我的Movies.h文件,看看我是否错误地声明了这些方法。实际上,错误发生在if条件下,如下所示:“委托”未声明(首次在此函数中使用)Sry,我假设助手定义了一个delegat,这是我的错。getMovies需要在.h文件中定义一个id委托。我会更新我的答案。谢谢。现在编译,但我在运行时崩溃在这行:movieListCall.delegate=self;错误为[Movies setDelegate:]:无法识别的选择器已发送到实例。顺便说一句,“Movies”是类名,getMovies是方法名。有什么想法吗?嗨,我知道这是一篇非常古老的帖子,但是,如果有多个连接几乎同时启动,我们如何确定哪个连接产生了哪个结果?非常感谢。