Lcs*_*est 7 cocoa-touch asynchronous nsoperationqueue grand-central-dispatch ios
我创建了一个NSOperationQueue下载图像(从Twitter获取Cell):
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
NSString *ImagesUrl = [[NSString alloc]initWithFormat:@"http://api.twitter.com/1/users/profile_image/%@",[[status objectForKey:@"user"]objectForKey:@"screen_name"]];;
NSURL *imageurl = [NSURL URLWithString:ImagesUrl];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageurl]];
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
if (img.size.width == 0 || [ImagesUrl isEqualToString:@"<null>"]) {
[statusCell.imageCellTL setFrame:CGRectZero];
statusCell.imageCellTL.image = [UIImage imageNamed:@"Placeholder"] ;
}else
[statusCell.imageCellTL setImage:img];
Run Code Online (Sandbox Code Playgroud)
这工作正常,但当它似乎移动滚动和查看图像仍在加载,并且他们正在改变几次,直到你得到一张图片.
而且我不喜欢诊断时间的轮廓,所以我想以某种方式NSOperationQueue在背景中做到这一点
还可以展示如何使"Imagecache"无需下载已下载的图像.
**(状态= Twitter时间轴的NSDictionary).
编辑::(所有单元格)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Celulatime";
UITableViewCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if ( [Cell isKindOfClass:[TimeLineCell class]] ) {
TimeLineCell *statusCell = (TimeLineCell *) Cell;
status = [self.dataSource objectAtIndex:indexPath.row];
statusCell.TextCellTL.text = [status objectForKey:@"text"];
statusCell.NomeCellTL.text = [status valueForKeyPath:@"user.name"];
statusCell.UserCellTL.text = [NSString stringWithFormat:@"@%@", [status valueForKeyPath:@"user.screen_name"]];
NSDate *created_at = [status valueForKey:@"created_at"];
if ( [created_at isKindOfClass:[NSDate class] ] ) {
NSTimeInterval timeInterval = [created_at timeIntervalSinceNow];
statusCell.timeCellTL.text = [self timeIntervalStringOf:timeInterval];
} else if ( [created_at isKindOfClass:[NSString class]] ) {
NSDate *date = [self.twitterDateFormatter dateFromString: (NSString *) created_at];
NSTimeInterval timeInterval = [date timeIntervalSinceNow];
statusCell.timeCellTL.text = [self timeIntervalStringOf:timeInterval];
}
NSString *imageUrlString = [[NSString alloc]initWithFormat:@"http://api.twitter.com/1/users/profile_image/%@",[[status objectForKey:@"user"]objectForKey:@"screen_name"]];;
UIImage *imageFromCache = [self.imageCache objectForKey:imageUrlString];
if (imageFromCache) {
statusCell.imageCellTL.image = imageFromCache;
[statusCell.imageCellTL setFrame:CGRectMake(9, 6, 40, 40)];
}
else
{
statusCell.imageCellTL.image = [UIImage imageNamed:@"TweHitLogo57"];
[statusCell.imageCellTL setFrame:CGRectZero];
[self.imageluckluck addOperationWithBlock:^{
NSURL *imageurl = [NSURL URLWithString:imageUrlString];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageurl]];
if (img != nil) {
[self.imageCache setObject:img forKey:imageUrlString];
// now update UI in main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
TimeLineCell *updateCell = (TimeLineCell *)[tableView cellForRowAtIndexPath:indexPath];
if (updateCell) {
[updateCell.imageCellTL setFrame:CGRectMake(9, 6, 40, 40)];
[updateCell.imageCellTL setImage:img];
}
}];
}
}];
}
}
return Cell;
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 12
几点意见:
您可能应该NSOperationQueue在类中定义一个并在其中初始化viewDidLoad(以及a NSCache)并向该队列添加操作,而不是NSOperationQueue为每个图像创建一个新的.此外,许多服务器限制了每个客户端支持的并发请求数,因此请务必进行相应设置maxConcurrentOperationCount.
@interface ViewController ()
@property (nonatomic, strong) NSOperationQueue *imageOperationQueue;
@property (nonatomic, strong) NSCache *imageCache;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageOperationQueue = [[NSOperationQueue alloc]init];
self.imageOperationQueue.maxConcurrentOperationCount = 4;
self.imageCache = [[NSCache alloc] init];
}
// the rest of your implementation
@end
Run Code Online (Sandbox Code Playgroud)您tableView:cellForRowAtIndexPath:应该(a)image在启动异步图像加载之前初始化(因此您不会在那里看到重用单元格中的旧图像); (b)在更新之前确保单元格仍然可见:
NSString *imageUrlString = [[NSString alloc]initWithFormat:@"http://api.twitter.com/1/users/profile_image/%@",[[status objectForKey:@"user"]objectForKey:@"screen_name"]];;
UIImage *imageFromCache = [self.imageCache objectForKey:imageUrlString];
if (imageFromCache) {
statusCell.imageCellTL.image = imageFromCache;
[statusCell.imageCellTL setFrame: ...]; // set your frame accordingly
}
else
{
statusCell.imageCellTL.image = [UIImage imageNamed:@"Placeholder"];
[statusCell.imageCellTL setFrame:CGRectZero]; // not sure if you need this line, but you had it in your original code snippet, so I include it here
[self.imageOperationQueue addOperationWithBlock:^{
NSURL *imageurl = [NSURL URLWithString:imageUrlString];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageurl]];
if (img != nil) {
// update cache
[self.imageCache setObject:img forKey:imageUrlString];
// now update UI in main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// see if the cell is still visible ... it's possible the user has scrolled the cell so it's no longer visible, but the cell has been reused for another indexPath
TimeLineCell *updateCell = (TimeLineCell *)[tableView cellForRowAtIndexPath:indexPath];
// if so, update the image
if (updateCell) {
[updateCell.imageCellTL setFrame:...]; // I don't know what you want to set this to, but make sure to set it appropriately for your cell; usually I don't mess with the frame.
[updateCell.imageCellTL setImage:img];
}
}];
}
}];
}
Run Code Online (Sandbox Code Playgroud)不需要特殊处理,UIApplicationDidReceiveMemoryWarningNotification因为虽然NSCache没有响应此内存警告,但它会在内存变低时自动驱逐其对象.
我没有测试过上面的代码,但希望你能得到这个想法.这是典型的模式.你的原始代码有一个检查[ImagesUrl isEqualToString:@"<null>"],我不知道怎么可能是这种情况,但如果除了我之外还需要一些额外的逻辑if (img != nil) ...,那么相应地调整该行.
| 归档时间: |
|
| 查看次数: |
10099 次 |
| 最近记录: |