2017-03-19 1 views
8

다음은 클래스 확장을 다루는 코드 조각입니다. 내가 뭘하려는 건 메모리에 암호화 된 형식으로 저장되어있는 내부 ID (나중에 프로그램에서 사용하는)라는 임의의 ID를 생성하는 것입니다. 이 코드는 gcc와 clang (Windows의 GNUStep을 통해 Objective C를 실행 중입니다)에서 코드의 주석으로 언급 된 각 컴파일러에 대해 다른 오류 메시지와 함께 컴파일되지 않습니다.Objective-C의 확장 기능과 관련된 문제

이 문제는 확장 프로그램 사용을 무시하고 기본 @interface (즉 # import 문 다음에 나오는 자체)에서 메소드와 속성을 선언함으로써 쉽게 해결할 수 있다는 사실을 알고 있습니다. 확장 기능을 사용하는 유일한 이유는이 클래스가 "internalID"속성에 액세스 할 수 없어야하는 몇 가지 하위 클래스에 상속된다는 것입니다. 사전에

# 
# Command script for clang 
# C:\GNUstep\msys\1.0\home\hecate\my\GNUmakefile 
# 

GNUSTEP_MAKEFILES=/GNUStep/System/Library/Makefiles 

include $(GNUSTEP_MAKEFILES)/common.make 

TOOL_NAME = fwdORM 

fwdORM_OBJC_FILES = fwdORM.m 
fwdORM_OBJCFLAGS = -std=c99 

# Implementation mixing Objective-C/CPP file going to be compiled; Currently not required 
#fwdORM_OBJCC_FILES = fwdORM_21.mm 

# Implementation CPP file going to be compiled; Currently N/A 
#fwdORM_CC_FILES = sec_class_exec.cpp 

# Header files of project 
#fwdORM_HEADER_FILES = .h // N/A 

# Define compilation flags 
ADDITIONAL_CPPFLAGS = -Wall -Wno-import -fblocks 

# Include rules for creating a command line tool for Objective-C 
include $(GNUSTEP_MAKEFILES)/tool.make 

감사 :

#import <Foundation/Foundation.h> 

@interface Foo : NSObject 
{ 
    NSString * idStr; 
} 
- (void)setInternalID; 
- (NSString *)fetchExternalID; 
@end 

// Extension declaration 
@interface Foo() 
{ // Compilation via gcc throws error at this line stating "Expected identifier or '(' before '{' token" 
    NSString *internalID; // Compilation via clang throws error at this line stating "instance variables may not be placed in class extension" 
} 
@end 

@implementation Foo 
- (void)setInternalID{ 
    internalID = [NSString stringWithFormat: 
    @"__KEY__INTERNAL__DUMP2872167841398551___8765%d98KLPYFGF(&^$#ESFK___JNHGV",arc4random()%100]; 
} 
- (NSString *)fetchExternalID{ 
    NSString * externalID=[internalID stringByReplacingOccurrencesOfString: 
    @"__KEY__INTERNAL__DUMP2872167841398551___8765" withString:@""]; 
    externalID=[externalID stringByReplacingOccurrencesOfString: 
    @"98KLPYFGF(&^$#ESFK___JNHGV" withString:@""]; 
    return externalID; 
} 
@end 

int main(int argc, const char * argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    Foo * bar = [[Foo alloc]init]; 
    [bar setInternalID]; 
    NSLog(@"External ID: %@",[bar fetchExternalID]);   
    [pool drain]; 
    return 0; 
} 

내가 사용 GCC의 컴파일 문자열은 그 소리에 대해 다음과 같습니다 gcc -o _exec fwdORM.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString

내 GNUmakefile '은 찾지입니다. 대신 바르의 클래스 확장에서 선언 된 @property를 사용하여이를 구현

+0

clang/Mac OS에서 오류를 재현 할 수 없습니다. 그러나 목표에 도달하려면'@ 구현 '에서 ivar을 정의하는 것이 좋습니다. –

+0

@ AminNegm-Awad 이봐, 해결 방법을 좀 더 구체적으로 알려주시겠습니까? 왜냐하면 내가 아는 바에 따르면 모든 ivars는 '@interface'에 있어야하기 때문입니다. 그리고 clang/Mac OS에서 오류가 없다고 말하면 동일한 GNUmakefile을 구현 했습니까? 나는 코드가 Mac OS에서 컴파일되고 GNUStep/Windows에서 실패 할 수 있다고 생각하지 않는다. 늦게 답장을 보내 드려 죄송합니다. 나는 프로젝트의 다른 부분에 꽤 몰두했다. – hecate

+0

아니, 나는 makefile없이 그것을했다. ivars가'@interface' 섹션에 정의되어야한다는 것은 사실이 아닙니다. '@ 구현'에서 똑같은 일을 할 수 있습니다. –

답변

4

봅니다 :

#import <Foundation/Foundation.h> 

@interface Foo : NSObject 
- (void)setInternalID; 
- (NSString *)fetchExternalID; 
@end 

// Extension declaration 
@interface Foo() 
@property (strong) NSString *internalID; 
@end 

@implementation Foo 

- (void)setInternalID { 
    self.internalID = [NSString stringWithFormat:@"__KEY__INTERNAL__DUMP2872167841398551___8765%d98KLPYFGF(&^$#ESFK___JNHGV",arc4random()%100]; 
} 

- (NSString *)fetchExternalID { 
    NSString * externalID = [self.internalID stringByReplacingOccurrencesOfString:@"__KEY__INTERNAL__DUMP2872167841398551___8765" withString:@""]; 
    externalID = [externalID stringByReplacingOccurrencesOfString:@"98KLPYFGF(&^$#ESFK___JNHGV" withString:@""]; 
    return externalID; 
} 

@end 

이 효과적으로 private 변수, 그리고 아마도 컴파일러 지원을 얻기의 더 나은 기회가 무엇의 약자인지에 대한 표준 의미입니다.

관련 문제