2010-01-29 1 views
0

NSTimer를 사용하여 75 초 (설정 한 시간 제한에 관계없이 측정 한 시간) 전에 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 방법에 설정되어있는 경우, 내가 얻을 다음 오류 :

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

0

방법은 형식이어야합니다 :

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

이름은 임의하지만 당신은 무효 반환해야 및 타이머에 동의해야합니다. 나는 그것이 귀하의 오류의 원인이라고 생각합니다. 어떤 경우이든 표준 양식으로 변경해야합니다.

+0

iPhone에서는 NSTimer 인수없이 NSTimers가 정상적으로 작동합니다. 나는 항상 그런 식으로 사용한다. 오류는 다른 곳에서 발생합니다. 오류 메시지는 XML-RPC 라이브러리를 가리 킵니다. 그것은'timedOut'을 언급합니다. –

+0

감사합니다. 동기화 된 메서드가 클래스 메서드 인 것 같습니다. https://devforums.apple.com/thread/37609?tstart=0 – Leonard