在 NSTimer 方法中更改时 UIView 没有响应

UIView is not responding when changed in NSTimer method

我有这个 NSTimer 重复循环,它会检查我的应用程序中是否有任何新闻。检查部分是无关紧要的,它工作正常,但为了显示是否有新闻,我制作了一个名为 orangeDot 的 UIView。如果有新闻,这应该是 orangeDot.alpha = 1.0,如果没有,则应该是 orangeDot orangeDot.alpha = 0.0。但它并不总是有效。有时,当有新闻时,orangeDot 会隐藏 (alpha=0),有时则相反。这是代码:

-(void) checkForNews {
    NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
    bool news = (([defaults boolForKey:@"newsFromChat"]) || ([defaults boolForKey:@"newsFromAwaiting"])) ? YES : NO;

    if (news) {
        NSLog(@"yay news");
        [orangeDot setAlpha:1.0f];
    } else {
        NSLog(@"nothing new");
        [orangeDot setAlpha:0.0f];
    }

    NSLog(@"%@",orangeDot);
}

NSLog 工作完美,这部分从来没有问题,但即使日志显示 "yay news" orangeDot 也可能被隐藏,反之亦然。但有时它会起作用......我还没有在错误中找到模式。 我不得不提到 .alpha 和 .hidden 都不能正常工作。

orangeDot 是这样坐起来的:

@property (nonatomic, retain) IBOutlet UIView * orangeDot;

并在故事板中连接。

请帮忙:)

根据您的代码,我有两点想法:

  1. UIView 更新应该在主线程上进行。检查你是从主线程调用这个方法,还是从主线程调用这个方法。

    - (void)checkForNews {
    
        dispatch_async(dispatch_get_main_queue(), ^{
    
            NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
            bool news = (([defaults boolForKey:@"newsFromChat"]) || ([defaults boolForKey:@"newsFromAwaiting"])) ? YES : NO;
    
            if (news) {
                NSLog(@"yay news");
                [orangeDot setAlpha:1.0f];
            } else {
                NSLog(@"nothing new");
                [orangeDot setAlpha:0.0f];
            }
    
            NSLog(@"%@",orangeDot);
        });
    }
    
  2. 您的 orangeDot 声明似乎有点可疑。您是否声明了其他同名变量?尝试调用 self.orangeDot 而不是仅调用 orangeDot。通常 Xcode 不要让我们像您那样访问 IBOutlet。如果您声明了一次并且正确,您将能够通过 self.orangeDot_orangeDot(带有初始下划线字符)访问该对象。

    //using .self
    [self.orangeDot setAlpha:1.0f];
    
    //or using underline to access the var. without setter
    [_orangeDot setAlpha:1.0f];
    

更新:

您真的需要循环检查用户默认设置的更新吗?忘记这个计时器的东西并实现 NSNotification 模式(或委托,或其他)怎么样?你只需要发送一个通知事件并在你的相关视图控制器上监听它:我希望你已经知道如何实现它,但我会在这里留下一个小例子:

//Somewhere ... just after you update your news data.
[[NSNotificationCenter defaultCenter] postNotificationName:@"NewChatDataAvailable" object:nil];

此时,您是在告诉整个应用程序您有可用的新聊天数据,而无需循环进行不必要的检查。现在我们需要做的就是注册以接收此通知:

//In this example I will register on viewDidLoad:

- (void)viewDidLoad:(BOOL)animated {

    [super viewDidLoad:animated];

    //Now, your method will be called on when necessary (when data arrives)
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(checkForNews)
                                                 name:@"NewChatDataAvailable"
                                               object:nil];
}

现在,让我们稍微改进一下您的代码:

- (void)checkForNews {

    dispatch_async(dispatch_get_main_queue(), ^{

        NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];

        //You don't need to put the ? YES : NO stuff, and BOOL in capital letters
        BOOL hasNews = (([defaults boolForKey:@"newsFromChat"]) ||
                         ([defaults boolForKey:@"newsFromAwaiting"]));

        if (hasNews) {
            NSLog(@"yay news");
            [self.orangeDot setAlpha:1.0f];
        } else {
            NSLog(@"nothing new");
            [self.orangeDot setAlpha:0.0f];
        }

        NSLog(@"%@",self.orangeDot);
    });
}

希望对你有所帮助。而且......当你用代码或其他东西更新你的问题时,编辑你的问题并在那里插入代码,不要post它作为答案。

感谢您到目前为止的帮助!

更好地概述代码:

...
@synthesize orangeDot; 
... 

- (void) viewDidLoad {
   ...
   [self reloader];
   ...
}

- (void) reloader{
    if (refreshAuto == nil) {
    refreshAuto = [NSTimer scheduledTimerWithTimeInterval: 2.0
                      target: self selector:@selector(checkForNews) userInfo: nil repeats:YES];
    }    
}

 - (void)checkForNews {
    dispatch_async(dispatch_get_main_queue(), ^{
    NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
    bool news = (([defaults boolForKey:@"newsFromChat"]) || ([defaults boolForKey:@"newsFromAwaiting"])) ? YES : NO;

    if (news) {
        NSLog(@"yay news");
        [orangeDot setAlpha:1.0f];
    } else {
        NSLog(@"nothing new");
        [orangeDot setAlpha:0.0f];
    }

    NSLog(@"%@",orangeDot);
    });
}

当显示 orangeDot 时,日志有时看起来像这样:

...
2015-05-25 12:02:23.788 Teazr[1314:442396] nothing new
2015-05-25 12:02:23.789 Teazr[1314:442396] <UIButton: 0x154520f40; frame = (322 47; 11 11); alpha = 0; opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x17422a740>>
...

@synthesizing 是个人喜好,不是必需的。但它的工作方式与 self.orangeDot 相同,没有合成..