在实例创建时自动运行选择器

时间:2013-12-02 05:36:43

标签: objective-c string objective-c-runtime

在Objective-C中,每次实例化对象时,有没有办法自动运行特定的选择器? (我知道+initialize,但我需要一个实例方法。)

具体来说,我正在编写一个自定义字符串类(它继承自我自己的根类,并具有与NSObject类似的接口),并且我试图使用Objective-C常量字符串“很好地”使用它。为此,我有以下类定义(根据运行时的要求):

// 1) Required Layout
@interface MYConstantString : MYObject {
    //Class isa; inherited from MYObject
    char *c_string;
    unsigned int length;
}

现在,我想通过在类中使用指向C-struct的指针来实现我的字符串类(这个“C对象”已经很好地实现了,所以我基本上只想将它包装在Objective-C类中)。因此,理想情况下,我的Objective-C类看起来像这样:

// 2) Desired Laout
@interface MYConstantString : MYObject {
    // Class isa;
    StringObject *string;
}

然后类和实例方法只使用StringObject包装C函数调用。

因为我不能拥有所需的ivar布局(2),我希望破解所需的ivar布局(1)以便为我工作。例如:

- (void)fixup {
    // Pseudocode
    temp = copystring(c_string);
    c_string = (void *)StringObjectNewWithString(temp); // Fudge pointer
    length = ... // I can do something else with this.
}

那么,回到这个问题,有没有办法自动调用-fixup,而不是每次我写一个Objective-C常量字符串时都必须执行以下操作?

MYConstantString *str = @"Constant string";
[str fixup];

我知道这是一个淫秽的黑客攻击,而Objective-C常量字符串互操作性并不是我所需要的完全至关重要,但是能够使用@""语法并使代码更多更好'自然'Objective-C。

2 个答案:

答案 0 :(得分:1)

我猜你遗漏了一个重要的事实:你在构建时使用-fconstant-string-class=MYConstantString让编译器将你的类用于常量字符串对象(@"...")。

鉴于此,那么,没有。有两个重要问题。首先,常量字符串的“实例创建”发生在编译时,而不是运行时。存在必需布局的原因是编译器什么都不做,只是在数据部分中布置字符串的数据,并引用isa指针所在的相应类对象。它不会调用任何自定义代码。它在编译时甚至不一定意识到这样的自定义代码。给定的翻译单元可能不包括常量字符串类。对此的引用在链接时解决。

其次,常量字符串实例几乎肯定是在只读数据部分中布局的。甚至在您的问题中手动调用-fixup方法也很有可能会遇到访问冲突,因为您要修改只读内存。

您应该考虑使用类集群。使MYConstantString成为抽象基类的一个具体子类。使其符合所需的布局,只需使用字符指针和长度ivars。如果在各个点转换为StringObject会很方便,请在这些点上进行。如果需要,实现其他单独的具体子类,以在内部使用StringObject

答案 1 :(得分:0)

MYConstantString *str = @"Constant string";

这不起作用,因为@"..."NSString,并且它不仅是布局问题,而且是实例大小问题。如果你想要0副本或类似的东西,你需要做的是:

MYConstantString *str = [MyConstantString stringWithNSString:@"Constant string"];

-stringWithNSString:识别传递的字符串何时是常量字符串(我很确定常量字符串的具体类很容易识别,并且由于向后兼容性原因可能没有改变)然后破解它以获取指向字节和类似事物的指针。