修复我的网络活动指示器

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)];
}

我在stackoverflow上找到了这篇文章,它立刻指出我的函数使用出现了问题。

我的所有网络活动都是通过一个单例类管理的单个NSOperationQueue运行的。每个操作都是NSOperation的子类(实际上是继承自模板操作TemplateOperationNSOperation子类)。

无论如何,所有的下载和上传都正常工作,我是通过以下方式进行操作的...

- (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
1个回答

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)];
}

@Fogmeister:请看一下http://stackoverflow.com/questions/17176190/objective-c-thread-safe-counter/17177772#17177772,了解我的回答中的缺陷 :-) - Martin R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接