所以在我的视图控制器中,我运行代码来填充客户(自定义类)对象的 NSArray。这个自定义类的对象属于另一个名为 Address 的自定义类(客户有一个帐单地址和一个送货地址)。在视图控制器中,当列表中的客户被选中时,它会向新的视图控制器传递一个客户对象,如下所示:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
InfoViewController *customerinfoViewController = [[InfoViewController alloc] initWithStyle:UITableViewStyleGrouped andCustomer:[[[customers objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] retain]];
[self.navigationController pushViewController:customerinfoViewController animated:YES];
[customerinfoViewController release];
}
我第一次在运行应用程序时访问这个视图控制器,它工作正常。但是,当我重新访问视图控制器时,会发生一些有趣的事情。应用程序崩溃,无法识别的选择器发送到实例 0x00whatever。使用 xCode 中的鼠标悬停调试功能,我发现客户的 shipAddress 变量的第一个对象的类型从 NSString 更改为 NSIndexPath。这不会发生在客户的 billAddress 对象上。有人知道这里发生了什么吗?似乎我可能遇到了内存管理问题,但在我撕开我的代码跟踪所有保留和释放之前,我肯定希望对此进行确认......
编辑:更多信息在这里。使用以下代码,我在类级别有一个 NSMutableArray。在循环的每次迭代中,我都会遍历 XML 中的节点(效果很好)。每次检测到一个新字母作为名称的第一个字母时,我都会创建一个新的子数组并将客户添加到其中,从而为我的类级别 NSMutableArray (customers) 填充每个检测到的字母表中的客户子数组。我的问题是关于循环客户对象的保留和释放。Clang Static 说客户有一个过度保留的错误,但是当我根据 Clang 修复它时,循环崩溃了。是什么赋予了?相关代码如下:
DDXMLDocument *rootDoc = [[[DDXMLDocument alloc] initWithData:xmlData options:0 error:nil] autorelease];
NSArray *elems = [rootDoc nodesForXPath:@"QBXML/QBXMLMsgsRs/CustomerQueryRs/CustomerRet" error:nil];
DDXMLNode *node;
sectionTitles = [[[NSMutableArray alloc] initWithCapacity:1] retain]; // Letters for UITableView section titles
NSMutableArray *subArray;
NSString *lastchar = @"A";
NSString *testchar;
int indexCount = -1;
customers = [[[NSMutableArray alloc] initWithCapacity:[elems count]] retain];
Customer *newCust;
for (int i = 0; i < [elems count]; i++) {
node = [elems objectAtIndex:i];
newCust = [[Customer alloc] initWithCustomerRetNode:node];
testchar = [[newCust fullName] substringToIndex:1];
if (i == 0 || ![[testchar uppercaseString] isEqualToString:lastchar]) {
[sectionTitles addObject:testchar];
lastchar = testchar;
indexCount++;
subArray = [[NSMutableArray alloc] initWithCapacity:1];
[customers addObject:subArray];
[subArray release];
[[customers lastObject] addObject:[newCust retain]];
}
else {
[[customers lastObject] addObject:[newCust retain]];
}
[newCust release];
}
注意:这段代码在大多数情况下都有效,但 clang 不喜欢它。
编辑: Customer 类中的地址是这样分配的(在 Clang 修复后现在不起作用)
...
else if ([tempname isEqualToString:@"BillAddress"])
billAddress = [billAddress initWithAddressNode:tempnode];
else if ([tempname isEqualToString:@"ShipAddress"])
shipAddress = [shipAddress initWithAddressNode:tempnode];
...