Ios 修复我的网络活动指示器

Ios 修复我的网络活动指示器,ios,objective-c,network-programming,nsoperation,nsoperationqueue,Ios,Objective C,Network Programming,Nsoperation,Nsoperationqueue,我的网络活动指示器有一个问题,有时它会在不应该显示的时候继续显示 我为它编写了自己的管理器,并将其替换为一个使用NSAssert语句的管理器,如下所示 - (void)setNetworkActivityIndicatorVisible:(BOOL)setVisible { static NSInteger NumberOfCallsToSetVisible = 0; if (setVisible) NumberOfCallsToSetVisible++;

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

我为它编写了自己的管理器,并将其替换为一个使用
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)];
}
- (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];
}
我发现它是这样的,它立即指出我使用这个函数时出了问题

我的所有网络活动都是通过单个
NSOperationQueue
独家运行的,该队列由singleton类管理。每个操作都是NSOperation的子类(实际上是TemplateOperation的子类,TemplateOperation是NSOperation的子类)

不管怎样,所有的下载和上传都很好,我就是这样做的

- (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)];
}
- (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
之前和之后

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

但NSAssert指出,在某些地方,这种情况并没有正常发生


是否从多个线程运行此函数可能会导致问题?如何解决这个问题?

整数递增或递减不是线程安全的(据我所知),因此如果两个线程“同时”调用您的方法,计数可能无法正确更新

一种解决方案是添加一些同步指令(例如
@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)];
}
#包括
-(void)SetNetworkActivityIndicator可视:(BOOL)setVisible{
静态易失性int32_t NumberOfCallsToSetVisible=0;
int32_t newValue=OSAtomicAdd32((setVisible?+1:-1),&NumberOfCallsToSetVisible);
NSAssert(newValue>=0,@“要求网络活动指示器隐藏的频率高于显示的频率”);
[[UIApplication sharedApplication]SetNetworkActivityIndicator可视:(newValue>0)];
}

这应该会有帮助,非常感谢!两个很棒的答案:D@Fogmeister当前位置请看一下我答案中的缺陷:-)