我在Objective-C中编写一个方法以使对象为零时遇到一些麻烦。这是一些例子:
@interface testA : NSObject
{
NSString *a;
}
@property (nonatomic, retain) NSString *a;
+(testA*)initWithA:(NSString *)aString;
-(void)displayA;
-(void)nillify;
@end
@implementation testA
@synthesize a;
+(testA*)initWithA:(NSString *)aString{
testA *tst=[[testA alloc] init];
tst.a=aString;
return [tst autorelease];
}
-(void)displayA{
NSLog(@"%@",self.a);
}
-(void)nillify{
self=nil;
}
- (void)dealloc {
[a release];
[super dealloc];
}
@end
int main(int argc, char **argv){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
testA *test=[testA initWithA:@"some test"];
[test displayA];
test=nil;
//[test nillify];
NSLog(@"after setting to nil");
[test displayA];
[pool release];
return 0;
}
显然,当我将测试对象设置为nil然后调用某个方法时,没有任何反应,但如果我调用nillify而不是直接将其设置为nil,则displayA方法正常工作,就像测试对象仍然存在一样。 nillify方法是否有解决方法才能正常运行?
非常感谢您的帮助!
答案 0 :(得分:4)
你实际上不能做这样的事情,因为将'self'设置为nil只会在该方法的范围内产生任何影响(在你的情况下,'nilify')。例如,您没有任何实际方法来实现位于堆栈其他部分或堆中随机位置的指针值。
基本上任何包含对某个对象的引用的代码都负责维护和清除这些引用本身。如果您有一些用例,其中代码的随机部分可能需要引用某种类型的“实时”对象,但您希望这些对象引用响应某些外部事件(可能是用户跟踪系统或其他内容)而消失,您可以对通知执行某些操作,但跟踪这些“实时”对象的各种模块仍然负责收听通知并在收到通知时清理引用。
然而,'nilify'的东西不可行。答案 1 :(得分:2)
你无法做你想做的事。 self
只是对其他地方实际存在的对象的本地引用。将其设置为nil
并不意味着什么。通常,对象本身并不拥有自己,并且它当然不会控制其他对象对它的引用。由管理其生命周期的拥有对象决定。
答案 2 :(得分:1)
您的代码存在一些问题。
首先,按照惯例,类名以大写字母开头。请坚持这些命名约定,因为这会使其他开发人员更难以使用您的代码(甚至让您感到困惑)。
接下来,您的initWithName:
...根据命名约定,名称中包含init
的方法应该是实例方法,而不是类方法。因此要么将其命名为newWithName:
,要么将其转换为如下所示的实例方法:
-(testA*)initWithA:(NSString *)aString{
self = [super init];
if (!self) return nil;
tst.a=aString;
return self;
}
如果将其保留为类方法(并将其命名为newWithName:
),则应不返回自动释放的对象,因为根据以init...
开头的命名约定方法或new...
返回一个保留的对象。如果你不遵守这些约定,静态分析器会给你“假”警告,它对你来说就没用了。
现在因为nillify
不起作用的原因:self
实际上是方法的参数。在引擎盖下,您的nillify
方法实际上有两个您没有看到的参数:self
指针和选择器指针。这意味着,self
实际上是堆栈中的变量。如果你覆盖它,你只会覆盖那个堆栈变量,但这不会影响你在其他地方的test
变量。
举个例子,考虑一个方法- (void)foo:(NSString *)bar;
。编译器将其转换为C函数(void) foo(id self, SEL _cmd, NSString *bar)
的等价物。