iOS:在调用view.hidden = NO之后,有没有办法确定UIView何时出现?

时间:2011-05-31 16:37:30

标签: ios uiview

我有一个UIView,有8到10个大图像(每个加载到UIImageView中)作为子视图。这些图像彼此相邻排列,因此它们构成了一个真正的长水平图像。此视图放入UIScrollView,以便用户可以沿着这个长水平图像滚动。

加载所有这些图像(来自网络)需要相当长的时间,所以我决定将加载代码放入NSOperation子类中。在操作的main方法中,每个ImageView都被添加到容器视图中。

在此过程中隐藏视图,而是有一个小的旋转图像(非常像UIActivityIndi​​catorView)。这是一些代码:

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,但这不是一个选项,因为我不知道它何时出现在第一位)。

此外,我不能只是做肮脏的技巧并改变backgroundViewloadIndicator的顺序来隐藏它,因为大多数图像都有一些透明度,所以用户仍然会看指标。

所以我真的希望,你们中的任何人都有关于如何检测backgroundview何时实际可见的建议。

谢谢, 克里斯

哦,对不起,如果某些代码与问题有些无关。只是想让你了解我正在做的事情。

2 个答案:

答案 0 :(得分:2)

你可以做的是创建一个UIViewController子类,并使其成为该视图的所有者,并且在该方法中,您可以尝试在viewDidLoad方法中放置所需的代码,看看是否更准确,但我认为真正的问题是你使用的imageViews正在花时间加载图像,而不是UIView。因此,UIView是可见的,但是imageViews还没有加载他们的图像,所以你什么也看不见。

答案 1 :(得分:1)

如果你在滚动视图中显示很多大图像,你应该考虑平铺它们,以便可以单独加载部分图像,而不必将几个大图像保存在内存中。同时。请查看CATiledLayerPhotoScroller示例代码。