0

我已经阅读了大量关于这个特定主题的 SO 帖子——似乎有很多人在使用带有 UIScrollView 和 UIImageView 的 Autolayout 时遇到问题。或者也许只是有大量的人(比如我自己!)正在阅读教程的 iOS 开发新手碰巧使用这两个对象作为示例。无论如何,虽然我猜测我的问题在某种程度上与这些其他帖子有关,但我的问题是不同的,因为我已经能够完全按照我的意愿使用这些具有自动布局的对象,直到我尝试使用块/线程!

我对自动布局和控制器生命周期的理解是,viewDidLayoutSubviews当自动布局完成“确定”页面上的内容应该放置的位置时,会调用一个“事件”。我正在/正在使用它对 UIImageView 的zoomScale属性进行一些计算以缩放图像,使其适合 UISCrollView 提供的空间宽度。

- (void) viewDidLayoutSubviews
{
   [super viewDidLayoutSubviews];

    CGRect scrollViewBounds = self.scrollView.bounds;

    CGFloat scrollAspectRatio = scrollViewBounds.size.width/scrollViewBounds.size.height;

    CGSize imageViewSize = self.imageView.image.size;
    CGFloat imageAspectRatio = imageViewSize.width/imageViewSize.height;

    if(imageAspectRatio < scrollAspectRatio){
        self.scrollView.zoomScale = scrollViewBounds.size.height/imageViewSize.height;
    }else{
        self.scrollView.zoomScale = scrollViewBounds.size.width/imageViewSize.width;
    }

}

这段代码运行得非常好,直到我开始在不同的线程中加载图像数据(见下文)。现在,我的猜测是,因为我正在异步调用它,所以viewDidLayoutSubviews在我的图像数据实际返回之前或在它完全加载之前被触发/调用。

//This is called by an external controller and is what "kicks off" the entire process
- (void) setImageURL:(NSURL *)imageURL
{
    _imageURL = imageURL;
    [self setupImage];
}

//Required for zooming
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

//Here is where the threading/block logic comes in play. If I literally just comment
//out the block/threading related code, everything works perfectly, other then the
//image loading "blocking" the interface
- (void) setupImage
{
    if(self.imageView){
        self.scrollView.contentSize = CGSizeZero;
        self.imageView.image = nil;

        NSURL *imageURL = self.imageURL;

        dispatch_queue_t imageFetchQ = dispatch_queue_create("image fetcher", NULL);
        dispatch_async(imageFetchQ, ^{
            NSData *imageData = [[NSData alloc]initWithContentsOfURL:self.imageURL];
            UIImage *image = [[UIImage alloc] initWithData:imageData];
            if(self.imageURL == imageURL){
                if(image){
                    dispatch_async(dispatch_get_main_queue(), ^{
                        self.scrollView.contentSize = image.size;
                        self.imageView.image = image;
                        self.imageView.frame = CGRectMake(0,0, image.size.width, image.size.height);
                    });
                }
            }

        });
    }
}

我的猜测是我应该监听不同的回调(不确定回调是否是正确的术语),或者我只需要以某种方式“等待”一段时间来强制我的setupImage逻辑运行(即等待任意时间,希望自动布局完成它并为 UIScrollView 和 UIImageView 的边界分配适当的值等)。

如果它有帮助,可以在此处找到此代码的运行版本:https ://github.com/develpr/PhotoViewr/tree/assignment-5 (请注意,如果您实际下载此代码,则需要输入FlickrAPIKey.h 文件中的 Flickr API 密钥以使其正常工作)。

4

1 回答 1

0

事实证明,我的问题的解决方案相对简单直接,虽然加载图像数据的异步调用是问题的“原因”,但唯一真正的问题是我做事的顺序。

主要问题似乎setupImage是被调用了两次。一旦我删除了对setupImage事情的调用,它就到位了。我删除了对 viewDidLayoutSubviews 无效的调用,我相信是通过异步图像加载(在加载图像数据和相应大小之前调用了 viewDidLayoutSubviews)。

基本上,我只需要记住项目的执行顺序(NSLog对此有帮助)并检查 size/zoomScale 值以查看它们的设置。

于 2013-07-28T06:29:43.743 回答