19

尽管 的重载@开始涉足危险领域,但我喜欢在 Clang 3.1 中添加新的 Objective-C 文字。不幸的是,新文字对我的用处有限。除了代码需要与 AppKit 交互的情况外,我大多放弃使用 Foundation 类,转而使用我自己的自定义框架(出于各种原因;其中大部分是我需要直接控制所使用的内存分配模式按对象)。

我总是可以使用一些运行时技巧将新创建的对象作为我的自定义类传递(这是我已经与字符串对象文字有关的事情,因为只有非 Apple GCC 运行时支持该-fconstantstring=class标志),但这是一个 hack充其量并抛出我通过替换等效的基础课程获得的所有好处。

与字符串对象字面量不同,Clang 实现的新字面量实际上并不是常量类(内存布局是硬编码的);相反,适当的消息被发送到它们各自的类,以在运行时创建和初始化一个新对象。效果与您自己创建对象没有什么不同。从理论上讲,这意味着新文字所使用的类和调用的方法不是硬编码的。在实践中,我找不到任何方法将它们更改为指向我自己的自定义类和方法(事实上,我很乐意指向自定义类;在运行时将虚拟方法指向实际方法并不困难)。

当我第一次研究这个时,我真的希望找到一组可以用来做我所要求的标志,但由于我没有找到任何标志,我希望有人有一个解决方案。

4

2 回答 2

12

@compatibility_alias您可以用关键字技巧替换一些 Objective-C 文字的类。

这是一个例子。

@compatibility_alias NSNumber AAA;

当然,您应该为新类提供正确的实现。

#import <Foundation/NSObject.h>

@interface  AAA : NSObject
+ (id)numberWithInt:(int)num;
@end

@implementation AAA
+ (id)numberWithInt:(int)num
{
    return  @"AAAAA!!!";    // Abused type system just to check result.
}
@end

@compatibility_alias NSNumber AAA;

现在 Clang 将为您完成这项工作。我确认这适用于数字、数组、字典文字。不幸的是,字符串文字似乎是静态发出的,所以它不起作用。

有关@compatibility_alias关键字的更多信息,请参见此处

笔记

由于@compatibility_alias关键字是适用于当前编译单元的编译器指令,因此您需要将编译单元分开以避免与 Apple Foundation Kit 中的 NSObject 类的符号重复。这就是我的做法。

主文件

#import "test.h" // Comes before Foundation Kit.
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        NSLog(@"return of test = %@", test());
        // insert code here...
        NSLog(@"Hello, World!");

    }
    return 0;
}

测试.h

id test();

测试.m

#import "test.h"
#import <Foundation/NSObject.h>

@interface  
AAA : NSObject
+ (id)numberWithInt:(int)v;
+ (id)arrayWithObjects:(id*)pobj count:(int)c;
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c;
@end
@implementation AAA
+ (id)numberWithInt:(int)v
{
    return  @"AAAAA as number!!!";
}
+ (id)arrayWithObjects:(id*)pobj count:(int)c
{
    return  @"AAAAA as array!!!";
}
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c
{
    return  @"AAAAA as dictionary!!!";
}
@end



@compatibility_alias NSDictionary AAA;
@compatibility_alias NSArray AAA;
@compatibility_alias NSNumber AAA;



id test()
{
//  return  @{};
//  return  @[];
    return  @55;
}

结果。

2013-03-23 08:54:42.793 return of test = AAAAA!!!
2013-03-23 08:54:42.796 Hello, World!
于 2013-03-23T00:08:22.500 回答
11

评论都正确,但只是总结一下:

  • 不。

Apple 的 、 和文字的含义@{}@[]@""编码到 Clang 中。你可以在这里看到它:http: //llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp ?view=markup这都是相当模块化的,这意味着它不会很难Clang 黑客添加了她自己的文字语法……但“模块化”并不意味着“可从外部访问”。添加新语法甚至将现有语法重定向到新类肯定需要自己重建 Clang。

这是一篇关于NSURL通过对其内部进行黑客攻击来向 Clang 添加文字的博客文章:http: //www.stuartcarnie.com/2012/06/llvm-clang-hacking-part-3.html(感谢@Josh Caswell)


如果您愿意使用带有 C++11 扩展的 Objective-C++,您可以拥有“用户定义的文字”,它允许您编写类似的东西

NSURL *operator ""URL (const char *s) { return [NSURL URLWithString: @(s)]; }

int main() {
    ...
    NSURL *myurl = "ftp://foo"URL;
    ...
}

Mike Ash 博客上的评论中提到了这一点。http://www.mikeash.com/pyblog/friday-qa-2012-06-22-objective-c-literals.html但这看起来不太像 Objective-C-ish(或非常 C++ish!) ,并且它仅适用于 Objective-C++11 编译器,一般情况下请不要这样做。:)

于 2012-08-24T22:17:22.090 回答