2012-09-07 13 views
15

का उपयोग कर लोड हो रहा है मैं वर्तमान में फ़्लिकर फोटो (सीएस 1 9 3 पी आईओएस स्टैनफोर्ड, असाइनमेंट 5) की यूआईटीबल व्यू सूची लोड करने की कोशिश कर रहा हूं। यूआई अवरुद्ध करने से बचने के लिए, मैंने प्रत्येक सेल के थंबनेल डाउनलोड को एक अलग कतार में स्थगित कर दिया है (लेकिन यूआई को मुख्य कतार में वापस अपडेट करें)। यह कोड छवियों को अतुल्यकालिक रूप से लोड नहीं करता है, हालांकि एक बार जब मैं UITableViewCell पंक्ति पर क्लिक करता हूं तो थंबनेल जोड़ता है। (नीचे स्क्रीनशॉट देखें)। कोई विचार क्या मैं गलत कर रहा हूँ?असीमित यूआईटीबल व्यूसेल छवि जीसीडी

पीएस: मैंने पहले से ही कुछ अन्य स्टैक ओवरफ्लो प्रश्नों में देखा है & ऐप्पल के LazyTableImages उदाहरण, लेकिन मुझे विश्वास है कि वांछित परिणाम प्राप्त करने का यह सबसे साफ तरीका है।

धन्यवाद!

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Photo List Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    // Configure the cell 
    NSDictionary *photo = [self.photoList objectAtIndex:indexPath.row]; 


    if (photo != nil) { 
     if ([[photo objectForKey:@"title"] length] > 0) { 
      cell.textLabel.text = [photo objectForKey:@"title"]; 
     } else if ([[[photo objectForKey:@"description"] objectForKey:@"_content"] length] > 0) { 
      cell.textLabel.text = [[photo objectForKey:@"description"] objectForKey:@"_content"]; 
     } else { 
      cell.textLabel.text = @"Unknown"; 
     } 
    } 
    cell.imageView.image = [[UIImage alloc] initWithCIImage:nil]; 

    // Fetch using GCD 
    dispatch_queue_t downloadThumbnailQueue = dispatch_queue_create("Get Photo Thumbnail", NULL); 
    dispatch_async(downloadThumbnailQueue, ^{ 
     UIImage *image = [self getTopPlacePhotoThumbnail:photo]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      if ([self.tableView.visibleCells containsObject:cell]) { 
       [cell.imageView setImage:image]; 
      } 
     }); 
    }); 
    dispatch_release(downloadThumbnailQueue); 

    return cell; 
} 

पंक्ति After selecting the row

अद्यतन चयन करने के बाद एक पंक्ति Before clicking a row

क्लिक करने से पहले:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Photo List Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    // Configure the cell 
    NSDictionary *photo = [self.photoList objectAtIndex:indexPath.row]; 

    if (photo != nil) { 
    if ([[photo objectForKey:@"title"] length] > 0) { 
     cell.textLabel.text = [photo objectForKey:@"title"]; 
    } else if ([[[photo objectForKey:@"description"] objectForKey:@"_content"] length] > 0) { 
     cell.textLabel.text = [[photo objectForKey:@"description"] objectForKey:@"_content"]; 
    } else { 
     cell.textLabel.text = @"Unknown"; 
    } 
    } 
    cell.imageView.image = [[UIImage alloc] initWithCIImage:nil]; 

    // Fetch using GCD 
    dispatch_queue_t downloadThumbnailQueue = dispatch_queue_create("Get Photo Thumbnail", NULL); 
    dispatch_async(downloadThumbnailQueue, ^{ 
    UIImage *image = [self getTopPlacePhotoThumbnail:photo]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     UITableViewCell *cellToUpdate = [self.tableView cellForRowAtIndexPath:indexPath]; // create a copy of the cell to avoid keeping a strong pointer to "cell" since that one may have been reused by the time the block is ready to update it. 
     if (cellToUpdate != nil) { 
      [cellToUpdate.imageView setImage:image]; 
      [cellToUpdate setNeedsLayout]; 
     } 
    }); 
    }); 
    dispatch_release(downloadThumbnailQueue); 

    return cell; 
} 
+0

अरे, यह बजाय पर वस्तु समानता के लिए जाँच की पूरी तरह से विषय बंद है, लेकिन सोच ब्लॉक के अंदर आप मुख्य थ्रेड को भेजें, 'सेल', जांचें कि 'इंडेक्सपाथ' पर कोई सेल मौजूद है या नहीं? –

+0

मैंने अभी यह कोशिश की: यदि ([self.tableView cellForRowAtIndexPath: indexPath]! = Nil) {... आदि} और यह ठीक काम करता है। क्या यह आपके मन में था? – sybohy

+0

दाएं, और सीधे अपने ब्लॉक में 'cell.imageView' का उपयोग नहीं करते बल्कि 'indexPath' पर सेल को पकड़कर और इसके छवि दृश्य का उपयोग करके। मुझे लगता है कि यदि आप 'सेल' का उपयोग सीधे अपने मुख्य थ्रेड ब्लॉक के अंदर स्कॉप्ड करते हैं तो आप सेल पुन: उपयोग के साथ समस्याओं में भाग ले सकते हैं। –

उत्तर

15

: उन दिलचस्पी के लिए, यह अंतिम कोड मैं प्रयोग किया जाता है आपकोपर कॉल करना चाहिए थंबनेल सेट करने के बाद सेल पर।

एप्पल डॉक्टर से:। जब आप किसी दृश्य के subviews के लेआउट समायोजित करना चाहते हैं

"अपने आवेदन की मुख्य थ्रेड पर इस विधि कॉल इस विधि अनुरोध का एक नोट बना देता है और तुरंत वापस लौट क्योंकि इस विधि से करता है। तत्काल अद्यतन को मजबूर नहीं करें, बल्कि इसके बजाय अगले अपडेट चक्र की प्रतीक्षा कर रहे हैं, आप इसका उपयोग किसी भी दृश्य को अपडेट करने से पहले कई दृश्यों के लेआउट को अमान्य करने के लिए कर सकते हैं। यह व्यवहार आपको अपने सभी लेआउट अपडेट को एक अपडेट चक्र में समेकित करने की अनुमति देता है, जो प्रदर्शन के लिए आमतौर पर बेहतर होता है। "

+0

वाह।यह जल्दी था! धन्यवाद कार्ल, मैं इसे अपने आप पर कभी नहीं सोचा होगा। एक बार फिर धन्यवाद!! – sybohy

+0

आपका स्वागत है, खुशी हुई यह काम किया! –

+0

असल में, त्वरित प्रश्न: क्या यह तकनीकी रूप से [सेल सेटNeedsLayout] को कॉल करने के लिए बेहतर नहीं होगा? मैं लेआउटसब्यूव्यू के लिए ऐप्पल दस्तावेज़ पढ़ रहा था और यही मुझे मिला: "आपको इस विधि को [layoutSubviews] को सीधे कॉल नहीं करना चाहिए। अगर आप लेआउट अपडेट को मजबूर करना चाहते हैं, तो अगले ड्राइंग अपडेट से पहले ऐसा करने के बजाय setNeedsLayout विधि को कॉल करें । " तुम क्या सोचते हो? (दोनों कामकाजी तरीके से काम करते हैं) – sybohy

0

एक और समाधान (और जिसे मैंने उस असाइनमेंट के लिए उपयोग किया था) सेल की छवि पर सेटनेड्स डिस्प्ले को कॉल करना है एक बार जब आपने उस छवि को UIImage असाइन किया है तो देखें।

तो मूल रूप से, मैंने फ़्लिकरडाउनलोडर नामक एक कक्षा बनाई जो फ़्लिकरफ़ेचर (साथ ही साथ मेरे कैशिंग कोड) की कार्यक्षमता को लपेटता है। FlickrDownloader इस विधि है:

(void)getImageForPhotoInfo:(NSDictionary *)photoInfo ofFormat:(FlickrPhotoFormat)format withCallback:(image_setter_callback_t)callback; 

यह मूलतः FlickrFetcher का एक ही कार्य करने के लिए एक फोन है, लेकिन यह एक कॉलबैक thats तस्वीर को डाउनलोड करने के पूरा होने पर कहा जाता है कहते हैं। एक UITableViewCell की imageView को अद्यतन करने के मामले में कॉलबैक इस तरह दिखता है:

image_setter_callback_t setImage = ^(UIImage *image){ 
    cell.imageView.image = image; 
    [cell.imageView setNeedsDisplay]; 
}; 
+0

क्या यह फ्रेम को '(0,0,0,0)' पर सेट करने वाले सेल के आसपास मिलता है? जब मैंने कुछ ऐसा करने की कोशिश की, तब तक इसका आकार बदल नहीं आया जब तक कि मैंने 'लेआउटस्यूव्यूव्स' को कॉल करने के लिए मजबूर नहीं किया। क्या आप प्लेसहोल्डर छवि का उपयोग कर रहे थे? –

+0

यदि आप [cell.imageView setNeedsDisplay] को कॉल करते हैं, तो क्या आपके वर्ग को drawRect विधि को लागू करने की आवश्यकता नहीं है? गिरावट पर वापस जांचना 2011 व्याख्यान 4 स्लाइड # 8, setNeedsDisplay DrawRect को कॉल करने के लिए सब कुछ सेट अप करता है। यह वास्तव में नहीं कहता है कि यह उससे कम या कम करता है। क्या यह? – sybohy

+0

@CarlVeazey आप सही हैं कि मैंने प्लेसहोल्डर छवि का उपयोग किया है जैसे LazyTableImages उदाहरण। चूंकि यह शुरुआत से मेरा दृष्टिकोण था, शायद इस तरह मैं फ्रेम को सेट करने के लिए मिला। –

संबंधित मुद्दे