많은경우 여러개의 리턴값을 받기위해 참조를 이용한 값전달 받기를 한다. 이러한 방식은 에러를 전달할 때 가장 많이 사용되므로 아마도 익숙할 것이다. 


보통 이런방식으로..


//output parameter를 사용한 메소드

- (BOOL)huga:(NSString*)s error:(NSError**)outError {


    if (outError) {

        *outError = [NSError errorWithDomain:@"domine" code:-1 userInfo:nil];

        return NO;

    }

    return YES;

}



//사용하기

NSError *error = nil;

BOOL success = [self huga:@"hahaha" error:&error];



그런데 유심히보면 포인터를 두개를 사용한 참조를 이용하는데 왜 그럴까? 그 이유를 내 나름대로 해석하자면 이렇다.

만약 hoge라는 메소드를 만들고 출력 파라메타를 이용한다면 이런식으로 구현할 것이다.


- (void)hoge:(NSString **)outValue {

    *outValue = @"Kjcode!";

}


//값을 줄때 요렇게..

NSString *str = nil;

[obj hoge:&str];




이런식으로 구현된 소스는 컴파일러에서 아래와 같이 해석한다고 한다. 


//complier code.

- (void)hoge:(NSString *__autoreleasing *)value {

    *value = @"Test";




//complier code.

NSString *__strong s = nil;

NSString *__autoreleasing temp = str;

[obj hoge:&temp];

str = temp;




이 이야기는 참조로 넘어가는 값을 __autoreleasing을 해줌으로 인하여 ARC를 적용시켜주는 것이다.

뿐만아니라 시각적으로도 개발자가 포인터에 값을 넣어주어야 하기때문에 반환되는 파라메터라는 것을 금방 눈치챌 수 있을것이다.


만약 포인터 딸랑 하나로 output파라메타를 사용하는 메소드를 만들었다면 문제가 생길소지가 다분하다.

예를 들어 플젝 개발자가 경험이 부족하거나 아니면 경험자라도 메소드안을 꼼꼼히 보지 않는다면 아무생각없이 그 파라메터를 strong프로터피에 값을 전달시킬수도 있을것이다.

그럼 그순간 순환참조가 일어날 것이고 영원히 메모리에서 젖은낙엽처럼 붙어있게 될것이고 짜증나는 야근을 경험할지도 모른다.



휴~ 지금 내가 하는 플젝에서도 출력파라메터를 잔뜩 사용해놓구선 메모리를 잔뜩 잡아먹는 코드를 만들어놔서 고생중인데 물론.. 그 당사자는 이미 그만둔 상태이므로 리팩토링은 남은자의 몫이 되어 버렸다.


암튼 개고생중. (여기서 "개"라는 표현은 욕이 아닌 강조를 위한 최상급 표현임.)



참고사이트

https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html




Posted by 악당잰 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply 김기봉 2015.02.03 08:26

    형 이부분
    //complier code.
    NSString *__strong s = nil;
    NSString *__autoreleasing temp = str;
    [obj hoge:&temp];
    str = temp;

    에서
    NSString *__strong s = nil; -> str = nil; 이죠?