gpt4 book ai didi

ios - 图像持久化和延迟加载与 Dispatch_Async 冲突

转载 作者:可可西里 更新时间:2023-11-01 05:37:14 26 4
gpt4 key购买 nike

我正在开发一个提要阅读器,我是通过使用 nsxmlparser 解析 rss 提要来实现的。我还有从 CDATA block 中获取的缩略图对象。

-(void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

NSString *someString = [[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];
NSString *storyImageURL = [self getFirstImageUrl:someString];

NSURL *tempURL = [NSURL URLWithString:storyImageURL];

NSData *tempData = [NSData dataWithContentsOfURL:tempURL];
thumbnail = [UIImage imageWithData:tempData];

});
}

我正在使用归档和编码解码方法保存图像和其他 tableview 对象。

问题是当我按原样使用上面的代码时,它不会保留图像,而其他 tableview 对象(如标题和发布日期)会保留。但是当我在没有 dispatch_async 的情况下使用上面的代码时,它会开始保留图像但会锁定用户界面。

如何在不锁定用户界面的情况下保留图像?

请不要回答某些存储和缓存图像的库或 Apple 的延迟加载示例。谢谢

更新:

根据提供的答案并在 iTunes 上观看了斯坦福大学关于多线程的讲座后,我将上述代码实现如下:

  NSString *someString = [[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];
NSString *storyImageURL = [self getFirstImageUrl:someString];
NSURL *tempURL = [NSURL URLWithString:storyImageURL];

dispatch_queue_t downloadQueue = dispatch_queue_create("image downloader", NULL);

dispatch_async(downloadQueue, ^{
NSData *tempData = [NSData dataWithContentsOfURL:tempURL];

dispatch_async(dispatch_get_main_queue(), ^{
thumbnail = [UIImage imageWithData:tempData];
});
});
}

从逻辑上讲,现在一切都正确了,但仍然没有用。我都被阻止了如何解决这个问题。

更新:

我正在使用 Model View Controller 存储方法,我的存储和连接代码在单独的文件中定义。下面是我使用 NSKeyedArchiver 的代码。

- (FeedChannel *) FeedFetcherWithCompletion:(void (^)(FeedChannel *, NSError *))block {

NSURL *url = [NSURL URLWithString:@"http://techcrunch.com/feed/"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];

FeedChannel *channel = [[FeedChannel alloc] init];

TheConnection *connection = [[TheConnection alloc] initWithRequest:req];

NSString *pathOfCache = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
pathOfCache = [pathOfCache stringByAppendingPathComponent:@"check.archive"];

FeedChannel *channelCache = [NSKeyedUnarchiver unarchiveObjectWithFile:pathOfCache];


if (!channelCachel) {
channelCache = [[FeedChannel alloc] init];
}
FeedChannel *channelCopy = [channelCache copy];

[connection setCompletionBlock:^(FeedChannel *obj, NSError *err) {
if (!err) {
[channelCopy addItemsFromChannel:obj];
[NSKeyedArchiver archiveRootObject:channelCopy toFile:pathOfCache];
}
block(channelCopy, err);
}];

[connection setXmlObject:channel];
[connection start];

return channelCache;
}

以下是我的编码和解码方法。

- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:title forKey:@"title"];
[aCoder encodeObject:link forKey:@"link"];
[aCoder encodeObject:creator forKey:@"creator"];
[aCoder encodeObject:pubDate forKey:@"pubDate"];
[aCoder encodeObject:thumbnail forKey:@"thumbnail"];
//[aCoder encodeObject:UIImagePNGRepresentation(thumbnail) forKey:@"thumbnail"];
[aCoder encodeObject:publicationDate forKey:@"publicationDate"];

}

- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self)
{
[self setTitle:[aDecoder decodeObjectForKey:@"title"]];
[self setLink:[aDecoder decodeObjectForKey:@"link"]];
[self setCreator:[aDecoder decodeObjectForKey:@"creator"]];
[self setPubDate:[aDecoder decodeObjectForKey:@"pubDate"]];
[self setThumbnail:[aDecoder decodeObjectForKey:@"thumbnail"]];
//[self setThumbnail:[UIImage imageWithData:[aDecoder decodeObjectForKey:@"thumbnail"]]];
[self setPublicationDate:[aDecoder decodeObjectForKey:@"publicationDate"]];

}
return self;
}

根据答案,我不知道我是否必须使用一些额外的代码来保存图像。因为其他对象(如标题、创建者等)会准确保留。

最佳答案

阅读您的评论后,我倾向于认为这个问题与您如何保留与 dispatch_async block 相关的图像有关。我会尝试解释,但这只是一个猜测,因为我不知道你把图像保存在哪里:

  1. 在某个时候你的 parser:foundCDATA:被执行并且您异步检索您的图像;

  2. 图像在一段时间内不会存在(直到同步块(synchronized block)完成),所以 thumbnail在完成 parser:foundCDATA: 后的一段时间内,ivar/property 将没有正确的值;

  3. 现在,如果你坚持thumbnail在异步 block 完成之前,您将保留错误的(nil?)值;

  4. 事实上,如果您不执行异步获取图像,那么一切正常,这让我认为您保存图像太早(在上述意义上)。

对此的修复是仅在异步 block 完成后才保留图像。这可能意味着:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

NSString *someString = [[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];
NSString *storyImageURL = [self getFirstImageUrl:someString];

NSURL *tempURL = [NSURL URLWithString:storyImageURL];

NSData *tempData = [NSData dataWithContentsOfURL:tempURL];
thumbnail = [UIImage imageWithData:tempData];

<code here to make the thumbnail be persisted>

});

<code here to make the thumbnail be persisted>可以是方法调用、通知帖子,任何适合您当前设计的内容。如果您的持久化代码不是线程安全的,您可能还需要使用将调用分派(dispatch)到主线程的技巧:

  dispatch_async(dispatch_get_main_queue(), ^{
<persist thumbnail>;
}

希望对您有所帮助。

编辑:

经过我们的交谈,上述分析得到证实。事实上,您不仅仅是在下载一张图片:您正在下载一堆图片,它们都属于同一个“ channel ”。这意味着应用于整个 channel 的持久化操作只有在所有这些图像都已下载后才会执行。

因此,我 fork 了你的要点并添加了一些逻辑,使 GCD dispatch_group 能够跟踪所有下载操作。你可以找到它here .

关于ios - 图像持久化和延迟加载与 Dispatch_Async 冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14388248/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com