@synthesize를 언제 명시 적으로 사용해야합니까?


81

내가 아는 한, XCode 4.4 이후로 @synthesize속성 접근 자를 자동 생성합니다. 그러나 방금에 대한 코드 샘플을 읽었 NSUndoManager으며 코드에서이 @synthesize명시 적으로 추가 되었음을 알 수 있습니다. 처럼:

@interface RootViewController  ()

@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSUndoManager *undoManager;

@end

@implementation RootViewController
//Must explicitly synthesize this
@synthesize undoManager;

지금 당황 스럽습니다 ... 언제 @synthesize코드 에 명시 적으로 추가해야 합니까?


1
샘플 코드가 오래되었을 수 있습니다. 기본적으로 문제가되지 않는 한 사용하십시오 (예 : 델리게이트의 속성이 자동 합성되지 않음)
borrrden

1
아웃 주석보십시오 @sythesize. 코드가 여전히 작동하면 필요하지 않습니다.
ThomasW

답변:


171

많은 답변이 있지만 큰 혼란도 있습니다. 나는 주문을하려고 노력할 것입니다 (또는 엉망진창을 늘리십시오, 우리는 보게 될 것입니다 ...)

  1. Xcode에 대한 이야기는 그만합시다. Xcode는 IDE 입니다. clang은 컴파일러 입니다. 우리가 논의하고있는이 기능 은 속성의 자동 합성 이라고 하며 Xcode에서 사용하는 기본 컴파일러 인 clang 에서 지원 하는 Objective-C 언어 확장 입니다.
    명확히하기 위해, Xcode에서 gcc로 전환하면이 기능의 이점을 얻지 못할 것입니다 (Xcode 버전에 관계없이). 같은 방식으로 텍스트 편집기를 사용하고 명령 줄에서 clang을 사용하여 컴파일하는 경우 의지.

  2. 자동 합성 기능 덕분에 속성을 명시 적으로 합성 할 필요가 없습니다. 컴파일러에 의해 자동으로 합성되므로

    @synthesize propertyName = _propertyName
    

    그러나 몇 가지 예외가 있습니다.

    • 사용자 정의 getter 및 setter가있는 readwrite 속성

      getter 및 setter 사용자 지정 구현을 모두 제공 할 때 속성이 자동으로 합성되지 않습니다.

    • 사용자 정의 getter가있는 읽기 전용 속성

      readonly 속성에 대한 사용자 정의 getter 구현을 제공 할 때 이것은 자동으로 합성되지 않습니다.

    • @동적

      사용하는 경우 @dynamic propertyName,이 건물은 자동으로 (매우 명백 이후 합성되지 않습니다 @dynamic@synthesize상호 배타적입니다)

    • @protocol에 선언 된 속성

      프로토콜을 준수 할 때 프로토콜이 정의하는 속성은 자동으로 합성되지 않습니다.

    • 카테고리에 선언 된 속성

      이것은 @synthesize지시문이 컴파일러에 의해 자동으로 삽입되지 않는 경우이지만이 속성도 수동으로 합성 할 수 없습니다. 범주는 속성을 선언 할 수 있지만 범주는 ivar를 만들 수 없으므로 전혀 합성 할 수 없습니다. 완전성을 위해 Objective-C 런타임을 사용하여 속성 합성을 위조 할 수 있다는 점을 추가하겠습니다 .

    • 재정의 된 속성 (clang-600.0.51 이후 새로운 기능, Xcode 6과 함께 제공, Marc Schlüpmann에게 감사드립니다)

      슈퍼 클래스의 속성을 재정의 할 때 명시 적으로 합성해야합니다.

속성을 합성하면 백업 ivar가 자동으로 합성되므로 명시 적으로 선언하지 않는 한 속성 합성이 누락 된 경우 ivar도 누락됩니다.

마지막 세 가지 경우를 제외하고 일반적인 철학은 속성에 대한 모든 정보를 수동으로 지정할 때마다 (모든 접근 자 메서드를 구현 @dynamic하거나을 사용하여 ) 컴파일러가 속성에 대한 모든 권한을 원한다고 가정하고 자동 합성을 비활성화한다는 것입니다. 그것.

위에 나열된 경우를 제외하고 명시 @synthesize적의 유일한 다른 용도 는 다른 ivar 이름을 지정하는 것입니다. 그러나 규칙이 중요하므로 항상 기본 이름을 사용하는 것이 좋습니다.


원래 질문자가 아직 여기에 있다면이 대답을 받아 들여야한다고 생각합니다. 가장 완벽합니다.
Steven Fisher

3
내가 기억하는 한 카테고리에 지정된 속성도 자동으로 합성되지 않습니다. (근본 이유는 범주에 인스턴스 변수를 추가 할 수 없기 때문입니다.)
Martin R

@MartinR, 좋은 지적입니다. 자동으로 합성되지는 않지만 @synthesize카테고리에서 금지되어 있으므로 수동으로 합성 할 수도 없습니다 (이미 언급했듯이 카테고리에 ivar 없음). 메모를 추가하겠습니다.
Gabriele Petronella 2013

그러나이 답변은 구체적인 질문을 다루지 않습니다. @synthesize를 언제 사용해야합니까? 항상, 절대로 특정 조건이 충족 될 때만?
Jeff

21

명시 적으로 사용하지 않으면 @synthesize컴파일러는 다음과 같은 방식으로 속성을 이해합니다.

@synthesize undoManager=_undoManager;

그러면 다음과 같은 코드를 작성할 수 있습니다.

[_undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter

이것은 일반적인 관습입니다.

당신이 쓰면

@synthesize undoManager;

당신은 할 것 :

[undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter

@synthesize더 이상 필수가 아니기 때문에 개인적으로 사용을 중지 합니다. 나를 위해 사용하는 유일한 이유는 @synthesize을 연결하는 iVarA를 @property. 특정 getter 및 setter를 생성하려는 경우. 그러나 주어진 코드에는 아무것도 없습니다. iVar이것은 @synthesize쓸모가 없다고 생각합니다 . 하지만 이제는 새로운 질문이 "언제 사용해야 iVar합니까?" 라고 생각합니다.이 질문에 대해서는 "절대"라는 답변이 없습니다!


2
@synthesize더 이상 할 이유가 없어서 사용 을 중단 했습니다. 또한 선행 밑줄은 속성이 제공하는 메모리 관리 및 스레딩 안전망에 대해 작업하고 있음을 알려주는 멋진 시각적 플래그 역할을합니다 ( initdealloc메서드를 건너 뛰어야 함 ).
BergQuester 2013

1
질문은 언제 명시 적으로 합성해야 하는가였습니다. 당신은 그것에 대해 전혀 대답하지 않았습니다.
Fogmeister 2013

1
나는이 아니라는 것을 오늘 발견 매우 사실. @synthesize가 없으면 지원 인스턴스 변수를 만들어야합니다. 그것으로 컴파일러는 당신을 위해 그것을 할 것입니다.
Steven Fisher

1
그리고 저는이 발견에 대해 누구에게도 반대표를 던지지 않았습니다. :)
Steven Fisher

1
-1 명시 적 합성이 필요한 경우가 완전히 누락되었습니다. 또한 이것은 Xcode가 아닌 컴파일러 기능입니다.
Gabriele Petronella 2013

14

언제 @synthesize코드 에 명시 적으로 추가해야 합니까?

일반적으로 필요한 경우 : 필요한 경우에는 결코 맞지 않을 것입니다.

그래도 유용하다고 생각되는 경우가 하나 있습니다.

커스텀 getter와 setter를 모두 작성하고 있지만 인스턴스 변수가이를 지원하고 싶다고 가정 해 보겠습니다. (원자 속성의 경우 이는 사용자 지정 setter를 원하는 것만 큼 간단합니다. 단원 속성에 대해 setter를 지정하면 컴파일러가 getter를 작성하지만 원자 속성은 지정하지 않습니다.)

이걸 고려하세요:

@interface MyObject:NSObject
@property (copy) NSString *title;
@end

@implementation MyObject

- (NSString *)title {
    return _title;
}
- (void)setTitle:(NSString *)title {
    _title = [title copy];
}

@end

_title존재하지 않기 때문에 작동하지 않습니다. getter 또는 setter를 모두 지정 했으므로 Xcode는 (올바르게) 이에 대한 백업 인스턴스 변수를 생성하지 않습니다.

여기에 이미지 설명 입력

존재하도록하기위한 두 가지 선택이 있습니다. 다음 중 하나로 변경할 수 있습니다 @implementation.

@implementation MyObject {
    NSString *_title;
}

- (NSString *)title {
    return _title;
}
- (void)setTitle:(NSString *)title {
    _title = [title copy];
}

@end

또는 다음과 같이 변경하십시오.

@implementation MyObject

@synthesize title = _title;

- (NSString *)title {
    return _title;
}
- (void)setTitle:(NSString *)title {
    _title = [title copy];
}

@end

즉, 합성이 실제 목적을위한 것은 절대 필요하지 않지만 *, getter / setter를 제공 할 때 속성 지원 인스턴스 변수 를 정의하는 데 사용할 수 있습니다 . 여기에서 사용할 양식을 결정할 수 있습니다.

과거에는에서 인스턴스 변수를 지정하는 것을 선호 @implementation {}했지만 이제는 @synthesize중복 유형을 제거하고 백업 변수를 속성에 명시 적으로 연결하므로 경로가 더 나은 선택 이라고 생각 합니다.

  1. 속성의 유형을 변경하면 인스턴스 변수의 유형이 변경됩니다.
  2. 저장소 한정자를 변경하면 (예 : 강함 대신 약하게 또는 약함 대신 강하게) 저장소 한정자가 변경됩니다.
  3. 속성을 제거하거나 이름을 바꾸면 @synthesize컴파일러 오류가 생성됩니다. 길잃은 인스턴스 변수로 끝나지 않을 것입니다.

*-여러 파일의 범주간에 기능을 분할하는 것과 관련하여 필요한 경우 한 가지를 알고 있습니다. 그리고 애플이 이것을 고치거나 이미 수정했다고해도 놀라지 않을 것입니다.


확실해? 시도해 봤어? 나는 많은 사용자 정의 세터와 게터를 작성했으며 내 속성을 합성하지 않았습니다. (그리고 나는 작동하지 않는다고 말한 첫 번째 예를 사용했습니다.)
Marc

네, 확실합니다. 새 프로젝트에서 코드를 복사하여 붙여 넣었습니다. 속성에 nonatomic을 지정 하지 않는 한 최신 버전의 Xcode에서는 작동하지 않습니다 .
Steven Fisher

1
네, 사실입니다.하지만 99 %의 시간 동안 귀하의 속성은 비원 자적입니다. 따라서 속성이 원자적이고 실제로 합성해야하는 사용자 지정 getter / setter를 원하는 경우에만 드문 경우입니다.
Marc

setter와 getter 모두에 대한 사용자 정의 구현을 제공 하면 컴파일러는 사용자가 속성을 제어하고 있다고 가정하고이를 합성하지 않습니다.
Gabriele Petronella 2013

2
나는 애플이 처음에 그것이 좋은 생각이라고 생각한 이유를 이해할 수 있지만 거기에 동의합니다. 진짜 고통은 atomic나중에까지 속성 지정자로 추가되지 않았다는 것입니다. 이제 거기에 있으므로 경고 플래그가 CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES흥미 롭다 는 것을 알 수 있습니다 .
Steven Fisher

7

좋아요, 속성을 만들 때 ...

@property NSString *name;

Xcode는 당신이 쓴 것처럼 iVar를 자동 합성합니다.

@synthesize name = _name;

이것은 당신이 재산에 접근 할 수 있음을 의미합니다 ...

self.name;
// or
_name;

둘 다 작동하지만 self.name실제로는 접근 자 메서드 만 사용합니다.

자동 합성이 작동하지 않는 경우 는 한 번뿐입니다. 덮어 쓰고 setter 및 getter 메서드를 사용하면 iVar를 합성해야합니다.

setter 만 무시하거나 getter 만 무시해도 괜찮습니다. 그러나 두 가지를 모두 수행하면 컴파일러가이를 이해하지 못하므로 수동으로 합성해야합니다.

그래도 경험상.

iVars를 만들지 마십시오. 속성을 사용하십시오. 그것을 종합하지 마십시오.


1
자가 합성이 수행되지 않는 더 많은 경우가 있습니다. 내 대답을 확인하십시오.
Gabriele Petronella 2013

@GabrielePetronella 일반 독자를 위해 이러한 사례를 간결하게 나열 할 수 있습니까?
Dan Rosenstark

@DanRosenstark 이것은 지금 프로그래밍하는 모든 사람과 관련이 없습니다. 정말 Swift를 사용해야합니다. 그리고 TBH 저는 전체 합성 작업이 더 이상 ObjC에있는 것이 아니라고 생각합니다. 5 년 이상 된 코드베이스에서 작업하지 않는 한.
Fogmeister

@Fogmeister 예, 답변에서 언급 한 경우에는 여전히 문제가 있습니다 (세터와 게터 모두 재정의). 그리고 Objective-C가 "지금 프로그래밍하는 모든 사람과 관련이 없다"는 것에 관해서는 제 직장에 전화하여 그들에게 알려주십시오. 또한 내부적으로 Objective-C를 사용하고있는 Facebook, Google 및 Apple에게도 큰 영향을 미칩니다.
Dan Rosenstark

나는 이것이 Quora 없이는 사실이라고 확신하지만 어쨌든 : quora.com/…
Dan Rosenstark

1

프로토콜에서 속성을 선언 할 때 속성 합성이 필요합니다. 구현 인터페이스에서 자동으로 합성되지 않습니다.


사실이지만 한 가지 경우 일뿐입니다. 더 자세히 설명하고 싶을 수도 있습니다.
Gabriele Petronella 2013

@GabrielePetronella이 늦은 시간에 내가 생각할 수있는 유일한 사람입니다. =]
Leo Natan 2013

0

명확히 해주셔서 감사합니다. 비슷한 문제가있었습니다.

@synthesize firstAsset, secondAsset, audioAsset;
@synthesize activityView;

그래서 이제 그것들을 주석 처리 한 후, 나는 각 사건을 예를 들어

self.firstAsset firstAsset도 사용할 수있는 것 같지만 " "이 (가) 너무 자주 표시되지 않습니다.


-1

Xcode는 명시적인 @synthesize선언이 필요하지 않습니다 .

@synthesize다음과 같이 작성하지 않으면 다음 을 수행하십시오.

@synthesize manager = _manager;

샘플 코드가 오래되었을 수 있습니다. 곧 업데이트됩니다.

다음과 같은 속성에 액세스 할 수 있습니다.

[self.manager function];

이것은 Apple에서 권장하는 규칙입니다. 나는 그것을 따르고 당신도 그렇게 할 것을 권장합니다!


2
[_manager function]은 속성에 액세스하지 않고 대신 기본 ivar에 직접 액세스합니다 .
CouchDeveloper 2013

@CouchDeveloper 당신이 nitpicking을한다면 정확해야합니다. 속성은 ivar를 포함하여 몇 가지로 구성됩니다. 따라서 속성의 접근 자를 사용[_manager function] 하지 않는다고 말하는 것이 좋습니다 .
Nikolai Ruhe 2013

@CouchDeveloper-감사합니다! 고쳤다! :)
Sam Fischer

1
@NikolaiRuhe 당신이 맞아요 Nikolai, 내가 더 정확해야 했어. ;)
CouchDeveloper 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.