我正在使用TouchXML解析iOS中的元素。我使用NSInvocationOperation从Web服务检索响应,然后解析并显示结果。一切正常,因为后台线程使用[self performSelectorOnMainThread:@selector(displayLoginresult:) withObject:res waitUntilDone:NO];
在主线程上显示结果,但后来我收到错误:
2011-07-18 11:58:06.108 billsApp[873:7107] *** -[CFString release]: message sent to deallocated instance 0x5d809b0
解析元素的代码是:
-(LoginResult *) tryLogin:(NSString *)userName withPassword:(NSString*)password{
NSURL *url = [UrlUtility TryLogin:userName passwordHash:password];
CXMLDocument *responseObj = [UrlUtility xmlDocWithUrl:url];
if(responseObj == [NSNull null])
return [NSNull null];
CXMLElement *eleUser = [responseObj nodeForXPath:@"//User" error:nil];
CXMLElement *eleResult = [responseObj nodeForXPath:@"//Result" error:nil];
LoginResultType resultType;
//NSLog(@"Result: ");
//NSLog(eleResult );
// NSLog([[eleResult stringValue] lowercaseString]);
if ([[[eleResult stringValue] lowercaseString ] isEqualToString: @"successful"]){
resultType = Successful;
} else {
resultType = InvalidUsernameOrPassword;
}
LoginResult *res = [[LoginResult alloc] init];
res.result = resultType;
for (CXMLElement *resultElement in [responseObj children] ) {
NSLog([NSString stringWithFormat:@"%@ %@", [resultElement name], [resultElement stringValue]]);
}
//todo: fix enum parsing =[LoginResult loginResultTypeStringToEnum: [eleResult stringValue]];
if(eleUser != nil) {
CXMLElement *eleClientID = [eleUser nodeForXPath:@"ClientID" error:nil];
CXMLElement *eleCompanyName = [eleUser nodeForXPath:@"CompanyName" error:nil];
CXMLElement *eleCompanyContact = [eleUser nodeForXPath:@"CompanyContact" error:nil];
CXMLElement *eleIsAgent = [eleUser nodeForXPath:@"IsAgent" error:nil];
CXMLElement *eleParentID = [eleUser nodeForXPath:@"ParentID" error:nil];
NSInteger *clientId = [[eleClientID stringValue] integerValue];
NSString *companyName = [eleCompanyName stringValue];
NSString *companyContact = [eleCompanyContact stringValue];
bool isAgent = [Utils stringToBool:[eleIsAgent stringValue]];
NSInteger *parentId = [[eleParentID stringValue] integerValue];
User *user = [[User alloc] initWithData:clientId companyName:companyName companyContact:companyContact isAgent:isAgent parentId:parentId];
res.user = user;
// release elements
// [eleClientID release];
// [eleCompanyName release];
// [eleCompanyContact release];
// [eleIsAgent release];
// [eleParentID release];
//release raw values
// [companyName release];
// [companyContact release];
}
// [eleResult release];
// [eleUser release];
return res;
}
部分我想说这是TouchXML的一个错误,但我发现这不太可能。有没有办法进一步追踪错误?
编辑:User类属性的定义是:
@property (nonatomic, readwrite) NSInteger clientId;
@property (nonatomic, retain) NSString *companyName;
@property (nonatomic, retain) NSString *companyContact;
@property (nonatomic, readwrite) bool isAgent;
@property (nonatomic, readwrite) NSInteger parentId;
实例初始化为:
-(User*)initWithData:(NSInteger *)clientId companyName:(NSString *)company companyContact:(NSString*)contact isAgent:(bool)agent parentId:(NSInteger*)parentId {
//[self = super init];
self.clientId= clientId;
self.companyName= company;
self.companyContact= contact;
self.isAgent = agent;
self.parentId = parentId;
return self;
}
LoginResult类是:
@interface LoginResult : NSObject {
LoginResultType result;
User *user;
NSString * const loginResultTypeArray[4];
}
@property (nonatomic, readwrite) LoginResultType result;
@property (nonatomic, retain) User *user;
答案 0 :(得分:0)
试一试:您是否正确地在companyName
课程中保留了companyContatct
和User
?
编辑:
接下来我要检查的是loginResultTypeArray
。如何分配字符串?我想这个建议对你来说也是微不足道的,但是很难用这么少的代码提出有用的建议......
你不能对哪个 CFString
实际发布有所了解吗?如果它不是一个自动释放的对象,可能堆栈跟踪可能指向发送release
消息的方法......这将非常有用......
否则,我会尝试NSLog
一些NSString
的地址,以便您可以将它们与您在错误日志中找到的地址进行比较(同样,请尝试找出哪些地址)在重新分配后,字符串实际上被重用了。
最后,另一种找出删除后使用哪个字符串的方法可能是使用方法调整来用您的方法替换NSString
的{{1}},然后调用调优的{{1} },做一些对象的记录。这将产生很多日志信息,但是知道字符串的地址,您可以轻松找到所需内容。查找有关调配的here信息。
答案 1 :(得分:0)
这是追踪的噩梦。我有一个返回NSString *
的方法,然后由另一个方法解析以生成XML文档,然后通过第二个方法释放。我实际上需要在第一种方法中自动释放它。