iOS: есть ли способ определить, когда UIView появился, после вызова view.hidden = NO - PullRequest
3 голосов
/ 31 мая 2011

У меня есть UIView с 8-10 большими изображениями (каждое загружено в UIImageView) в качестве подпредставлений.Эти изображения выровнены рядом друг с другом, так что они составляют очень длинное горизонтальное изображение.Это представление помещается в UIScrollView, так что пользователь может прокручивать это длинное горизонтальное изображение.

Загрузка всех этих изображений (из Интернета) занимает довольно много времени, поэтому я решил поместить этот код загрузки вПодкласс NSOperation.Внутри основного метода операции каждый ImageView добавляется к представлению контейнера.

Представление скрывается во время этого процесса, и вместо этого появляется небольшое вращающееся изображение (почти как UIActivityIndicatorView).Вот некоторый код:

CategoryViewController.m

- (id)initWithFrame:(CGRect)frame
{
    self = [super init];
    if(self)
    {
        // do some unrelated stuff
        [...]

        loadIndicator = [[UIImageView alloc] initWithImage:img];
        [loadIndicator setFrame:CGRectMake((frame.size.width - width) / 2, (frame.size.height - height) / 2, width, height)];
        [loadIndicator setHidden:YES];

        // this is the view which will contain those large images
        backgroundView = [[UIView alloc] init];
        backgroundView.hidden = YES;

        scrollView = [[UIScrollView alloc] initWithFrame:frame];
        [scrollView setDelegate:(id<UIScrollViewDelegate>)self];
        [scrollView addSubview:backgroundView];  

        [self.view setFrame:frame];
    }
    return self;
}

- (void)viewDidLoad
{
    // do some unrelated stuff
    [...]

    [self.view addSubview:loadIndicator];
    [self.view addSubview:scrollView];

    // setup a custom activity indicator
    loadIndicator.hidden = NO;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    loadIndicatorRotation = 0;
    rotationTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector:@selector(updateRotation:) userInfo: nil repeats: YES];
    [UIView commitAnimations];

    // setup the operation to load all background images
    operationQueue = [[NSOperationQueue alloc] init];
    LoadBackgroundImagesOperation* operation = [[LoadBackgroundImagesOperation alloc] initWithImages:bgImageNames View:backgroundView Frame:frame];

    // register to recieve the finish notification
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFinishedLoadingBgImages) name:@"BgImagesFinishedLoading" object:operation];

    // Add the operation to the queue
    [operationQueue addOperation:operation];
    [operation release];
    [super viewDidLoad];
}

основной метод LoadBackgroundImagesOperation.m

- (void)main
{
    int left = 0;
    int width, height;

    int i;
    for(i = 0; i < imageNames.count; i++)
    {
        if([self isCancelled])
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"BgImagesCancelled" object:self];
            return;
        }

        // code to retrieve the url of current image
        [...]

        NSData* data = [[NSData alloc] initWithContentsOfURL:imgURL];
        UIImage* image = [[UIImage alloc] initWithData:data];
        [data release];

        double scalingFactor = frame.size.height / image.size.height;
        width = image.size.width * scalingFactor;
        height = image.size.height * scalingFactor;

        UIImageView* imgView = [[UIImageView alloc] initWithImage:image];
        [image release];

        [imgView setFrame:CGRectMake(left, 0, width, height)];
        [background addSubview:imgView];
        [imgView release];

        left += width;
        [background setFrame:CGRectMake(0, 0, left, height)];
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:@"BgImagesFinishedLoading" object:self];
}

Когда операция завершена, я скрываю вращающееся изображение и показываюпредставление, которое содержит большие изображения.

(снова в CategoryViewController.m)

- (void) onFinishedLoadingBgImages
{
    [scrollView setContentSize:backgroundView.frame.size];

    backgroundView.hidden = NO;
    loadIndicator.hidden = YES;

    if(operationQueue != nil)
    {
        [operationQueue cancelAllOperations];
        [operationQueue release];
        operationQueue = nil;
    }
    [rotationTimer invalidate];
    rotationTimer = nil;
}

Проблема в том, что для симулятора требуется около 2 секунд и до 5 секунд нареальное устройство, пока изображения на самом деле не видны после вызова backgroundView.hidden = NO

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

Я попытался поместить backgroundview в свой собственный UIViewController и уведомить мой родительский контроллер представления, когда вызывается viewDidAppear, но это не работает.(Я читал, что во вложенных контроллерах представления мне пришлось бы вызывать viewDidAppear вручную, но это не вариант, потому что я не знаю, когда он вообще появился).

Кроме того, я могу 'просто сделайте грязный трюк и измените порядок backgroundView и loadIndicator, чтобы скрыть его, потому что большинство изображений имеют некоторую прозрачность, поэтому пользователь все равно будет видеть индикатор.

Так что яочень надеюсь, что у каждого из вас есть предложение, как определить, когда backgroundview действительно виден.

Спасибо, Крис

О, и извините, если какой-то код несколько не связанк проблеме.Просто хотел дать вам общую картину того, что я делаю.

Ответы [ 2 ]

2 голосов
/ 31 мая 2011

Что вы можете сделать, это сделать подкласс UIViewController и сделать его владельцем этого представления, и в этом методе вы можете попытаться поместить нужный код в метод viewDidLoad и посмотреть, является ли это более точным, однако я думаю, чтореальная проблема заключается в том, что используемые вами imageViews тратят время на загрузку изображений, а не UIView.Поэтому UIView видим, однако imageViews еще не загрузили свои изображения, поэтому вы ничего не видите.

1 голос
/ 31 мая 2011

Если вы показываете много больших изображений в режиме прокрутки, вам следует подумать о том, чтобы разделить их на части, чтобы части изображений можно было загружать отдельно, и вам не нужно хранить несколько больших изображений в памяти одновременно. в то же время. Взгляните на CATiledLayer и PhotoScroller пример кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...