2017-03-19 34 views
8

Poniżej znajduje się fragment kodu, który zajmuje się rozszerzeniami klas. Co próbuję zrobić, to wygenerować losowy identyfikator o nazwie internal ID (który jest używany później przez program), który jest przechowywany w postaci zaszyfrowanej w pamięci. Kod nie kompiluje się z gcc i clang (korzystam z Objective C przez GNUStep na Windows) z różnymi komunikatami o błędach dla każdego kompilatora, który jest wymieniony jako komentarz w kodzie.Problem z rozszerzeniami w Objective-C

Należy pamiętać, że zdaję sobie sprawę z tego, że problem ten można łatwo rozwiązać, pomijając użycie rozszerzeń i deklarując metody i właściwości w głównym interfejsie @ (to znaczy po instrukcji #import). Jedynym powodem, dla którego używam rozszerzeń, jest to, że ta klasa jest dziedziczona przez kilka innych podklas, do których właściwość "internalID" musi być niedostępna.

#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; 
} 

Ciąg kompilacja dla gcc używam jest gcc -o _exec fwdORM.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString

My GNUmakefile dla brzękiem jest następujący:

# 
# 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 

Z góry dzięki.

+0

Nie mogę odtworzyć błędu w systemie clang/Mac OS. Jednak, aby osiągnąć swój cel, lepiej jest zdefiniować ivar w '@ implementacji'. –

+0

@ AminNegm-Awad Hej, czy możesz nieco bardziej szczegółowo opisać zalecany sposób rozwiązania problemu? Ponieważ zgodnie z tym, co wiem, wszystkie znaki muszą być umieszczone w "interfejsie". A kiedy mówisz, że nie masz błędu w klang/Mac OS, czy zaimplementowałeś ten sam GNUmakefile? Nie wydaje mi się, żeby kod mógł się skompilować w systemie Mac OS i nie powiedzie się w GNUStep/Windows. Przepraszamy za spóźnioną odpowiedź. Byłem pochłonięty kolejną częścią projektu :) – hecate

+0

Nie, zrobiłem to bez makefile. Nie jest prawdą, że ivars należy zdefiniować w sekcji '@ interface'. Możesz zrobić to samo w "@ implementacji". –

Odpowiedz

4

Spróbuj realizacji tego za pomocą @property zadeklarowanej w rozszerzeniu klasy zamiast na ivar:

#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 

Jest to standardowe semantyki dla co skutecznie zmienna private i prawdopodobnie oznacza większą szansę na uzyskanie wsparcia kompilatora.