0

我正在尝试开发一个应用程序来接收来自 Web 服务的数据以显示在某些视图中。在应用程序的第一个版本中,我只有一个视图控制器和一个对 Web 服务的 GET 请求(通过 NSURLconnection):NSURLconnection 的所有方法都在 Viewcontroller 中,并且一切正常。

现在我需要添加其他视图并发出其他一些 GET 请求,所以我认为最好的办法是应用 MVC 模式:特别是我创建了一个类(FV_Data),我在其中放置所有 GET 请求并管理 NSURLconnections ,而在每个 ViewController 中,我为所需的 GET 请求调用方法(在 FV_Data 类中)。

我的问题是如何将带有数据的数组从 Web 服务返回到请求数据的 ViewController:在我的第一个测试中,正确启动了 NSURLconnection 并且数组(在 connectionDidFinishLoading 方法中)填充了来自Web 服务,但在视图控制器中,数组为空。

我读过不同的帖子,但我不明白我做错了什么。

这是我编写的代码(我省略了有效方法中的代码)。

谢谢, 科拉多

FV_Data.h

#import <Foundation/Foundation.h>

@interface FV_Data: NSObject {

    NSMutableData *responseStatistic;
    NSMutableData *responseGetStatus;

    NSURLConnection *connectionStatistic;
    NSURLConnection *connectionGetStatus;
}

-(NSArray *)richiediGetStatistic;
-(NSArray *)richiediGetStatus;


@property (nonatomic, retain) NSArray *ArrayStatistic;
@property (nonatomic, retain) NSArray *ArrayGetStatus;


@end

FV_Data.m

#import "FV_Data.h"

@implementation FV_Data

-(id)init {
    self = [super init];
    return self;
}

-(void)richiediGetStatistic{
    ...
}

-(void)richiediGetStatus{
    ...
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
...
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
   ...
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    if(connection == connectionStatistic){
        NSString *responseStatisticString = [[NSString alloc] initWithData:responseStatistic encoding:NSUTF8StringEncoding];
        self.ArrayStatistic = [responseStatisticString componentsSeparatedByString:@","];
    }

    else if(connection == connectionGetStatus){
        NSString *responseGetStatusString = [[NSString alloc] initWithData:responseGetStatus encoding:NSUTF8StringEncoding];
        self.ArrayGetStatus = [responseGetStatusString componentsSeparatedByString:@","];
    }
}

@end

FV_Live_ViewController.h

#import <UIKit/UIKit.h>
#import "FV_Data.h"

@interface FV_Live_ViewController : UIViewController {
    IBOutlet UILabel *energia;
}

@property (nonatomic, retain) FV_Data *PVOutputData;

@end

FV_Live_ViewController.m

#import "FV_Live_ViewController.h"

@implementation FV_Live_ViewController

-(void)viewWillAppear:(BOOL)animated{

    self.PVOutputData = [[FV_Data alloc] init];

    [self.PVOutputData richiediGetStatistic];

    energia.text = [self.PVOutputData.ArrayStatistic objectAtIndex:0];
}

@end
4

3 回答 3

2

哦,伙计……网络请求需要时间来完成,所以你应该在 connectionDidFinishLoading 之后设置你的视图(energia.text):
对不起,但看起来你正在发明一辆自行车。如果你知道这些块在 Objective-C 中是如何工作的,我建议使用AFNetworking框架。
如果你不知道积木是如何工作的——首先阅读关于积木的 Apple 文档——成功地为 iOS / OS X 开发是非常有必要的

于 2013-09-24T17:32:40.483 回答
1

connectionDidFinishLoading正在成功完成下载,但您似乎没有做任何事情来告诉视图控制器在数据请求完成后做任何事情来更新用户界面。您想这样做,因为加载过程是异步进行的。例如,如果您在 中启动此过程viewDidLoad,加载将始终不完全,直到viewDidLoad完成之后。

您需要提供某种机制FV_Data来通知FV_Live_ViewController请求已完成,此时您将让视图控制器使用新数据更新 UI。两种典型的方法是:

  • 实现您自己的委托协议模式,这是解决此类问题的一种相当传统的解决方案,您FV_Data可以通过它通知视图控制器请求已完成。请参阅Cocoa 核心能力中的委派模式)。这类似于您在 中实现的方法,但在这种情况下,它不是通知信息的机制,而是通知机制。NSURLConnectionDataDelegateFV_DataNSURLConnectionFV_DataFV_DataFV_Live_ViewController

  • 使用完成块,这是一种更现代的解决方案,它FV_Live_ViewController可以在请求完成时告知FV_Data要做什么。这类似于您在 AFNetworking 或 Cocoa 方法(如sendAsynchronousRequest.

但在您深入研究这两种方法之前,我必须说,我对您FV_Data执行两个单独请求的体系结构并不感到疯狂,从而导致两组类属性和方法中的代码重复。稍有不同的类结构可以最大限度地减少这种冗余代码(当前代码只会使出错的机会增加一倍)。

此外,我将进一步说明 Petro 的建议,即您考虑使用经过验证的现有第三方框架来管理这些请求,例如AFNetworkingNSOperation像 AFNetworking 这样的基于方法提供了许多优点,但是一个优雅的实现可能会很复杂(因此建议使用 AFNetworking,它可以享受这些优势,同时让您远离实现的杂草)。不幸的是,像这样的NSURLConnection方法sendAsynchronousRequest看起来很方便,但实际上存在局限性。

无论哪种方式,我们都很乐意为您提供帮助,但这只是一个建议。

于 2013-09-24T20:00:44.473 回答
-1

看起来你想要做的事情 sendAsynchronousRequest:queue:completionHandler: 可能比实现委托更合适。

于 2013-09-24T17:26:57.557 回答