0

Web サービスからデータを受け取り、いくつかのビューに表示するアプリを開発しようとしています。アプリの最初のバージョンでは、1 つのビュー コントローラーと Web サービスへの 1 つの GET 要求 (NSURLconnection による) しかありません。NSURLconnection のすべてのメソッドは Viewcontroller にあり、すべてがうまく機能しています。

ここで、他のビューを追加して他の GET リクエストを作成する必要があるため、MVC パターンを適用するのが最善であると考えていました。特に、すべての GET リクエストを配置して NSURL 接続を管理するクラス (FV_Data) を作成しました。 、各 ViewController で、必要な GET 要求のメソッド (FV_Data クラス内) を呼び出します。

私の問題は、Web サービスからのデータを含む配列を、データを要求した ViewController に返す方法です。最初のテストでは、NSURLconnection が正しく開始され、配列 (connectionDidFinishLoading メソッド内) にデータが入力されます。 Web サービスですが、View Controller では配列は空です。

さまざまな投稿を読みましたが、何が間違っているのか理解できません。

これは私が書いたコードです (機能するメソッドのコードは省略します)。

ありがとう、コラード

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

1

あなたconnectionDidFinishLoadingはダウンロードを正常に完了していますが、データ要求が完了したときにユーザー インターフェイスを更新するために何かをするようにビュー コントローラーに指示するために何もしていないようです。読み込みプロセスは非同期で行われるため、これを行う必要があります。たとえば、このプロセスを で開始した場合viewDidLoad、読み込みは必ず、完了してから十分な時間が経過するまで完全には行われませんviewDidLoad

FV_Dataリクエストが完了したことを通知できる何らかのメカニズムを提供する必要がありFV_Live_ViewControllerます。その時点で、View Controller が新しいデータで UI を更新します。2 つの典型的なアプローチは次のとおりです。

  • 独自のデリゲート プロトコル パターンを実装します。これは、この種の問題に対するかなり伝統的な解決策です。これFV_Dataにより、リクエストが完了したことをビュー コントローラーに通知できます。Cocoa Core CompetenciesのDelegation Patternを参照してください)。これは、で実装したメソッドに似ていますが、この場合、に情報を通知するメカニズムではなく、 に通知するメカニズムになります。NSURLConnectionDataDelegateFV_DataNSURLConnectionFV_DataFV_DataFV_Live_ViewController

  • リクエストが完了したときに何をすべきかをFV_Live_ViewController通知できる、より現代的なソリューションである完了ブロックを使用します。FV_Dataこれは、AFNetworking や のような Cocoa メソッドで見られるものに似ていますsendAsynchronousRequest

FV_Dataしかし、どちらのアプローチにも深く入り込む前に、私は、2 つの別々の要求を実行し、2 つのクラス プロパティのセットとメソッド内のコードの重複をもたらすアーキテクチャに夢中ではないことを言わなければなりません。クラス構造を少し変えると、この冗長なコードを最小限に抑えることができます (現在のコードでは、間違いの可能性が 2 倍になるだけです)。

さらに、さらに一歩進んで、AFNetworkingなどの実績のある既存のサード パーティ フレームワークを使用してこれらのリクエストを管理することを検討するように、2 番目の Petro の提案に進みます。AFNetworkingのNSOperationような に基づくアプローチには多くの利点がありますが、洗練された実装は複雑になる可能性があります (したがって、実装の雑草を避けながらこれらの利点を享受する AFNetworking を使用することをお勧めします)。残念ながら、このNSURLConnectionような方法はsendAsynchronousRequest便利に見えますが、実際には制限があります。

どちらの方法でも喜んでお手伝いしますが、単なる提案です。

于 2013-09-24T20:00:44.473 に答える
-1

Mayを使用してやろうとしていることは sendAsynchronousRequest:queue:completionHandler: 、デリゲートを実装するよりも適しているようです。

于 2013-09-24T17:26:57.557 に答える