2013-01-17 25 views
4

我正在使用供稿閱讀器,並且我正在使用nsxmlparser解析rss提要。我也有從CDATA塊取得的縮略圖對象。使用Dispatch_Async進行圖片持久性和延遲加載衝突

-(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時,它會啓動持久化圖像但鎖定用戶界面。

如何在不鎖定用戶界面的情況下堅持圖像?

請不要回答一些圖書館來存儲和緩存圖像或蘋果的懶加載示例。由於

UPDATE:

根據所提供的答案,並觀看由斯坦福大學的演講中對多線程的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]; 
     }); 
    }); 
} 

從邏輯上講,一切都現在糾正,但仍然無效。我都被封鎖瞭如何解決這個問題。

UPDATE:

我使用的模型 - 視圖 - 控制器存儲方法和我的商店和連接的代碼在不同的文件中定義。以下是我使用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; 
} 

基於這個答案,我不知道我是否需要使用一些額外的代碼來保存圖像。因爲像標題,創作者等其他對象正在持續準確。

回答

5

閱讀您的評論後,我傾向於認爲這個問題與您如何堅持圖像相對於dispatch_async塊有關。我會盡量解釋,但這僅僅是一種猜測,因爲我不知道你堅持的圖像:

  1. 在執行您parser:foundCDATA:某些時候,你異步檢索你的形象;

  2. 圖像將不會在那裏一段時間(直到同步塊完成),因此在完成parser:foundCDATA:之後thumbnail ivar /財產將不會有一段時間的正確值;

  3. 現在,如果在異步塊完成之前持續thumbnail,則會持續出現錯誤的(nil?)值;

  4. 事實上,如果你不執行異步獲取圖像,那麼一切正常,使我認爲你是堅持圖像太早(在上述意義上)。

對此的修復只會在異步塊完成後纔會保留圖像。這可能意味着類似:

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_async(dispatch_get_main_queue(), ^{ 
     <persist thumbnail>; 
    } 

希望它能幫助。

編輯:

我們聊天后,上述分析得到證實。實際上,您並不是簡單地下載一張圖片:您正在下載一組圖片,所有圖片都屬於同一個「頻道」。這意味着應用於整個頻道的持久操作只有在所有這些圖像被下載後才能執行。

我已經分出了你的要點,並添加了一些邏輯,使GCD dispatch_group能夠跟蹤所有的下載操作。你可以找到它here

+0

@Jessica:花了一些時間才能達到最終版本......希望它適合你。 – sergio

+0

我已經嘗試了兩種解決方案,但問題相同。當我使用dispatch_asyc或dispatch_sych時,圖像停止持續。他們第一次加載,但當我關閉並打開應用程序時,所有其他對象都在那裏,但沒有圖像。 – Jessica

+0

你猜對了。一切正在發生,你如何解釋。我已經使用了您在更新的答案中建議的使用主隊列的代碼,但仍然無效。你能猜到還有什麼可能是錯的。謝謝 – Jessica