Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > iOS > Прогрузка и ленивая загрузка UIView перед доба...


Автор: Shklyar 28.2.2014, 13:28
Есть желание показать UIView c тяжелой картинкой. Я пытаюсь сделать такую загрузку, которая позволит остальной программке работать

Класс этой вью
Код

- (id)initWithSpinset:(NSString*)spinset withSize:(CGSize)size {
    self = [super initWithFrame:(CGRect){0, 0, size}];
    if (!self) return nil;
    
    self.clipsToBounds = YES;
    
    [NSThread detachNewThreadSelector:@selector(loadImage:) toTarget:self withObject:spinset];
    
    return self;
}

- (void)loadImage:(NSString*)spinset {
    NSString *filePath = [[NSBundle mainBundle] pathForResource:spinset ofType:nil];
    NSData *imageData = [[NSData alloc] initWithContentsOfFile:filePath];
    UIImage *spinsetImage = [[UIImage alloc] initWithData:imageData];
    if (!spinsetImage) return;
    
    _spinsetImageView = [[UIImageView alloc] initWithImage:spinsetImage];
    if (_spinsetImageViewPosition)
        _spinsetImageView.frame = CGRectOffset(_spinsetImageView.frame, 0, _spinsetImageViewPosition);
    [self addSubview:_spinsetImageView];
    
    self.isReady = YES;
}


Потом, в другом месте, создаю экземпляр вышеприведенного класса и по KVO слежу за свойством isReady. По isReady == YES добавляю вью на главную вью и там еще всякого делаю.

Проблема в том, что isReady срабатывает очень быстро. Т.е. это не решает задачу предварительной прогрузки UIView. Подскажите где моя ошибка и как логично решать такую задачу.

Автор: sadisasha 28.2.2014, 16:57
Код

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    /* Код, который должен выполниться в фоне */

dispatch_sync(dispatch_get_main_queue(), ^{ 
/* Код, который нужно выполнить в главном 
потоке */
 /* Мы ждем, пока он выполниться */

 });

/* Продолжаем работать в фоновом потоке */ });

http://idev.by/ios/21112/ - про механизм распаралеливания задач GCD

Автор: lesovoi87 24.3.2014, 13:14
А зачем вообще нужна подгрузка тяжелого файлика? Я думаю это лишняя заморочка

Автор: Shklyar 24.3.2014, 14:12
Цитата(lesovoi87 @  24.3.2014,  13:14 Найти цитируемый пост)
А зачем вообще нужна подгрузка тяжелого файлика? Я думаю это лишняя заморочка 

В этом случае я делал вращение объекта 360 градусов на изображении. Т.е. много фотографий в одной картинке и по тачу изменял видимый фрейм, довольно быстро.
Как лучше делать такую задачу?

Автор: Bitter 24.3.2014, 17:34
Цитата(Shklyar @  24.3.2014,  14:12 Найти цитируемый пост)
Как лучше делать такую задачу?

Задача поворота картинки?

Автор: Shklyar 24.3.2014, 17:42
Цитата(Bitter @  24.3.2014,  17:34 Найти цитируемый пост)
Задача поворота картинки?

)) Есть набор кадров вращения объекта. Это может быть одна огромная картинка или много меньших. По тачу я показываю разные картинки и выходит, якобы, вращаем объект.

Автор: Bitter 24.3.2014, 22:05
а ясно, псевдо 3Д? проблема та же, что и в первом посте осталась?

Автор: Shklyar 24.3.2014, 22:32
Собственно, проблема закончена, хотя без костылей не обошлось ))
Плюс KVO оказалась не такой простой штуковиной, как казалось ранее (там проблема существования объекта, которому посылается сообщение была).

А вот сегодня, набрел на такую штуковину, что вроде не в главном потоке менять свойства некоторых UI штуковин нельзя. Как бы это сказать правильнее, на примере? Создаю новый поток (хоть через NSThread, хоть GCD), в этом потоке создаю UITextView - создается. Меняю текст шрифта - ошибка, в которой говорится, что выполнять операцию можно только в главном потоке. Вы такое встречали? Или это я в ином месте накосячил? ))

Автор: Bitter 25.3.2014, 01:54
Цитата(Shklyar @  24.3.2014,  22:32 Найти цитируемый пост)
Или это я в ином месте накосячил?

Нет, не на косячил, любой параметр касающийся UI можно менять только в главном потоке.
Для изменения такого параметра можно использовать dispatch_async(dispatch_get_main_queue, ...

Автор: Shklyar 1.4.2014, 12:07
Код

@interface InfiniteScrollView : UIScrollView
@end;

@implementation InfiniteScrollView {
    bool _recentered;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    [self recenterIfNecessary];
}

- (void)recenterIfNecessary {
    CGPoint currentOffset = [self contentOffset];
    CGFloat contentWidth = [self contentSize].width;
    CGFloat centerOffsetX = (contentWidth - [self bounds].size.width) / 2.0;
    CGFloat distanceFromCenter = fabs(currentOffset.x - centerOffsetX);
    
    if (distanceFromCenter < contentWidth / 4.0) {
        if (_recentered)
            _recentered = NO;
        return;
    }
    
    if (!_recentered) {
        _recentered = YES;
        
        // !
        NSLog(@"recenter");
        sleep(1);
    }
}
@end;

@interface ViewController : UIViewController
@end;

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    InfiniteScrollView * scrollView = [[InfiniteScrollView alloc] initWithFrame:[self viewBounds]];
    scrollView.contentSize = CGSizeMake([self viewBounds].size.width * 3, [self viewBounds].size.height);
    scrollView.contentOffset = CGPointMake([self viewBounds].size.width, 0);
    scrollView.pagingEnabled = YES;
    [self.view addSubview:scrollView];
    
    UIView *view1 = [[UIView alloc] initWithFrame:[self viewBounds]];
    view1.backgroundColor = [UIColor redColor];
    [scrollView addSubview:view1];
    
    UIView *view2 = [[UIView alloc] initWithFrame:CGRectOffset([self viewBounds], [self viewBounds].size.width, 0)];
    view2.backgroundColor = [UIColor greenColor];
    [scrollView addSubview:view2];
    
    UIView *view3 = [[UIView alloc]  initWithFrame:CGRectOffset([self viewBounds], [self viewBounds].size.width * 2, 0)];
    view3.backgroundColor = [UIColor blueColor];
    [scrollView addSubview:view3];
}

- (CGRect) viewBounds {
    CGRect bounds = [[UIScreen mainScreen] bounds]; // portrait bounds
    if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
        bounds.size = CGSizeMake(bounds.size.height, bounds.size.width);
    return bounds;
}

@end

Посмотрите на такую конструкцию. Есть три View, которые находятся на ScrollView. На некотором scrollView.contentOffset нужно подготовить новую View, что занимает немного времени.
Код

        // !
        NSLog(@"recenter");
        sleep(1);

Т.е. вместо sleep(1); я сознаю экземпляр класса, в котором много элементов UI. Выполняя это в главном потоке, ScrollView приостанавливается. А нужно, чтоб он продолжал скролиться и одновременно создавался объект с UI. Что можно сделать?

Автор: Bitter 1.4.2014, 12:16
ну создание UI не может занимать много времени, может много времени занимает что-то другое? Например загрузка картинок или наполнение массивов

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)