如何为iOS实现-[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]
< 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
答案 0 :(得分: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
答案 1 :(得分:0)
我通常创建一个NSOperation的子类,并在操作的main方法中执行同步请求。为了调用操作,我创建了一个子类的实例并将其抛给队列(而不是主线程)。然后,当操作完成时,它可以使用收到的数据调用委托,也可以通过NSNotificationCenter发布通知。
答案 2 :(得分:-1)
我会使用已经构建的框架,如ASIHTTPRequest(不再开发,但仍然非常好)或RestKit(我之前从未使用它,但听说它很不错)。这些将在不同版本的操作系统中为您提供相同的功能(异步http请求)。
ifdefs不是那种方法,因为它们是在编译时完成的,你不会为每个平台编译应用程序的单独版本。
你可能会在运行时做一些恶作剧,但它似乎比它的价值更麻烦。