仪器报告每次使用SodzC生成的代码对Soap Web服务进行调用时都会泄漏2个对象。
我使用一个调用免费的公共Web服务(http://www.webservicex.net/geoipservice.asmx?WSDL)且不进行身份验证的代码将其简化为一个简单的案例。
不幸的是,要运行SudzC项目需要进行大量设置,但是您可以通过将WSDL URL放入http://www.sudzc.com/并选择“ iOS中的Objective-C”来查看生成的代码。
Leaked Object # Address Size Responsible Library Responsible Frame
Malloc 1.00 KB, 0x5035400 1.00 KB Foundation-[NSCFString appendString:]
NSCFString, 0x4c3d390 32 Bytes Foundation -[NSPlaceholderMutableString init]
每个对象的调用堆栈是
3 Foundation -[NSCFString appendString:]
4 SoapDemo +[Soap createEnvelope:forNamespace:forParameters:withHeaders:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/Soap/Soap.m:50
5 SoapDemo +[Soap createEnvelope:forNamespace:withParameters:withHeaders:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/Soap/Soap.m:114
6 SoapDemo -[WSXGeoIPService GetGeoIP:action:IPAddress:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/Generated/WSXGeoIPService.m:55
7 SoapDemo -[SoapDemoViewController callWebService] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/SoapDemoViewController.m:14
8 SoapDemo -[SoapDemoViewController press:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/SoapDemoViewController.m:19
调用代码:
- (IBAction)press:(id)sender {
NSLog(@"pressed");
[self callWebService];
}
-(void)callWebService {
WSXGeoIPService* service = [WSXGeoIPService service];
[service GetGeoIP:self action:@selector(handleResponse:) IPAddress:@"209.85.147.103"];
}
-(void) handleResponse:(id)value{
NSLog(@"%@", value);
}
根据[Soap createEnvelope]中的工具,Soap.m中令人反感的行看起来没有什么冒犯性(带有注释)。
+ (NSString*) createEnvelope: (NSString*) method forNamespace: (NSString*) ns forParameters: (NSString*) params withHeaders: (NSDictionary*) headers
{
NSMutableString* s = [NSMutableString string];
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendFormat: @"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns=\"%@\">", ns];
if(headers != nil && headers.count > 0) {
[s appendString: @"<soap:Header>"];
for(id key in [headers allKeys]) {
if([[headers objectForKey: key] isMemberOfClass: [SoapNil class]]) {
[s appendFormat: @"<%@ xsi:nil=\"true\"/>", key];
} else {
[s appendString:[Soap serializeHeader:headers forKey:key]];
}
}
[s appendString: @"</soap:Header>"];
}
[s appendString: @"<soap:Body>"];
[s appendFormat: @"<%@>%@</%@>", method,[params stringByReplacingOccurrencesOfString:@"&" withString:@"&"], method];
[s appendString: @"</soap:Body>"];
[s appendString: @"</soap:Envelope>"]; // *** this is reported as causing the leak ***
return s;
}
我尝试过修改方法(通过合并appendString调用,添加一些虚拟日志记录等),但是此方法始终会发生泄漏。
我可以想到几种可能性:
在代码的其他地方,Instruments无法正确识别泄漏。
appendString使用不正确。
苹果的NSMutableString appendString方法泄漏。
没有实际泄漏。
谁能推断出正在发生的事情(或如何发现这一点)?
我正在使用iOS SDK 4.3。
计划B是将项目转换为自动参考计数...
最佳答案
对于那些不喜欢的人,请按照我的更改来修复您的泄漏,因为它可以正常工作:
在SoapRequest.h中,将变量声明id postData
替换为NSString* postData
在SoapRequest.h中,将其属性声明替换为@property (copy, nonatomic) NSString* postData
(在此,我另外将所有NSString属性代币更改为“ copy”)。
在SoapRequest.m中,方法(SoapRequest*) create: (SoapHandler*) handler action: (SEL) action urlString: (NSString*) urlString soapAction: (NSString*) soapAction postData: (NSString*) postData deserializeTo: (id) deserializeTo
将行request.postData = [postData retain]
更改为request.postData = postData
。
这3个步骤将解决您的问题。希望它也将在SudzcC框架中实现。
关于iphone - 适用于iPhone的SudzC似乎每个Web服务调用都会泄漏1kB,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9740609/