3

私が開発するアプリケーションは、OS X サーバーと通信する iOS クライアントです。このアプリケーションの現在のバージョンは、メイン スレッドですべてのネットワーク ロジックを実行します。

ただし、次のバージョンでは、ネットワーク ロジックをより柔軟にしたいと考えています。これが機能するために、別のスレッドを専用にしたいと思いますが、どのソリューションが私のニーズに適しているのかよくわかりません。

最初は GCD が適しているように見えましたが、別のスレッドで実行される作業のチャンクにのみ適しているようです。私がやりたいことは、すべてのネットワーク ロジックを別のスレッドに配置することです。iOS クライアントと OS X サーバー間の接続は永続的であり、すべてのデータ ストリーミングと処理はその別のスレッドで行われる必要があります。

問題は、このシナリオに最も適したアプローチはどれかということです。

編集:混乱を避けるために、私が使用する接続ではソケットと NSStream インスタンスを使用します。リモート Web サーバーへの接続は扱っていません。言い換えれば、AFNetworking と ASIHttpRequest は私にとって選択肢ではありません。

4

2 に答える 2

6
  1. 次のコードを実行して、runloop (NetworkThread と呼びます) でスレッドを作成できます。

    while (!self.isCancelled) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        [pool release];
    }
    
  2. 次に- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait、NetworkThread でネットワーク リクエスト セレクターを実行するために使用できます。

  3. すべてのネットワーク コールバックは NetworkThread で呼び出され、NetworkThread で応答データを処理し、最終データをメイン スレッドにプッシュし、UI を更新します。

于 2012-04-19T10:25:46.743 に答える
0

AFネットワーキングは素晴らしいです。ブロックと GCD を使用します。かなり簡単に呼び出すことができる NetworkClient クラスを作成しました。自由に使用またはカスタマイズしてください。ただし、私は何も保証しません :)

API キーは、必要に応じて削除できるものです。すべてのネットワーク リクエストにセキュリティを追加する方法として追加しました。私の Web サービスは、何かを返す前に、渡された APIKey の有効性をチェックします。

また、物事をどのように行うかについては、かなり柔軟に対応できます。同期または非同期のリクエスト、失敗時にユーザーに警告しないリクエストなどを行うことができます。

基本的な使用例:

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
                                @"GetAllParkingLots", @"Command",
                                nil];

        [NetworkClient processURLRequestWithURL:nil andParams:params block:^(id obj) {
            // I check to see what kind of object is passed back, in this case I was expecting an Array
            if ([obj isKindOfClass:[NSArray class]]) {
                // Do something with the Array
                [self processNetworkRequestWithArray:(NSArray *)obj];
            }
        }];

NetworkClient.h:

//
//  NetworkClient.h
//
//  Created by LJ Wilson on 2/18/12.
//  Copyright (c) 2012 LJ Wilson All rights reserved.
//

#import <Foundation/Foundation.h>

extern NSString * const APIKey;

@interface NetworkClient : NSObject

+(void)processURLRequestWithURL:(NSString *)url 
                      andParams:(NSDictionary *)params 
                          block:(void (^)(id obj))block;

+(void)processURLRequestWithURL:(NSString *)url 
                      andParams:(NSDictionary *)params 
                    syncRequest:(BOOL)syncRequest
                          block:(void (^)(id obj))block;

+(void)processURLRequestWithURL:(NSString *)url 
                      andParams:(NSDictionary *)params 
                    syncRequest:(BOOL)syncRequest
             alertUserOnFailure:(BOOL)alertUserOnFailure
                          block:(void (^)(id obj))block;

+(void)handleNetworkErrorWithError:(NSError *)error;

+(void)handleNoAccessWithReason:(NSString *)reason;

@end

NetworkClient.m:

//
//  NetworkClient.m
//
//  Created by LJ Wilson on 2/18/12.
//  Copyright (c) 2012 LJ Wilson All rights reserved.
//

#import "NetworkClient.h"
#import "AFHTTPClient.h"
#import "AFHTTPRequestOperation.h"
#import "SBJson.h"

#warning Set APIKey or set to nil
NSString * const APIKey = @"YourAPIKEYGoesHere";

@implementation NetworkClient

+(void)processURLRequestWithURL:(NSString *)url 
                      andParams:(NSDictionary *)params 
                          block:(void (^)(id obj))block {

    [self processURLRequestWithURL:url andParams:params syncRequest:NO alertUserOnFailure:NO block:^(id obj) {
        block(obj);
    }];
}

+(void)processURLRequestWithURL:(NSString *)url 
                      andParams:(NSDictionary *)params 
                    syncRequest:(BOOL)syncRequest
                          block:(void (^)(id obj))block {
    [self processURLRequestWithURL:url andParams:params syncRequest:syncRequest alertUserOnFailure:NO block:^(id obj) {
        block(obj);
    }];
}


+(void)processURLRequestWithURL:(NSString *)url 
                      andParams:(NSDictionary *)params 
                    syncRequest:(BOOL)syncRequest
             alertUserOnFailure:(BOOL)alertUserOnFailure
                          block:(void (^)(id obj))block {

#warning Fix default url
    // Default url goes here, pass in a nil to use it
    if (url == nil) {
        url = @"YourDefaultURLGoesHere";
    }

    NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:params];
    [dict setValue:APIKey forKey:@"APIKey"];

    NSDictionary *newParams = [[NSDictionary alloc] initWithDictionary:dict];

    NSURL *requestURL;
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:requestURL];

    NSMutableURLRequest *theRequest = [httpClient requestWithMethod:@"POST" path:url parameters:newParams];

    __block NSString *responseString = @"";

    AFHTTPRequestOperation *_operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
    __weak AFHTTPRequestOperation *operation = _operation;

    [operation  setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        responseString = [operation responseString];

        id retObj = [responseString JSONValue];

        // Check for invalid response (No Access)
        if ([retObj isKindOfClass:[NSDictionary class]]) {
            if ([[(NSDictionary *)retObj valueForKey:@"Message"] isEqualToString:@"No Access"]) {
                block(nil);
                [self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]];
            }
        } else if ([retObj isKindOfClass:[NSArray class]]) {
            if ([(NSArray *)retObj count] > 0) {
                NSDictionary *dict = [(NSArray *)retObj objectAtIndex:0];
                if ([[dict valueForKey:@"Message"] isEqualToString:@"No Access"]) {
                    block(nil);
                    [self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]];
                }
            }
        }
        block(retObj);
    } 
                                      failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                          NSLog(@"Failed with error = %@", [NSString stringWithFormat:@"[Error]:%@",error]);
                                          block(nil);
                                          if (alertUserOnFailure) {
                                              // Let the user know something went wrong
                                              [self handleNetworkErrorWithError:operation.error];
                                          }

                                      }];

    [operation start];

    if (syncRequest) {
        // Process the request syncronously
        [operation waitUntilFinished];
    } 


}


+(void)handleNetworkErrorWithError:(NSError *)error {
    NSString *errorString = [NSString stringWithFormat:@"[Error]:%@",error];

    // Standard UIAlert Syntax
    UIAlertView *myAlert = [[UIAlertView alloc] 
                            initWithTitle:@"Connection Error" 
                            message:errorString 
                            delegate:nil 
                            cancelButtonTitle:@"OK" 
                            otherButtonTitles:nil, nil];

    [myAlert show];

}

+(void)handleNoAccessWithReason:(NSString *)reason {
    // Standard UIAlert Syntax
    UIAlertView *myAlert = [[UIAlertView alloc] 
                            initWithTitle:@"No Access" 
                            message:reason 
                            delegate:nil 
                            cancelButtonTitle:@"OK" 
                            otherButtonTitles:nil, nil];

    [myAlert show];

}


@end
于 2012-04-19T09:51:06.603 に答える