-1

我目前正在实现从应用程序到我的网络服务的连接,目前我正在尝试找出正确的方法。我决定使用 AFNetworking 库进行连接,并通过 AFNetworking 处理 JSON 输出。我在这里读到,实现这种异步的最佳方法是使用回调委托。这是我的两个课程的链接。我真的很喜欢一些关于我的实施的提示和批评,尤其是要改进的地方。

视图控制器

网络服务类

代码:

#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 Phrasebook 所暗示的,可以在没有 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 建议-initWithNibName::用于视图控制器,因为这会将 XIB 名称保留在类之外。您几乎不需要使用不同的 XIB 进行初始化,因此我宁愿在“-init”中指定 XIB。像这样:

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

    return self;
}

干杯,希望这会有所帮助!

于 2013-01-12T00:32:26.407 回答