0

我对保留数组中的对象有疑问。我正在构建一个框架来与 Amazon Route 53 交互,并尽可能地关注 AWS IOS 开发工具包的其余部分。我正在调用返回 XML 的 Web 服务。来自 Web 服务的响应由 NSXMLParser 委托编组到一个类中。委托切换到另一个委托来处理 XML 的嵌套部分。第二个委托类将嵌套部分解组为第二个类。第二类的对象放在第一类的一个数组中。当第二个委托被释放时,它正在释放对象(不是它们所在的数组,只是对象本身。当响应返回时,所有属性都被填充,

这涉及到很多代码,所以我希望从委托中将对象分配给数组有明显的意义。我很确定我在整个过程中都在维护强引用,并且我认为如果将对象添加到数组中,它们将无法/不会从数组中释放,直到数组被释放。

如果您有兴趣查看代码,可在此处获得:

https://bitbucket.org/entr04y/aws-sdk-ios

该应用程序位于示例子目录 (Route53_demo) 中,初始调用位于 ListHostedZonesViewController.m (viewWillAppear) 中。这会调用 src 目录中的 Route53 框架 - AmazonRoute53Client.m,它调用 Route53ListHostedZonesRequestMarshaller.m 作为解组响应的委托。第二个代表是 Route53HostedZoneUnmarshaller.m。

希望有人能指出我遗漏的东西......过去四天我一直在盯着它看,但我无法弄清楚我所做的与以下 AWS 的一些示例代码不同这个相同的模式。

按照下面的要求,我将尝试添加代码的相关部分,因为这样做的方式似乎并不明显:

初始请求是从这样的视图控制器发出的:

Route53ListHostedZonesRequest *request = [[Route53ListHostedZonesRequest alloc] initWithMaxItems:100];

Route53ListHostedZonesResponse *listHostedZonesResponse = [[AmazonClientManager r53] listHostedZones:request];

然后在 AmazonRoute53Client.m (在我的框架中)中处理:

-(Route53ListHostedZonesResponse *)listHostedZones:(Route53ListHostedZonesRequest *)listHostedZonesRequest
{

AmazonServiceRequest *request = [Route53ListHostedZonesRequestMarshaller createRequest:listHostedZonesRequest];

return (Route53ListHostedZonesResponse *)[self invoke:request rawRequest:listHostedZonesRequest unmarshallerDelegate:[Route53ListHostedZonesResponseUnmarshaller class]];
}

响应被发送到 Route53ListHostedZonesResponseUnmarshaller.m 并解析为 Route53ListHostedZonesResponse 类的实例:

 -(Route53ListHostedZonesResponse *)response
 {
 if (nil == response) {
    response = [[Route53ListHostedZonesResponse alloc] init];
}
return response;
}

当解析器命中包含托管区域的嵌套部分时,它被委派给另一个解组器 Route53HostedZoneUnmarshaller:

if ([elementName isEqualToString:@"HostedZone"]) {
    [parser setDelegate:[[[Route53HostedZoneUnmarshaller alloc] initWithCaller:self withParentObject:self.response.hostedZones withSetter:@selector(addObject:)] autorelease]];
}

(hostedZones 被声明为 NSMutableArray 并且是 Route53HostedZonesResponse 类的非原子保留属性),它将 XML 中的项目放入 XML 中包含的每个托管区域的 Route53HostedZone 实例中:

-(Route53HostedZone *)response
{
if (nil == response) {
    response = [[Route53HostedZone alloc] init];
}
return response;
}

在 xml 块的末尾,对象被返回给调用者,如下所示:

if ([elementName isEqualToString:@"HostedZone"])  {
    if ( caller != nil) {
        [parser setDelegate:caller];
    }
   if (parentObject != nil && [parentObject respondsToSelector:parentSetter]) {
        [parentObject performSelector:parentSetter withObject:self.response];
    } 
    return;

}

在 xml 响应结束时,Route53ListHostedZonesResponse 对象填充如下:

if ([elementName isEqualToString:@"ListHostedZonesResponse"])
{
    if (caller != nil) {
        [parser setDelegate:caller];
    }

    if (parentObject != nil && [parentObject respondsToSelector:parentSetter]) {
        [parentObject performSelector:parentSetter withObject:self.response];
    }

    return;
}

至此,AWS 运行时库和 Route53 库完成了对响应的处理,解组器对象、Route53ListHostedZonesResponse 对象和所有 Route53HostedZone 对象都被释放。

回到视图控制器,当我尝试访问 listHostedZoneResponse 中的对象时,所有属性都可用,除了 hostsZones 数组中的对象现在是僵尸。我在 Route53HostedZoneUnmarshaller.m 中覆盖了 dealloc,如下所示:

-(void)dealloc
{
AMZLogDebug(@"deallocating zone object unmarshaller");
//   [response release];
//    [super dealloc];
}

这会阻止 unmarshaller 被释放并通过扩展 hostsZones 对象,此时代码可以工作(但当然会像筛子一样泄漏) 我怎样才能将 Route53HostedZone 对象放入 hostsZones 数组以便保留它们?

4

1 回答 1

0

哇,这是一些令人费解的代码。我只是猜测问题可能出在这一行:

[parser setDelegate:
 [[[Route53HostedZoneUnmarshaller alloc]
                               initWithCaller:self 
                             withParentObject:self.response.hostedZones 
                                   withSetter:@selector(addObject:)] 
  autorelease]
 ];

我看不到parser's 的类型是什么,但在 Objective-C 中,通常不会保留代表。所以整体Route53HostedZoneUnmarshaller在使用时可能是垃圾。

尝试删除对委托对象的调用autorelease并将其存储在属性中,直到解析过程完成。

于 2013-07-14T13:40:12.233 回答