【问题标题】:Issue with extensions in Objective-CObjective-C 中的扩展问题
【发布时间】:2017-08-10 11:32:55
【问题描述】:

以下是处理类扩展的代码 sn-p。我想要做的是生成一个称为内部 ID 的随机 ID(稍后由程序使用),它以加密形式存储在内存中。该代码无法同时使用 gcc 和 clang 编译(我在 Windows 上通过 GNUStep 运行 Objective C),每个编译器都有不同的错误消息,在代码中被称为 cmets。

请注意,我知道这个问题可以通过忽略扩展的使用以及在主@interface(即#import 语句之后的那个)本身中声明方法和属性来轻松解决。我使用扩展的唯一原因是这个类被其他一些“internalID”属性必须不可访问的子类继承。

#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

我的 clang GNUmakefile 如下:

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

提前致谢。

【问题讨论】:

  • 我无法使用 clang/Mac OS 重现该错误。但是,为了达到您的目标,最好将 ivar 定义为 @implementation
  • @AminNegm-Awad 嘿,你能更具体地谈谈你推荐的解决方法吗?因为据我所知,所有 ivars 都必须放在“@interface”中。当您说您在 clang/Mac OS 中没有错误时,您是否实现了相同的 GNUmakefile?我认为代码不可能在 Mac OS 中编译并在 GNUStep/Windows 中失败。这么晚才回复很抱歉。我非常全神贯注于项目的另一部分:)
  • 不,我是在没有 makefile 的情况下完成的。不是真的,必须在 @interface 部分中定义 ivars。你可以在“@implementation”做同样的事情。
  • @hecate 是否有理由让 internalId 成为 ivar 而不是类扩展中的属性?使用属性,您仍然可以获得相同的“私有”行为,事实上,这是目前推荐的此类事情的语义。

标签: objective-c gcc llvm-clang gnustep class-extensions


【解决方案1】:

尝试使用在类扩展中声明的 @property 而不是 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

这是有效的private 变量的标准语义,并且可能有更好的机会获得编译器支持。

【讨论】:

    猜你喜欢
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多