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;