53

Objective-C의 속성 및 인스턴스 변수에 대해 다소 혼란 스럽습니다.Objective-C의 속성 및 인스턴스 변수

저는 Aaron Hillegass의 "Mac OS X 용 Cocoa Programming"의 중간 단계입니다. 모든 것이 논리적입니다.

  • 다른 물체가 우리의 nameitems 인스턴스 변수를 조작해야하기 때문에

    @class Something; 
    
    @interface MyClass : NSObject { 
        NSString *name; 
        NSArray *items; 
    
        Something *something; 
    
        IBOutlet NSTextField *myTextField; 
    } 
    
    @property (nonatomic, retain) NSString *name; 
    @property (nonatomic, retain) NSArray *items; 
    
    , 우리는 그들에게 접근/뮤 테이터를 생성하는 @property/@synthesize를 사용 :이 같은 클래스 뭔가를 선언 할 것입니다. 클래스 내에서는 접근 자/변형자를 사용하지 않고 인스턴스 변수와 직접 상호 작용합니다.

  • something은 우리 클래스에서 사용할 인스턴스 변수 일 뿐이며, 아무도 사용하지 않아도되므로 한 쌍의 접근 자와 mutator를 만들지 않습니다.

  • UI의 텍스트 필드와 상호 작용해야하므로 IBOutlet을 선언하고 연결하면 완료됩니다.

매우 논리적입니다.

그러나 iPhone 세계에서는 상황이 달라 보이는 것 같습니다. 사람들은 모든 단일 인스턴스 변수에 대한 속성을 선언하고 IBOutlets의 속성을 선언하고 접근 자/변경자를 사용하여 클래스 (예 : name = @"Test"이 아닌 [self setName:@"Test"])을 클래스 내에서 상호 작용합니다 (예 :).

왜? 무슨 일 이니? 이러한 차이점이 iPhone에만 해당합니까? 모든 인스턴스 변수의 속성을 선언하고 IBOutlets의 속성을 선언하고 자신의 클래스에서 접근 자/변경자를 사용하면 어떤 이점이 있습니까?

+1

처럼 쓸 수 있습니다 : 아래의 답변뿐만 아니라, http://stackoverflow.com/questions/1221516/does-an-iboutlet-needs- 참조 IBOutlets을 속성으로 선언하는 이유에 대해서는 http://stackoverflow.com/questions/1250518/what-happens-if-i-dont-retain-iboutlet을 참조하십시오. –

답변

29

iPhone 세계에는 사용할 수있는 가비지 수집기가 없습니다. 참조 카운팅을 통해주의 깊게 메모리를 관리해야합니다. 직접 인스턴스 변수를 설정 한 경우 이전에 고려하지 않고, 당신은 이전 값에 대한 참조를 잃게됩니다 당신이 할 수있는,

name = @"Test"; 

self.name = @"Test"; 
// which is equivalent to: 
[self setName: @"Test"]; 

: 염두에두고, 사이의 차이를 고려 보유 수를 조정하지 마십시오 (수동으로 release해야합니다). 속성을 통해 액세스하면 자동으로 처리되며 새롭게 할당 된 객체의 보유 수를 증가시킵니다.

기본 개념은 iPhone과 관련이 없지만 가비지 수집기가없는 환경에서는 매우 중요합니다.

+0

... "Mac OS X 용 코코아 프로그래밍"에서 Aaron Hillegass는 가비지 수집기를 사용하지 않습니다 ... 우리는 수동으로 메모리를 관리합니다 ... –

+3

스티브 : 가이드를 보지 못했습니다. 어쨌든 속성을 사용하지 않고 인스턴스 변수 * 아무 곳이나 *에 할당하면 클래스 내에 있는지 여부에 관계없이 참조 횟수에주의해야합니다. 그 외에도 Mac OS X 프레임 워크는 iPhone보다 오래되었습니다. Objective-C 2.0은 이미 iPhone SDK가 출시되었을 때 이미 OS X 개발자가 사용했던 것보다 더 많은 속성 사용이 발생했습니다. 전반적으로 엄격한 규칙보다는 스타일의 문제입니다. –

+0

@Mehrdad : 알겠습니다. 감사! –

6

속성은 인스턴스 변수에 대한 접근자를 생성하는 데 사용되며 마법 같은 일이 발생하지 않습니다.

동일한 접근자를 직접 구현할 수 있습니다.

멤버 변수에 대한 3 가지 메모리 관리 전략의 예제 인 Aaron Hillegass의 책에서 찾을 수 있습니다. 그들은 assign/copy/retain입니다. 해당 변수 중 하나를 선택합니다.

나는

은 접근자는 복잡성과 각 변수에 대한 메모리 관리의 차이를 숨길 수 ... 당신이 목표 - C의 메모리 관리를 이해 가정합니다. 예를 들어

:

name = @"Test" 

name 해주기 NSString @"Test" 참조를 보유하고, 단순한 과제이다. 그러나 copy 또는 retain을 사용할 수 있습니다. 메모리 관리의 버전이 접근을 선택했다 상관없이 복잡성을 숨기고 당신은 항상 가변 (또는 유사한)에 액세스 :

[self setName:@"Test"] 
[self name] 

이제 setName:assign/copy or retain을 사용할 수 있습니다 그리고 당신이 그것에 대해 걱정할 필요는 없습니다.

내 생각에 iPhone 튜토리얼은 속성을 사용하여 새로운 개발자가 메모리 관리를 쉽게 할 수 있도록 해줍니다 (매번 손으로 직접 구현하지 않고 속성을 가진 적절한 접근자를 생성하는 것이 편리 할지라도).

+0

좋습니다, 이것도 의미가 있습니다. 감사! –

3

그러나 아이폰 세계에서는 상황이 달라 보이는 것 같습니다. 사람들은 모든 단일 인스턴스 변수에 대해 속성을 선언하고 IBOutlets의 속성을 선언하고 클래스 내의 인스턴스 변수와 상호 작용하기 위해 접근 자/변형자를 사용합니다 (예 : name = @"Test"이 아닌 [self setName:@"Test"]으로 작성).

아이폰에만 해당되는 것은 아닙니다. init 메서드와 dealloc 메서드를 제외하고 항상 접근자를 사용하는 것이 좋습니다. 특히 Mac에서 (코코아 바인딩이 포함 된) 주요 이점은 접근자를 사용하면 무료 KVO 알림을 의미한다는 것입니다.

사람이 "모든 단일 인스턴스 변수에 대한 속성 선언"이유는 아마도 모든 인스턴스 변수가 속성으로 공개하고자하는 것일 수 있습니다. 그들이 개인적으로 유지하고자하는 것이 있다면 헤더 파일에 속성을 선언하지 않을 것입니다. (그러나, 위에서 언급 한 무료 KVO 알림을 얻기 위해 구현 파일의 클래스 확장에서 속성을 만들 수도 있습니다.)

아웃렛에 대한 속성을 선언하는 것은 과도한 행동입니다. 나는 그것에 대한 요점을 보지 못한다. 속성을 만들지 않으면 닙로드 기가 직접 인스턴스 변수 액세스를 통해 콘센트를 설정합니다. 이는 해당 작업에 적합합니다.

+0

http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6에 따르면, 그렇지 않은 경우 iPhone에서 펜촉을로드 한 후 최상위 오브젝트를 유지하면 해당 오브젝트가 할당 취소됩니다. OS X 데스크탑의 최상위 레벨 객체는 1의 보유 수를가집니다. 그러나 속성 (또는 적어도 setters/getters)을 사용하면 진행 상황을 명확하게 알 수 있으며 특히 iPhone에서 좋은 아이디어입니다. –

+0

나는 그것이 보존을 명백하게한다는 것에 동의하지만,이 경우 반드시 필요하다고 생각하지 않습니다. 콘센트는 항상 소유 관계라는 것을 기억하십시오. –

+0

@Peter Hosey : 감사합니다! 이제는 모두 이해하기 시작했습니다. 한 가지 질문 :'init' 메소드에서 액세서/뮤 테이터 메소드를 사용하면 안되는 이유는 무엇입니까? –

2

나는 현대 개발이 모범 사례를 확인하고 정의하고 적용하기위한 매우 강력한 시도를했음을 제안합니다.

이러한 우수 사례 중 연속성과 일관성이 있습니다. 그렇다 initdealloc 방법에 접근의 사용을 논쟁에서

는 접근은 일반적으로 모두 허용 encapsulation, 다형성 VAR 구현을 포함하여 그들이 제공하는 혜택 (대한 (클래스의 내부 및 외부) 모든 시간을 사용한다 추상화 및 리팩토링) 및 연속성 및 일관성의 모범 사례를 용이하게합니다. 객체 지향 언어의 근본적인 이점은 이런 식으로 일을하고 언어 기능의 충만 함을 활용할 때 효과를 발휘합니다. 수석 프로그래머가 보통 증명할 것이기 때문에 항상 코딩에서 일관성을 유지하는 것이 바람직하지 않습니다.

0

당신은 비슷한 상황에서 누군가를 위해이

//MyClass.h 

@class Something; 

@interface MyClass : NSObject 

@property (nonatomic, strong) NSString *name; 
@property (nonatomic, strong) NSArray *items; 

@end 

//MyClass.m 
@interface MyClass() 

@property (nonatomic, strong) IBOutlet NSTextField *myTextField; 
@property (nonatomic, strong) Something *something; 

@end