Objective-C의 읽기 전용 속성?
내 인터페이스에서 다음과 같이 읽기 전용 속성을 선언했습니다.
@property (readonly, nonatomic, copy) NSString* eventDomain;
속성을 오해하고 있을지 모르지만으로 선언 readonly
하면 구현 ( .m
) 파일 내에서 생성 된 setter를 사용할 수 있지만 외부 엔터티는 값을 변경할 수 없다고 생각했습니다. 이 SO 질문 은 그것이 일어나야한다고 말합니다. 그것이 내가 추구하는 행동입니다. 그러나 표준 setter 또는 도트 구문을 사용하여 eventDomain
init 메서드 내부 를 설정 하려고하면 unrecognized selector sent to instance.
오류가 발생합니다. 물론 나는 @synthesize
재산을 소유하고 있습니다. 다음과 같이 사용하려고합니다.
// inside one of my init methods
[self setEventDomain:@"someString"]; // unrecognized selector sent to instance error
그래서 나는 readonly
재산에 대한 선언을 오해하고 있습니까? 아니면 다른 일이 일어나고 있습니까?
세터도 필요하다고 컴파일러에 알려야합니다. 일반적인 방법은 .m 파일 의 클래스 확장자 에 넣는 것입니다 .
@interface YourClass ()
@property (nonatomic, copy) NSString* eventDomain;
@end
읽기 전용 속성으로 작업하는 또 다른 방법은 @synthesize를 사용하여 백업 저장소를 지정하는 것입니다. 예를 들면
@interface MyClass
@property (readonly) int whatever;
@end
그런 다음 구현에서
@implementation MyClass
@synthesize whatever = _whatever;
@end
그러면 멤버 변수이기 때문에 메서드에서 _whatever를 설정할 수 있습니다.
지난 며칠 동안 제가 깨달은 또 다른 흥미로운 점은 다음과 같은 하위 클래스에서 쓰기 가능한 읽기 전용 속성을 만들 수 있다는 것입니다.
(헤더 파일에서)
@interface MyClass
{
@protected
int _propertyBackingStore;
}
@property (readonly) int myProperty;
@end
그런 다음 구현에서
@synthesize myProperty = _propertyBackingStore;
헤더 파일의 선언을 사용하므로 하위 클래스는 읽기 전용을 유지하면서 속성 값을 업데이트 할 수 있습니다.
데이터 숨김 및 캡슐화 측면에서 약간 유감스럽게도.
에이코와 다른 사람들이 정답을주었습니다.
더 간단한 방법은 다음과 같습니다 . 전용 멤버 변수에 직접 액세스합니다.
예
헤더 .h 파일에서 :
@property (strong, nonatomic, readonly) NSString* foo;
구현 .m 파일에서 :
// inside one of my init methods
self->_foo = @"someString"; // Notice the underscore prefix of var name.
그게 전부입니다. 소란스럽지 않고 소란스럽지 않습니다.
세부
Xcode 4.4 및 LLVM 컴파일러 4.0 ( Xcode 4.4의 새로운 기능)부터는 다른 답변에서 논의 된 집안일을 망칠 필요가 없습니다.
synthesize
키워드- 변수 선언
- 구현 .m 파일에서 속성을 다시 선언합니다.
속성을 선언 한 후 foo
Xcode가 underscore : 접두사로 명명 된 전용 멤버 변수를 추가했다고 가정 할 수 있습니다 _foo
.
If the property was declared readwrite
, Xcode generates a getter method named foo
and a setter named setFoo
. These methods are implicitly called when you use the dot notation (my Object.myMethod). If the property was declared readonly
, no setter is generated. That means the backing variable, named with the underscore, is not itself readonly. The readonly
means simply that no setter method was synthesized, and therefore using the dot notation to set a value fails with a compiler error. The dot notation fails because the compiler stops you from calling a method (the setter) that does not exist.
The simplest way around this is to directly access the member variable, named with the underscore. You can do so even without declaring that underscore-named variable! Xcode is inserting that declaration as part of the build/compile process, so your compiled code will indeed have the variable declaration. But you never see that declaration in your original source code file. Not magic, just syntactic sugar.
Using self->
is a way to access a member variable of the object/instance. You may be able to omit that, and just use the var name. But I prefer using the self+arrow because it makes my code self-documenting. When you see the self->_foo
you know without ambiguity that _foo
is a member variable on this instance.
By the way, discussion of pros and cons of property accessors versus direct ivar access is exactly the kind of thoughtful treatment you'll read in Dr. Matt Neuberg's Programming iOS book. I found it very helpful to read and re-read.
See Customizing Existing Classes in the iOS Docs.
readonly Indicates that the property is read-only. If you specify readonly, only a getter method is required in the @implementation. If you use @synthesize in the implementation block, only the getter method is synthesized. Moreover, if you attempt to assign a value using the dot syntax, you get a compiler error.
Readonly properties only have a getter method. You can still set the backing ivar directly within the property's class or using key value coding.
You are misunderstanding the other question. In that question there is a class extension, declared thus:
@interface MYShapeEditorDocument ()
@property (readwrite, copy) NSArray *shapesInOrderBackToFront;
@end
That is what generates the setter only visible within the class's implementation. So as Eiko says, you need to declare a class extension and override the property declaration to tell the compiler to generate a setter only within the class.
The shortest solution is:
MyClass.h
@interface MyClass {
int myProperty;
}
@property (readonly) int myProperty;
@end
MyClass.h
@implementation MyClass
@synthesize myProperty;
@end
If a property is defined as readonly, that means that there effectively wont be a setter that can be used either internally to the class or externally from other classes. (i.e.: You'll only have a "getter" if that makes sense.)
From the sounds of it, you want a normal read/write property that's marked as private, which you can achieve by setting the class variable as private in your interface file as such:
@private
NSString* eventDomain;
}
참고URL : https://stackoverflow.com/questions/4586516/readonly-properties-in-objective-c
'IT박스' 카테고리의 다른 글
Grunt.js 복사를 사용하여 디렉토리의 모든 파일을 다른 디렉토리로 복사하십시오. (0) | 2020.09.09 |
---|---|
CSS : 오른쪽 하단에 요소를 배치하는 방법은 무엇입니까? (0) | 2020.09.09 |
행 내부의 TextField로 인해 레이아웃 예외 발생 : 크기를 계산할 수 없음 (0) | 2020.09.09 |
레코드가 없을 때 nil과 함께 find () (0) | 2020.09.09 |
레일에서 열 유형을 더 긴 문자열로 변경 (0) | 2020.09.09 |