开发者

Iphone cellForRowAtIndexPath Jerky when scrolling asynchronously problem

开发者 https://www.devze.com 2023-01-21 19:54 出处:网络
I\'ve released my app and noticed the jerkyness when scrolling in the CellForRowAtIndexPath, this is because i\'m rendering an image from an JSON Feed via a URL. I\'ve searched the internet and found

I've released my app and noticed the jerkyness when scrolling in the CellForRowAtIndexPath, this is because i'm rendering an image from an JSON Feed via a URL. I've searched the internet and found a few examples and this one i've almost got working. The problem is when it renders the images don't match the correct title. Can someone please have a look and see what if i'm doing something obviously wrong.

Anyway here is my code:

- (void)displayImage:(UIImage *)image {
[photo setImage:image]; 

}

-(void)loadImage:(NSString *)url {
NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage* image = [[[UIImage alloc] initWithData:imageData] autorelease];
[imageData release];
[self performSelectorOnMainThread:@selector(displayImage:) withObject:image waitUntilDone:NO];

}

CellForRowAtIndexPath Methord

#define DATELABEL_TAG 1 #define MAINLABEL_TAG 2 #define PHOTO_TAG 3 UIImageView *photo;



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {




 static NSString *MainNewsCellIdentifier = @"MainNewsCellIdentifier";

UILabel *mainLabel, *dateLabel;


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: MainNewsCellIdentifier];

if (cell == nil)
{
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: MainNewsCellIdentifier] autorelease];
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;

    dateLabel = [[[UILabel alloc] initWithFrame:CGRectMake(15.0,15.0,170.0,15.0)] autorelease];
    dateLabel.tag = DATELABEL_TAG;
    dateLabel.font = [UIFont systemFontOfSize:10.0];
    dateLabel.textAlignment = UITextAlignmentLeft;
    dateLabel.textColor = [UIColor darkGrayColor];
    dateLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; 
    [cell.contentView addSubview:dateLabel]; 开发者_运维知识库   

    mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(15.0,28.0,170.0,60.0)] autorelease];
    mainLabel.tag = MAINLABEL_TAG;
    mainLabel.font = [UIFont boldSystemFontOfSize:14.0];
    mainLabel.textColor = [UIColor blackColor];
    mainLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin;
    mainLabel.numberOfLines = 0;
    [cell.contentView addSubview:mainLabel];


    photo = [[[UIImageView alloc] initWithFrame:CGRectMake(190.0,15.0,85.0,85.0)] autorelease];
    photo.tag = PHOTO_TAG;    
    photo.contentMode = UIViewContentModeScaleAspectFit;

    [cell.contentView addSubview:photo];
}
else {

    dateLabel = (UILabel *)[cell.contentView viewWithTag:DATELABEL_TAG];
    mainLabel = (UILabel *)[cell.contentView viewWithTag:MAINLABEL_TAG];
    photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
}

NSUInteger row = [indexPath row];
NSDictionary *stream = (NSDictionary *) [dataList objectAtIndex:row];
NSString *title = [stream valueForKey:@"title"];


NSString *titleString = @"";

if( ! [title isKindOfClass:[NSString class]] )
{
    titleString  = @"";
}
else
{
    titleString = title;
}

CGSize maximumSize = CGSizeMake(180, 9999);

UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [titleString sizeWithFont:dateFont
                               constrainedToSize:maximumSize
                                   lineBreakMode:mainLabel.lineBreakMode];

CGRect dateFrame = CGRectMake(15.0, 28.0, 170.0, dateStringSize.height);
mainLabel.frame = dateFrame;

mainLabel.text = titleString;
dateLabel.text = [stream valueForKey:@"created"];

NSString *i = [NSString stringWithFormat:@"http://www.domain.co.uk/images/stories/%@", [stream valueForKey:@"image"]];


photo.image = [UIImage imageNamed:@"i_digital_media.png"];
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                    initWithTarget:self
                                    selector:@selector(loadImage:)
                                    object:i];
[queue addOperation:operation];
[operation release];


return cell;}


By the time that your image is loaded, the photo variable is pointed to a different photo :)

You need to pass both the loaded image and the UIImageView you want to update back - try using a NSDictionary to pass variables between threads :

- (void)displayImage:(NSDictionary *)info {
    [[info objectForKey:@"photo"] setImage:[info objectForKey:@"image"]]; 
}


-(void)loadImage:(NSDictionary *)info {
    NSString *imagePath = [info objectForKey:@"imagePath"];
    UIImageView *photo = [info objectForKey:@"photo"];

    // Load the image
    NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
    UIImage* image = [[[UIImage alloc] initWithData:imageData] autorelease];
    [imageData release];

    // Pass it back to the main thread
    NSDictionary *mainThreadInfo = [NSdictionary dictionaryWithObjectAndKeys:image, @"image", photo, @"photo", nil]; 
    [self performSelectorOnMainThread:@selector(displayImage:) withObject:mainThreadInfo waitUntilDone:YES];
}

so now, your operation will pass the photo and the image data back to the main thread. Create the operation like this :

NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:i, @"imagePath", photo, @"photo", nil];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                    initWithTarget:self
                                    selector:@selector(loadImage:)
                                    object:info];

And get rid of the global photo variable :)

0

精彩评论

暂无评论...
验证码 换一张
取 消