【问题标题】:UITableView custom class huge leakUITableView 自定义类巨大泄漏
【发布时间】:2011-03-17 12:51:56
【问题描述】:

我正在使用自定义类在表格视图上显示一些信息。 问题是只要我滚动tableview内存就会泄漏...

我想我的课堂出了点问题。

请看:

    @interface Person : NSObject {

 NSString *name;
 NSString *surname;
 NSString *address;
 NSString *email;

}

@property (nonatomic, copy) NSString *name, *surname, *address, *email;



@implementation Person
@synthesize name, surname, address, email;

-(id)init {

 [super init];
 name = [[NSString alloc] init];
 surname = [[NSString alloc] init];
 address = [[NSString alloc] init];
 email = [[NSString alloc] init];
 return self;
}



- (void)dealloc
{
 [name release];
 [surname release];
 [address release];
 [email release];
 [super dealloc];
}


#import "Person.h"

@interface Group : NSObject {

 NSString *groupTitle;
 NSMutableArray *persons;

}

@property (readwrite, copy) NSString *groupTitle;

- (void)addPerson:(Person *)person;
- (void)removeAll;
- (NSArray *)getPersons;
- (int)PersonsCount;

@end




@implementation Group
@synthesize groupTitle;



-(id)init {

 [super init];
 persons = [[NSMutableArray alloc] init];
 return self;
}


-(void)addPerson:(Person *)person {


 [persons addObject:person];

}

-(void)removeAll {

 [persons removeAllObjects];

}

-(NSArray *) getPersons {

 return [persons copy];
 [persons release];


}

-(int)personsCount {

 return [persons count];

}

-(void)dealloc {

 [groupTitle release], groupTitle = nil;
 [persons release], persons = nil;
 [super dealloc];
}


@end




- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  …….


  Group *groupForRow = [[Group alloc] init];
  Person *personForRow = [[Person alloc] init];
  personForRow = [[groupForRow getPersons] objectAtIndex:indexPath.row];

  _personName = personForRow.name;
  _personSurname = personForRow.surname;
  _personAddress = personForRow.address;
  _personEmail = personForRow.email;


  [groupForRow release], groupForRow = nil;
  [personForRow release], personForRow = nil;

  …..

  return cell

【问题讨论】:

  • NSString 是不可变的。不要到处使用副本,并使用retain 而不是copy 定义您的属性。
  • 拥有NSString 属性作为副本很好,但alloc 没有用(您只是分配空字符串)。

标签: iphone uitableview memory-management


【解决方案1】:

少量更正(阅读 cmets):

@interface Person : NSObject {
    NSString *name;
    NSString *surname;
    NSString *address;
    NSString *email;
}

// copy is OK for strings...
@property (nonatomic, copy) NSString *name, *surname, *address, *email;

@end


@implementation Person

@synthesize name, surname, address, email;

- (id)init {
    if (self = [super init]) {
        // There is no need to allocate the strings
        // In addition, once you write 'name = [[NSStrin alloc] init];' you don't use the property.
        // If you do want to use the property setter then you should write 'self.name = @"some string";'
    }
    return self;
}


- (void)dealloc {
    [name release];
    [surname release];
    [address release];
    [email release];
    [super dealloc];
}

@end


#import "Person.h"

@interface Group : NSObject {
    NSString *groupTitle;
    NSMutableArray *persons;
}

// Any special reason for "readwrite" instead of "nonatomic"?
@property (readwrite, copy) NSString *groupTitle;
// This property is more important than the string:
@property (nonatomic, retain) NSMutableArray *persons;

- (void)addPerson:(Person *)person;
- (void)removeAll;
- (NSArray *)getPersons;
- (int)PersonsCount;

@end


@implementation Group

@synthesize groupTitle, persons;

- (id)init {
    if (self = [super init]) {
        // Use the autoreleased array instance ([NSMutableArray array]) and set it to the property setter that will retain the object:
        self.persons = [NSMutableArray array];
    }
    return self;
}


- (void)addPerson:(Person *)person {
    // I prefer using properties (the "self." in the beginning) instead of the members directly...
    [self.persons addObject:person];
}

- (void)removeAll {
    [self.persons removeAllObjects];
}

// I think that this getter is unnecessary - use the property instead...
- (NSArray *) getPersons {
    // There is no need to copy
    return [persons copy];
    // Don't you have a warning for this line? It is never executed
    [persons release];
}

- (int)personsCount {
    return [self.persons count];
}

- (void)dealloc {
    [groupTitle release], groupTitle = nil;// The "groupTitle = nil" is unnecessary.
    [persons release], persons = nil;// The "persons = nil" is unnecessary.
    [super dealloc];
}

@end


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    …….


    Group *groupForRow = [[Group alloc] init];// Do you REALLY have to allocate this object each "cellForRowAtIndexPath"??
    Person *personForRow = [[Person alloc] init];// Get rid of the "= [[Person alloc] init]" - this is a leak (because of the next line)
    personForRow = [[groupForRow getPersons] objectAtIndex:indexPath.row];// If you will use the property persons instead of the "getPersons" (that copies the array) then you will get rid of another leak

    // What are these?
    _personName = personForRow.name;
    _personSurname = personForRow.surname;
    _personAddress = personForRow.address;
    _personEmail = personForRow.email;

    // The " = nil" is unnecessary here...
    [groupForRow release], groupForRow = nil;// If you won't allocate the group then you won't need this line...
    [personForRow release], personForRow = nil;// NSZombie - you release object that you don't owe (do you have crashes, that you don't know why they are happen?)

    …..

    return cell;
}

【讨论】:

  • 非常感谢,大部分漏洞都消失了,我学到了很多东西。再次感谢。
【解决方案2】:

这里有很多错误,请深入研究 Objective-C 以掌握使用 @property@synthesize 来获得正确运行的 getter/setter 方法。

至于滚动时的内存泄漏,它是由cellForRowAtIndexPath 中的allocs 引起的,它们没有被releaseautorelease 平衡。

这个:

Group *groupForRow = [[[Group alloc] init] autorelease];
Person *personForRow = [[[Person alloc] init] autorelease];

应该可以修复大部分漏洞。浏览 SO 以了解更多信息。

【讨论】:

  • groupForRow 和 personForRow 均已发布。因此,使用 autorelease 和记录 retainCount 会返回完全相同的数字。
  • 我明白了。 Group 和 Person 内部会发生什么?例如。你能[[[Group alloc] init] release] 在没有内存爆炸的情况下循环吗?
猜你喜欢
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 2021-10-02
  • 2014-02-10
相关资源
最近更新 更多