2009-08-12 3 views
3

내가로드 내 jQuery과 방법 cellAtRowForIndexPath 내부 사람 개체어떻게 메모리가 누출됩니까?

에게 Person.h

#import <UIKit/UIKit.h> 
#import "TwitterHelper.h" 

@interface Person : NSObject { 
    NSDictionary *userInfo; 
    NSURL *image; 
    NSString *userName; 
    NSString *displayName; 
    NSArray *updates; 
} 
/* 
@property (retain) NSString *userName; 
@property (retain) NSString *displayName; 
@property (retain) NSDictionary *userInfo; 
*/ 
@property (nonatomic, copy) NSURL *image; 
@property (retain) NSArray *updates; 

- (id)initWithUserName:userName; 

@end 

Person.m

#import "Person.h" 


@implementation Person 

/* 
@synthesize userName; 
@synthesize displayName; 
@synthesize userInfo; 
*/ 
@synthesize image; 
@synthesize updates; 

- (id)initWithUserName:(NSString *)user{ 

    userName = user; 
    userInfo = [TwitterHelper fetchInfoForUsername:user]; 
    displayName = [userInfo valueForKey:@"name"]; 
    image = [NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]]; 
    updates = [TwitterHelper fetchTimelineForUsername:userName]; 

    return self; 
} 

- (void)dealloc 
{ 
    /* 
    [userName release]; 
    [displayName release]; 
    [updates release]; 
    [userInfo release]; 
    [image release]; 
    */ 
    [super dealloc]; 
} 

@end 

을 만들 때 나는 각 사람 개체를 만드는 오전 테이블보기를 가지고 이미지 속성을 할당하면 ...

Person *person = [[Person alloc] initWithUserName:userName]; 

NSData *data = [[NSData alloc] initWithContentsOfURL:person.image]; 
[data release]; 

인스 트루먼 테이션에서 이것을 실행하면 NSData * 데이터 ... 행이 누설되는 부분을 강조 표시합니다.

왜 누수가 있습니까? 당신이 속성을 만들하기로 선택한 경우

답변

1

, 당신은 사용한다 : 당신의 init 메시지에

self.image = [NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]]; 

image = [NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]]; 

self 접두사없이 값을 설정하지 않으면 호출되지 않습니다 copy 또는 retain 메시지를 보내고 메모리 문제 (누출 일 필요는 없음)를 생성합니다.

이것은 계기가 당신을 가리키고있는 것일 수 있습니다.

는 (이것은 분명히 모든 속성에 적용됩니다!)

다른 방법으로, 다음, 예를 들어 retain 또는 copy 값 검색, 접근을 사용하지 않으려는 경우 :

image = [[NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]] retain]; 
+0

속성을 선언하는 방식 (원자, 유지, 복사 등)에 차이가 있습니까? – Jason

+0

글쎄, 나는 그것이 차이를 만들어 낸다는 것을 말해야한다. 그러나 나의 위의 예에서는 무엇이되어야 하는가? – Jason

+2

No! 이니셜 라이저 또는 dealloc 메소드에서 접근 자 (명시 적으로 또는 점 표기법을 통해)를 사용하지 않아야합니다. 이 메서드에서는 직접 속성 액세스 *를 사용합니다.getter/setter를 호출하면이 두 상황에서 의도하지 않은 (부적절한) 결과가 발생할 수 있습니다. 그러나 * NSURL을 복사해야합니다. Cocoa 용 메모리 관리 안내서를 다시 읽어야합니다. –

5

먼저, 당신 인스턴스 변수와 속성 및 getter/setter의 차이점을 이해해야합니다.

  • 인스턴스 변수 (ivars)는 개체에 저장된 변수입니다. 메소드 내에서 ivar에 접근하는 것은 간단하게 이름을 지정하여 (예 : "userName") 수행합니다.
  • 속성은 객체에 대한 인터페이스를 정의하므로 정보를 객체에 읽고 쓸 수 있습니다 ( ).
  • 게터/세터가 인터페이스를 구현하고 백킹 저장 같은 바르를 사용할 수

하면, 게터/세터를 이용하여 속성 액세스 명시 적으로 (예 [자기 이름]) 또는 (등가) 도트 구문을 사용하여 self.userName. 이 두 표기법은 정확히 동일합니다.

- (NSString*) userName; 
- (void) setUserName: (NSString*) theUserName; 

:

@property (copy) NSString* userName; 

이 declartion가 입력 본질적으로 동일합니다 : 당신은 뭔가처럼 객체의 인터페이스에서 @property를 사용하여 (당신이 당신의 객체 인터페이스를 선언 예) 속성을 선언 @synthesize (단순히 컴파일러에게 getter/setter를 작성하도록 지시 함) 또는 직접 구현 (즉, userName 및 setUserName에 대한 메소드 구현 작성)하여 속성을 구현합니다. 거의 사용되지 않는 세 번째 옵션 인 @dynamic도 있습니다.이 옵션은 런타임에 메소드를 처리 할 컴파일러에게 알려주며, 그렇지 않으면 얻을 수있는 경고를 silincing합니다.

다음으로 memory management rules을 읽고 이해해야합니다. 그것의 단 9 짧은 단락, 지금 그것을 읽으십시오, 나는 기다릴 것이다. 끝난? 좋은.

또한 init 또는 dealloc 루틴에서 getters/setter를 사용하면 안된다는 것을 알아야합니다. 당신은 유지하거나 사본과 바르에 저장 한 각 값의 소유권을

- (id)initWithUserName:(NSString *)user{ 
    userName = [user copy]; 
    userInfo = [[TwitterHelper fetchInfoForUsername:user] retain]; 
    displayName = [[userInfo valueForKey:@"name"] copy]; 
    image = [[NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]] copy]; 
    updates = [[TwitterHelper fetchTimelineForUsername:userName] retain]; 
    return self; 
} 

참고 :

그래서 초기화 루틴은 다음과 같이 보일 것이다. 일반적으로 NSString에 copy를 사용하면 NSMutableString을 NSString으로 변환 할 수 있습니다. 같은 문제가 NSArray/NSDictionary에도 적용되지만, TwitterHelper는 가져온 데이터를 전달하려고합니다.

귀하의 dealloc 다양한 인스턴스 변수를 해제해야합니다 : 코드는 속성에 액세스하거나 변경 self.userName를 사용하기보다는 직접 인스턴스 변수에 액세스 할에서 다른 곳

- (void)dealloc 
{ 
    [userName release]; 
    [displayName release]; 
    [updates release]; 
    [userInfo release]; 
    [image release]; 
    [super dealloc]; 
} 

합니다.

displayName (및 이와 유사한 이미지)을 저장하지 않을 수도 있지만 userInfo에서 검색하는 속성 가져 오기 도구를 구현하기 만하면됩니다. 이렇게하려면 displayName ivar을 삭제하고 속성을 다음으로 변경합니다.

@property (읽기 전용) NSString * displayName;

는 @synthesize의 나 displayName을 제거하고 수동 게터 추가

- (NSString*) displayName 
{ 
    return [userInfo valueForKey:@"name"]; 
} 

및 할당 해제에 출시를 제거합니다.

displayName에 값을 보유/해제 할 필요가 없습니다. 수신자 이 소유하지 않은 값을으로 반환합니다.이 값을 그대로 유지하려면 복사/보관해야합니다.

+0

이것은 대단한 답변이었습니다. 정말 고마워요. 내가 놓친 유일한 것은 @property와 @synthesize 선언에 대한 이해입니다. 그 분야에 대해 좀 더 통찰력을 줄 수 있습니까? 다시 한번 감사드립니다. – Jason

0

귀하는 alloc (으)로 전화를 걸지만이를 공개하지 마십시오. person 개체가 유출되었습니다. (셀 구성에서)

+0

죄송합니다. 제공된 코드에서 [사람 해제] 메소드를 제외 시켰습니다. 그것은 거기에있다. 또한 그러한 경우라면, Instruments는 저에게 그 라인을 가르쳐주지 않습니까? – Jason

+0

아, 네. Clang 정적 분석기를 통해 코드를 실행 해 보셨습니까? 이전에 사용 해본 적이 없다면 본질적으로 그래픽 프론트 엔드 인 "AnalysisTool"에 대한 인터넷 검색을 시도하여 프로젝트를 분석 할 수 있습니다. 그것은 누출을 발견 할뿐만 아니라 단계별로 당신에게 보여줍니다. 환상적인 도구입니다. – jbrennan

관련 문제