iOS 8.x + увеличение памяти AFNetworking

У меня есть приложение, которое остается открытым в течение длительного времени, делая периодические вызовы API на наш сервер с AFNetworking 2.5.0. В iOS 8.x я наблюдаю постоянное увеличение объема памяти при каждом вызове API, что в конечном итоге приводит к сбою из-за нехватки памяти.

Я выбросил весь свой код, чтобы просто использовать AFNetworking (и iOS под ним), и все еще вижу этот рост памяти. Вот очень простой пример, который воссоздает то, что я вижу: запустите приложение и начните выполнять HTTP GET.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.manager = [AFHTTPRequestOperationManager manager];

    // Don't block out text/html extensions, for this example.
    _manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
    _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", nil];

    [self getApiLoop];
    return YES;
}


- (void) getApiLoop {
    [_manager GET:@"http://www.stackoverflow.com" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"Success!");

        // Do it again
        dispatch_async(dispatch_get_main_queue(), ^{
            [self getApiLoop];
        });

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Failure!");

        // Do it again
        dispatch_async(dispatch_get_main_queue(), ^{
            [self getApiLoop];
        });

    }];
}

Я запустил тот же пример на iOS 7.0 и не вижу такого же безудержного роста памяти.

Instruments предполагает, что CFNetworking использует malloc и не освобождает часть памяти под ним.

Любые обходные пути? Нужно ли нам сообщать об ошибке в Apple?


person Moss    schedule 19.11.2014    source источник
comment
Может быть связано с этой проблемой AFNetworking: github.com/AFNetworking/AFNetworking/issues/2306 Попробуйте упомянутое там исправление и посмотрите, работает ли оно.   -  person Jon Shier    schedule 19.11.2014
comment
Тоже столкнулся с подобным поведением. Ошибки OOM из-за многократного использования вызовов AFNetworking.   -  person DoctorDbx    schedule 26.11.2014


Ответы (1)


Я нашел решение, которое хорошо работает для моей кодовой базы, рад поделиться им.

AFNetworking 2.x имеет 2 точки входа:

  • AFHTTPSessionManager.m — рекомендуется для приложений, предназначенных для iOS 7 и iOS 8.
  • AFHTTPRequestOperationManager.m — рекомендуется для приложений, которым необходимо вернуться к iOS 6.

Для моего приложения требуется iOS 6 и выше, поэтому я начал с AFHTTPRequestOperationManager.m. К сожалению, AFHTTPRequestOperationManager.m демонстрирует проблемы с памятью в iOS 8, а AFHTTPSessionManager.m — нет (!). Дважды, к сожалению, программные API для этих двух менеджеров совершенно разные.

Мое решение состояло в том, чтобы создать уровень абстракции между AFNetworking и остальной частью моего приложения, который служил для меня двум целям: приложение, которое работает на iOS 6 и не будет работать с памятью на iOS 8; и уровень абстракции, который должен помешать моей команде редактировать каждый вызов API в моем приложении каждый раз, когда изменяется AFNetworking.

Моему приложению не обязательно нужен доступ ко всему спектру функций, предоставляемых AFNetworking, поэтому я реализовал только то, что мне было нужно:

  • initWithBaseURL
  • getResponseSerializer - (Явно назван, чтобы не запутаться)
  • getRequestSerializer - (Явно назван, чтобы не запутаться)
  • setResponseSerializer - (Явно назван, чтобы не запутаться)
  • setRequestSerializer - (Явно назван, чтобы не запутаться)
  • установить заголовки с помощью setValue: forHTTPHeaderField:
  • ПОЛУЧАТЬ
  • ПОМЕЩАТЬ
  • СООБЩЕНИЕ
  • УДАЛЯТЬ
  • ... и возможность отмены операции

Одним из преимуществ уровня абстракции над AFNetworking является то, что разработчики могут эффективно упорядочивать изменения, применяемые к AFNetworking ниже. Например, при переходе AFNetworking с версии 1.x на версию 2.x потребовалась значительная доработка кода во всех приложениях для приведения их в соответствие с новыми API. С помощью уровня абстракции у вас есть возможность поддерживать согласованность API-интерфейсов вашего приложения при одновременном переводе новых API-интерфейсов AFNetworking, что ускоряет разработку.

Я поделился своим кодом под лицензией Apache 2.0 по адресу:

https://github.com/eemoss/afnetworking-abstractionlayer-ios

person Moss    schedule 26.11.2014