3

У меня проблема с индикатором активности в сети, так как иногда он будет отображаться, когда это не должно быть.Фиксация индикатора активности в сети

я написал свой собственный менеджер для него и сменил его за один, который использует NSAssert заявление, как это ...

- (void)setNetworkActivityIndicatorVisible:(BOOL)setVisible { 
    static NSInteger NumberOfCallsToSetVisible = 0; 
    if (setVisible) 
     NumberOfCallsToSetVisible++; 
    else 
     NumberOfCallsToSetVisible--; 

    // The assertion helps to find programmer errors in activity indicator management. 
    // Since a negative NumberOfCallsToSetVisible is not a fatal error, 
    // it should probably be removed from production code. 
    NSAssert(NumberOfCallsToSetVisible >= 0, @"Network Activity Indicator was asked to hide more often than shown"); 

    // Display the indicator as long as our static counter is > 0. 
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:(NumberOfCallsToSetVisible > 0)]; 
} 

Я нашел его на SO, и он сразу же обратил внимание на то, что что-то происходит не так с моим использованием этой функции.

Вся моя сетевая деятельность осуществляется исключительно через один NSOperationQueue, который управляется одним типом класса. Каждая операция является подклассом NSOperation (фактически подклассом TemplateOperation, который является подклассом NSOperation).

Во всяком случае, все загрузки и добавления работают отлично, и я делаю их все, как это ...

- (void)sendRequest:(NSURLRequest *)request 
{ 
    NSError *error = nil; 
    NSURLResponse *response = nil; 

    [[NetworkManager sharedInstance] setNetworkActivityIndicatorVisible:YES]; 
    NSData *data = [NSURLConnection sendSynchronousRequest:request 
             returningResponse:&response 
                error:&error]; 
    [[NetworkManager sharedInstance] setNetworkActivityIndicatorVisible:NO]; 

    // other stuff... 

    [self processData:data]; 
} 

важные линии непосредственно до и после того, как я посылаю NSURLConnection синхронно.

Непосредственно перед отправкой запроса я установил индикатор сетевой активности в видимый (используя мой класс менеджера), а затем сразу же после того, как я верну его обратно к невидимому.

Кроме того, NSAssert указал, что где-то это происходит неправильно.

Может случиться так, что запуск этой функции из нескольких потоков может вызвать проблему? Как я могу это решить?

+1

Это должно помочь https://github.com/rs/SDNetworkActivityIndicator – Moxy

+0

Спасибо очень много! Два замечательных ответа: D – Fogmeister

ответ

7

Целочисленное приращение или уменьшение не является потокобезопасным (насколько я знаю), поэтому, если два потока вызовут ваш метод «одновременно», счетчик может не обновиться должным образом.

Одним из решений было бы добавить некоторую директиву синхронизации (например, @synchronized) к вашему методу. Или использовать атомные функции инкремента/декремента:

#include <libkern/OSAtomic.h> 

- (void)setNetworkActivityIndicatorVisible:(BOOL)setVisible { 
    static volatile int32_t NumberOfCallsToSetVisible = 0; 
    int32_t newValue = OSAtomicAdd32((setVisible ? +1 : -1), &NumberOfCallsToSetVisible); 

    NSAssert(newValue >= 0, @"Network Activity Indicator was asked to hide more often than shown"); 
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:(newValue > 0)]; 
} 
+0

Отлично, спасибо большое. – Fogmeister

+0

@Fogmeister: Пожалуйста, посмотрите на http://stackoverflow.com/questions/17176190/objective-c-thread-safe-counter/17177772#17177772 о недостатке в моем ответе :-) –

Смежные вопросы