【问题标题】:ARC doesn't free memory when using blocksARC 使用块时不释放内存
【发布时间】:2014-03-28 13:40:06
【问题描述】:

我在使用 ARC 时遇到了问题。 我所做的是同步:我从 Web 服务请求数据并将其写入数据库(使用 fmdb)。

这是我的完整代码

dispatch_async(queue, ^{

    hud.labelText = [NSString stringWithFormat:@"Sincronizzo le aziende"];
    [Model syncAziende:^(id response, NSError *error) {
        hud.progress += offset;
        dispatch_semaphore_signal(sema);
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    hud.labelText = [NSString stringWithFormat:@"Sincronizzo i contatti"];
    [Model syncContatti:^(id response, NSError *error) {
        hud.progress += offset;
        dispatch_semaphore_signal(sema);
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

            ....

+ (void)syncAziende:(RequestFinishBlock)completation
{
    [self syncData:^(id response, NSError *error) {
        completation(response,error);
    } wsEndPoint:kCDCEndPointGetAziende tableName:kCDCDBAziendeTableName];
}

+ (void)syncData:(RequestFinishBlock)completation wsEndPoint:(NSString*) url tableName:(NSString *)table
{
    NSLog(@"%@",url);
    [self getDataFromWS:^(id WSresponse, NSError* WSError)
     {
         if (!WSError)
             [self writeDatatoDB:^(id DBresponse,NSError* DBError)
              {
                  completation(DBresponse,DBError);
              }table:table shouldDeleteTableBeforeUpdate:YES data:WSresponse];
         else
             completation(nil,WSError);
         WSresponse = nil;
     }WSUrl:url];
}

+ (void)getDataFromWS:(RequestFinishBlock)completation WSUrl:(NSString *)svcUrl
{
    [self getJsonDataFromURL:^(id response, NSError *error)
     {
         completation(response,error);
     }url:svcUrl];
}

+(void)getJsonDataFromURL:(RequestFinishBlock)completation url:(NSString*)url
{
    AFHTTPRequestOperationManager *manager = [self getAuthorizedRequestionOperationManager];

    if (manager) { //OK I'have internet connection
        [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        [manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];

        [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
            completation([responseObject objectForKey:@"d"],nil);
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            completation(nil,error);
        }];
    }
    else //ERROR: I don't have internet connection
    {
        NSDictionary *dError = [[NSDictionary alloc] initWithObjectsAndKeys:kCDCErrorNoInternetConnectionStatusMessage,@"error", nil];
        NSError *error = [[NSError alloc]initWithDomain:url code:kCDCErrorNoInternetConnectionStatusCode userInfo:dError];
        completation(nil,error);
    }
}


+ (void) writeDatatoDB:(RequestFinishBlock)completion
                 table:(NSString *)tableName
shouldDeleteTableBeforeUpdate:(BOOL)deleteTable
                  data:(NSMutableArray *)data
{
    NSLog(@"Inizio le operazioni sul database");
    __block int errors = 0;

    classAppDelegate *appDelegate = (classAppDelegate *)[[UIApplication sharedApplication]delegate];
    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:appDelegate.dbFilePath];
    [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        if (deleteTable)
            [db executeUpdate:[NSString stringWithFormat:@"DELETE FROM %@", tableName]];

        for (NSDictionary *jString in data)
        {
            NSMutableArray* cols = [[NSMutableArray alloc] init];
            NSMutableArray* vals = [[NSMutableArray alloc] init];

            for (id currentValue in jString)
            {
                if (![currentValue isEqualToString:@"__metadata"]) {
                    [cols addObject:currentValue];
                    [vals addObject:[jString valueForKey:currentValue]];
                }
            }

            NSMutableArray* newCols = [[NSMutableArray alloc] init];
            NSMutableArray* newVals = [[NSMutableArray alloc] init];
            NSString *value = @"";

            for (int i = 0; i<[cols count]; i++) {
                @try {
                    NSString *element = [vals objectAtIndex:i];
                    if (![element isKindOfClass:[NSNull class]]) {
                        value = [element stringByReplacingOccurrencesOfString:@"'" withString:@"''"];
                        [newCols addObject:[NSString stringWithFormat:@"'%@'", [cols objectAtIndex:i]]];
                        [newVals addObject:[NSString stringWithFormat:@"'%@'", value]];
                    }
                }
                @catch (NSException *exception) {

                }
            }

            NSString* sql = [NSString stringWithFormat:@"INSERT INTO %@ (%@) VALUES (%@)",tableName, [newCols componentsJoinedByString:@", "], [newVals componentsJoinedByString:@", "]];
            [db executeUpdate:sql];

            if([db lastErrorCode] == 1) //ERRORE!!
            {
                errors++;
            }
        }
        completion(nil,nil);


        NSLog(@"Ho completato le operazioni sul database con %i errori",errors);
    }];
}

我从 webservice 获得的数据约为 75mb,但在 Xcode 中我看到内存达到 500mb,这导致 iPad 2 崩溃。

【问题讨论】:

    标签: ios objective-c memory-management automatic-ref-counting


    【解决方案1】:

    你确实在你的区块中做了一个保留周期

    这主要发生在你在块中调用 self 时。所以 self 保留在块和主序列中。所以两者都相互支持,ARC 认为两者都是对方所需要的。

    你应该使用弱自我或其他类似的方法。

    这里有一些帮助:The Correct Way to Avoid Capturing Self in Blocks With ARC

    【讨论】:

    • 感谢您的回复,但我不会在任何地方使用 self。
    • 如果您使用 iVar(例如 _myLabel),则结束相同。
    • 如果你看到代码模型使用静态方法没有本地实例的类型。
    • 我在第 37 行看到一个 self
    • 我根据您的建议更正了代码:paste.ubuntu.com/7173485 但没有任何变化。
    【解决方案2】:

    libextobjc 有一些有用的宏来帮助解决这个问题,请参阅http://aceontech.com/objc/ios/2014/01/10/weakify-a-more-elegant-solution-to-weakself.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      • 2013-12-23
      • 2012-05-22
      • 2014-02-10
      • 2016-01-06
      • 2012-04-17
      相关资源
      最近更新 更多