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

Трофiменко Катерина Сергiївна

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

Спеціальність:
«Інформаційні управляючі системи та технології» (ІУС)

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

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

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

Використання 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];

}

Запускаємо і починаємо прокручувати скрол у рiзних напрямках. Ось тут і виникає проблема: для того, щоб картинка плавно переміщалася, більша частина ресурсів віддається на анімацію UIScrollView. І всi таймери припиняються.

Проблема вирішується за допомогою додаткового потоку:

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];

}

Отже, тепер все працює як потрібно. Але, варто нагадати про те, що не слід зловживати потоками. І чітко вiдстежувати їх життєвий цикл.

Тестовий проект можна завантажити тут


Нижче, відео реального проекту, в якому було застосовано дане рішення. ;)

Ссылки

  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 додатків в Україні