2010-01-29 52 views
0

我需要在75秒之前(我測量的時間與我設置的時間無關)使用NSTimer取消NSURLRequest。我正在使用Eric Czarny的XMLRPC類。 XMLRPCConnection基本上是NSURLConnection類的圖像。iphone NSURLConnection NSTimer在initWithRequest中工作,但在sendSynchronousRequest中導致無法識別的選擇器錯誤

這裏的接口和實現文件:

#import <Foundation/Foundation.h> 

@class XMLRPCRequest, XMLRPCResponse; 

/* XML-RPC Connecion Notifications */ 
extern NSString *XMLRPCRequestFailedNotification; 
extern NSString *XMLRPCSentRequestNotification; 
extern NSString *XMLRPCReceivedResponseNotification; 

@interface XMLRPCConnection : NSObject { 
NSURLConnection *_connection; 
NSString *_method; 
NSMutableData *_data; 
id _delegate; 
UIViewController* _requester; 
} 

@property(nonatomic, retain) NSMutableData* _data; 

- (id)initWithXMLRPCRequest: (XMLRPCRequest *)request delegate: (id)delegate; 
- (id)initWithXMLRPCRequest: (XMLRPCRequest *)request delegate: (id)delegate    requester:(UIViewController*)requester; 

- (void) timedOut; 

#pragma mark - 

+ (XMLRPCResponse *)sendSynchronousXMLRPCRequest: (XMLRPCRequest *)request; 

#pragma mark - 

- (void)cancel; 

@end 

#pragma mark - 

@interface NSObject (XMLRPCConnectionDelegate) 

- (void)connection: (XMLRPCConnection *)connection didReceiveResponse: (XMLRPCResponse    *)response 
forMethod: (NSString *)method; 

    - (void)connection: (XMLRPCConnection *)connection didFailWithError: (NSError *)error 
forMethod: (NSString *)method; 

@end 

實現文件:

#import "XMLRPCConnection.h" 
#import "XMLRPCRequest.h" 
#import "XMLRPCResponse.h" 

NSString *XMLRPCRequestFailedNotification = @"XML-RPC Failed Receiving Response"; 
NSString *XMLRPCSentRequestNotification = @"XML-RPC Sent Request"; 
NSString *XMLRPCReceivedResponseNotification = @"XML-RPC Successfully Received Response"; 

@interface XMLRPCConnection (XMLRPCConnectionPrivate) 

- (void)connection: (NSURLConnection *)connection didReceiveData: (NSData *)data; 
- (void)connection: (NSURLConnection *)connection didFailWithError: (NSError *)error; 
- (void)connectionDidFinishLoading: (NSURLConnection *)connection; 

- (void) timedOut; 

@end 

#pragma mark - 

@implementation XMLRPCConnection 

@synthesize _data; 


- (id)initWithXMLRPCRequest: (XMLRPCRequest *)request delegate: (id)delegate requester:(UIViewController*)requester { 

    if (self = [super init]) 
    { 
     _connection = [[NSURLConnection alloc] initWithRequest: [request request] delegate: self]; 
     _delegate = delegate;  
     _requester = requester; 


     // set the timer for timed out requests here 
     NSTimer* connectionTimer = [NSTimer timerWithTimeInterval:10.0f target:self selector:@selector(timedOut) userInfo:nil repeats:NO]; 
     [[NSRunLoop currentRunLoop] addTimer:connectionTimer forMode:NSDefaultRunLoopMode]; 

     if (_connection != nil) 
     { 
      _method = [[NSString alloc] initWithString: [request method]]; 
      _data = [[NSMutableData alloc] init]; 

      [[NSNotificationCenter defaultCenter] postNotificationName: 
      XMLRPCSentRequestNotification object: nil]; 
     } 
     else 
     { 
      if ([_delegate respondsToSelector: @selector(connection:didFailWithError:forMethod:)]) 
      { 
       [_delegate connection: self didFailWithError: nil forMethod: [request method]]; 
      } 

      return nil; 
     } 
    } 

    return self; 

} 

- (void) timedOut { 

    NSLog(@"connection timed out now!"); 
} 


#pragma mark - 

+ (XMLRPCResponse *)sendSynchronousXMLRPCRequest: (XMLRPCRequest *)request 
{ 
    NSURLResponse *urlres; 
    //NSHTTPURLResponse *urlres; 

    NSError *err = NULL; 

    // set the timer for timed out requests here 
    NSTimer* connectionTimer = [NSTimer timerWithTimeInterval:10.0f target:self selector:@selector(timedOut) userInfo:nil repeats:NO]; 
    [[NSRunLoop currentRunLoop] addTimer:connectionTimer forMode:NSDefaultRunLoopMode]; 

    NSData *data = [NSURLConnection sendSynchronousRequest: [request request] 
        returningResponse: &urlres error: &err]; 



     if ([urlres isKindOfClass:[NSHTTPURLResponse class]]) { 

      NSLog(@"Received status code: %d %@", [(NSHTTPURLResponse *) urlres statusCode], 
       [NSHTTPURLResponse localizedStringForStatusCode:[(NSHTTPURLResponse *) urlres statusCode]]) ; 

      NSDictionary* headerFields = [(NSHTTPURLResponse*)urlres allHeaderFields]; 



      NSArray* cookie = [NSHTTPCookie cookiesWithResponseHeaderFields:headerFields forURL:[request host]]; 

      if ([cookie count] != 0) { 
       NSString* cookieName = [[cookie objectAtIndex:0] name]; 
       NSString* cookieValue = [[cookie objectAtIndex:0] value]; 
       NSLog(@"cookie name=value: %@=%@", cookieName, cookieValue); 
       [[User getInstance] setCookieID:[NSString stringWithFormat:@"%@=%@", cookieName, cookieValue] ]; 

      } else { 
       NSLog(@"cookie array empty!"); 
      } 

    } 

    // if an error occured while processing the request, this variable will be set 
    if(err != NULL) 
    { 
     //TODO: we may need to create a XMLRPCResponse with the error. and return 
     return (id) err; 
    } 

    if (data != nil) 
    { 
     NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
     NSLog(@"response is: %@",str); 
     if (! str) { 
      str = [[NSString alloc] initWithData:data encoding:[NSString defaultCStringEncoding]]; 
      data = [str dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; 
     } 

      //Check for HTML code 400 or greater in response statusCode (from header) and throw error if so 
      if ([urlres isKindOfClass:[NSHTTPURLResponse class]]) { 

       // HTTP codes equal or higher than 400 signifies an error 
       if ([(NSHTTPURLResponse *) urlres statusCode] >= 400) { 

//     NSLog(@"Received status code: %d %@", [(NSHTTPURLResponse *) urlres statusCode], 
//      [NSHTTPURLResponse localizedStringForStatusCode:[(NSHTTPURLResponse *) urlres statusCode]]) ; 

        NSString *errorIntString = [NSString stringWithFormat:@"%d", [(NSHTTPURLResponse *) urlres statusCode]]; 
        NSString *stringForStatusCode = [NSHTTPURLResponse localizedStringForStatusCode:[(NSHTTPURLResponse *) urlres statusCode]]; 
        NSString *errorString = [[errorIntString stringByAppendingString:@" "] stringByAppendingString:stringForStatusCode]; 

        NSInteger code = -1; //This is not significant, just a number with no meaning 
        NSDictionary *usrInfo = [NSDictionary dictionaryWithObject:errorString forKey:NSLocalizedDescriptionKey]; 
        err = [NSError errorWithDomain:@"org.wordpress.iphone" code:code userInfo:usrInfo]; 
        return (id) err; 
      } 
     } 

     //[str release]; 
     return [[[XMLRPCResponse alloc] initWithData: data] autorelease]; 
    } 

    return nil; 
} 

#pragma mark - 

- (void)cancel 
{ 
    [_connection cancel]; 
    [_connection autorelease]; 
} 

#pragma mark - 

- (void)dealloc 
{ 
    [_method autorelease]; 
    [_data autorelease]; 

    [super dealloc]; 
} 

@end 

#pragma mark - 

@implementation XMLRPCConnection (XMLRPCConnectionPrivate) 

.... 
@end 

在initWithXMLRPCRequest方法設置的定時器工作正常,但如果它在sendSycnhronousXMLRPCRequest Method的設置,我得到出現以下錯誤:

2010-01-29 11:36:40.442 ActiveE[1071:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[XMLRPCConnection timedOut]: unrecognized selector sent to class 0x32610' 
2010-01-29 11:36:40.443 ActiveE[1071:207] Stack: (
    31044699, 
    2497855305, 
    31426811, 
    30996086, 
    30848706, 
    609709, 
    30829248, 
    30825544, 
    39135117, 
    39135314, 
    3100675 
) 

我不理解,我沒有在實現文件中聲明timeOut方法?

回答

0

我認爲你的timedOut方法應該是公共的。不隱藏在使用私有方法的類別中。

+0

這也是如此 - 我剛剛修復它。接口與實現混合在一起,我完全迷失了。 – Leonard 2010-01-29 23:35:44

0

計時器調用具有的方法是這樣的形式:

- (void)timerFireMethod:(NSTimer*)theTimer; 

名稱是任意的,但你必須返回void,並且必須接受一個計時器。我懷疑這是你錯誤的根源。無論如何,您應該將其更改爲標準格式。

+0

在iPhone上,NSTimers可以在沒有NSTimer參數的情況下正常工作。我一直都是這樣使用它們的。錯誤在別的地方。該錯誤消息指向XML-RPC庫。它提到'timedOut'。 – 2010-01-29 21:33:22

+0

謝謝!這似乎是事實,同步方法是類方法: https://devforums.apple.com/thread/37609?tstart=0 – Leonard 2010-01-29 22:58:29

相關問題