Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective-C-正在解除分配/释放的对象实例的测试_Objective C_Cocoa_Cocoa Touch - Fatal编程技术网

Objective-C-正在解除分配/释放的对象实例的测试

Objective-C-正在解除分配/释放的对象实例的测试,objective-c,cocoa,cocoa-touch,Objective C,Cocoa,Cocoa Touch,有一些方法可以测试objective-c实例是否被解除分配/释放(retaincount==0) 举例来说,对象A有一个指向对象B的引用(指针),但对象B可以在内存低级别中释放,我如何测试引用B以确保它被解除分配 @interface A : NSObject { B b; } @implementation A { - (void) someAction:(id) sender { //is b previously dealloced?? if ..... ??

有一些方法可以测试objective-c实例是否被解除分配/释放(retaincount==0)

举例来说,对象A有一个指向对象B的引用(指针),但对象B可以在内存低级别中释放,我如何测试引用B以确保它被解除分配

@interface A : NSObject {
    B b;
}

@implementation A {

- (void) someAction:(id) sender {
    //is b previously dealloced?? 
    if ..... ???? {
        b = [[B alloc] init];
    }
    // continue
}
}

谢谢

您无法测试对象是否已解除分配,因为很明显,该对象已不再存在,无法与之对话。但是,如果在释放时将
b
设置为nil(例如,通过执行
self.b=nil
),则可以测试nil并创建对象。

如果正确保留b,它将不会在内存不足的情况下释放

也就是说,除非您自己解除分配它,否则在这种情况下,在手动删除对它的任何引用之前(用nil替换它),这一点很重要

在这种情况下,只需测试它的nil值即可:

  if (nil == b)
  { 
    reallocate b;
  }

如果您的对象似乎是自动解除分配的,那么您需要检查您的代码以检查您是否充分保留了它。

您可以尝试将NSLog消息放入对象解除分配方法中。这至少会告诉您对象何时被释放。

因为变量
b
完全在类
A
内部,并且没有声明为
@public
(默认值为
@protected
),了解
b
是否已解除分配的最佳方法是释放它并将指针设置为
nil
。这样,您只需检查
if(b==nil)
并在必要时创建一个新实例

然而,更大的问题是
b
的真正本质和记忆行为是什么。您声明“对象B可以在内存低级别中释放”,但不解释原因。如果您在Objective-C中使用的是retain release的标准习惯用法,我认为A将是决定B是否应该被释放的一个习惯用法,因为它正在创建一个新实例。如果您不打算让A做出这样的决定,允许它分配一个新的B将导致所有权混乱和内存错误

如果A不负责B,并且如果您在Leopard(或更高版本)上并且启用了垃圾收集,那么您可能需要将弱引用归零。这是在实例变量声明之前使用
\uu-weak
声明的,不会阻止垃圾收集器收集它指向的对象。(默认情况下为“强”引用,垃圾回收器不会将其可以从根目录通过强引用跟踪的对象解除分配。)此外,如果/当对象解除分配时,GC会自动将弱引用设置为0


回到“更大的问题”,除非
b
已经是一个弱引用,并且GC处于启用状态(以及其他一些条件保持不变),否则系统不会自动为您解除分配b。如果“<代码> b>代码>的原因是B的实例随着时间的推移而增长,(例如,一个可有可无的项目的缓存),那么最好有一个空B的方法。例如,基础中的可变集合有一个<代码> -ReleValbObjs方法。这种方法可以避免大多数关于
b
是否仍然存在的混淆,并且比重复(取消)分配对象更有效。

如果设置
NSZombieEnabled
环境变量,则取消分配的对象将成为
NSZombie
的实例。它们在下一条消息发出时抛出,导致您的代码崩溃和烧坏——这正是调试这种情况所需要的

更新:对于XCode 4.0,请参见

“尝试捕获”是否有效


这对于代码中的测试不起作用,测试对象是否已被释放。充其量,这将有助于调试与B相关的retain发行代码是否(可能)正确。标签上写着Cocoa Touch,因此他不在Leopard上。其中一个标签也是“Cocoa”,问题并没有具体说明iPhone,所以我认为最好用“if”来概括和限定,以便对那些可能在Leopard上的人有所帮助。这就是问题所在,我没有显式地释放对象,它是由框架类释放的,这不会发生在可预测的时间(例如didReceiveMemoryWarning:method调用),因此我需要测试我的引用(指针)是否仍然指向有效实例,如果没有,则alloc和init是一个新实例。哪个框架类释放这个类的实例变量?为什么这个类没有自己的ivar?我想你可能需要在这个问题上提供更多的信息。正如Alex所说,你的属性不应该神秘地消失。哇,这正是我今天需要的。谢谢非常确定在解除分配的实例上调用消息不会引发正常的异常,而是sigbart。听起来,本文可能会向您展示如何执行此操作:
 @try {
      [b description]; // test it... 
 }
 @catch (NSException * e) {
    NSLog(@"Exception: %@", e);
 }
 @finally {
    NSLog(@"finally");
 }