IOS开发之带返回值的函数当不应加autorelease
在数据层,我们会常写类似下面的函数:
我一开始是这样写的
-(NSArray*) getBrandHonor:(NSString*) filePath{
NSArray * result = [NSArray new];
if ([self isFileExist:filePath]) {
NSData * data = [NSData dataWithContentsOfFile:filePath];
NSDictionary * dic = [data objectFromJSONData];
result=[dic objectForKey:@"Contents"];
}
return [result autorelease];
}
然后会在视图层 这样调用
@interface HonorTableView : UIView<UITableViewDelegate,UITableViewDataSource>{
UITableView * tableView;
//NSArray * currentDatas;
}
@property (nonatomic,retain) NSArray* currentDatas;
@end
@implementation HonorTableView
@synthesize currentDatas;
- (id)initWithFrame:(CGRect)frame templeteFilePath:(NSString*)filePath
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) style:UITableViewStyleGrouped];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[tableView setShowsHorizontalScrollIndicator:false];
[tableView setShowsVerticalScrollIndicator:false];
[tableView setDelegate:self];
[tableView setDataSource:self];
[self addSubview:tableView];
[tableView release];
[tableView setBackgroundView:[[[UIView alloc] init] autorelease]];
ResourceLoader *loader = [ResourceLoader getInstance];
self.currentDatas = [loader getBrandHonor:filePath];//执行完这行 currentDatas retainCount =2
}
return self;
}
#pragma mark - TableView Delegate & DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary * dic = [currentDatas objectAtIndex:section];
NSArray * arrContent = [dic objectForKey:@"Content"];
return arrContent == nil ?0:[arrContent count];
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return currentDatas == nil?0:[currentDatas count];//总崩溃到这行,我就郁闷了好半天,百思不得姐啊
}
@end
两种修改方案:
一 、数据层 返回时把autorelease去掉,可以运行了,但总感觉会有内存泄露,没有正确释放内存。
二、 数据层做如下修改,NSArray改为NSMutableArray,看项目中其他类似方法,都用的NSMutableArray,但原理还不是很明白。这可作为一道挑错的面试题了。
-(NSArray*) getBrandHonor:(NSString*) filePath{
NSMutableArray * result = [NSMutableArray new];
if ([self isFileExist:filePath]) {
NSData * data = [NSData dataWithContentsOfFile:filePath];
NSDictionary * dic = [data objectFromJSONData];
[result addObjectsFromArray:[dic objectForKey:@"Contents"]];
}
return [result autorelease];
}
- 1楼wzzvictory_tjsd昨天 22:52
- 刚开始的写法有两个问题:n问题一:nNSArray * result = [NSArray new];你alloc了一个NSArray,分配了一块由result指向的内存,里面却没有保存任何内容,然后又result=[dic objectForKey:@"Contents"];让result指向另一个NSArray对象,这样刚分配的那块内存就没有指针指向了,这就是所谓的野指针,必然会内存泄露;n问题二:n在返回的时候使用return [result autorelease];这样写肯定会崩溃,因为result此时指向的NSArray并不是你alloc出来的那个,而是result=[dic objectForKey:@"Contents"];这个NSArray不需要你维护引用计数,因此返回的时候不能使用autorelease。nn至于楼主修正后的写法,不会有内存问题,也不会有崩溃,只是完全没必要,效率不高,这个问题最简单的改法:n-(NSArray*) getBrandHonor:(NSString*) filePath{n NSArray * result = nil;n if ([self isFileExist:filePath]) {n NSData * data = [NSData dataWithContentsOfFile:filePath];n NSDictionary * dic = [data objectFromJSONData];n result=[dic objectForKey:@"Contents"];n n }n n return result;n}
- Re: xdrt81y5小时前
- 回复wzzvictory_tjsdn分析的很有道理,确实是这两个问题。你的该法也很完美,谢谢!