0
[client enqueueBatchOfHTTPRequestOperations:@[profileOperation,commFriendsOperation] progressBlock:^(NSUInteger finished, NSUInteger total){} completionBlock:^(NSArray *completedRequests){
//Code here
}]

下面的代码位于 AFNetworking 批处理请求成功块中。仪器表明,正如它所评论的那样,代码爆炸存在内存泄漏。但是,我无法弄清楚它是如何泄漏的以及如何修复它,有人知道吗?

提前致谢。

AFHTTPRequestOperation *commFriendsRequest = [completedRequests objectAtIndex:1];
    if(!commFriendsRequest.error&&commFriendsRequest.responseData){
        //Leak 46.2%
        NSDictionary *commDic = [NSJSONSerialization JSONObjectWithData:commFriendsRequest.responseData options:NSJSONReadingMutableContainers error:NULL];
        int status1 = [[commDic objectForKey:@"status"]intValue];
        if(status1 == kSuccessCode){
            NSArray *commFriendsArray = [commDic objectForKey:@"data"];
            if(commFriendsArray&&commFriendsArray.count){
                //Leak 30.8%
                NSMutableArray *userItems = [NSMutableArray arrayWithCapacity:commFriendsArray.count];
                for(NSDictionary *dic in commFriendsArray){
                    //Leak 23.1%
                    userItem *item = [[userItem alloc]initFromServer:dic];
                    [userItems addObject:item];
                }
                if(profile){//Both Success
                    profile.commonFriends = userItems;
                    successBlock(profile);//block call back
                }else{
                    if(status0==kSuccessCode){
                        successBlock(userItems);//block call back
                    }else{
                        NSError *error = [NSError errorWithDomain:kErrorDomain code:status0 userInfo:nil];
                        failedBlock(error);//block call back
                    }
                }
            }else if(status0==kSuccessCode){//CommFriends 0 has profile
                successBlock(profile);//block call back
            }
        }else{
            if(status0==kSuccessCode){//CommFriends failed has profile
                successBlock(profile);//block call back
            }else{//Both failed
                NSError *error = [NSError errorWithDomain:kErrorDomain code:status1 userInfo:nil];
                failedBlock(error);//block call back
            }
        }
    }else{
        failedBlock(commFriendsRequest.error);
    }


//[[userItem alloc] initFromServer:dict] code
-(id)initFromServer:(NSDictionary *)dict{
if ((self = [super init])) {
    NSString *_userID = [dict objectForKey:@"userID"];
    NSString *_userName = [dict objectForKey:@"userName"];
    genderType _userGender = [[dict objectForKey:@"userGender"] integerValue];
    NSString *_userHeadImageURL = [dict objectForKey:@"userHeadImageURL"];
    NSString *_source = [dict objectForKey:@"source"];
    int _likeCount = [[dict objectForKey:@"likedCount"] intValue];
    int _sameFriends = [[dict objectForKey:@"sameFriends"] intValue];
    NSString *_homePage = [dict objectForKey:@"homePage"];

    NSString *_createTime = [dict objectForKey:@"createTime"];
    if([dict objectForKey:@"dis"])
        _distance = [[dict objectForKey:@"dis"]floatValue];
    else
        _distance = 0;

    if ([dict objectForKey:@"uid"]) {
        self.uid = [[dict objectForKey:@"uid"] intValue];
    }
    else{
        self.uid = -1;
    }

    self.userID = _userID;
    self.userName = _userName;
    self.userGender = _userGender;
    self.userHeadImageURL = _userHeadImageURL;
    self.source = _source;
    self.likeCount = _likeCount;
    self.sameFriends = _sameFriends;
    if (_homePage && ![_homePage isKindOfClass:[NSNull class]]) {
        self.homePage = _homePage;
    }

    if([dict objectForKey:@"hasJoin"]){
        self.hasJoined = [[dict objectForKey:@"hasJoin"]boolValue];
    }

    if (_createTime && ![_createTime isKindOfClass:[NSNull class]]) {
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
        self.createTime = [dateFormatter dateFromString:_createTime];
    }

    NSString *c = [dict objectForKey:@"comment"];
    if (c && ![c isKindOfClass:[NSNull class]]) {
        self.comment = c;
    }
}
return self;

}

4

2 回答 2

0

将alloccopynew创建的对象添加到容器后,您应该释放它。添加消息将增加保留计数。

//Leak 23.1%
userItem *item = [[userItem alloc]initFromServer:dic];  // [item retainCount] == 1 
[userItems addObject:item];  // [item retainCount] == 2
[item release];  // [item retainCount] == 1

如果 userItems 被释放,[item retainCount] == 0,将被销毁。

于 2013-11-15T07:20:11.490 回答
0

请注意,Instruments 会告诉您泄漏对象的分配位置(因为这有助于您了解它是哪个对象),但这并不意味着泄漏位于或接近分配位置。泄漏可能是由于某些其他代码过度保留或释放对象不足引起的。您必须查看特定泄漏对象的历史记录(单击地址旁边的带圆圈箭头按钮),以查看释放未通过保留平衡的位置。

您可能在后台线程上运行此代码,并且没有自动释放池。ARC 有时仍会为您自动释放对象,如果您调用 Apple 框架,它们可能仍然是非 ARC,因此它们绝对可以为您自动释放对象。所以你仍然需要一个自动释放池。

Cocoa在主线程上为您创建一个自动释放池,但在后台线程上不为您做任何事情。如果您要在不使用 NSOperation 或其他东西的情况下将某些内容启动到后台线程,您需要将该线程包装在 @autoreleasepool 中,如下所示:

- (void)doSomething {
    [self performSelectorInBackground:@selector(backgroundSomething)];
}

- (void)backgroundSomething {
    @autoreleasepool {
        NSLog(@"Here I am in the background, doing something.");
        myArray = [[NSMutableArray alloc] init];
        // etc.
    }
}
于 2013-11-15T07:37:41.983 回答