除非您与UITableViewController交互,否则UIImageView类别不会更新

时间:2014-11-07 10:33:13

标签: ios objective-c uitableview ios7 uiimageview

要查看问题的演示以及代码,请have a look at the following 60 second video.

Here is a simple project demonstrating the problem。 挑战,看看你是否可以在运行时使用我创建的类别触摸tableviewcontroller来显示图像。

我创建了一个简单的UIImageView类别,其中我公开了一个imageURL属性,该属性在设置时应该开始异步下载。调用完成块后,我将类“image属性设置为下载的图像。

然后我有一个继承自UITableViewController的类,我在其中导入自定义UIImageView类别。我通过设置单元格的imageview willDisplayCell:属性,在imageURL方法中开始下载。图像是异步下载并设置的,但是除非我将单元格从表格中滚动,否则单元格的imageview不会更新,或者我单击单元格本身。

我尝试了[self setNeedsDisplay];之类的内容以及其他一些内容,例如在主线程上执行图像的设置,但都无济于事。

有人可以看看,让我知道我应该做什么吗?


一些代码:

的UIImageView + AsyncDLImageView.h

#import <UIKit/UIKit.h>
@interface UIImageView (AsyncDLImageView)
@property (nonatomic, retain) NSURL *imageURL;
@end

的UIImageView + AsyncDLImageView.m

#import "UIImageView+AsyncDLImageView.h"
@implementation UIImageView (AsyncDLImageView)
- (void)setImageURL:(NSURL *)imageURL{
    [self loadImageWithURL:imageURL completionHandler:^(UIImage *image, NSError *error) {
        if(!error) {
            NSLog(@"image has been set: %@", image);
            self.image = image;
        }
    }];
}
-(NSURL *)imageURL{
    return self.imageURL;
}
-(void)loadImageWithURL:(NSURL*)url completionHandler:(void(^)(UIImage *image, NSError *error))completionBlock{
    NSLog(@"set image url request called: %@", [url absoluteString]);

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                               if ( !error )
                               {
                                   NSLog(@"no error");
                                   UIImage *image = [[UIImage alloc] initWithData:data];
                                   completionBlock(image, nil);
                               } else{
                                   completionBlock(nil, error);
                                   NSLog(@"error");
                               }

                           }];
}

3 个答案:

答案 0 :(得分:0)

看起来因为表格单元格上的imageView没有初始化,所以图像不会显示。我添加了一个透明的placeHolder图像(使您想要图像的大小)并在等待图像加载时使用它。 (这对我有用)

所以我改变了代码如下......

DisplayXMLImageDataTVC.m

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [_xmlImageURLArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     static NSString *cellIdentifier = @"xmlCellIdentifier";

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
     if(cell == nil){
         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        cell.imageView.image = [UIImage imageNamed:@"placeHolder"];
     }
    [cell.imageView setImageURL:[_xmlImageURLArray objectAtIndex:indexPath.row]];

    return cell;
 }

和您的类别类回到原来的状态....

- (void)setImageURL:(NSURL *)imageURL
{

//    objc_setAssociatedObject(self, @selector(imageURL), imageURL, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self loadImageWithURL:imageURL completionHandler:^(UIImage *image, NSError *error) {
        if(!error) {
            self.image = image;
        }
    }];
}
-(void)loadImageWithURL:(NSURL*)url completionHandler:(void(^)(UIImage *image, NSError *error))completionBlock{
    NSLog(@"set image url request called: %@", [url absoluteString]);

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                               if ( !error )
                               {
                                   NSLog(@"no error");
                                   UIImage *image2 = [[UIImage alloc] initWithData:data];

                                   completionBlock(image2, nil);
                               } else{
                                   completionBlock(nil, error);
                                   NSLog(@"error");
                               }

                           }];
}

答案 1 :(得分:0)

原因是在设置图像后不重绘单元格。通常我们会在cellForRowAtIndexPath中发送图像的异步请求,在我们获取图片后,我们会调用单元格setNeedsLayout

所以你可以做到以下几点。

- (void)setImageURL:(NSURL *)imageURL
{
    UITableViewCell *cell = (UITableViewCell *)self.superview.superview;

    [self loadImageWithURL:imageURL  completionHandler:^(UIImage *image, NSError *error) {
        if(!error) {
            NSLog(@"image has been set: %@", image);
            self.image = image;
            [cell setNeedsLayout];
        }
    }];
}

答案 2 :(得分:0)

问题似乎是UITableViewCell使用imageView的初始帧来布局单元格。如果未设置,则获得0x0帧,即使稍后设置图像,帧也不会更改。如果将其设置为某个占位符图像,则会继续使用该占位符图像中的帧,这可能不是您想要的。

一个可能的解决方案是拥有一个自定义UITableViewCell,它会覆盖layoutSubviews并根据您拥有的图像设置框架。从您的imageView类别,在设置图像后,调用[self setNeedsLayout]。这将导致在下次重绘时调用layoutSubviews。

你也可以看一下 - http://www.wrichards.com/blog/2011/11/sdwebimage-fixed-width-cell-images/