3

如何爲iOS < 5實施-[NSURLConnection sendAsynchronousRequest:queue:completionHandler:] 5?iOS4的實現 - [NSURLConnection sendAsynchronousRequest:queue:completionHandler:]?

#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, "[email protected]:@@@"); 
    } 
} 

@end 

#endif 

回答

-1

我會去與像ASIHTTPRequest已經建成框架(不再發展,但還是很不錯的)或RestKit(我以前從未使用過,但聽說它的體面)。這些將在不同版本的OS中爲您提供相同的功能(異步HTTP請求)。

ifdefs不是要走的路,因爲它們是在編譯時完成的,而且您不會爲每個平臺編譯單獨的應用程序版本。

你可能會在運行時做一些神祕的工作來讓它工作,但它似乎比它的價值更麻煩。

+0

RestKit不支持 KDaker 2013-01-23 01:01:46

0

我通常做一個NSOperation的子類,並在操作的主要方法內執行同步請求。爲了調用這個操作,我創建了一個子類的實例並把它放到一個隊列中(而不是主線程)。然後,當操作完成時,它會使用收到的數據調用委託或通過NSNotificationCenter發佈通知。

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, "[email protected]:@@@"); 
    } 
} 

@end 

#endif 
+0

嘿馬特,有沒有這個代碼的某個版本的github或類似的地方?這將是很好的,讓人們可以輕鬆地提交錯誤修復和改進 – Andrea 2012-07-20 22:57:26

+0

而不是'instancesRespondToSelector',我們不應該使用'respondsToSelector'?我們正在檢查類方法的存在。 – adbie 2013-01-08 09:33:57

相關問題