-1

現在、アプリから Web サービスへの接続を実装しています。現時点では、これを行う正しい方法を見つけようとしています。接続には AFNetworking ライブラリを使用し、AFNetworking 経由でも JSON 出力を処理することにしました。このような非同期を実装する最良の方法は、コールバック デリゲートを使用することです。これが私の2つのクラスへのリンクです。私の実装、特に何を改善すべきかについて、いくつかのヒントと批評を本当に楽しんでいます。

ViewController

WebServiceClass

コード:

#import "SLLoginViewController.h"

@interface SLLoginViewController ()

@end

@implementation SLLoginViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    sharedWebService = [SLWebService sharedWebService];
    [sharedWebService setDelegate:self];
    [sharedWebService login:@"test@hotmail.de" withPassword:@"12345"];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (void)requestFinished:(NSString *)name withResult:(NSDictionary *)result andError:(NSError *)error
{
    NSLog(@"%@", result);
}
@end

ウェブサービス

#import <Foundation/Foundation.h>
#import "AFNetworking.h"

@class SLWebService;

@protocol SLWebServiceDelegate <NSObject>

@required
- (void)requestFinished:(NSString *)name withResult:(NSDictionary *)result andError:(NS

Error *)error;

@end

@interface SLWebService : NSObject
{
    NSURL *baseURL;
    AFHTTPClient *client;
}
@property id <SLWebServiceDelegate> delegate;

+ (id)sharedWebService;

- (void)login:(NSString *)email withPassword:(NSString *)password;

- (NSError *)generateError:(NSString *)description domain:(NSString *)domain;

@end

#import "SLWebService.h"

@implementation SLWebService

@synthesize delegate;

+ (id)sharedWebService
{
    static SLWebService *sharedWebService = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedWebService = [[self alloc] init];
    });
    return sharedWebService;
}

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

    if(self)
    {
        baseURL = [[NSURL alloc] initWithString:@"http://www.domain.de/"];
        client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
    }

    return self;
}

-(void)login:(NSString *)email withPassword:(NSString *)password
{
    NSDictionary *params = @{@"email":email, @"password":password};
    NSMutableURLRequest *request = [client requestWithMethod:@"GET" path:@"login.php" parameters:params];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
    {
        NSString *result = [JSON objectForKey:@"result"];
        if ([result isEqualToString:@"fail"])
        {
            [[self delegate] requestFinished:@"login" withResult:nil andError:[self generateError:[JSON objectForKey:@"reason"] domain:@"de.Searchlight.WebServiceError"]];
        }
        else
        {
            NSDictionary *dic = @{@"firstname":[JSON objectForKey:@"firstname"], @"lastname":[JSON objectForKey:@"lastname"], @"gender":[JSON objectForKey:@"gender"]};
            [[self delegate] requestFinished:@"login" withResult:dic andError:[self generateError:[JSON objectForKey:@"reason"] domain:@"de.Searchlight.WebServiceError"]];
        }
    }
    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *err, id JSON)
    {
        [[self delegate]requestFinished:@"login" withResult:nil andError:err];
    }];

    [operation start];
}

-(NSError *)generateError:(NSString *)description domain:(NSString *)domain
{
    NSError *error;
    NSDictionary *userInfo = @{NSLocalizedDescriptionKey : description};
    error = [NSError errorWithDomain:domain code:200 userInfo:userInfo];
    return error;
}
@end
4

1 に答える 1

1

AFNetworkingは素晴らしい選択です!ログインリクエストと結果の処理を一緒に保ちながら、ブロックを使用することをお勧めします。また、コードを単純化および短縮します。

次に、最後にAFNetworkingのGetting Startedが示唆するように、サブクラス化することをお勧めしAFHTTPCLIENTます。

一般的な注意:すばらしいObjective-Cの会話集 が示唆しているように、言語のを使用して、GCDなしでシングルトンを作成できます+initialize。また、共有変数は通常、インスタンス変数ではなく静的変数です。

最初の部分は次のようになります。

@class SLWebService;

@interface SLWebService : AFHTTPClient

+ (SlWebService)sharedWebService;

- (void)login:(NSString*)email 
     password:(NSString*)password
      success:(void (^)(AFHTTPRequestOperation* operation, NSDictionary* response))success
      failure:(void (^)(AFHTTPRequestOperation* operation, NSError* error))failure;

@end

#import "SLWebService.h"

@implementation SLWebService

static SLWebService*  sharedWebService;

+ (void)initialize
{
   if ([SLWebService class] == self)
   {
        sharedWebService = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.domain.de/"]];

        // Let AFNetworking do conversion to/from JSON.
        [sharedWebService setParameterEncoding:AFJSONParameterEncoding];
        [sharedWebService setDefaultHeader:@"Accept" value:@"application/json"];
        [sharedWebService registerHTTPOperationClass:[AFJSONRequestOperation class]];
    }
}

+ (id)allocWithZone:(NSZone*)zone
{
    if (sharedWebService && [SLWebService class] == self)
    {
        [NSException raise:NSGenericException format:@"Duplicate SLWebService singleton creation"];
    }

    return [super allocWithZone:zone];
}

+ (SLWebService*)sharedWebService
{
    return sharedWebService;
}

... 

最後のトピック外の発言として:私はApple / Xcodeの提案をViewControllerに使用するのは好きではありません-initWithNibName::。これは、XIB名をクラスの外に保持するからです。別のXIBで初期化する必要はほとんどないため、「-init」内でXIBを指定することをお勧めします。そのようです:

- (id)init
{
    if (self = [super initWithNibName:@"SLLoginView" bundle:nil])
    {
    }

    return self;
}

乾杯、これがお役に立てば幸いです!

于 2013-01-12T00:32:26.407 に答える