1
votes

All

When I using NSTimer to complete my task, I meet some problem. I need Some Help, thanks.

Here is the Problem.

When I am using the NSTimer to show animation on UIImageView. but the UIImageView just update at the first time when I run the code in my iphone4s, using xcode. when the UIImageView appear again, it does not update the image content. I have checked the log, the timer is called every time, and the code is covered when it runs.

NSTimer:

if (networkStatusTimer == nil) {
        networkStatusTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(getcurrentNetworkDelayStatus) userInfo:nil repeats:YES];

The networkStatusImageView Initialization Part:

- (UIImageView *)networkStatusImageView
{
    if (nil == _networkStatusImageView) {
        CGRect rect = CGRectMake(246, 12, 24, 8);
        _networkStatusImageView = [[UIImageView alloc]initWithFrame:rect];
        _networkStatusImageView.contentMode = UIViewContentModeRight | UIViewContentModeTop;

        UIImageView *img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_redsolid_1X"]];
        UIImageView *img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_redhollow_1x"]];
        UIImageView *img3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"talk_icon_whitehollow_1x"]];

        img2.left = img1.right;
        img3.left = img2.right;

        [_networkStatusImageView setNeedsDisplay];
        [_networkStatusImageView addSubview:img1];
        [_networkStatusImageView addSubview:img2];
        [_networkStatusImageView addSubview:img3];
    }
    return _networkStatusImageView;
}

The Selector Code:

- (void) getcurrentNetworkDelayStatus {
    currentNetworkDelayTime = 0;
    [_networkStatusImageView removeAllSubviews];
    UIImageView *img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_redhollow_1x"]];
    UIImageView *img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_redhollow_1x"]];
    UIImageView *img3 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_redhollow_1x"]];

    dispatch_async(dispatch_get_main_queue(), ^{
    if (currentNetworkDelayTime == 0) { 
        if (currentISRed) {
            img1.image = [UIImage imageNamed:@"talk_icon_redhollow_1x"];
            img2.image = [UIImage imageNamed:@"talk_icon_redhollow_1x"];
            img3.image = [UIImage imageNamed:@"talk_icon_redhollow_1x"];
        } else {    // 显示红色实心
            img1.image = [UIImage imageNamed:@"talk_icon_redsolid_1X"];
            img2.image = [UIImage imageNamed:@"talk_icon_redsolid_1X"];
            img3.image = [UIImage imageNamed:@"talk_icon_redsolid_1X"];
        }
        currentISRed = !currentISRed;
    } else if(currentNetworkDelayTime > 0 && currentNetworkDelayTime <= 500){ 
        img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_greensolid1X"]];
        img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_greensolid1X"]];
        img3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"talk_icon_greensolid1X"]];
    } else if(currentNetworkDelayTime > 500 && currentNetworkDelayTime <= 3000){   
        img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_greensolid1X"]];
        img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_greensolid1X"]];
        img3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"talk_icon_greenhollow_1x"]];
    } else if (currentNetworkDelayTime > 3000){
        img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_greensolid1X"]];
        img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"talk_icon_greenhollow_1x"]];
        img3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"talk_icon_greenhollow_1x"]];
    }

    img2.left = img1.right;
    img3.left = img2.right;

    [img1 setNeedsDisplay];
    [img2 setNeedsDisplay];
    [img3 setNeedsDisplay];
    [_networkStatusImageView setNeedsDisplay];

    [_networkStatusImageView addSubview:img1];
    [_networkStatusImageView addSubview:img2];
    [_networkStatusImageView addSubview:img3];
    });
}
3
the setNeedsDisplay calls are not needed - Daij-Djan
likely your _networkStatusImageView is nil - Daij-Djan
lastly: why the dispatch_async? - Daij-Djan
Yes, I also didn't see the setNeedsDisplay works, I will remove the setNeedsDisplay calls. _networkStatusImageView is initialized before, It will not be nil. Code Below: - 陈健 Mark
I think maybe the problem is for process synchronization. so I added the dispatch_async to update UI in the main thread. - 陈健 Mark

3 Answers

0
votes

Every time the function gets called you set the currentNetworkDelayTime to 0. Which means that only the:

if (currentNetworkDelayTime == 0) { 
    if (currentISRed) {
        img1.image = [UIImage imageNamed:@"talk_icon_redhollow_1x"];
        img2.image = [UIImage imageNamed:@"talk_icon_redhollow_1x"];
        img3.image = [UIImage imageNamed:@"talk_icon_redhollow_1x"];
    } else {    // 显示红色实心
        img1.image = [UIImage imageNamed:@"talk_icon_redsolid_1X"];
        img2.image = [UIImage imageNamed:@"talk_icon_redsolid_1X"];
        img3.image = [UIImage imageNamed:@"talk_icon_redsolid_1X"];
    }
    currentISRed = !currentISRed;
}

Gets called. So you need to change the line currentNetworkDelayTime = 0; to currentNetworkDelayTime++;

And you don't have to add the images to the current UIView every time, just create them one time in ex. viewDidLoad and make a global variable for them.

Once you have done that, add this method to make your code shorter:

-(void)changeView:(NSArray *)strArray {
    NSArray *viewArray = [[NSArray alloc] initWithObjects:view1, view2, view3, nil];
    for (int a = 0; 0 < 3; a++) {
        UIImageView *img = viewArray[a];
        img.image = [UIImage imageNamed:strArray[a]];
        [img setNeedsDisplay]; // If you really want to do this.
    }
}

And call it like this

[self changeView:[[NSArray alloc] initWithObjects:@"Image_for_img1.suffix", @"Image_for_img2.suffix", @"Image_for_img3.suffix", nil]];
0
votes

I have tested your code on my computer and I got it working.

In Header file:

@property(nonatomic,strong)UIImageView *networkStatusImageView;

In viewDidLoad:

[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(test) userInfo:Nil repeats:YES];
self.networkStatusImageView = [self networkStatusImageView];
[self.view addSubview:self.networkStatusImageView];

function networkStatusImageView:

- (UIImageView *)networkStatusImageView
{
if (nil == _networkStatusImageView) {
    CGRect rect = CGRectMake(0, 0, 300, 50);
    _networkStatusImageView = [[UIImageView alloc]initWithFrame:rect];
    _networkStatusImageView.contentMode = UIViewContentModeRight | UIViewContentModeTop;

    for (int a = 0; a < 3; a++) {
    UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(100*a, 0, 100, 50)];
    [img setBackgroundColor:[UIColor blueColor]];
    [_networkStatusImageView addSubview:img];
}
}
return _networkStatusImageView;
}

function test:

-(void)test {
int currentNetworkDelayTime = 0;
BOOL currentISRed = NO;
NSArray *subViews = [self.networkStatusImageView subviews];
UIImageView *img1 = [subViews objectAtIndex:0];
UIImageView *img2 = [subViews objectAtIndex:1];
UIImageView *img3 = [subViews objectAtIndex:2];
if (currentNetworkDelayTime == 0) {
    if (currentISRed) {
        [img1 setBackgroundColor:[UIColor redColor]];
        [img2 setBackgroundColor:[UIColor redColor]];
        [img3 setBackgroundColor:[UIColor redColor]];
    } else {
        [img1 setBackgroundColor:[UIColor greenColor]];
        [img2 setBackgroundColor:[UIColor greenColor]];
        [img3 setBackgroundColor:[UIColor greenColor]];
    }
}
}

I used background color instead of images because I didn't want to make images for testing this, just change it to setImage: and it should work.

-1
votes

I have solved my problem, solution below:

I checked the problem carefully and I create three UIImage field var. below:

@property (nonatomic, weak) UIImage *imgFile1;
@property (nonatomic, weak) UIImage *imgFile2;
@property (nonatomic, weak) UIImage *imgFile3;

and link them with the xib image resource.

This implementation of the feature is not good and I plan to re-implement it next version, there is too much memory allocation and release, some allocation and release can be removed to make the code more efficient.

Thanks all the guys help me.