2017-03-19 5 views
8

Das folgende ist ein Code-Snippet, das Klassenerweiterungen behandelt. Was ich versuche zu tun, ist eine zufällige ID namens interne ID (die später vom Programm verwendet wird), die in einer verschlüsselten Form im Speicher gespeichert wird. Der Code kann sowohl mit gcc als auch mit clam (ich führe Objective C über GNUStep unter Windows) mit verschiedenen Fehlermeldungen für jeden Compiler, der als Kommentar im Code erwähnt wird, nicht kompilieren.Problem mit Erweiterungen in Objective-C

Bitte beachten Sie, dass mir bewusst ist, dass dieses Problem leicht gelöst werden kann, indem die Verwendung von Erweiterungen ignoriert und Methoden und Eigenschaften in der Hauptschnittstelle (d. H. Nach der Anweisung #import) deklariert werden. Der einzige Grund, warum ich mit Erweiterungen gehe, ist, dass diese Klasse von einigen anderen Unterklassen geerbt wird, auf die die Eigenschaft "internalID" nicht zugreifen darf.

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

Die Compilation-String für gcc Ich verwende gcc -o _exec fwdORM.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString

Mein GNUmakefile für Klirren ist wie folgt:

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

Vielen Dank im Voraus.

+0

Ich kann den Fehler nicht mit clang/Mac OS reproduzieren. Um jedoch Ihr Ziel zu erreichen, ist es besser, den ivar bei '@ implementation' zu definieren. –

+0

@ AminNegm-Awad Hey, kannst du etwas genauer auf deine empfohlene Lösung eingehen? Denn nach dem, was ich weiß, müssen alle Ivars in der @interface platziert werden. Und wenn Sie sagen, Sie haben keinen Fehler im Zusammenhang mit clam/Mac OS, haben Sie das gleiche GNUmakefile implementiert? Ich denke nicht, dass der Code in Mac OS kompiliert werden kann und in GNUStep/Windows fehlschlägt. Entschuldigung für die späte Antwort. Ich war ziemlich in einen anderen Teil des Projekts vertieft :) – hecate

+0

Nein, ich habe es ohne Makefile gemacht. Es ist nicht wahr, dass Ivars in einer '@ interface'-Sektion definiert werden müssen. Sie können dasselbe bei '@ implementation' tun. –

Antwort

4

Versuchen Sie, diese Umsetzung durch einen @property anstelle eines Ivar in der Klassenerweiterung erklärt werden:

#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 

Dies ist Standard-Semantik für das, was effektiv eine private Variable, und wahrscheinlich steht eine bessere Chance, Compiler-Unterstützung zu bekommen.

Verwandte Themen