Установить таймер из другого класса для запуска в другом представлении - PullRequest
0 голосов
/ 22 мая 2011

РЕДАКТИРОВАТЬ: Добавил NSRunLoop из моего кода, как упоминал Дипак ниже. Это было изначально в моем коде и забыл добавить, как это было закомментировано.

У меня есть 2 класса: MainViewController и ConfigViewController. Пользователь переключается на ConfigView и использует комбо UIDatePicker / UIButton для установки даты / времени. После получения правильного времени от объекта UIDatePicker, я настроил NSTimer для запуска согласно следующему коду:

ConfigViewController.m

-(IBAction)setAlarmDate:(id)sender {
//Instantiate to get access to doAlarm:
MainViewController *mvc = [[MainViewController alloc] init];

dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
[dateFormat setTimeStyle:NSDateFormatterShortStyle];
NSString *target = [NSString stringWithFormat:@"%@",[dateFormat stringFromDate:datePicker.date]];

alarmDate = [datePicker date];

mvc.fireTimer = [[NSTimer alloc] 
                  initWithFireDate:alarmDate interval:1 target:mvc
                  selector:@selector(doAlarm:) userInfo:nil repeats:YES];

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:mvc.timer forMode:NSDefaultRunLoopMode];


[self dismissModalViewControllerAnimated:NO];
}

Метод doAlarm: выглядит следующим образом:

MainViewController.m

- (void)doAlarm:(NSTimer *)timer {

NSLog(@"Called doAlarm:");

UIImage *ac = [UIImage imageNamed:@"alarmclock.png"];
[self.alarmview setImage:ac];
[self.alarmview setHidden:NO];
[self.view addSubview:alarmview];
[self.view bringSubviewToFront:alarmview];

}

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

1) Я создаю экземпляр нового экземпляра класса MainViewController, настраиваю таймер, а затем возвращаю управление обратно «оригинальному» экземпляру MainViewController, когда увольняю MVC. На данный момент, вероятно, «новый» экземпляр MainViewController - не что иное, как свисающий указатель, и на него никогда больше не ссылаются, следовательно, нет ошибки.

2) doAlarm: ссылается на self.view, который должен предполагаться как MainViewController.view, но, поскольку он создается в контексте ConfigViewController, изображение тревоги никогда не будет видно в любом случае ...

Я полагаю, что мои теории немного необоснованны, но с моим нынешним уровнем знаний они имеют смысл для меня.

Любой свет, который ты можешь пролить на вышеприведенное, будет разбит.

Большое спасибо!

швейцарский сыр.

1 Ответ

0 голосов
/ 22 мая 2011

Если вы перейдете к документации для initWithFireDate:interval:target:selector:userinfo:repeats:, вы заметите, что во время инициализации таймера он еще не запланирован. Вам нужно будет добавить его NSRunLoop, чтобы оно заработало. Сделайте это после того, как вы инициализировали сигнал тревоги, как указано выше.

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

Вы также можете использовать scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:, который сделает это за вас.

Здесь, конечно, есть несколько других вещей.

Новый объект MainViewController

Вы правильно догадались. Вы создаете несвязанный объект, который будет просто протекать. Чтобы решить эту проблему, вы можете поддерживать слабую ссылку на объект MainViewController. Вы можете сделать это следующим образом -

@class MainViewController; // Forward declaration 

@interface ConfigViewController {
    ...
    MainViewController *mainViewController;
}
...
@property (nonatomic, assign) MainViewController *mainViewController;
...
@end

in ConfigViewController.m:

#import "MainViewController.h"

@implementation ConfigViewController

@synthesize mainViewController;
...

- (IBAction)setAlarmDate:(id)sender {
    dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateStyle:NSDateFormatterMediumStyle];
    [dateFormat setTimeStyle:NSDateFormatterShortStyle];

    alarmDate = [datePicker date];

    mainViewController.fireTimer = [[NSTimer alloc] 
                  initWithFireDate:alarmDate interval:1 target:mainViewController
                  selector:@selector(doAlarm:) userInfo:nil repeats:YES];

    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [runLoop addTimer:mainViewController.timer forMode:NSDefaultRunLoopMode];

    mainViewController = nil;
    [self dismissModalViewControllerAnimated:NO];
}
...
@end

Таймер

Я не уверен, нужен ли вам здесь повторяющийся таймер. Есть альтернатива - performSelector:withObject:afterDelay:. Это вызовет метод для объекта, который вызывается после желаемой задержки. Делает то, что называет сам. Это будет примерно так -

[mvcReference performSelector:@selector(doAlarm) 
                   withObject:nil 
                   afterDelay:[datePicker.date timeIntervalSinceNow]];

doAlarm:

Я не получил то, что вы хотели знать здесь, но вы правы. self является ссылкой на объект MainViewController. Если бы вы не сохранили контроллер представления, который отображался модально, он к тому времени был бы отклонен и освобожден.

...