1

Google 클라우드 데이터베이스 서비스의 정적 라이브러리를 ARC로 포팅하는 데 문제가 있습니다.iOS 5.0 respondsToSelector는 항상 NSOperation에서 false를 반환합니다.

나는 컴파일하고 실행하는 단계에 도달했으나 결코 대리인을 다시 호출하지 않습니다.

나는 프록시 클래스와 APIOperation의 두 클래스가 있습니다.

APIOperation은 NSURLConnection을 사용하여 웹 API에서 데이터를 가져 오는 NSOperation의 하위 클래스입니다.

프록시에는 NSOperationQueue가 있으며 기본적으로 모든 APIOperation 호출에 대한 위임자입니다. 다음과 같이

사용법 모델은 다음과 같습니다

  • 사용자 클래스는 프록시 객체의 인스턴스를 만듭니다.
  • APIOperation 프록시 객체를 인스턴스화하고
  • APIOperation 다음있는 NSInvocation 통해 프록시 클래스로 다시 전달 파싱
    • 응답 connectionDidFinishLoading에있는 NSURLConnection
    • 를 생성 NSOperationQueue에 추가한다.
    • 프록시 클래스는 delegate (사용자 클래스)를 호출하고 API 응답을 전달합니다.

코드는 다음과 같다 :

프록시 클래스 :

@implementation theProxy 

@synthesize callbackSelector,delegate,opQueue; 

-(theProxy*)init{ 
    opQueue = [[NSOperationQueue alloc]init]; 
    return self; 
} 

- (void) apiOperation:(APIOperation*)operation didCompleteWithResult:(NSArray*)theResult{ 
    SEL selector = [operation callbackSelector]; 
    if ([delegate respondsToSelector:selector]) { 
    NSInvocation* inv = [NSInvocation invocationWithMethodSignature:[[delegate class] instanceMethodSignatureForSelector:selector]]; 
    [inv setTarget:delegate]; 
    [inv setSelector:selector]; 
    theProxy* tmp = self; 
    [inv setArgument:&tmp atIndex:2]; 
    [inv setArgument:&operation atIndex:3]; 
    [inv setArgument:&theResult atIndex:4]; 
    [inv invoke];   
} 

} 

- (void) apiOperation:(APIOperation*)operation didFailWithError:(NSString*)theError{ 
if ([delegate respondsToSelector:@selector(API:apiOperation:didFailWithError:)]) { 
    [delegate API:self apiOperation:operation didFailWithError:theError]; 
} 
} 

-(void)cancelAllOperations{ 
[opQueue cancelAllOperations]; 
} 

- (void)dealloc 
{ 
[opQueue cancelAllOperations]; 
[opQueue release], opQueue = nil; 
delegate = nil; 
//[delegate release]; delegate should not be retained. 

[super dealloc]; 
} 

APIOperation 클래스 (크게 단순화) :

@implementation APIOperation 
@synthesize delegate,APIKey,secretKey,debugMode,callbackSelector,successCallbackMethodSignature,errorCallbackMethodSignature,delegateCallbackMethodSignature,tag,APIServer,requestProcessingTime,requestReceivedTime,responseCode,responseMessage,timestamp,requestRoundTripTime,requestStartMicroTime,useSSL; 

-(void) main{ 
    receivedData = [NSMutableData data]; 
    connFinished = NO; 
    // create the connection with the request 
    // and start loading the data 
    theConnection=[[NSURLConnection alloc] initWithRequest:[self buildRequest] delegate:self]; 
    if (theConnection) { 

     do { 
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
      } while (!connFinished); 
    } 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{ 

    id pList = [NSPropertyListSerialization propertyListFromData:receivedData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&errorStr]; 

    theResponse = (NSDictionary*) pList; 

    if ([delegate respondsToSelector:@selector(apiOperation: didCompleteWithResult:)]) { 

     NSArray* theResultsArray = [theResponse objectForKey:@"payload"]; 

     NSInvocation *inv = [NSInvocation invocationWithMethodSignature:successCallbackMethodSignature]; 
     [inv setTarget:delegate]; 
     [inv setSelector:@selector(apiOperation: didCompleteWithResult:)]; 
     KSAPIOperation* tmp = self; 
     [inv setArgument:&tmp atIndex:2]; 
     [inv setArgument:&theResultsArray atIndex:3]; 
     [inv performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES]; 

    }  
} 
@end 

을 지금이가 작동 말한대로 때까지 라인 'if ([delegate respondsToSelector ...'in connectionDidfinishLoa 땡땡. 그 시점에서 항상 false를 반환합니다. 나는 respondsToSelector 체크를 제거하면

@property (unsafe_unretained) id<KSAPIOperationDelegate,NSObject> delegate; 

: 지금 이것은, 내가 대리자가 null가 아닌 것을 확인했고 값도 위임 속성으로 APIOperation.h에 선언되어있다 ARC과 관련되는 가정 다음과 같은 백 트랙을 사용하여 main()에서 앱이 다운됩니다.

#0 0x0156b09b in objc_msgSend() 
#1 0xbfffde10 in ??() 
#2 0x0132d437 in -[NSInvocation invoke]() 
#3 0x013c8e72 in -[NSObject performSelector:withObject:]() 
#4 0x009369ef in __NSThreadPerformPerform() 
#5 0x0139b97f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__() 
#6 0x012feb73 in __CFRunLoopDoSources0() 
#7 0x012fe454 in __CFRunLoopRun() 
#8 0x012fddb4 in CFRunLoopRunSpecific() 
#9 0x012fdccb in CFRunLoopRunInMode() 
#10 0x012b0879 in GSEventRunModal() 
#11 0x012b093e in GSEventRun() 
#12 0x0001ea9b in UIApplicationMain() 
#13 0x00002a58 in main (argc=1, argv=0xbfffed50) at /Users/MikeW/Desktop/ARC test proj/lib1.0Test/lib1/main.m:16 
#14 0x000029b5 in start() 

제공할만한 도움을 주셔서 감사합니다.

감사

마이크

+0

위임 속성을 (강함)으로 변경하면 코드가 완벽하게 작동합니다. 그러나 이로 인해 메모리 누수가 발생하고 루프가 유지 될 수 있습니다. – MWharton

답변

0

David가 제안한대로 대표단이 배포되는 것이 문제였습니다.

문제는 unsafe_unretained 또는 __weak가 아닌 "(강하게)"속성을 변경하여 해결되었습니다.

@property (strong) id<KSAPIOperationDelegate,NSObject> delegate; 
0

이 ARC와는 아무 상관이 없을 것입니다.

선택기에 응답하지 않는다고보고하면 선택기에 응답하지 않습니다. 밖으로 그 그림. 대체로 선택기에 오타가있을 가능성이 있습니다 (대/소문자를 구분합니다). 또는 대의원은 실제로 당신이 생각하는 것이 아닙니다.

지금까지 선택기에서 공백을 제거했습니다. 예 : 컴파일러가 좋아하는 경우에도 @selector(apiOperation: didCompleteWithResult:)은 잘못 보입니다.

+0

ARC없이 프로젝트에서 동일한 코드를 사용하면 완벽하게 작동합니다. 따라서 논리는 ARC가 그와 관련이 있다고 가정하게 만듭니다. – MWharton

+1

그러면 대의원이 석방되는 데 문제가 있습니다. –

관련 문제