我认为将setString:
发送给尚未NSMutableString
呼叫的init
但尚未自行调用init
。例如:
NSMutableString *string; // Declare, but do not init yet
[string setString:@"foo"];
NSLog (@"%@",string); // Prints "(null)"
我想覆盖这种行为,所以基本上是
- (void) setString:(NSString *)aString
{
if (!self)
{
self = [self initWithString:aString];
}
else
{
[super setString:aString];
}
}
我可以使用子类来完成,但是我必须完成我的项目并将所有NSMutableString
替换为我的子类,这很痛苦。我正在查看Apple Docs,我想要做的就是为NSMutableString
创建一个类别。我之前没有使用类别,所以我有几个问题:
首先,看起来类别只允许我添加新方法,它不允许我覆盖现有方法。我想简单地创建一个可以满足我想要的setStringWithInit:
方法就足够了,所以这第一个问题毕竟不是一个问题(尽管我仍然需要通过我的项目进行查找替换{ {1}},但是哦,好吧)。
其次,更重要的是,如何检查新方法的发件人是否为setString
?如果nil
返回setString:
之外的其他内容,我想我可以让它工作,但事实并非如此。如何从上面的代码中获取void
检查以使用类别?
或者类别不适合这种事情,毕竟我会更好地进行分类?
编辑:
所以我使用它的字符串实际上是自定义if (!self)
子类的@property
。在我的代码中,我实际上将调用NSObject
,并且当我尝试执行此操作时调试器向我显示[myObject.someProperty setString:@"foo"];
为nil。此外,在我的应用的其他部分,我正在检查someProperty
以查看该属性是否已被使用,因此我不想仅在if (!myObject.someProperty)
方法中自动self.someProperty = [[NSMutableString alloc] init];
init
的课程。
虽然我现在考虑过这个问题,但我认为我可以将myObject
替换为if (!myObject.someProperty)
,这样我就可以立即执行并分配init事件。但是,如果我马上初始化一切,那将为它创造一些内存空间,对吗?但它可能是微不足道的。嗯,也许这就是我应该做的事情。
答案 0 :(得分:3)
正确的代码只是:
NSMutableString *string = [NSMutableString string];
[string setString:@"foo"];
NSLog (@"%@",string);
为什么不初始化变量?无需覆盖setString:
或任何其他方法。不要试图以与任何其他类别不同的方式对待NSMutableString
。
此外,覆盖setString:
仍然无法解决任何问题。只要指针为nil
,就无法在其上调用方法。
答案 1 :(得分:1)
您可以使用方法调配重新实现没有子类化的方法。这是a tutorial。不过有两个理由不这样做。
setString:
会做
没有。即使你覆盖了这个方法。因此,我建议在NSMutableString
上创建一个类别,并在那里实施[NSMutableString initWithString:]
。这是一个更清洁的解决方案。
答案 2 :(得分:1)
你正在走向疯狂的道路。所有进入这里的人都放弃了希望!
不要尝试更改语言语义,以便以某种方式向nil对象发送消息,从而神奇地创建对象的实例。这不是语言的运作方式。
您尝试做的事情可能是不可能的,如果您能够成功,您将创建与标准Objective-C根本不兼容的程序。您也可以找到一种新语言Objective-D
将消息发送到Objective C中的nil对象是合法的。结果是消息被静默删除,没有任何反应。在许多其他面向对象的其他语言中,向nil对象/零指针发送消息会导致崩溃。
Objective C对象创建的语义是:
首先使用类方法alloc:
为对象分配内存NSMutableString* aString = [NSMutableString alloc];
然后向新创建的对象发送一个init方法,将其设置为初始状态:
aString = [aString init];
这两个步骤几乎总是合并为一行:
NSMutableString* aString = [[NSMutableString alloc] init];
类有时包括为您执行2步alloc / init的快捷方便“方便”方法,并在一次调用中返回一个对象,例如:
NSMutableString *aString = [NSMutableString stringWithCapacity: 50];
不要试图打击这个惯例。学会遵循它。如果您无法容忍此约定,请使用其他语言编程。真。
答案 3 :(得分:0)
你真的不能那样做 - 你有一个只能在这个对象的实例上调用的方法,所以你必须先创建它才能使用它。
在你的代码中,无论如何它都将是“无” - 它不会自己创建。
你为什么这样做而不仅仅是:
NSMutableString *string = @foo";
我无法想象避免分配对象的理由
答案 4 :(得分:0)
宏FTW!
#define setString(X,Y) if(!X){X=[[NSMutableString alloc] initWithString:Y];}else{[X setString:Y];}
当我尝试使用此值分配值时:
NSMutableString
,或者如果Y不是NSString
或NSMutableString
Y
是nil
,但我预计会导致崩溃,这就是我想要的。缺点:
setString()
代替库存setString:
setValue:forKey:
,这是我广泛使用的 - 我猜是一次一步 - 一个尺寸适合所有解决方案本来不错 - 也许是另一个问题的主题。 无论我传入的是什么,在传递之前都必须是NSString
,我无法将其转换为符合字符串的字符串 - 但至少如果我尝试这样做,我会收到构建错误,所以我不记得这样做(尽管仍然会增加混乱)
NSMutableString *X;
int y = 0;
setString(X, [NSString stringWithFormat:@"%d",y]) // <--- Doesn't work
NSString *Y = [NSStirng stringWithFormat:@"%d",y];
setString(X,Y) // <--- Does work