我开始研究IOS开发,我对发布没有存储引用的对象有一些疑问。我看了一下“释放一个没有指针的对象?”的问题。建议在创建对象后立即向对象发送自动释放消息,因此我尝试在下面的代码中执行相同的操作:
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data;
data = [NSURLConnection
sendSynchronousRequest: [[NSURLRequest requestWithURL:
[[NSURL URLWithString: @"http://www.google.it"]
autorelease]
] autorelease]
returningResponse: &response
error: &error];
[data writeToFile: @"/tmp/test.html"
atomically:NO];
[data release];
[pool drain];
return 0;
}
我还没有尝试在XCode中执行程序,但是我在linux下编译并且发送到NSURLRequest对象的自动释放消息导致了分段错误(我认为它不是由消息本身引起的,而是由池引起的由于自动释放消息,尝试释放对象的排水)。我发送给NSURLRequest对象的自动释放消息有什么问题?
我认为如果像requestWithUrl这样的类方法的引用文档说它“创建并返回一个URL请求”,则意味着我负责在我使用它时释放该对象,我错了吗?在进一步研究其他任何事情之前,我想非常了解这个内存管理规则。我希望我的问题不是太愚蠢;-)
呃,还有最后一个问题:我是否应该同时发布同步请求返回的错误和数据对象?
提前感谢您的帮助!
答案 0 :(得分:3)
+requestWithURL:
(以及其他)方法已经返回自动释放的对象,因此您不应再向其发送一次自动释放。
代码中的额外自动释放会使对象过度释放并使应用程序崩溃。
要知道是否必须释放对象的经验法则 - 只有在使用名称中包含“alloc”,“new”,“copy”的方法创建对象时才需要释放。所有标准API都遵循此规则,您应该在开发自己的方法时遵循它。
如此纠正的代码将是:
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data;
data = [NSURLConnection
sendSynchronousRequest: [NSURLRequest requestWithURL:
[NSURL URLWithString: @"http://www.google.it"]
returningResponse: &response
error: &error];
[data writeToFile: @"/tmp/test.html"
atomically:NO];
[pool drain];
return 0;
}
P.S。出于上述原因,不应释放数据和错误对象。
答案 1 :(得分:1)
您的代码应如下所示:
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data;
data = [NSURLConnection
sendSynchronousRequest: [NSURLRequest requestWithURL:[NSURL URLWithString: @"http://www.google.it"]] returningResponse:&response error: &error];
[data writeToFile: @"/tmp/test.html"
atomically:NO];
[pool drain];
return 0;
}
您无需向使用该方法创建的对象调用autorelease
。\
您无需发布data
和error
。
使用下一个符号NSClass *object = [NSClass classSomeMagicWords];
返回对象的所有方法都将返回自动释放的对象,如果不调用retain
,则不应释放该对象。
答案 2 :(得分:0)
你应该删除自动释放。在iOS / Mac OSX开发中,使用Apple提供的类,几乎可以规定,如果使用不涉及单词init的方法创建对象,则会给出一个已经自动释放的对象。
例如:
NSString *blaah = [[NSString alloc] init];
将返回稍后需要释放的对象。
NSURL *googlelink = [NSURL URLWithString: @"http://www.google.it"];
另一方面,将为您提供一个自动释放的对象,如果再次释放它,它将崩溃。
答案 3 :(得分:0)
在iOS内存管理中,您只拥有通过为其分配内存或复制它而创建的对象(方法以alloc开头或名称中包含“copy”)。
如果您拥有它们,则只需要释放/自动释放它们。 requestWithURL
或URLWithString
等方法返回已自动释放的对象。
从Apple开发者网站查看this doc以获取更多信息。