Objective-C에서 상수를 만드는 가장 좋은 방법은 무엇입니까


156

학습 목적으로 Reddit 클라이언트를 만들고 있습니다. 상수가있는 파일이 필요합니다. Reddit-Prefix.pch모든 파일에서 상수를 사용할 수 있도록 파일에서 파일을 가져 오는 것에 대해 생각하고있었습니다 . 좋은 일입니까? 또한 연구를 수행하고 상수를 만드는 몇 가지 방법을 찾았지만 사용할 방법을 모르겠습니다.

  • #define 매크로
  • const
  • static const
  • extern const
  • enum

어떤 방법이 선호 되는가? 컨벤션이란 무엇입니까? 나는 "그것이 달려있다"는 것을 알고 있지만 내 질문은 더 구체적으로 다음과 같습니다. 각 솔루션의 사용 사례는 무엇입니까?

또한를 사용하는 경우 extern const파일을 가져와야합니까, 아니면 파일을 가져 오지 않고 전역에서 상수를 사용할 수 있습니까?

논리적으로 결론을 내릴 수있는 한 가지는 enum사용자 정의 오류 도메인과 같은 것을 정의 할 때 최선의 선택 이라는 것 입니다 (실제로 맞습니까?). 그러나 다른 사람들은 어떻습니까?


stackoverflow.com/questions/11153156/… 이 링크를 방문하십시오 ... 솔루션이이 게시물에 있습니다
사용자 1531343

3
@BhavikKama : 그것은 두 가지 특정 솔루션을 대조하는 더 좁은 질문입니다.
Peter Hosey 2016 년

용 - const 정적, #DEFINE, 열거,이 링크는 유용합니다 stackoverflow.com/questions/1674032/static-const-vs-define-in-c 형 구조 그 3 대안에 좋은 설명을 제공합니다
사용자 1,531,343

enum적분 값에만 유용합니다. #define상수는 모든 데이터 유형이 될 수 있습니다.
rmaddy 2016 년

const, static const, 및 extern const모든 범위를 제외하고 동일합니다. 따라서 실제로 세 가지 선택 만 있습니다.
rmaddy 2016 년

답변:


385

첫 번째 질문은 상수가 원하는 범위이며 실제로 두 가지 질문입니다.

  • 이 상수는 단일 클래스에만 적용됩니까, 아니면 응용 프로그램 전체에 적용하는 것이 합리적입니까?
  • 그들이 수업에 특화된 경우, 수업의 클라이언트 또는 수업 내에서만 사용할 수 있습니까?

그것들이 단일 클래스에 대해 구체적이고 내부적이라면 static const, .m 파일의 맨 위에 다음과 같이 선언 하십시오.

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

이들이 단일 클래스와 관련이 있지만 다른 클래스에서 공개 / 사용해야하는 extern경우 헤더에서와 같이 선언하고 .m에서 정의하십시오.

//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

전역 적이어야하는 경우 헤더로 선언하고 해당 상수에 대해 해당 모듈에서 정의하십시오.

서로 다른 상수에 대해 원하는 전역 수준과 서로 합치 지 않는 다른 전역 상수에 대해 이들을 혼합하고 일치시킬 수 있습니다. 별도의 모듈에 각각 고유 한 헤더가있는 별도의 모듈에 넣을 수 있습니다 필요.

왜 안돼 #define?

오래된 대답은 "매크로는 타입 정보를 가지고 있지 않다"고하지만 오늘날 컴파일러는 변수뿐만 아니라 리터럴 (매크로가 확장되는 것)에 대한 모든 타입 검사를 수행하는 것이 현명합니다.

현대의 대답은 디버거가 매크로에 대해 알지 못하기 때문입니다. 매크로 인 [myThing addObserver:self forKey:MyThingNotificationKey]경우 디버거 명령에서 말할 수 없습니다 MyThingNotificationKey. 디버거는 변수 인 경우에만 알 수 있습니다.

왜 안돼 enum?

글쎄, rmaddy는 주석에서 나를 이겼습니다 : enum정수 상수 만 정의 할 수 있습니다. 일련 식별자 번호, 비트 마스크, 4 바이트 코드 등

그러한 목적을 위해서는 enum위대하고 절대적으로 사용해야합니다. (더 나은 사용 매크로를 .) 다른 것들 들어 있어야 다른 것을 사용한다; 정수 외에는 아무것도하지 않습니다.NS_ENUMNS_OPTIONSenum

그리고 다른 질문들

Reddit-Prefix.pch 파일에서 파일을 가져 와서 모든 파일에서 상수를 사용할 수 있도록 생각하고있었습니다. 좋은 일입니까?

아마 무해하지만 아마도 과도합니다. 상수 헤더를 필요한 곳에 가져옵니다.

각 솔루션의 사용 사례는 무엇입니까?

  • #define: 꽤 제한적입니다. 솔직히 더 이상 상수에 이것을 사용해야하는 이유가 확실하지 않습니다.
  • const: 지역 상수에 가장 적합합니다. 또한 헤더에 선언하고 정의하고있는 것에 대해서도 이것을 사용해야합니다.
  • static const: 파일 별 (또는 클래스 별) 상수에 가장 적합합니다.
  • extern const: 헤더에서 상수를 내보낼 때 이것을 사용해야합니다.

또한를 사용하는 경우 extern const파일을 가져와야합니까, 아니면 파일을 가져 오지 않고 전역에서 상수를 사용할 수 있습니까?

파일을 사용하는 각 파일 또는 접두사 헤더에서 파일을 가져와야합니다.


3
왜 사용하지 static NSString *const에서 .h모두 파일?
Iulian Onofrei 1

3
@IulianOnofrei : 프레임 워크가 아닌 응용 프로그램에 있다면 가능합니다. 그렇게하면 static NSString *const foo = @"foo";헤더가 문자열이 무엇인지 결정하고 문자열이 어느 곳에서나 동일해야합니다. 문자열을 변경하고 다른 당사자가 다른 버전의 헤더를 다른 문자열로 사용하는 경우 실행시 문자열이 일치하지 않습니다 시각. 프레임 워크에서는 심볼에 대한 액세스 만 제공하고 프레임 워크가 해당 심볼의 진정한 가치를 제공하는 유일한 소스가되게하여 모든 사람이 한 곳에서 동일한 문자열을 얻도록합니다. 그것이 extern당신을 얻는 것입니다.
Peter Hosey

에 대한 추가 참고 사항 #define: 메모리에 동일한 주소가 있다고 보장되지는 않습니다 (선언 방법에 따라 매번 새 인스턴스를 할당 할 수 있음) myObject == MyDefine. 그러나 myObject == MyStaticConst것입니다.
Ben Leggiero

?? static NSString *const대신 철자에 의미가 있습니까 static NSString const*? 어떤 차이가 있습니까?!
kokos8998

@ kokos8998 차이가 있습니까? 그렇습니다. "상수 NSString에 대한 (변경 가능) 포인터"와 static NSString const *동일 static const NSString *하고 의미-NSString이 이미 변경 불가능하므로 여기에서는 약간 쓸모가 없습니다. 당신이 오직 원하는 것은 static NSString * const-는 "있는 NSString 상수 포인터"인
데이비드

8

FOUNDATION_EXPORT

기본적 으로 정의되어 있고 C, C ++ 및 Win32에 대해 호환 가능한 형식으로 컴파일되므로 FOUNDATION_EXPORT약간 더 호환성을 고려하십시오 extern.

NSObjCRuntime.h에 정의 된대로

#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif

#if TARGET_OS_WIN32

    #if defined(NSBUILDINGFOUNDATION)
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
    #else
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
    #endif

    #define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)

#else
    #define FOUNDATION_EXPORT  FOUNDATION_EXTERN
    #define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.