Objective c 释放对象后调用方法?

Objective c 释放对象后调用方法?,objective-c,uinavigationcontroller,release,Objective C,Uinavigationcontroller,Release,我正在阅读这段代码,其中setRegions在RootViewController发布后被调用:我觉得有点奇怪:这是否意味着RootViewController仍然可以访问,即使它被发布并且self.navigationController拥有它 谢谢以上代码非常危险。这可能会起作用,但只是运气好而已。在释放变量后,永远不要访问它。事实上,如果变量没有立即超出范围,最好在释放变量后立即将其设置为nil。有些人只在发布模式下执行此操作,因此创建一个宏,如: #ifdef DEBUG #define

我正在阅读这段代码,其中
setRegions
RootViewController
发布后被调用:我觉得有点奇怪:这是否意味着
RootViewController
仍然可以访问,即使它被发布并且
self.navigationController
拥有它


谢谢

以上代码非常危险。这可能会起作用,但只是运气好而已。在释放变量后,永远不要访问它。事实上,如果变量没有立即超出范围,最好在释放变量后立即将其设置为
nil
。有些人只在发布模式下执行此操作,因此创建一个宏,如:

#ifdef DEBUG
#define RELEASE(x) [x release];
#else
#define RELEASE(x) [x release]; x = nil;
#endif
这样做的原因是为了帮助在调试模式下捕获bug(通过崩溃而不仅仅是无声的
nil
指针),同时在发布模式下更安全一些


但是在任何情况下,您都不应该在释放变量后访问它。

上述代码非常危险。这可能会起作用,但只是运气好而已。在释放变量后,永远不要访问它。事实上,如果变量没有立即超出范围,最好在释放变量后立即将其设置为
nil
。有些人只在发布模式下执行此操作,因此创建一个宏,如:

#ifdef DEBUG
#define RELEASE(x) [x release];
#else
#define RELEASE(x) [x release]; x = nil;
#endif
这样做的原因是为了帮助在调试模式下捕获bug(通过崩溃而不仅仅是无声的
nil
指针),同时在发布模式下更安全一些

但是在任何情况下,您都不应该在释放变量后再访问它。

这是错误的代码

一个对象应该保留另一个对象,只要它关心它。在这种情况下,这个规则被打破了。
rootViewController
被释放,然后正如您所注意到的,一个方法被调用。这可能很危险

在这种情况下,它是有效的。这是因为
rootViewController
被传递给另一个对象,该对象将保留它。所以当我们释放它时,它仍然有一个正的保留计数,并且没有被释放。因此,我们对它的引用仍然有效,调用它的方法也很有效

但是,假设某些实现发生了更改,
initWithRootViewController:
由于某种原因不再保留它的参数(这是一种假设,您不能一直这样做)。突然,这一切都崩溃了,因为
rootViewController
被解除分配

要解决这个问题,只需移动
[rootViewController release]到。然后,您的代码变得更加健壮和正确

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    // Create the navigation and view controllers
    RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
    [rootViewController setRegions:[Region knownRegions]];
    UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    self.navigationController = aNavigationController;

    // Release temporary objects since we've now sent them to other other objects
    // which may or may not retain them (we don't really care which here)
    [aNavigationController release];
    [rootViewController release];

    // Configure and display the window
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];
}

最后要注意的是:
release
dealoc
是非常不同的事情<代码>发布
不一定会销毁对象。它只是将
retain
计数减一。如果
retain
count值为零,那么对象才会被释放。因此,此代码之所以有效,是因为发生了
发布
,但没有触发
解除锁定
,这是错误的代码

RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
一个对象应该保留另一个对象,只要它关心它。在这种情况下,这个规则被打破了。
rootViewController
被释放,然后正如您所注意到的,一个方法被调用。这可能很危险

在这种情况下,它是有效的。这是因为
rootViewController
被传递给另一个对象,该对象将保留它。所以当我们释放它时,它仍然有一个正的保留计数,并且没有被释放。因此,我们对它的引用仍然有效,调用它的方法也很有效

但是,假设某些实现发生了更改,
initWithRootViewController:
由于某种原因不再保留它的参数(这是一种假设,您不能一直这样做)。突然,这一切都崩溃了,因为
rootViewController
被解除分配

要解决这个问题,只需移动
[rootViewController release]到。然后,您的代码变得更加健壮和正确

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    // Create the navigation and view controllers
    RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
    [rootViewController setRegions:[Region knownRegions]];
    UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    self.navigationController = aNavigationController;

    // Release temporary objects since we've now sent them to other other objects
    // which may or may not retain them (we don't really care which here)
    [aNavigationController release];
    [rootViewController release];

    // Configure and display the window
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];
}

最后要注意的是:
release
dealoc
是非常不同的事情<代码>发布
不一定会销毁对象。它只是将
retain
计数减一。如果
retain
count值为零,那么对象才会被释放。这段代码之所以有效,是因为发生了
发布
,但没有触发
解除锁定

RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
(objectA已创建,保留计数为1,rootViewController指向它)

(objectB已创建,保留计数为1,aNavigationController指向它) (objectA保留计数现在为2,rootViewController和self.aNavigationController中的某些属性都指向它)

(objectB retain count现在是2,aNavigationController和self.navigationController都指向它;假设self.navigationController是一个retain属性)

(objectB retain count现在是1,但是aNavigationController和self.navigationController都指向它)

(objectA retain count现在是1,但是,rootViewController和self.aNavigationController中的某些属性都指向它)

(使用rootViewController访问objectA) (这不好)

以下是我推荐的方法:

RootViewController *rootViewController = [[[RootViewController alloc] initWithStyle:UITableViewStylePlain] autorelease];
[rootViewController setRegions:[Region knownRegions]];

UINavigationController *aNavigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
self.navigationController = aNavigationController;
(objectA已创建,保留计数为1,rootViewController指向它)

(objectB已创建,保留计数为1,aNavigationController指向它) (objectA保留计数现在为2,rootViewController和self.aNavigationController中的某些属性都指向它)

(objectB retain count现在是2,aNavigationController和self.navigationController都指向它;假设self.navigationController是一个retain属性)

(objectB retain count现在是1,但是aNavigationController和self.navigationController都指向它)

(objectA retain count现在是1,但是,rootViewController和一些pro
[rootViewController release];
[rootViewController setRegions:[Region knownRegions]];
RootViewController *rootViewController = [[[RootViewController alloc] initWithStyle:UITableViewStylePlain] autorelease];
[rootViewController setRegions:[Region knownRegions]];

UINavigationController *aNavigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
self.navigationController = aNavigationController;