IT

ObjectiveC에서 변수 위치의 선언 / 정의?

lottoking 2020. 8. 2. 17:13
반응형

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;

readwriteivar에 직접 액세스 할 수있는 옵션 구문을 사용하여이를 접근 가능 구현 파일에 다시 선언하십시오 .

변수 @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 속성에 대해서는 논의하지 않았습니다.

참고 URL : https://stackoverflow.com/questions/12632285/declaration-definition-of-variables-locations-in-objectivec

반응형