목표 C에서 변수 위치의 선언/정의?
iOS 앱과 목표 C에서 일하기 시작한 이후로 저는 변수를 선언하고 정의할 수 있는 다른 위치에 대해 정말로 당황했습니다.한편으로는 기존의 C 접근 방식을 사용하고, 다른 한편으로는 OOO를 추가하는 새로운 목표 C 지침을 사용합니다.여러분, 제 변수에 이러한 위치를 사용하고 현재의 이해를 수정하고자 하는 모범 사례와 상황을 이해하는 데 도움을 주실 수 있습니까?
다음은 샘플 클래스(.h 및 .m)입니다.
#import <Foundation/Foundation.h>
// 1) What do I declare here?
@interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
@end
그리고.
#import "SampleClass.h"
// 4) what goes here?
@interface SampleClass()
// 5) private interface, can define private methods and properties here
@end
@implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
@end
- 제가 이해하는 1과 4는 클래스의 개념을 전혀 이해하지 못하는 C 스타일 파일 기반 선언 및 정의이므로 C에서 사용되는 방식을 정확하게 사용해야 한다는 것입니다.정적 변수 기반 싱글톤을 구현하는 데 사용되는 것을 이전에 본 적이 있습니다.제가 놓치고 있는 다른 편리한 용도가 있나요?
- iOS에서 작업한 제 견해는 아이바가 @synthesize 지침 밖에서 완전히 사라졌기 때문에 대부분 무시될 수 있다는 것입니다.그런가요?
- 5와 관련하여: 개인 인터페이스에서 메서드를 선언하려는 이유는 무엇입니까?제 개인 클래스 메소드는 인터페이스에서 선언 없이도 잘 컴파일되는 것 같습니다.그것은 대부분 가독성을 위한 것입니까?
감사합니다, 여러분!
저는 당신의 혼란을 이해할 수 있습니다.특히 최근 Xcode와 새로운 LLVM 컴파일러에 대한 업데이트 이후 ivar와 속성을 선언할 수 있는 방식이 변경되었습니다.
"모던" 오브젝티브-C("오래된" Obj-C 2.0) 이전에는 선택의 폭이 넓지 않았습니다.는 괄호 안에 할 때 됩니다.{ }
:
// MyClass.h
@interface MyClass : NSObject {
int myVar;
}
@end
이러한 변수는 구현에서만 액세스할 수 있고 다른 클래스에서는 액세스할 수 없습니다.그러기 위해서는 다음과 같은 접근자 메소드를 선언해야 했습니다.
// MyClass.h
@interface MyClass : NSObject {
int myVar;
}
- (int)myVar;
- (void)setMyVar:(int)newVar;
@end
// MyClass.m
@implementation MyClass
- (int)myVar {
return myVar;
}
- (void)setMyVar:(int)newVar {
if (newVar != myVar) {
myVar = newVar;
}
}
@end
이렇게 하면 일반적인 대괄호 구문을 사용하여 메시지를 보내는 다른 클래스에서도 이 인스턴스 변수를 가져오고 설정할 수 있습니다(호출 메서드).
// OtherClass.m
int v = [myClass myVar]; // assuming myClass is an object of type MyClass.
[myClass setMyVar:v+1];
하는 것이 귀찮았기 에, 모든접근수을동선실것때에문일귀기이었찮은상히당은,@property
그리고.@synthesize
액세스 방법을 자동으로 생성하기 위해 도입되었습니다.
// MyClass.h
@interface MyClass : NSObject {
int myVar;
}
@property (nonatomic) int myVar;
@end
// MyClass.m
@implementation MyClass
@synthesize myVar;
@end
결과는 훨씬 더 명확하고 짧은 코드입니다.접근자 메소드가 구현되며 이전과 마찬가지로 괄호 구문을 사용할 수 있습니다.그러나 도트 구문을 사용하여 속성에 액세스할 수도 있습니다.
// OtherClass.m
int v = myClass.myVar; // assuming myClass is an object of type MyClass.
myClass.myVar = v+1;
4 Xcode 4.4를 .@synthesize
하고 ivar를 합니다.@synthesize
.
자동으로 생성되는 ivar의 기본 이름은 밑줄로 시작하는 이름 또는 속성입니다.ivar의 은 ivar 의할다 수있변다음습 할 수 .@synthesize myVar = iVarName;
// MyClass.h
@interface MyClass : NSObject
@property (nonatomic) int myVar;
@end
// MyClass.m
@implementation MyClass
@end
이것은 위의 코드와 똑같이 작동합니다.호환성을 위해 헤더에 ivar를 선언할 수 있습니다.그러나 속성을 선언하지 않고 개인 변수를 생성하는 것이 유일한 이유이기 때문에 이제 구현 파일에서도 이러한 작업을 수행할 수 있습니다. 이 방법이 좋습니다.
안 안@interface
구현 파일의 블록은 실제로 확장이며 메서드를 전달하고(더 이상 필요하지 않음) 속성을 (재) 선언하는 데 사용할 수 있습니다.예를 들어 다음과 같이 선언할 수 있습니다.readonly
머리글에 속성이 있습니다.
@property (nonatomic, readonly) myReadOnlyVar;
에서 " 구현파일다같다이시선언합니다음과에선다니합언cl"로 다시 합니다.readwrite
ivar에 구문을 할 수 .
@interface
또는@implementation
블럭, 예, 일반 C 변수이며 정확히 동일하게 작동합니다.
먼저, @DrummerB의 대답을 읽습니다.일반적으로 해야 하는 이유와 방법에 대한 좋은 개요입니다.이 점을 염두에 두고, 구체적인 질문에 대해:
#import <Foundation/Foundation.h>
// 1) What do I declare here?
실제 변수 정의는 여기에 표시되지 않습니다(정확하게 작업 내용을 알고 있지만 절대로 수행하지 않는 경우에는 기술적으로 그렇게 하는 것이 합법적입니다).다음과 같은 몇 가지 다른 유형을 정의할 수 있습니다.
- 활자체.
- 열거하다
- 외제품
외부는 변수 선언처럼 보이지만 실제로 다른 곳에서 선언하겠다는 약속일 뿐입니다.ObjC에서는 상수를 선언하는 데만 사용해야 하며 일반적으로 문자열 상수만 사용해야 합니다.예를 들어:
extern NSString * const MYSomethingHappenedNotification;
그러면 당신은 당신의.m
파일이 실제 상수를 선언합니다.
NSString * const MYSomethingHappenedNotification = @"MYSomethingHappenedNotification";
@interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
드러머 B가 언급한 것처럼, 이것은 유산입니다.여기에 아무것도 넣지 마세요.
// 3) class-specific method / property declarations
@end
네.
#import "SampleClass.h"
// 4) what goes here?
위에서 설명한 바와 같이 외부 상수.파일 정적 변수도 여기에 사용할 수 있습니다.이것들은 다른 언어의 클래스 변수에 해당합니다.
@interface SampleClass()
// 5) private interface, can define private methods and properties here
@end
네.
@implementation SampleClass
{
// 6) define ivars
}
하지만 아주 드물게.거의 항상 변수를 생성하기 위해 clang(Xcode)을 허용해야 합니다.예외는 일반적으로 CoreFoundation 개체, 특히 ObjC++ 클래스인 경우 C++ 개체와 같은 비 ObjCivar 또는 스토리지 의미론이 이상한 ivar(어떤 이유로 속성과 일치하지 않는 ivar)와 관련이 있습니다.
// 7) define methods and synthesize properties from both public and private
// interfaces
일반적으로 더 이상 @synthesis를 사용하면 안 됩니다.클랑(Xcode)이 해줄 것이고, 당신은 그것을 허락해야 합니다.
지난 몇 년 동안, 상황은 극적으로 단순해졌습니다.부작용은 이제 세 가지 다른 시대(파손 ABI, 비파손 ABI, 비파손 ABI + 자동 합성)가 있다는 것입니다.그래서 당신이 오래된 코드를 볼 때, 그것은 조금 혼란스러울 수 있습니다.따라서 단순성에서 발생하는 혼란:d
저는 또한 꽤 새로운 사람이기 때문에, 제가 아무것도 망치지 않기를 바랍니다.
1과 4: C 스타일 글로벌 변수: 파일 범위가 넓습니다.두 가지 차이점은 파일 범위가 넓기 때문에 첫 번째는 헤더를 가져오는 모든 사용자가 사용할 수 있는 반면 두 번째는 그렇지 않다는 것입니다.
2: 인스턴스 변수.대부분의 인스턴스 변수는 속성을 사용하여 액세스 프로그램을 통해 합성 및 검색/설정됩니다. 이는 메모리 관리를 쉽고 간편하게 할 뿐만 아니라 이해하기 쉬운 도트 표기법을 제공하기 때문입니다.
6: 구현 ivar는 다소 새로운 것입니다.여기는 개인 아이바를 놓기에 좋은 장소입니다. 왜냐하면 당신은 공개 헤더에 필요한 것만 노출하기를 원하지만 하위 클래스는 AFAIK를 상속하지 않기 때문입니다.
3 & 7: 공개 방법 및 재산 신고, 그 다음 구현.
5: 전용 인터페이스.저는 항상 개인 인터페이스를 사용하여 청결을 유지하고 일종의 블랙박스 효과를 만듭니다.그들이 그것에 대해 알 필요가 없다면, 그것을 거기에 두세요.저도 가독성 때문에 하는데, 다른 이유가 있는지 모르겠습니다.
이것은 목표-C에서 선언된 모든 종류의 변수의 예입니다.변수 이름은 액세스를 나타냅니다.
파일: Animal.h
@interface Animal : NSObject
{
NSObject *iProtected;
@package
NSObject *iPackage;
@private
NSObject *iPrivate;
@protected
NSObject *iProtected2; // default access. Only visible to subclasses.
@public
NSObject *iPublic;
}
@property (nonatomic,strong) NSObject *iPublic2;
@end
파일: Animal.m
#import "Animal.h"
// Same behaviour for categories (x) than for class extensions ().
@interface Animal(){
@public
NSString *iNotVisible;
}
@property (nonatomic,strong) NSObject *iNotVisible2;
@end
@implementation Animal {
@public
NSString *iNotVisible3;
}
-(id) init {
self = [super init];
if (self){
iProtected = @"iProtected";
iPackage = @"iPackage";
iPrivate = @"iPrivate";
iProtected2 = @"iProtected2";
iPublic = @"iPublic";
_iPublic2 = @"iPublic2";
iNotVisible = @"iNotVisible";
_iNotVisible2 = @"iNotVisible2";
iNotVisible3 = @"iNotVisible3";
}
return self;
}
@end
iNotVisible 변수는 다른 클래스에서 볼 수 없습니다.문제이기 에 는이가문다같음선다이로 합니다.@property
또는@public
그것을 바꾸지 않습니다.
것이 .@property
대신 사용하기self
부작용을 피하기 위해.
변수에 액세스해 보겠습니다.
파일: Cow.h
#import "Animal.h"
@interface Cow : Animal
@end
파일: Cow.m
#import "Cow.h"
#include <objc/runtime.h>
@implementation Cow
-(id)init {
self=[super init];
if (self){
iProtected = @"iProtected";
iPackage = @"iPackage";
//iPrivate = @"iPrivate"; // compiler error: variable is private
iProtected2 = @"iProtected2";
iPublic = @"iPublic";
self.iPublic2 = @"iPublic2"; // using self because the backing ivar is private
//iNotVisible = @"iNotVisible"; // compiler error: undeclared identifier
//_iNotVisible2 = @"iNotVisible2"; // compiler error: undeclared identifier
//iNotVisible3 = @"iNotVisible3"; // compiler error: undeclared identifier
}
return self;
}
@end
런타임을 사용하여 보이지 않는 변수에 액세스할 수 있습니다.
파일: Cow.m (2부)
@implementation Cow(blindAcess)
- (void) setIvar:(NSString*)name value:(id)value {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
object_setIvar(self, ivar, value);
}
- (id) getIvar:(NSString*)name {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
id thing = object_getIvar(self, ivar);
return thing;
}
-(void) blindAccess {
[self setIvar:@"iNotVisible" value:@"iMadeVisible"];
[self setIvar:@"_iNotVisible2" value:@"iMadeVisible2"];
[self setIvar:@"iNotVisible3" value:@"iMadeVisible3"];
NSLog(@"\n%@ \n%@ \n%@",
[self getIvar:@"iNotVisible"],
[self getIvar:@"_iNotVisible2"],
[self getIvar:@"iNotVisible3"]);
}
@end
보이지 않는 변수에 액세스해 보겠습니다.
파일: main.m
#import "Cow.h"
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
@autoreleasepool {
Cow *cow = [Cow new];
[cow performSelector:@selector(blindAccess)];
}
}
인쇄합니다.
iMadeVisible
iMadeVisible2
iMadeVisible3
백업 아이바에 액세스할 수 있었습니다._iNotVisible2
하위 클래스 전용입니다.에서는 변수를 모두 있고 할 수도 있습니다. 심지어는 "-"-"라고도 마찬가지입니다.@private
예외는 없습니다.
연관된 개체나 C 변수는 다른 새이기 때문에 포함하지 않았습니다.는 C 수 경 외 에 모 변 우 정 든 된 수 의 부 의 변 ▁c ▁variable ▁outside ▁defined 변 ▁as 수 ▁any , 든 모 ▁variables@interface X{}
또는@implementation X{}
는 파일 범위와 정적 저장소를 가진 C 변수입니다.
메모리 관리 특성이나 읽기 전용/읽기 쓰기, getter/setter 특성에 대해 논의하지 않았습니다.
언급URL : https://stackoverflow.com/questions/12632285/declaration-definition-of-variables-locations-in-objectivec
'programing' 카테고리의 다른 글
파이썬 프로젝트에는 MANIFEST.in 이 필요하며, 그 안에 무엇이 있어야 합니까? (0) | 2023.07.16 |
---|---|
Oracle: 현재 날짜에 6개월을 추가하는 방법 (0) | 2023.07.16 |
대문자 단어가 시작되는 모든 위치에서 문자열 분할 (0) | 2023.07.16 |
데이터 프레임을 열 값으로 분할한 판다 (0) | 2023.07.16 |
LINQ를 사용하여 Excel 읽기 (0) | 2023.07.16 |