Проблемы с контроллерами вида, переходящими в фоновый режим UITabBarController


У меня есть UITabBarController с 3 контроллерами вида, подключенными к нему. Все работает нормально, кроме того, когда вы переключаетесь с одного вида на другой, новый вид занимает некоторое время, чтобы перезагрузить то, что он делал. Я знаю, что это не такая уж большая проблема, но это просто делает приложение немного неряшливым. Кто-нибудь знает, как я могу держать приложение запущенным в фоновом режиме, или что-то такое, что не нужно перезагружать каждый раз.

Как вы, возможно, заметили, я очень новичок в Objective-C, поэтому я могу понять если я неясен, но любая помощь действительно ценится!

ПРАВКА: ДЛЯ ДЭВИДА

Это код для секундомера в поле .файл m:

@implementation StopwatchViewController

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    isCounting = false;
}

- (IBAction)startOrStop:(id)sender
{
    if (self->isCounting == false) {
        self->isCounting = true;
        [self startStopwatch];
    } else {
        self->isCounting = false;
        [self stopStopwatch];
    }
}

- (void)startStopwatch
{
    [startStopButton setTitle:@"STOP" forState:UIControlStateNormal];
    [self performSelector:@selector(stopwatch) withObject:self afterDelay:1.0];
}

- (IBAction)resetStopwatch:(id)sender
{
    [self reset];
}

- (void)stopwatch
{
    if (self->isCounting == false) {
        return;
    } else {

    NSInteger hourInt = [hourLabel.text intValue];
    NSInteger minuteInt = [minuteLabel.text intValue];
    NSInteger secondInt = [secondLabel.text intValue];

    if (secondInt == 59) {
        secondInt = 0;
        if (minuteInt == 59) {
            minuteInt = 0;
            if (hourInt == 23) {
                hourInt = 0;
            } else {
                hourInt += 1;
            }
        } else {
            minuteInt += 1;
        }
    } else {
        secondInt += 1;
    }

    NSString *hourString = [NSString stringWithFormat:@"%02d", hourInt];
    NSString *minuteString = [NSString stringWithFormat:@"%02d", minuteInt];
    NSString *secondString = [NSString stringWithFormat:@"%02d", secondInt];

    hourLabel.text = hourString;
    minuteLabel.text = minuteString;
    secondLabel.text = secondString;

    CGRect hourFrame = self->hourBar.frame;
    CGRect minuteFrame = self->minuteBar.frame;
    CGRect secondFrame = self->secondBar.frame;

    if ((NSInteger)hourFrame.size.height != hourInt) { // check if we need to modify
        hourFrame.origin.y -= ((hourInt * 10.0) - hourFrame.size.height);
        hourFrame.size.height = (hourInt * 10.0);

        self->hourBar.frame = hourFrame;
    }

    if ((NSInteger)minuteFrame.size.height != minuteInt) { // check if we need to modify
        minuteFrame.origin.y -= ((minuteInt * 4.0) - minuteFrame.size.height);
        minuteFrame.size.height = (minuteInt * 4.0);

        self->minuteBar.frame = minuteFrame;
    }

    if ((NSInteger)secondFrame.size.height != secondInt) { // check if we need to modify
        secondFrame.origin.y -= ((secondInt * 4.0) - secondFrame.size.height);
        secondFrame.size.height = (secondInt * 4.0);

        self->secondBar.frame = secondFrame;
    }

    [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(stopwatch) userInfo:nil repeats:NO];
    }
}

- (void)stopStopwatch
{
    [startStopButton setTitle:@"START" forState:UIControlStateNormal];
}

- (void)reset
{
    [startStopButton setTitle:@"START" forState:UIControlStateNormal];

    self->isCounting = false;

    hourLabel.text = @"00";
    minuteLabel.text = @"00";
    secondLabel.text = @"00";

    CGRect hourFrame = self->hourBar.frame;
    CGRect minuteFrame = self->minuteBar.frame;
    CGRect secondFrame = self->secondBar.frame;

    hourFrame.size.height = 0;
    minuteFrame.size.height = 0;
    secondFrame.size.height = 0;

    hourFrame.origin.y = 321.0;
    minuteFrame.origin.y = 321.0;
    secondFrame.origin.y = 321.0;

    self->hourBar.frame = hourFrame;
    self->minuteBar.frame = minuteFrame;
    self->secondBar.frame = secondFrame;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end    

ВТОРАЯ ПРАВКА ДЛЯ ДЭВИДА:

Изменил основные части кода, чтобы они выглядели следующим образом:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:YES];
    [self swapFrames];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];
    [self updateBars];
}

- (void)stopwatch
{
    if (self->isCounting == false) {
        return;
    } else {

    hourInt = [hourLabel.text intValue];
    minuteInt = [minuteLabel.text intValue];
    secondInt = [secondLabel.text intValue];

    if (secondInt == 59) {
        secondInt = 0;
        if (minuteInt == 59) {
            minuteInt = 0;
            if (hourInt == 23) {
                hourInt = 0;
            } else {
                hourInt += 1;
            }
        } else {
            minuteInt += 1;
        }
    } else {
        secondInt += 1;
    }

    NSString *hourString = [NSString stringWithFormat:@"%02d", hourInt];
    NSString *minuteString = [NSString stringWithFormat:@"%02d", minuteInt];
    NSString *secondString = [NSString stringWithFormat:@"%02d", secondInt];

    hourLabel.text = hourString;
    minuteLabel.text = minuteString;
    secondLabel.text = secondString;

    [self swapFrames];
    [self updateBars];

    [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(stopwatch) userInfo:nil repeats:NO];
    }
}

- (void)updateBars
{
    if ((NSInteger)hourFrame.size.height != hourInt) { // check if we need to modify
        hourFrame.origin.y -= ((hourInt * 10.0) - hourFrame.size.height);
        hourFrame.size.height = (hourInt * 10.0);

        self->hourBar.frame = hourFrame;
    }  

    if ((NSInteger)minuteFrame.size.height != minuteInt) { // check if we need to modify
        minuteFrame.origin.y -= ((minuteInt * 4.0) - minuteFrame.size.height);
        minuteFrame.size.height = (minuteInt * 4.0);

        self->minuteBar.frame = minuteFrame;
    }

    if ((NSInteger)secondFrame.size.height != (secondInt * 4.0)) { // check if we need to modify
        secondFrame.origin.y -= ((secondInt * 4.0) - secondFrame.size.height);
        secondFrame.size.height = (secondInt * 4.0);

        self->secondBar.frame = secondFrame;
    }
}

- (void)swapFrames
{
    hourFrame = self->hourBar.frame;
    minuteFrame = self->minuteBar.frame;
    secondFrame = self->secondBar.frame;
}

Я разделил код так, что непосредственно перед появлением вида он должен обновить бары. Однако это не сработало. Я провел небольшое исследование, распечатав значения некоторых переменных в определенных точках. Оказывается, что в viewWillAppear, secondBar.рамка (и минутная клавиша и т.д.) обновился до нужной высоты. Однако в viewDidAppear это значение сбрасывается до 0. Такого не бывает, чтобы secondInt, или secondFrame. Где-то между этими двумя методами кадр сбрасывается, но я не могу понять, что это такое.

1 2

1 ответ:

Насколько я понимаю, рамки для ваших свойств self.hourBar, self.minuteBar и self.secondBar устанавливаются в 0 при переключении между вкладками, и только обновлять их каждую секунду.

Если это действительно так, просто установите их правильные значения в методе viewControllers viewWillAppear: (назначьте их некоторому свойству в viewWillDisappear:).

Как сайднот, вы, кажется, исходите из C++. Нотация " - > "очень необычна для Objective-C, так как свойства доступны с помощью".", и соответствующие им переменная экземпляра с " ->". Использование нотации со стрелкой Не вызовет автосинтезированные методы геттера / сеттера свойств!

Кроме того, есть ли конкретная причина, по которой вы всегда создаете новые объекты NSTimer вместо установки repeats: в yes? Создание таймера и добавление его в runloop (что scheduledTimerWith:... и делает) является относительно дорогостоящей операцией.