使用json加载UITableView图像无法正确加载

时间:2015-03-02 08:07:42

标签: ios objective-c iphone json uitableview

我正在使用它来通过JSON解析到tableView来显示一些标签和图像,但是当滚动tableview图像来到并跳舞时,图像不会出现在第一次启动时我的意思是不按顺序格式帮助我这个

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
        self.customCellClass = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
        if (self.customCellClass == nil)
        {
            self.customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
        }
        self.customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:@"name"]; // label
        self.customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:@"region"]; // label

        NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:@"summary"] stripHtml]; //label
        self.customCellClass.detailLabel.text = stripped;
        self.customCellClass.mainImage.image = nil;


        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
            NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:@"images"]objectForKey:@"logo"]]];
            UIImage *image = [UIImage imageWithData:data0];

            dispatch_sync(dispatch_get_main_queue(), ^(void) {
                self.customCellClass.mainImage.image = image;
            });
        });
        return self.customCellClass;

}

3 个答案:

答案 0 :(得分:0)

使用UITableView's cellForRowAtIndexPath方法替换以下代码:

//Check if cell has image or not
if(!self.customCellClass.mainImage.image)
{
   dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
   dispatch_async(q, ^{

      NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:@"images"]objectForKey:@"logo"]]];
      UIImage *image = [UIImage imageWithData:data0];

      //Get main queue
      dispatch_async(dispatch_get_main_queue(), ^{

       /* This is the main thread again, where we set the tableView's image to be what we just fetched. */

       self.customCellClass.mainImage.image = image;

      });

   });
}

良好的解决方案,如果您使用的是AFNetworking,那么请使用UIImageView+AFNetworking类别

NSURL *imageURL = [NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:@"images"]objectForKey:@"logo"]]
[self.customCellClass.mainImage setImageWithURL:imageURL placeholderImage:nil];

答案 1 :(得分:0)

每次加载单元格并下载相同的图像时,都会指定image = nil。

您可以使用以下课程来无缝地执行此操作。

AsyncImageView.h

#import <UIKit/UIKit.h>


@interface AsyncImageView : UIView {
    NSURLConnection *connection;
    NSMutableData *data;
    NSString *urlString; // key for image cache dictionary
}

-(void)loadImageFromURL:(NSURL*)url;
-(void)loadBackgroundImage:(UIImage *)image;
-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url;
-(BOOL)getCachedImageWithUrl:(NSString*)url;

@end

和AsyncImageView.m

#import "AsyncImageView.h"
#import "ImageCacheObject.h"
#import "ImageCache.h"

//
// Key's are URL strings.
// Value's are ImageCacheObject's
//
static ImageCache *imageCache = nil;

#define SPINNY_TAG 5555   

@implementation AsyncImageView


- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
    }
    return self;
}


- (void)drawRect:(CGRect)rect {
    // Drawing code
}


- (void)dealloc {
    [connection cancel];

}

-(void)loadBackgroundImage:(UIImage *)image
{
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    imageView.contentMode = UIViewContentModeScaleAspectFill;
    imageView.layer.masksToBounds=YES;

    //imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self addSubview:imageView];
    imageView.frame = self.bounds;
    [imageView setNeedsLayout]; 
    [self setNeedsLayout];

    imageView=nil;

}

-(void)loadImageFromURL:(NSURL*)url
{
    if (connection != nil) {
        [connection cancel];
        connection = nil;
    }
    if (data != nil) {
        data = nil;
    }

    if (imageCache == nil) // lazily create image cache
        imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024];  // 2 MB Image cache
  //  NSLog(@"Value of the url here = %@",url);
    urlString = [[url absoluteString] copy];
    UIImage *cachedImage = [imageCache imageForKey:urlString];
    if (cachedImage != nil)
    {
        if ([[self subviews] count] > 0)
        {
            [[[self subviews] objectAtIndex:0] removeFromSuperview];
        }
        UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
        imageView.contentMode = UIViewContentModeScaleAspectFill;
        imageView.layer.masksToBounds=YES;

        [self addSubview:imageView];
        imageView.frame = self.bounds;
        [imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
        [self setNeedsLayout];

        imageView=nil;
        return;
    }


    UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    spinny.tag = SPINNY_TAG;
    spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
    spinny.center = self.center;
    [spinny startAnimating];
    [self addSubview:spinny];
    [self bringSubviewToFront:spinny];

    spinny=nil;

    NSURLRequest *request = [NSURLRequest requestWithURL:url 
                                             cachePolicy:NSURLRequestUseProtocolCachePolicy 
                                         timeoutInterval:60.0];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}


-(BOOL)getCachedImageWithUrl:(NSString*)url
{
    BOOL isIamgeCached=NO;

    if (imageCache == nil)
        imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024];  // 2 MB Image cache

    UIImage *cachedImage = [imageCache imageForKey:url];
    if (cachedImage != nil)
    {
        isIamgeCached=YES;
    }
    return isIamgeCached;
}


-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url
{
    if (connection != nil)
    {
        [connection cancel];
        connection = nil;
    }
    if (data != nil)
    {
        data = nil;
    }

    if (imageCache == nil) // lazily create image cache
        imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024];  // 2 MB Image cache
    //  NSLog(@"Value of the url here = %@",url);
    urlString = [[url absoluteString] copy];
    UIImage *cachedImage = [imageCache imageForKey:urlString];
    if (cachedImage != nil)
    {
        if ([[self subviews] count] > 0)
        {
            [[[self subviews] objectAtIndex:0] removeFromSuperview];
        }
        UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
        imageView.contentMode = UIViewContentModeScaleToFill;
        imageView.autoresizingMask =
        UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self addSubview:imageView];
        imageView.frame = self.bounds;
        [imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
        [self setNeedsLayout];

        imageView=nil;
        return cachedImage;
    }


    UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    spinny.tag = SPINNY_TAG;
    spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
    //spinny.center = self.center;
    [spinny startAnimating];
    [self addSubview:spinny];
    [self bringSubviewToFront:spinny];

    spinny=nil;

    NSURLRequest *request = [NSURLRequest requestWithURL:url
                                             cachePolicy:NSURLRequestUseProtocolCachePolicy
                                         timeoutInterval:20.0];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];


    return cachedImage;
}


- (void)connection:(NSURLConnection *)connection 
    didReceiveData:(NSData *)incrementalData {
    if (data==nil)
    {
        data = [[NSMutableData alloc] initWithCapacity:2048];
    }
    [data appendData:incrementalData];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
    connection = nil;

    UIView *spinny = [self viewWithTag:SPINNY_TAG];
    [spinny removeFromSuperview];

    if ([[self subviews] count] > 0)
    {
        [[[self subviews] objectAtIndex:0] removeFromSuperview];
    }

    UIImage *image = [UIImage imageWithData:data];

    [imageCache insertImage:image withSize:[data length] forKey:urlString];

    UIImageView *imageView = [[UIImageView alloc] 
                               initWithImage:image];
    imageView.contentMode = UIViewContentModeScaleToFill;
    imageView.autoresizingMask = 
        UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self addSubview:imageView];
    imageView.frame = self.bounds;
    [imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
    [self setNeedsLayout];

    imageView=nil;
    data = nil;
}

@end

答案 2 :(得分:0)

使用dispatch_async从远程加载图像,这意味着要在tableview单元格中显示的图像是异步加载的。并且您使用实例变量来记录当前单元格,这会导致您遇到的问题。

加载图像完成后(可能需要几分钟),它希望显示在单元格中(用此代码编写),

dispatch_sync(dispatch_get_main_queue(), ^(void) {
    self.customCellClass.mainImage.image = image;
});

仅发现self.customCellClass指向错误的单元格(- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath在加载图像期间被多次调用,并且每次调用都将self.customCellClass的指向更改为其他单元格)。

因此,图像的顺序是错误的。

试试这个:

使用位置变量使单元格从dequeueReusableCellWithIdentifier开始。像这样:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:     (NSIndexPath *)indexPath
{
    CellCustom *customCellClass = (CellCustom *)[tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (customCellClass == nil)
    {
        customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }
    customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:@"name"]; // label
    customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:@"region"]; // label

    NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:@"summary"] stripHtml]; //label
    customCellClass.detailLabel.text = stripped;
    customCellClass.mainImage.image = nil;


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
        NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:@"images"]objectForKey:@"logo"]]];
        UIImage *image = [UIImage imageWithData:data0];

        dispatch_sync(dispatch_get_main_queue(), ^(void) {
            customCellClass.mainImage.image = image;
        });
    });
    return customCellClass;
}

此外,请查看- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath之间的区别。