配列内のオブジェクトの保持に問題があります。私は、Amazon Route 53 とやり取りするためのフレームワークを構築しており、残りの AWS IOS SDK を可能な限り厳密にフォローしています。XML を返す Web サービスを呼び出しています。Web サービスからの応答は、NSXMLParser デリゲートによってクラスにマーシャリングされます。デリゲートは別のデリゲートに切り替えて、XML のネストされた部分を処理します。2 番目のデリゲート クラスは、ネストされた部分を 2 番目のクラスに非整列化します。この 2 番目のクラスのオブジェクトは、最初のクラスの配列に配置されます。2 番目のデリゲートが解放されると、オブジェクトが解放されます (オブジェクトが配置されている配列ではなく、オブジェクト自体だけです。応答が戻ってくると、すべてのプロパティが設定されます。
これには多くのコードが関係しているので、デリゲートから配列へのオブジェクトの割り当てについて明確な何かがあることを願っています。プロセス全体で強い参照を維持していると確信しています。オブジェクトが配列に追加された場合、配列が解放されるまでオブジェクトを解放できない/解放できないと思いました。
コードに興味がある場合は、次の場所から入手できます。
https://bitbucket.org/entr04y/aws-sdk-ios
アプリケーションはサンプル サブディレクトリ (Route53_demo) にあり、最初の呼び出しは ListHostedZonesViewController.m (viewWillAppear) にあります。これは、src ディレクトリの Route53 フレームワークを呼び出します - AmazonRoute53Client.m は、Route53ListHostedZonesRequestMarshaller.m を呼び出して、応答をアンマーシャリングするデリゲートとして呼び出します。2 番目のデリゲートは Route53HostedZoneUnmarshaller.m です。
誰かが私が欠けているものを指摘してくれることを願っています... 私は過去 4 日間それを見つめてきましたが、私が行ったことは、以下の 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 内のオブジェクトにアクセスしようとすると、hostedZones 配列内のゾンビ オブジェクトを除いて、すべてのプロパティが使用可能になります。Route53HostedZoneUnmarshaller.m の dealloc を次のようにオーバーライドしました。
-(void)dealloc
{
AMZLogDebug(@"deallocating zone object unmarshaller");
// [response release];
// [super dealloc];
}
これにより、アンマーシャラーが解放され、拡張機能によってhostedZonesオブジェクトが解放されなくなり、その時点でコードが機能します(もちろんふるいのように漏れます) Route53HostedZoneオブジェクトをhostedZones配列に取得して保持するにはどうすればよいですか?