3

-[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]iOS < 5に実装するにはどうすればよいですか?

#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0

#import <objc/runtime.h>
#import "NSURLConnection+iOS4.h"

// Dynamically add -[NSURLConnection sendAsynchronousRequest:queue:completionHandler:].
void *sendAsynchronousRequest4(id self, SEL _cmd, NSURLRequest *request, NSOperationQueue *queue, void (^handler)(NSURLResponse*, NSData*, NSError*));
void *sendAsynchronousRequest4(id self, SEL _cmd, NSURLRequest *request, NSOperationQueue *queue, void (^handler)(NSURLResponse*, NSData*, NSError*)) {

    // How should we implement this?

}

@implementation NSURLConnection (SendAsync)

+ (void)load {
    SEL sendAsyncSelector = @selector(sendAsynchronousRequest:queue:completionHandler:);
    if (![NSURLConnection instancesRespondToSelector:]) {
        class_addMethod([self class], sendAsyncSelector, (IMP)sendAsynchronousRequest4, "v@:@@@");
    }
}

@end

#endif
4

3 に答える 3

3
// NSURLConnection+SendAsync.h

#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0

#import <Foundation/Foundation.h>

@interface NSURLConnection (SendAsync)

@end

#endif


// NSURLConnection+SendAsync.m

#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0

typedef void (^URLConnectionCompletionHandler)(NSURLResponse *response, NSData *data, NSError *error);

@interface URLConnectionDelegate : NSObject <NSURLConnectionDataDelegate>

@property (nonatomic, strong) NSURLResponse *response;
@property (nonatomic, strong) NSMutableData *data;
@property (nonatomic, strong) NSOperationQueue *queue;
@property (nonatomic, copy) URLConnectionCompletionHandler handler;

@end 

@implementation URLConnectionDelegate 

@synthesize response;
@synthesize data;
@synthesize queue;
@synthesize handler;

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)theResponse {
    self.response = theResponse;
    [data setLength:0]; // reset data
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData {
    [data appendData:theData]; // append incoming data
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    self.data = nil;
    if (handler) { [queue addOperationWithBlock:^{ handler(response, nil, error); }]; }
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    // TODO: Are we passing the arguments to the block correctly? Should we copy them?
    if (handler) { [queue addOperationWithBlock:^{ handler(response, data, nil); }]; }
}

@end

#import <objc/runtime.h>
#import "NSURLConnection+SendAsync.h"

// Dynamically add @property (nonatomic,readonly) UIViewController *presentingViewController.
void sendAsynchronousRequest4(id self, SEL _cmd, NSURLRequest *request, NSOperationQueue *queue,
                              URLConnectionCompletionHandler handler);
void sendAsynchronousRequest4(id self, SEL _cmd, NSURLRequest *request, NSOperationQueue *queue,
                              URLConnectionCompletionHandler handler) {

    URLConnectionDelegate *connectionDelegate = [[URLConnectionDelegate alloc] init];
    connectionDelegate.data = [NSMutableData data];
    connectionDelegate.queue = queue;
    connectionDelegate.handler = handler;
    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request
                                                                delegate:connectionDelegate];
    NSAssert(connection, nil);
}

@implementation NSURLConnection (SendAsync)

+ (void)load {
    SEL sendAsyncSelector = @selector(sendAsynchronousRequest:queue:completionHandler:);
    if (![NSURLConnection instancesRespondToSelector:sendAsyncSelector]) {
        class_addMethod(object_getClass([self class]),
                        sendAsyncSelector, (IMP)sendAsynchronousRequest4, "v@:@@@");
    }
}

@end

#endif
于 2012-03-23T20:13:28.653 に答える
0

通常、NSOperation のサブクラスを作成し、操作のメイン メソッド内で同期要求を行います。操作を呼び出すには、サブクラスのインスタンスを作成し、それを (メイン スレッドではなく) キューにスローします。次に、操作が完了すると、受信したデータでデリゲートを呼び出すか、NSNotificationCenter を介して通知を送信します。

于 2012-03-22T20:53:44.827 に答える
-1

ASIHTTPRequest (もう開発されていませんが、まだ非常に優れています) または RestKit (これまで使用したことはありませんが、まともだと聞いています) などの既に構築されたフレームワークを使用します。これらは、OS の異なるバージョン間で同じ機能 (非同期の http 要求) を提供します。

ifdefs はコンパイル時に行われ、プラットフォームごとに個別のバージョンのアプリをコンパイルすることはないため、使用する方法ではありません。

おそらく実行時にいくつかのシェナニガンを実行して動作させることができますが、それは価値があるよりも多くの問題のようです.

于 2012-03-22T20:09:36.930 に答える