내가 아는 한, 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
코드 에 명시 적으로 추가해야 합니까?
답변
많은 답변이 있지만 큰 혼란도 있습니다. 나는 주문을하려고 노력할 것입니다 (또는 엉망진창을 늘리십시오, 우리는 보게 될 것입니다 …)
-
Xcode에 대한 이야기는 그만합시다. Xcode는 IDE 입니다. clang은 컴파일러 입니다. 우리가 논의하고있는이 기능 은 속성의 자동 합성 이라고 하며 Xcode에서 사용하는 기본 컴파일러 인 clang 에서 지원 하는 Objective-C 언어 확장 입니다.
명확히하기 위해, Xcode에서 gcc로 전환하면이 기능의 이점을 얻지 못할 것입니다 (Xcode 버전에 관계없이). 같은 방식으로 텍스트 편집기를 사용하고 명령 줄에서 clang을 사용하여 컴파일하는 경우 의지. -
자동 합성 기능 덕분에 속성을 명시 적으로 합성 할 필요가 없습니다. 컴파일러에 의해 자동으로 합성되므로
@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 이름을 지정하는 것입니다. 그러나 규칙이 중요하므로 항상 기본 이름을 사용하는 것이 좋습니다.
답변
명시 적으로 사용하지 않으면 @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
을 연결하는 iVar
A를 @property
. 특정 getter 및 setter를 생성하려는 경우. 그러나 주어진 코드에는 아무것도 없습니다. iVar
이것은 @synthesize
쓸모가 없다고 생각합니다 . 하지만 이제는 새로운 질문이 “언제 사용해야 iVar
합니까?” 라고 생각합니다.이 질문에 대해서는 “절대”라는 답변이 없습니다!
답변
언제 @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
중복 유형을 제거하고 백업 변수를 속성에 명시 적으로 연결하므로 경로가 더 나은 선택 이라고 생각 합니다.
- 속성의 유형을 변경하면 인스턴스 변수의 유형이 변경됩니다.
- 저장소 한정자를 변경하면 (예 : 강함 대신 약하게 또는 약함 대신 강하게) 저장소 한정자가 변경됩니다.
- 속성을 제거하거나 이름을 바꾸면
@synthesize
컴파일러 오류가 생성됩니다. 길잃은 인스턴스 변수로 끝나지 않을 것입니다.
*-여러 파일의 범주간에 기능을 분할하는 것과 관련하여 필요한 경우 한 가지를 알고 있습니다. 그리고 애플이 이것을 고치거나 이미 수정했다고해도 놀라지 않을 것입니다.
답변
좋아요, 속성을 만들 때 …
@property NSString *name;
Xcode는 당신이 쓴 것처럼 iVar를 자동 합성합니다.
@synthesize name = _name;
이것은 당신이 재산에 접근 할 수 있음을 의미합니다 …
self.name;
// or
_name;
둘 다 작동하지만 self.name
실제로는 접근 자 메서드 만 사용합니다.
자동 합성이 작동하지 않는 경우 는 한 번뿐입니다. 덮어 쓰고 setter 및 getter 메서드를 사용하면 iVar를 합성해야합니다.
setter 만 무시하거나 getter 만 무시해도 괜찮습니다. 그러나 두 가지를 모두 수행하면 컴파일러가이를 이해하지 못하므로 수동으로 합성해야합니다.
그래도 경험상.
iVars를 만들지 마십시오. 속성을 사용하십시오. 그것을 종합하지 마십시오.
답변
프로토콜에서 속성을 선언 할 때 속성 합성이 필요합니다. 구현 인터페이스에서 자동으로 합성되지 않습니다.
답변
명확히 해주셔서 감사합니다. 비슷한 문제가있었습니다.
@synthesize firstAsset, secondAsset, audioAsset;
@synthesize activityView;
그래서 이제 그것들을 주석 처리 한 후, 나는 각 사건을 예를 들어
self.firstAsset firstAsset도 사용할 수있는 것 같지만 “ “이 (가) 너무 자주 표시되지 않습니다.
답변
Xcode는 명시적인 @synthesize
선언이 필요하지 않습니다 .
@synthesize
다음과 같이 작성하지 않으면 다음 을 수행하십시오.
@synthesize manager = _manager;
샘플 코드가 오래되었을 수 있습니다. 곧 업데이트됩니다.
다음과 같은 속성에 액세스 할 수 있습니다.
[self.manager function];
이것은 Apple에서 권장하는 규칙입니다. 나는 그것을 따르고 당신도 그렇게 할 것을 권장합니다!