ObjectiveC에서 변수 위치의 선언 / 정의?
iOS 앱과 객관적인 C 작업을 선언하고 정의 할 수있는 다른 위치에 당황했습니다. 한편으로는 한편으로는 C 접근 방식이 있고 다른 한편으로는 OO를 추가하는 방법으로는 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에서 스타일의 개념을 전혀 이해하지 못합니다. 정적 변수 기반 싱글 톤을 구현하는 데 사용됩니다. 내가 놓친 다른 용도가 있습니까?
- iOS로 작업하면서 내가 가져간 것입니다. @synthesize 지시어 밖에서 완전히 단계적으로 제거됩니다. 그 경우입니까?
- 5와 관련하여 왜 개인 인터페이스에서 메소드를 선언하고 싶습니까? 내 개인 클래스 메소드는 인터페이스에 선언하지 않고 제대로 수행되는 것입니다. 대부분 가독성을위한 것입니까?
고마워요, 여러분!
당신의 임의를 있습니다. 특히 최근 Xcode 및 새로운 LLVM 컴파일러 업데이트로 인해 ivar 및 속성을 선언 할 수있는 방식이 변경되었습니다.
"현대"Objective-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;
Xcode 4.4부터 인스턴스 변수를 더 이상 선언 할 필요가 있지만 건너 뛸 수 @synthesize
있습니다. ivar 생성을 선언하지 컴파일러에서이를 추가하고 사용하지 않습니다 @synthesize
.
자동 생성 된 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;
readwrite
ivar에 직접 액세스 할 수있는 옵션 구문을 사용하여이를 접근 가능 구현 파일에 다시 선언하십시오 .
변수 @interface
또는 @implementation
블록 외부에서 변수를 완전히 선언 하는 경우 일반 C 변수는 정확히 동일하게 작동합니다.
@DrummerB의 먼저 먼저 먼저. 그 이유와 일반적으로해야 할 일에 대한 좋은 개요입니다. 이를 염두에두고 구체적인 질문에 :
#import <Foundation/Foundation.h>
// 1) What do I declare here?
실제 변수 정의는 여기에 없습니다 (실제로 수행중인 작업을 알고 절대 그렇게하지 않는 경우에 합법적입니다). 몇 가지 다른 종류를 정의 할 수 있습니다.
- typdefs
- 열거 형
- 외계인
Extern은 변수 선언처럼 보이지만 실제로 다른 곳에서 선언 할 것을 약속합니다. ObjC에서는 상수를 선언하는 데에만 사용됩니다. 예를 들어 :
extern NSString * const MYSomethingHappenedNotification;
그런 다음 .m
파일에서 실제 상수를 선언합니다.
NSString * const MYSomethingHappenedNotification = @"MYSomethingHappenedNotification";
@interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
Drummer 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)이 변수를 생성하도록 허용해야합니다. 일반적으로 ObjC 이외의 ivar (예 : Core Foundation 객체, 특히 C ++ 클래스 인 경우 ObjC ++ 클래스 인 경우) 또는 이상한 저장 의미가있는 ivar (일부 속성과 일치하지 않는 ivar 등)은 예외입니다.
// 7) define methods and synthesize properties from both public and private
// interfaces
일반적으로 더 이상 @synthesize. Clang (Xcode)이 대신 해줄 것입니다.
지난 몇 년 동안 상황이 크게 단순 해졌다. 부작용은 세 가지 다른 시대 (Fragile ABI, Non-Fragile ABI, Non-fragile ABI + auto-syntheisze)가 될 것입니다. 따라서 이전 코드를 볼 때 혼란 스러울 수 있습니다. 따라서 단순성으로 인한 혼란 : D
나는 또한 아주 새롭기 때문에 나는 아무것도 망치지 않기 때문에 바랍니다.
1 & 4 : C 스타일 전역 변수 : 파일 범위가 넓습니다. 이 둘의 차이점은 파일 범위가 넓기 때문에 첫 번째는 헤더를 가져 오는 사람은 사용할 수 있습니다.
2 : 인스턴스 변수. 대부분의 인스턴스 변수는 속성을 사용하여 접근 해 통해 합성 및 검색 / 설정됩니다. 메모리 관리를 훌륭하고 간단하게 만들뿐 아니라 이해하기 쉬운 점 표기법을 제공하기 때문입니다.
6 : 구현 ivar는 다소 새로운 것입니다. 공개 헤더에 필요한 것만 노출하고 싶지만 하위 클래스는 AFAIK를 상속하지 않기 때문에 비공개 ivar를 배치하는 것이 좋습니다.
3 & 7 : 공용 메서드 및 속성 선언 후 구현.
5 : 개인 인터페이스. 나는 물건을 깨끗하게 유지하고 일종의 블랙 박스 효과를 만들기 위해 항상 비공개 인터페이스를 사용합니다. 그들이 그것에 대해 알 필요가 없다면 거기에 넣으십시오. 나는 또한 가독성을 위해 그것을합니다. 다른 이유가 있는지 모르겠습니다.
이것은 Objective-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
하위 클래스 전용 인 백업 ivar에 액세스 할 수있었습니다 . Objective-C에서는 모든 변수를 읽거나 설정할 수 있으며,으로 표시된 변수 @private
도 예외없이 읽을 수 있습니다 .
나는 서로 다른 새이기 때문에 관련 객체 또는 C 변수를 포함하지 않았습니다. C 변수의 경우 외부에서 정의 된 모든 변수 @interface X{}
또는 @implementation X{}
파일 범위 및 정적 저장소가있는 C 변수입니다.
메모리 관리 속성, 읽기 전용 / 읽기 쓰기, getter / setter 속성에 대해서는 논의하지 않았습니다.
'IT' 카테고리의 다른 글
쉘 프로그래밍에서 "내보내기"는 무엇입니까? (0) | 2020.08.02 |
---|---|
PowerShell 및-포함 연산자 (0) | 2020.08.02 |
패키지 서브 디렉토리의 Python Access 데이터 (0) | 2020.08.02 |
Postgres의 테이블에 여러 열을 추가하는 방법은 무엇입니까? (0) | 2020.08.02 |
C #에서 Python 확장을 어떻게 실행 확장? (0) | 2020.08.02 |