Магистр ДонНТУ Трофименко Екатерина Сергеевна

Трофименко Екатерина Сергеевна

Факультет:
Компьютерных наук и технологий (КНТ)

Специальность:
«Информационные управляющие системы и технологии» (ИУС)

Кафедра:
Автоматизационные системы управления (АСУ)

Тема магистерской работы:
«Разработка автоматизированной системы тестирования знаний студентов в области компьютерных технологий с использованием механизмов адаптации»

Научный руководитель:
д-р техн. наук, проф., зав. кафедрой АСУ, Скобцов Юрий Александрович

Использование NSTimer с UIScrollView.

NSTimer – класс, для создания таймеров. По прошествии заданного интервала он посылает указанное сообщение объекту.

UIScrollView – позволяет скроллировать контент, большего размера, чем дисплей.

Однако, если использовать эти 2 объекта одновременно, возникают некоторые, на первый взгляд, незаметные особенности...


Итак, для начала, создадим простой ViewBasedProject, под названием TimerScroll2.

Создаем метку redTimerLabel, переменную redTime, в которой будет храниться текущее значениие времени, и переменную timeStamp, в которой будет храниться значение интервала, через которое будет изменяться текст метки.

ScrollTimer2ViewController.h

@interface ScrollTimer2ViewController : UIViewController {

UILabel *redTimerLabel;

float redTime;

float timeStamp;

}

ScrollTimer2ViewController.m

- (void)viewDidLoad {

[super viewDidLoad];

redTimerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 25)];

redTimerLabel.backgroundColor = [UIColor redColor];

redTime = 0;

timeStamp = 1.0;

[self.view addSubview:redTimerLabel];

}

Теперь создаем таймер. Он имеет следующие параметры:

  1. timeInterval – время, через которое вызовется метод
  2. target – cылка на объект, на котором будет вызываться метод
  3. selector – декларация метода
  4. userInfo – дополнительный параметр
  5. repeats – флаг, указывающий на то, будет ли таймер срабатывать несколько раз

ScrollTimer2ViewController.m

-(void) startTimer {

[NSTimer scheduledTimerWithTimeInterval:timeStamp

target:self

selector:@selector(setRedLabelText)

userInfo:nil repeats:YES];

}

Таймер ссылается на метод setRedLebelText. При каждом вызове он изменяет текст метки.

ScrollTimer2ViewController.m

-(void) setRedLabelText {

redTime+=timeStamp;

NSString *str = [[NSString alloc] initWithFormat:@"%.2f", redTime];

redTimerLabel.text = str;

[str release];

}

Запускаем:

ScrollTimer2ViewController.m

- (void)viewDidLoad {

.....

[self startTimer];

}

И все работает нормально :).

Теперь, добавим UIScrollView.

TimerScrollView.h

@interface TimerScrollView : UIScrollView {

UIImageView *imageView;

}

@end

TimerScrollView.m

@implementation TimerScrollView

- (id)initWithFrame:(CGRect)frame {

if ((self = [super initWithFrame:frame])) {

self.scrollEnabled = YES;

self.delegate = self;

self.minimumZoomScale = 0.1f;

self.maximumZoomScale = 5.0f;

imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image0.jpg"]];

[self addSubview:imageView];

[self setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];

}

return self;

}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {

return imageView;

}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale { }

- (void)dealloc {

[super dealloc];

}

@end


ScrollTimer2ViewController.m

- (void)viewDidLoad {

.....

TimerScrollView *sv = [[TimerScrollView alloc] initWithFrame:[UIScreen mainScreen].bounds];

[self.view addSubview:sv];

[self.view addSubview:redTimerLabel];

[self startTimer];

}

Запускаем и начинаем скроллировать. Вот тут и возникает проблема: для того, чтобы картинка плавно перемещалась, большая часть ресурсов отдается на анимацию UIScrollView. И все таймеры приостанавливаются.

Проблема решается при помощи дополнительного потока:

ScrollTimer2ViewController.m

-(void) startTimer {

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

[NSThread detachNewThreadSelector:@selector(launchTimer) toTarget:self withObject:nil];

[pool release];

}


-(void)launchTimer{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

[NSThread setThreadPriority:1.0];

continuePlaying = YES;

while (continuePlaying)

{

[NSThread sleepForTimeInterval:timeStamp];

[self performSelectorOnMainThread:@selector(setRedLabelText) withObject:nil waitUntilDone:NO];

}

[pool release];

}

Итак, теперь все работает как нужно. Но, стоит напомнить о том, что не следует злоупотреблять потоками. И четко ослеживать их жизненный цикл.

Тестовый проект можно скачать здесь


Ниже, видео реального проекта, в котором было применено данное решение. ;)

Ссылки

  1. http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSThread_Class/Reference/Reference.html

    Документация по классу NSThread

  2. http://developer.apple.com/iphone/library/documentation/uikit/reference/UIScrollView_Class/Reference/UIScrollView.html

    Документация по классу UIScrollView

  3. http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html

    Документация по классу NSTimer

  4. http://stackoverflow.com/questions/605027/uiscrollview-pauses-nstimer-until-scrolling-finishes

    Stack Overflow – cайт, позволяющий задавать и отвечать на различные вопросы, посвещенные программированию.

  5. http://iphonedevcamp.com.ua/

    Сообщество разработчиков iPhone/iPod Touch/iPad приложений в Украине