IOS开发之带返回值的函数当不应加autorelease

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分析的很有道理,确实是这两个问题。你的该法也很完美,谢谢!