变量在异步请求期间过早释放

时间:2012-04-27 09:14:16

标签: iphone objective-c memory-management

我的记忆管理和线程知识非常有限,所以我可能会遗漏一些非常基本的东西。我找到了解决这个问题的方法,但是我真的很困扰我,我看不到发生了什么。

我有一个类,它产生两个异步HTTP请求,一个用于XML配置文件,另一个用于图像。因为在同一个类中有两个异步请求,我正在重用相同的NSURLConnectionDelegate方法(可能是因子)。我首先异步获取配置文件并提取两个URL,存储为sponsorImagesponsorUrl。然后我使用sponsorImage的值来异步获取图像数据。不过,我发现在获得我的图像后(第二次异步事件完成后),sponsorUrl已被释放。

我意外地发现,如果我在创建图像请求的方法中“对它做了些什么”,我可以阻止sponsorUrl被释放 - 并且通过“做某事”,我的意思就是这样。基本上,我的代码看起来像这样:

- (void) loadImage
{
    sponsorUrl = [sponsorUrl stringByAppendingString:@""];

    NSURL *url = [NSURL URLWithString:sponsorImage];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setValue:dateString forHTTPHeaderField:@"If-Modified-Since"];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    [connection start];
    [connection release];   
}

如果我删除此方法的第一行(我将“”添加到url中),则保留变量。如果我删除它,它会被释放。这对我来说毫无意义。

我尝试用sponsorUrl声明@propterty (nonatomic, retain);我试过静态地宣布sponsorUrl;我尝试在设置它的地方添加[sponsorUrl retain],但它没有什么区别。唯一有效的方法是在发出第二个请求之前“触摸”变量。

我错过了什么?

2 个答案:

答案 0 :(得分:2)

当你使用便利构造函数时,变量是自动释放的!只有在使用alloc,copy或new等方法时,才会隐式保留它们。

其次,通过编写sponsorUrl = ....您不是使用生成的setter而是使用生成的实例变量。你需要写self.sponsorUrl = @“Blah”;或[self setSponsorUrl:@“blah”]以使setter保留变量。

答案 1 :(得分:1)

事实上,您似乎在内存管理方面存在一些问题。

很难解释发生了什么,因为您没有提供使用变量的完整代码。举个例子,请接受声明:

sponsorUrl = [sponsorUrl stringByAppendingString:@""];

您所做的是为sponsorURL分配一个新值;旧值(首先用变量初始化变量的值,即你提到的变量retain)被释放(stringByAppendingString伪造一个新对象); sponsorURL指向的新对象是一个自动释放的对象,其生命周期并不完全为人所知:我们只知道在某些时候它将被释放(可能在下一个主循环迭代中)。因此,通过“触摸”变量,您将为其分配一个新值,其寿命从您触摸变量的点开始......在任何情况下都非常不可靠。

我的建议如下:

  1. 在您的班级中定义两个属性来处理sponsorURLsponsorImage;

  2. 制作retain种;

  3. 仅通过其访问者方法为其赋值,即self.sponsorURL = [...]

  4. 确保您分配给属性的任何对象都是autoreleased个对象(否则,请使用分配执行发布)。

  5. 如果您提供更多代码,那么可以更全面地查看它,但如果您遵循上述指导原则,您将完全没有问题(约...)