2010-12-07 2 views
4

, 당신은 같은 것을 할 수 있습니다 : 그것은 나의 이해는 현대 런타임 함께@synthesized 인스턴스 변수를 언제 사용하지 않겠습니까? 현대 오브젝티브 C 런타임에서

@interface MyClass : NSObject { 
} 
@property NSString *stringProperty; 
@end 

@implementation MyClass 
@synthesize stringProperty; 
@end 

이 단지 내 속성에 대한 접근을 합성하지 않을 것이다, 그러나 또한 인스턴스 변수 자체, 그래서 나는이 클래스의 메서드 중 하나 인 [stringProperty length];에서 말할 수 있었고 마치 인스턴스 변수를 선언 한 것처럼 작동 할 것입니다.

필자는이 코드를 지금 모든 코드에서 사용하기 시작했습니다. 왜냐하면 필자가 반복해서 작성해야하는 것은 하나이기 때문입니다. 그리고 clang 2.0 컴파일러에 대해서 들었습니다. @synthesize을 건너 뛸 수도 있습니다 (하지만 다른 문제입니다). 그러나 나는 궁금해했다. 이것을하기에있어서의 단점은 무엇인가? 내 속성에 실례로 인스턴스 변수가 필요할 수 있습니까?

가끔은 변수를 비공개로 유지하고 외부 액세스 권한을 부여하지 않을 때가 있다는 것을 알고 있습니다 (하지만 보통 개인 클래스 확장에서 속성을 선언하거나 그 속성을 만들지 않습니다). 내가 접근자를 필요로하지 않는다면 모두).

내가 이것을하고 싶지 않은 경우가 있습니까?

+0

@joe 예, 속성을 선언하고 위와 같이 합성했지만 ivar을 명시 적으로 선언하지 않으면 컴파일러는 여전히 ivar을 만듭니다. 그래서 클래스 안에서 기대할 수있는'int len ​​= [self.stringProperty length]'를 할 수 있었고 접근 메소드를 사용하지 않고'int len ​​= [stringProperty length]'를 할 수도 있습니다. ivar (컴파일러가 setter + getter와 함께 나를 위해 합성했다). 정말 환상적입니다! – jbrennan

+0

@joe XCode4가 이제 앱 대리인을 위해 생성되는 스텁을 검사 한 결과 알게되었습니다. –

답변

4

합성 인스턴스 변수를 사용하지 않는 것이 가능한 이유 중 하나는 현재 버전의 Xcode (3.2.5)에서 디버그하는 데 약간의 고통이된다는 것입니다. GDB를 통해 코드를 실행할 때 라이브 디버거 뷰에 나타나지 않는 것 같습니다. po [0xOBJ_ADDRESS propertyName]과 같은 gdb 콘솔을 사용하는 유일한 방법입니다. 표준이 아닌 합성 된 ivar만큼이나 훌륭합니다.

어쩌면 Xcode 4에서는이 문제를 해결하지만 충분한 경험이 없으므로 (여전히 NDA에 의거하고 있습니다). 이 SO 질문에

상세 정보 : Seeing the value of a synthesized property in the Xcode debugger when there is no backing variable

+2

+1 역 호환과 함께 이것은 (IMO) 선언 된 ivars를 유지하는 유일한 이유입니다. 디버깅이 쉬워졌습니다. –

+0

Xcode 4가 출시 되었는데도 여전히 그런 경우입니까? – neoneye

+1

@neoneye 내가 말할 수있는 한, Xcode 4.0.2부터 Snow Leopard에서 이것은 여전히 ​​불행한 일입니다. – jbrennan

3

당신은 하나의 인스턴스 변수에 대한 많은 특성을 제공 할 수 있습니다, 예를 들어, :

  • 직사각형과 극 시스템
  • 를 모두 좌표를 액세스하기위한도, 라디안 모두 각도 값을 액세스하기위한

이러한 경우에는 인스턴스 변수 (이미 있음) 또는 접근 자 메소드 (변환을 제공하기 위해 제공하려는)를 합성하지 않으려 고합니다.

+1

물론, 인스턴스 변수를 합성하는 컴파일러와는 아무런 관련이 없습니다. 내 'stringProperty' 대신에'float angleInDegrees'에 속성을 대신 사용했다고 가정 해 보겠습니다. 그래서 이것은 각도로 내 각도를위한 ivar를 합성 할 것이고, 그것을 라디안으로 변환하고 리턴하는 두 번째 (readonly) 속성을 추가 할 수 있습니다. 물론 내가 뭔가를 놓치지 않는 한. – jbrennan

+0

두 번째 속성은 읽기 전용 일 필요는 없습니다. 라디안으로 표시된 값을 쓰고 싶다면 어떻게해야할까요? '@property float angleInRadians'을 추가하고,'@ 합성 '하지 말고, 양방향으로 변환을 수행하는 접근 자 메소드를 제공하십시오. – mouviciel

1

언제든지 직렬화해야하는 클래스에서 (누군가가 더 좋은 방법을 알지 못한다면) 변환해야합니다. 예를 들어, 숫자 값을 가진 클래스가있는 경우. 정수를 직렬화하여 클래스의 NSNumber로 저장할 수는 없지만 속성은 정수 유형입니다.

또 다른 예는 CoreData로 작업 할 때 Apple이 권장하는대로 코딩하는 경우입니다. NSManagedObject에서 파생 된 사용자 지정 클래스를 관리되는 개체의 클래스로 만들고 각 특성에 대해 속성을 사용해야한다고합니다. 그렇다면 @synthesize 대신 @dynamic을 사용할 것이고 iVar는 전혀 필요하지 않습니다.

+0

'[encoder encodeInteger : someIntVar forKey : @ "myIntKey"];'당신을 위해서하지 않습니까? – jbrennan

+0

그 이유는 "누군가가 더 나은 방법을 알지 않는 한"입니다. 필요가있을 때 코드를 기억하겠습니다. :-) – Rob

0

또 다른 이유는 변수 액세스를 직접 바로 가기를 방지하는 것입니다.개체 변수 - :

나는 개인 코딩 규칙에 따라하려고 밑줄 '_xxx' 와 접두사 - 속성을 : 밑줄없이 이름

이 내가 의도하지 않게 쓸

같은 절대 보장 'xxx는'
[xxx someMessage]; 

xxx = value; 

또는

나는 항상 게터/세터를 사용하고 싶습니다.

+0

그건 내 코딩 스타일이기도하다. 그러나 그것은 길고 지루한 속성 선언을 만들었습니다.나는 컴파일러가 ivar을 합성 할 때, ivarName이라는 속성을 위해 _ivarName이라는 이름으로 생성하기 위해 여전히 방법이있을 것이라고 확신한다. 나는 조사 할 것이다. – jbrennan

+0

방금 ​​해보기로 시도했지만 가능합니다. '@property NSString * myString;'그런 다음'@synthesize myString = _myString;'은 당신을 위해 ivar를 생성 할 것이고, 그것은'_myString'라고 불릴 것이고 당신의 속성은 여전히'myString'으로 불릴 것입니다. – jbrennan

+0

GDB에서 작업 할 수 없었습니다. 잘하고있어. 이 동작으로 전환 될 수 있습니다. BTW, Xcode 4는 속성을 선언하는 자체 메카니즘으로 데모되었습니다. 일부 코드는 작성할 필요가 없습니다. –

1

하지만 궁금했는데

self.xxx = value; 
[self.xxx someMessage]; 

당신이 개체 변수들에 대한 lazy 초기화를 사용하는 경우에 특히 유용합니다 ...,이 일의 단점은 무엇입니까? 내 속성에 실례로 인스턴스 변수가 필요할 수 있습니까?

가능한 이유 : 당신이 서브 클래스의 오버라이드 (override) 또는 KVO 걸려 넘어없이 initdealloc의 인스턴스 변수를 변경할 수 있습니다

  • .
  • 이 앱은 Mac OS X에서 32 비트 모드로 컴파일되고 실행됩니다. 64 비트를 지원하지 않는 인텔 맥이 여전히 있습니다.

첫 번째 요점이 실제로 얼마나 유효한 지 잘 모르겠습니다. 문제를 둘러싼 다른 방법이있을 수 있습니다. 두 번째 요점은 이전 Mac을 지원해야하는 경우 게임 오버가 발생한다는 것입니다.

+0

필자는 32 비트 구형 Mac 중 하나를 가지고 있으며, Mac 코드를 작성하지 않았지만 32 비트 시스템에서 시뮬레이터에서 iOS 코드를 실행할 때 내 코드가 정상적으로 실행된다고 말할 수있는 한 멀리 있습니다. 비트 맥, 잘 작동). 아마 더 조사해야합니다. – jbrennan

+0

KVO 예제에 따르면, 내 init 메소드에서 호출 된 경우에도 'stringProperty = [someString copy]; 원인은 무엇이겠습니까? 컴파일러는 실제로 나를 위해 ivar을 생성하기 때문에 setter를 호출하지 않고도 액세스 할 수 있습니다.이 경우 내 이해에 따라 KVO가 실행되지 않습니다. 그러나 어쩌면 나는 그것에 대해 잘못 생각합니다. – jbrennan

+0

오케이, 이전 버전의 32 비트 Mac에서 사용해 보았습니다. 주사위가 없습니다. 당신은 맥 애플 리케이션에 맞습니다. iOS 시뮬레이터가 동일한 Mac에서 실행 중일 때도 가능하다는 점이 궁금합니다. 구형 맥의 런타임을위한 기능 향상은 포함하지 않았다는 점이 수치 스럽다. – jbrennan