我是C,Obj-C和iPhone的初学者,我正在尝试使用大量的术语。我希望你们中的一位能帮助解决我几天来一直在努力解决的问题。
下面的代码是调用包含搜索字段和表格的笔尖的方法。该表是通过搜索为下面的'theList'创建的数组来填充的。使用'乐器',我在线上得到了泄漏: NSDictionary * theItem = [NSDictionary dictionaryWithObjectsAndKeys:clientName,@“Name”,clientId,@“Id”,nil]; ,但我无法弄清楚原因:(
我知道这可能是一个难以回答的问题,但如果有任何人可以提供任何帮助!
- (void)editClient:(id)sender {
if (pickList == nil) {
pickList = [[PickFromListViewController alloc] initWithNibName:@"PickList" bundle:nil];
}
TimeLogAppDelegate *appDelegate = (TimeLogAppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableArray *theList = [[NSMutableArray alloc] init];
int i;
for (i=0;i < [appDelegate.clients count];i++) {
Client *thisClient = [appDelegate.clients objectAtIndex:i];
NSString *clientName = [[NSString alloc] initWithString: thisClient.clientsName];
NSNumber *clientId = [[NSNumber alloc] init];
clientId = [NSNumber numberWithInt:thisClient.clientsId];
NSDictionary *theItem = [NSDictionary dictionaryWithObjectsAndKeys:clientName,@"Name",clientId,@"Id",nil];
[theList addObject:theItem];
theItem = nil;
[clientName release];
[clientId release];
}
[pickList createSearchItems:theList :NSLocalizedString(@"Client",nil)];
[theList release];
appDelegate.returningID = [NSNumber numberWithInt: projectsClientsId];
[self.navigationController pushViewController:pickList animated:YES];
}
提前致谢!
答案 0 :(得分:9)
返回已分配的NSNumber实例。
NSNumber *clientId = [[NSNumber alloc] init];
这一行用另一个NSNumber实例覆盖上面的clientId,numberWithInt返回自动释放的对象,因为你没有为它分配内存,你不应该调用release,它会自动释放。
clientId = [NSNumber numberWithInt:thisClient.clientsId];
您正在调用clientId上的release,因此您会遇到内存问题。 要修复它,请删除上面第一行在这种情况下无用,并将第二行更新为:
NSNumber * clientId = [NSNumber numberWithInt:thisClient.clientsId];
然后删除:
[clientId release]
因为clientId会自动释放。
编辑:重新出现问题...... 我不确定如何操纵app delegate中的客户端,否则代码应该可以正常工作,我创建了一个小例子,省略了我看不到的部分(app delegate和clients):
//命令行实用程序 - 基础工具项目:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableArray * theList = [[NSMutableArray alloc] init];
int i = 0;
for (i = 0; i < 10; ++i)
{
NSString * clientName = [NSString stringWithString:@"client"]; //no need to release
NSNumber * clientId = [NSNumber numberWithInt:i];
NSDictionary * theItem = [NSDictionary dictionaryWithObjectsAndKeys:
clientName, @"name",
clientId, @"id",
nil];
[theList addObject:theItem];
}
for (id item in theList) for (id key in item) NSLog(@"%@ - %@", key, [item objectForKey:key]);
[theList release];
[pool drain];
return 0;
}
答案 1 :(得分:3)
您正在使用[[NSNumber alloc] init]
创建clientID,然后立即使用自动释放的NSNumber实例[NSNumber numberWithInt]
覆盖它,然后您将在代码中稍后发布它,这是您不应该做的。摆脱[[NSNumber alloc] init]
行和[clientId release]
行,这应该稍微修复一下。
答案 2 :(得分:1)
除了NSNumber的明显泄漏之外,我还有一些其他可能有帮助的事情。大多数都是相当小的,但根据我对Objective-C的经验,更少的代码=更清晰的代码,对于像Bash或Perl这样的语言来说,这是不同的。 ; - )
- (void) editClient:(id)sender {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (pickList == nil) {
pickList = [[PickFromListViewController alloc] initWithNibName:@"PickList" bundle:nil];
}
TimeLogAppDelegate *appDelegate = (TimeLogAppDelegate*)[[UIApplication sharedApplication] delegate];
NSMutableArray *searchItems = [NSMutableArray array];
NSMutableDictionary *itemDict = [NSMutableDictionary dictionary];
for (Client *client in appDelegate.clients) {
[itemDict setObject:[client.clientsName copy] forKey:@"Name"];
[itemDict setObject:[NSNumber numberWithInt:client.clientsId] forKey:@"Id"];
[searchItems addObject:[[itemDict copy] autorelease]];
}
[pickList createSearchItems:searchItems :NSLocalizedString(@"Client",nil)];
[self.navigationController pushViewController:pickList animated:YES];
appDelegate.returningID = [NSNumber numberWithInt: projectsClientsId];
[pool drain];
}
有一些让我怀疑的神秘点:
-pushViewController:animated:
方法在指定新选择列表时正确释放现有选择列表。appDelegate.returningID
为returningID
属性调用setter。请确保该财产在必要时保留或复制NSNumber
。即使在乐器中,内存泄漏也很难追踪,你会发现它看起来像基础类(如NSDictionary
)像筛子一样泄漏,但我一直都能够将其追溯到我的代码中的异常。 : - )