簡體   English   中英

iPhone上的內存泄漏:(

[英]Leaking Memory on iPhone :(

我是C,Obj-C和iPhone的初學者,我正在嘗試掌握很多使用的術語。 我希望你們中的一個可以幫助解決我幾天來一直在苦苦掙扎的問題。

我下面的代碼是一種調用包含搜索字段和表的筆尖的方法。 該表是從下面為“ theList”創建的數組的搜索中填充的。 使用'Instruments',我得到了泄漏: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];

}

提前致謝!

這將返回分配的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將自動釋放。

編輯 :仍然有問題...我不確定如何在應用程序委托中操作客戶端,否則代碼應該可以正常工作,我創建了一個小示例,省略了我看不到的部分(應用程序委托和客戶端):

//命令行實用程序-基礎工具項目:

#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;
}

您正在使用[[NSNumber alloc] init]創建clientID,然后立即使用自動釋放的NSNumber實例[NSNumber numberWithInt]覆蓋它,然后稍后在代碼中釋放它,您不應該這樣做。 擺脫[[NSNumber alloc] init]行和[clientId release]行,這應該可以對其進行一些修復。

除了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];
}

有一些讓我懷疑的神秘之處:

  • for循環之后的那一行告訴pickList對NSMutableArray做一些事情。 該方法應保留新數組 ,如果存在則釋放舊數組 如果僅覆蓋指針,則舊數組將泄漏。 (此外,此方法的命名很差。匿名參數(沒有前文字的冒號)在Objective-C中是合法的,但被認為是非常糟糕的做法。請考慮重命名該方法以更好地表達其作用。)
  • 下一行似乎將選擇列表與導航控制器相關聯。 如果是自定義代碼,請確保-pushViewController:animated:方法在指定新的選擇列表后正確釋放現有的選擇列表。
  • 假定分配給appDelegate.returningID來調用setter的returningID屬性。 確保屬性根據需要保留或復制NSNumber

即使在Instruments中,內存泄漏也很難跟蹤,並且您經常會發現它看起來像是基礎類(例如NSDictionary )正在像篩子一樣泄漏,但是我一直能夠將其追溯到我的代碼。 :-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM