2009-09-09 5 views
3

NSString 인스턴스 변수 "planetName"이 나 (아래 예제 에서처럼)에 의해 할당/해제 될 필요가 있는지 또는 클래스 인스턴스가 생성/할당 될 때 수행되는 것인가?인스턴스 변수 할당?

나의 이해는 INT와 플로트가 될 필요가 없습니다,하지만있는 NSString &있는 NSArray에 대해 확실하지 ...

이 같이

@interface PlanetClass : NSObject { 
     NSString *planetName; 
} 
- (NSString *)planetName; 
- (void)setPlanetName:(NSString *)value; 
@end 
...

- (id) init { 
     [super init]; 
     planetName = [[NSString alloc] init]; 
return self; 
} 

- (void) dealloc { 
     [planetName release]; 
     [super dealloc]; 
} 

를 ** 않는다는 것입니다 - --------------------------------- ** EDIT : EDIT : 여기 다른 버전이 있습니다 ** --- ------------------------------- **

int main(int argc, const char *argv[]) { 

     // ** Allocated here 
     PlanetClass *newPlanet_01 = [[PlanetClass alloc] init]; 
     NSString *newPlanetName = [NSString alloc] init]; 

     // ** Set the instance variable pointer here 
     newPlanetName = @"Jupiter"; 
     [newPlanet_01 setPlanetName:newPlanetName]; 

     // ** Released here 
     [newPlanet_01 release]; 
     return 0; 
} 

초기화 &의 dealloc 방법은 다음 ... 이렇게 될 것

- (id) init { 
     [super init]; 
     return self; 
} 

- (void) dealloc { 
     // Always release the current copy of planetName 
     // pointed to by the class instance. 
     [planetName release] 
     [super dealloc]; 
} 

setPlanetName 방법은 다음과 같을 것입니다 ...

- (void)setPlanetName:(NSString *)newPlanetName { 
     if (planetName != newPlanetName) { 
       [planetName release]; 
       planetName = [newPlanetName copy]; 
     } 
} 

PS : 나는 속성을 사용하거나 합성하고 있지 않다, 나는 아직까지 그것을 얻지 못했다.

환호

+0

'NSString * newPlanetName = [NSString alloc] init]'은 즉시 다른 NSString을 변수에 할당하고 이전 값을 해제하지 않기 때문에 그냥 메모리 누수입니다. – Chuck

답변

1

새 코드에 여전히 문제가 있습니다.

주 기능에서 newPlanetName을 릴리스하지만 약간 잘못되었습니다. PlanetClasssetPlanetName: 방법으로 유지했지만 행성의 이름이 변경되지 않으면 다시 PlanetClass을 공개하지 않습니다. 문자열을 유지하려면 setPlanetName:의 발신자가되어서는 안되며 적절하게 처리하는 것은 수업 책임입니다.

이전 dealloc 방법이 정확합니다. 너의 PlanetClass이 더 이상 필요하지 않기 때문에 행성의 이름을 공개해야한다. stringWithString:에 의해 반환 된 문자열이 당신에게 속해 있지 않기 때문에 주된 방법은 행성의 이름을 공개해서는 안되며, 당신은 이것을 PlanetClass에게 주어야합니다.

따라서 기존의 dealloc 방법을 유지하고 [newPlanetName release]을 주 기능에서 제거하면 문제가 없어야합니다.

바로 가기로 [newPlanet_01 setPlanetName:@"Jupiter"]을 호출하고 주 기능에서 변수 newPlanetName을 삭제할 수도 있습니다.

+0

dealloc 메서드에 [planetName release]를 추가해야하는 이유를 알 수 있습니다. 클래스가 할당 해제되면 newPlanet의 현재 복사 된 버전이 해제됩니다. 메모리를 할당 할 때 newPlanetName에 대해 약간 혼란 스럽다. @ "목성"을 할당한다. newPlanet이 해제되어야한다. (수정 된 코드) – fuzzygoat

+0

일반적인 오해이다. main 함수에있는'newPlanetName' 변수는 * 객체에 대한 포인터입니다. '[[NSString alloc] init]'을 사용하면 newPlanetName 변수가 가리키는 빈 문자열을 할당하고 초기화합니다. '@ "목성과 같은 값을 할당하면'newPlanetName'이 가리키는 곳을 변경하고, 실제로 가리키는 원래의 객체 (빈 문자열)는 더 이상 접근 할 수 없게됩니다. – dreamlax

+0

이것은 내가 생각한 것입니다 ... (*) newPlanetName은 문자열 객체에 대한 포인터이며 처음에는 nil을 가리 킵니다. (*) newPlanetName = @ "Jupiter"는 포인터가 문자열 리터럴을 가리 키도록 설정합니다. 문자열 리터럴을 해제 할 필요가 없다고 생각합니다. ** BUT ** – fuzzygoat

3

귀하의 코드가 유효 -gary-하지만 빈 문자열로 planetName를 초기화 할 이유는 아마 없다. Objective-C의 멋진 기능 중 하나는 아무런 결과없이 메시지를 nil 객체에 보낼 수 있다는 것입니다. 클래스가 초기화되고 -setPlanetName:을 호출하지 않으면 planetName은 0이됩니다. 인스턴스 변수는 항상 nil으로 초기화되므로 -dealloc 메서드가 [planetName release]을 호출하면 아무 것도 발생하지 않습니다.

일반적으로 가장 좋은 방법은 NSString 인스턴스 변수를 설정할 때 -copy을 사용하고 다른 대부분의 개체를 인스턴스 변수로 설정할 때 -retain을 사용하는 것입니다. 따라서 -setPlanetName: 방법은 다음과 같이 표시됩니다.

- (void)setPlanetName:(NSString *)newPlanetName { 
    NSString *tempPlanetName = [newPlanetName copy]; 
    [planetName release]; 
    planetName = tempPlanetName; 
} 
+0

모든 개체가 nil로 초기화되는 것은 아니며 인스턴스 변수 만 초기화됩니다. 스택에서 생성 된 개체 포인터는 초기화되지 않은 상태로 남아 있습니다. – dreamlax

+0

planetName을 @property (비 원자 복사)로 만들려면 concider해야합니다. – PeyloW

0

코드가 좋아집니다. NSObject 하위 클래스 (NSString 포함)는 자신의 메모리를 소유하는 객체에 의해 관리되어야합니다. 이 경우 소유자는 PlanetClass입니다.

1

planetName는 INT 또는 플로트처럼, 할당 또는 초기화 할 필요가 없습니다하는 포인터입니다.

int 또는 float에 값을 할당하는 것처럼 문자열의 다른 인스턴스에서 planetName을 가리킬 수도 있고 아무 것도 가리 키지 않을 수도 있습니다.

클래스를 초기화 할 때 planetName은 nil (아무 것도 가리 키지 않음)이됩니다. planetName을 문자열의 인스턴스로 지정하면 문자열이이고 해당 문자열이 이고이 dealloc에 ​​있어야합니다.즉

이 :

planetName = [[NSString alloc] init]; 

은 불필요하고 무의미하다. 당신의 setPlanetName 방법에서

당신은, 출시 planetName가 가리키고있는 기존의 문자열에 필요한 새로운 문자열로 planetName을 할당 한 다음 새 문자열 유지할 것입니다.

dealloc 방법이 정확합니다.