UIView не отвечает при изменении в методе NSTimer

У меня есть этот повторяющийся цикл NSTimer, который проверит, есть ли какие-либо новости в моем приложении. Проверяющая часть не имеет значения и работает нормально, но чтобы показать, есть ли новости или нет, я сделал UIView под названием orangeDot. Это должно быть orangeDot.alpha = 1.0 если есть новости и апельсин orangeDot.alpha = 0.0 если не. Но это не всегда работает. Иногда orangeDot скрыт (альфа =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 работает отлично, и с этой частью проблем никогда не бывает, но, несмотря на то, что в журнале написано "ура новости", OrangeDot может быть скрыт, и снова наоборот. Но иногда это работает... Я еще не нашел шаблон в ошибке. Я должен отметить, что ни альфа, ни скрытый не работают правильно.

OrangeDot устроился так:

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

и подключен в раскадровке.

Пожалуйста помоги:)

2 ответа

Решение

Основываясь на вашем коде, я имею в виду две вещи:

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

Я надеюсь, что это поможет вам. И... когда вы обновляете свой вопрос кодом или чем-то другим, редактируйте свой вопрос и вставляйте туда код, не публикуйте его как ответ.

Спасибо за помощь!

Лучший обзор кода:

...
@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 и без синтеза.

Другие вопросы по тегам