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.
Nie mogę odtworzyć błędu w systemie clang/Mac OS. Jednak, aby osiągnąć swój cel, lepiej jest zdefiniować ivar w '@ implementacji'. –
@ 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
Nie, zrobiłem to bez makefile. Nie jest prawdą, że ivars należy zdefiniować w sekcji '@ interface'. Możesz zrobić to samo w "@ implementacji". –