为什么我需要创建一个指针来分配内存然后立即释放它?
换句话说,我不能这样做:
self.viewController = [[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController" bundle:[NSBundle mainBundle]];
而不是:
HelloWorldViewController *newViewController = [[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController" bundle:[NSBundle mainBundle]];
self.viewController = newViewController;
[newViewController release];
[编辑]
为我的问题提供更广泛的背景:(在@interface的@interface HelloWorldAppDelegate:NSObject< UIApplicationDelegate>中)
@synthesize window=_window;
@synthesize viewController=_viewController;
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
HelloWorldViewController *newViewController = [[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController" bundle:[NSBundle mainBundle]];
self.viewController = newViewController;
[newViewController release];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
...
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
所以,在didFinish ...方法中,我可以使用上面提供的短版本,还是会泄漏?
[第二编辑]
似乎我无法提供足够的信息。我总是犹豫要发一大堆代码。 我在HelloWorldAppDelegate.h中得到了这个:
@property (nonatomic, retain) IBOutlet HelloWorldViewController *viewController;
所以,如果我错了,请纠正我。鉴于头文件中viewController的声明,如果我使用快捷方法(在上面的第一个代码片段中),程序将泄漏。对象计数器由alloc增加一次,然后由retain增加第二次,然后在释放时递减一次,在指针引用计数器上产生+1的净值。
答案 0 :(得分:3)
你做必须释放你分配的对象,否则你最终会发生内存泄漏。对self.viewController
(可能)的分配保留了新分配的HelloWorldViewController
,因此您在对象上有两个“声明” - 一个来自您对alloc
的呼叫,另一个来自retain
,但您实际上不会再以newViewController
名称使用它,因此您可以通过调用release
来放弃该特定声明。
使用temp变量的“long”形式实际上是执行此操作的正确方法。在设置之后立即将release
发送到属性访问结果:[self.viewController release];
很可能会起作用,但是is incorrect(并且会为最近的LLVM版本生成编译器警告)。
也可以这样做:
self.viewController = [[[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController"
bundle:[NSBundle mainBundle]]
autorelease];
其中说“我已经创建了这个东西以便简单地使用它,但我不会在这个直接调用堆栈之外需要它,所以请继续以后为我发布它。”
如果viewController
不是retain
属性,那么所有这些都没有实际意义,并且不应向新视图控制器发送release
,因为它会在您使用之前被解除分配。
更新:您的扩展问题不会改变任何内容*。如果在release
超出范围之前没有发送newViewController
,则最终会发生泄漏。**其工作方式是,需要的任何对象(A,B,C)使用对象X,因此关心保持它,将retain
发送给X.当你alloc
一个对象时,假设你需要使用它。当A,B或C中的任何一个不再需要X时,它会向{X}发送release
,从而说“X可以被解除分配并且不会影响我”。您需要在具有该号码的对象上平衡您所声明的声明数量(使用retain
,alloc
,copy
/ mutableCopy
或new
)你所做的放弃(通过发送release
或autorelease
),否则你手上会有泄密或意外解除分配。
我现在要给你一个文档的链接,但不要生气,这只是你需要阅读和内化的一个页面:The Fundamental Rule of Cocoa Memory Management。
*实际上,你遗漏了唯一可以改变答案的部分,即你的
@property () HelloWorldViewController * viewController;
声明。如果在这些括号中显示“保留”,则在设置此属性时,您的应用委托会将retain
发送到传递的对象。如果它显示“assign”,或者括号不在那里,那么就像我说的那样,你不应该向该对象发送release
。
**注意任何看过的小伙伴:你当然可以在某个时候向release
发送viewController
两次,但这比泄漏更糟糕子>
答案 1 :(得分:2)
是的,你可以这样做。除非您必须释放self.viewController,以便在代码段末尾保留计数为1。
让我们算一算。在分配时,释放计数为1.将其分配给self.viewController(假设它是具有retain
行为的属性)将其增加到2。在第二个片段的末尾释放它使它再次成为1。这个想法是你将在当前类的dealloc中完全释放它,无论是什么。
唯一的缺点是释放一个对象变量假定你完成了它,在这里你必须去,释放self.viewController但稍后使用它。有点臭。