0

我正在尝试创建一个简单的 Twitter 客户端,延迟加载 Twitter 图像。我可以在 UITableView 中获取和显示推文,但我无法加载图像。

这就是我得到的,文本和用户名正确加载但没有图像:

在此处输入图像描述

我认为问题可能出在此方法中,该方法在图像加载后由委托调用并应在表格视图单元格中显示图像:

// Called by ImageDownloader when image is ready to be displayed
- (void)imageDidLoad:(NSString *)downloadedImageUrl downloadedImage:(UIImage *)downloadedImage
{
    for (Tweet *tweet in self.tweets) {
        if (tweet.userProfileImageUrl == downloadedImageUrl) {
            tweet.userProfileImage = downloadedImage;
            UITableViewCell *tweetCell = [self.tableView cellForRowAtIndexPath:tweet.uiTableViewCellIndexPath];
            tweetCell.imageView.image = downloadedImage;
        }
    }
}

但我在下面粘贴了更多我的代码,以确保......


我为我的推文定义了一个简单的类:

@interface Tweet : NSObject
{
    NSString *userName;
    NSString *text;
    NSString *userProfileImageUrl;
    UIImage *userProfileImage;
    NSIndexPath *uiTableViewCellIndexPath;
}

@property (nonatomic, retain) NSString *userName;
@property (nonatomic, retain) NSString *text;
@property (nonatomic, retain) NSString *userProfileImageUrl;
@property (nonatomic, retain) UIImage *userProfileImage;
@property (nonatomic, retain) NSIndexPath *uiTableViewCellIndexPath;
@end

我还实现了一个简单的图像下载器类:

@protocol ImageDownloaderDelegate

- (void)imageDidLoad:(NSString *)downloadedImageUrl downloadedImage:(UIImage *)downloadedImage;

@end

@interface ImageDownloader : NSObject
{
    NSString *imageUrl;
    UIImage *downloadedImage;
    id <ImageDownloaderDelegate> __unsafe_unretained delegate;
    NSMutableData *activeDownload;
    NSURLConnection *imageConnection;
}

@property (nonatomic, retain) NSString *imageUrl;
@property (nonatomic, retain) UIImage *downloadedImage;
@property (unsafe_unretained) id <ImageDownloaderDelegate> delegate;
@property (nonatomic, retain) NSMutableData *activeDownload;
@property (nonatomic, retain) NSURLConnection *imageConnection;

- (void)startDownload;
- (void)cancelDownload;

@end

有了这个实现:

#import "ImageDownloader.h"

#define kImageWidth 48
#define kImageHeight 48

@implementation ImageDownloader

@synthesize imageUrl;
@synthesize downloadedImage;
@synthesize delegate;
@synthesize activeDownload;
@synthesize imageConnection;

#pragma mark

- (void)startDownload
{
    self.activeDownload = [NSMutableData data];
    self.imageConnection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.imageUrl]] delegate:self];
}

- (void)cancelDownload
{
    [self.imageConnection cancel];
    self.imageConnection = nil;
    self.activeDownload = nil;
}

#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    // Clear the activeDownload property to allow later attempts
    self.activeDownload = nil;

    // Release the connection now that it's finished
    self.imageConnection = nil;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // Set userProfileImage and clear temporary data/image
    UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
    if (image.size.width != kImageWidth || image.size.height != kImageHeight) {
        CGSize itemSize = CGSizeMake(kImageWidth, kImageHeight);
        UIGraphicsBeginImageContext(itemSize);
        CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
        [image drawInRect:imageRect];
        self.downloadedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    } else {
        self.downloadedImage = image;
    }

    self.activeDownload = nil;

    // Release the connection now that it's finished
    self.imageConnection = nil;

    // Call our delegate and tell it that our image is ready for display
    [delegate imageDidLoad:self.imageUrl downloadedImage:self.downloadedImage];
}

@end

在我的主控制器中,我加载了推文:

// Fetch the Twitter timeline and assigns tweets to the tweets property
- (void)fetchTweets
{
    self.tweets = [[NSMutableArray alloc] init];

    NSString *userTimelineUrl = @"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=richardknop&count=25";

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:userTimelineUrl]];

        NSError *error;

        NSArray *tweetJsonObjects = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
        for (NSUInteger i = 0; i < [tweetJsonObjects count]; i++) {
            Tweet *tweet = [[Tweet alloc] init];
            tweet.userName = [[[tweetJsonObjects objectAtIndex:i] objectForKey:@"user"] objectForKey:@"name"];
            NSString * textString = [[tweetJsonObjects objectAtIndex:i] objectForKey:@"text"];
            tweet.text = textString;
            tweet.userProfileImageUrl = [[[tweetJsonObjects objectAtIndex:i] objectForKey:@"user"] objectForKey:@"profile_image_url"];
            [self.tweets addObject:tweet];
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadData];
        });

    });
}

这是我加载表格视图内容的方式:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    int count  = [self.tweets count];
    return count;
}

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

    UITableViewCell * tweetCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (tweetCell == nil) {
        tweetCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
    }

    if ([self.tweets count] > 0) {

        Tweet *tweet = [self.tweets objectAtIndex:indexPath.row];
        tweet.uiTableViewCellIndexPath = indexPath;

        tweetCell.textLabel.text = tweet.text;
        tweetCell.detailTextLabel.text = tweet.userName;

        // Only load cached images; defer new downloads until scrolling ends
        if (!tweet.userProfileImage) {
            if (self.tableView.dragging == NO && self.tableView.decelerating == NO) {
                [self startImageDownload:tweet.userProfileImageUrl];
            }
            // If a download is deferred or in progress, return a placeholder image
            tweetCell.imageView.image = [UIImage imageNamed:@"Placeholder.png"];
        } else {
            tweetCell.imageView.image = tweet.userProfileImage;
        }

    }

    return tweetCell;
}

如果推文图像,此方法开始下载:

- (void)startImageDownload:(NSString *)userProfileImageUrl
{
    BOOL downloadAlreadyInProgress = NO;
    for (ImageDownloader *storedImageDownloader in self.imageDownloadsInProgress) {
        if (storedImageDownloader.imageUrl == userProfileImageUrl) {
            downloadAlreadyInProgress = YES;
        }
    }

    if (downloadAlreadyInProgress == NO) {
        ImageDownloader *imageDownloader = [[ImageDownloader alloc] init];
        imageDownloader.imageUrl = userProfileImageUrl;
        imageDownloader.delegate = self;
        [self.imageDownloadsInProgress addObject:imageDownloader];
        [imageDownloader startDownload];
    }
}
4

1 回答 1

1

要么您删除了代码的重要部分,因为它太长而无法发布,或者您错过了NSURLConnectionDataDelegate(以前称为NSURLConnectionDelegate)协议中最重要的方法。您填写self.activeDownload实际数据的地方。

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.activeDownload appendData:data];
}
于 2012-04-03T20:29:14.353 回答