修复我的网络活动指示器

时间:2013-05-07 13:30:06

标签: ios objective-c network-programming nsoperation nsoperationqueue

我的网络活动指示器存在问题,有时它会在不应该显示时继续显示。

我为自己编写了自己的经理并将其换成了一个使用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进行的,该单- (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]; } 由单例类管理。每个操作都是NSOperation的子类(实际上是TemplateOperation的子类,它是NSOperation的子类)。

无论如何,所有的下载和上传都运行正常,我这样做就是这样......

NSURLConnection

重要的行是在我同步发送{{1}}之前和之后。

在我发送请求之前,我将网络活动指示器设置为可见(使用我的经理类),然后在我将其设置为不可见之后立即显示。

除了NSAssert指出某些地方没有正确发生这种情况。

可能是因为从多个线程运行此函数可能会导致问题吗?我怎么能解决这个问题?

1 个答案:

答案 0 :(得分: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)];
}