से छवियों को लोड करते समय स्क्रॉल दृश्य और तालिका दृश्य प्रदर्शन, मैं नेटवर्क पर जाने के बजाय डिस्क-आधारित छवि कैश का उपयोग कर अपने छवि-गहन आईफोन ऐप के प्रदर्शन को बेहतर बनाने की कोशिश कर रहा हूं। मैंने SDImageCache (http://github.com/rs/SDWebImage/blob/master/SDImageCache.m) के बाद अपनी छवि कैश का मॉडल किया है, और यह काफी समान है लेकिन असीमित कैश इन/आउट ऑपरेशन के बिना।डिस्क
मेरे पास कुछ स्क्रॉल दृश्य और तालिका दृश्य हैं जो इन छवियों को असीमित रूप से लोड करते हैं। यदि छवि डिस्क पर है, तो यह छवि कैश से लोड की जाती है, अन्यथा नेटवर्क अनुरोध किया जाता है और बाद का परिणाम कैश में संग्रहीत होता है।
जिस समस्या में मैं चल रहा हूं वह यह है कि जब मैं स्क्रॉल दृश्य या तालिका दृश्यों के माध्यम से स्क्रॉल करता हूं, तो छवि को डिस्क से लोड होने के कारण एक ध्यान देने योग्य अंतराल होता है। विशेष रूप से, स्क्रॉल व्यू पर एक पृष्ठ से दूसरे पृष्ठ पर जाने की एनीमेशन संक्रमण के बीच में एक छोटा सा फ्रीज होता है।
मैं इसका समाधान करने में की कोशिश की है: डिस्क पहुँच अनुरोध करने के लिए (SDImageCache के रूप में एक ही तरीके से) एक NSOperationQueue और NSInvocationOperation वस्तुओं का उपयोग करना
- , लेकिन यह कम से अंतराल के साथ मदद नहीं करता है सब।
- स्क्रॉल व्यू कंट्रोलर कोड को ट्वीक करना ताकि स्क्रॉल दृश्य अब स्क्रॉल न होने पर यह केवल छवियों को लोड कर सके। इसका मतलब यह है कि स्क्रॉल दृश्य स्क्रॉलिंग बंद होने पर डिस्क पहुंच केवल तभी होती है, लेकिन अगर मैं तुरंत अगले पृष्ठ पर स्क्रॉल करने का प्रयास करता हूं तो मैं डिस्क से छवि लोड के रूप में अंतराल को देख सकता हूं।
क्या मेरी डिस्क एक्सेस बेहतर प्रदर्शन करने या UI पर कम प्रभाव डालने का कोई तरीका है?
ध्यान दें कि मैं पहले ही स्मृति में छवियों को कैशिंग कर रहा हूं। तो एक बार सब कुछ स्मृति में लोड हो जाने पर, यूआई अच्छा और उत्तरदायी है। लेकिन जब ऐप शुरू होता है, या यदि कम मेमोरी चेतावनियां भेजी जाती हैं, तो मुझे इनमें से कई यूआई लैग का अनुभव होगा क्योंकि छवियों को डिस्क से लोड किया जाता है।
प्रासंगिक कोड स्निपेट नीचे दिए गए हैं। मुझे नहीं लगता कि मैं कुछ भी फैंसी या पागल कर रहा हूँ। अंतराल एक आईफोन 3 जी पर ध्यान देने योग्य प्रतीत नहीं होता है, लेकिन यह दूसरे-जनरल आइपॉड टच पर काफी स्पष्ट है।
छवि कैशिंग कोड:
यहाँ मेरी छवि कैशिंग कोड का एक टुकड़ा प्रासंगिक है। बहुत सीधा।
- (BOOL)hasImageDataForURL:(NSString *)url {
return [[NSFileManager defaultManager] fileExistsAtPath:[self cacheFilePathForURL:url]];
}
- (NSData *)imageDataForURL:(NSString *)url {
NSString *filePath = [self cacheFilePathForURL:url];
// Set file last modification date to help enforce LRU caching policy
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSDate date] forKey:NSFileModificationDate];
[[NSFileManager defaultManager] setAttributes:attributes ofItemAtPath:filePath error:NULL];
return [NSData dataWithContentsOfFile:filePath];
}
- (void)storeImageData:(NSData *)data forURL:(NSString *)url {
[[NSFileManager defaultManager] createFileAtPath:[self cacheFilePathForURL:url] contents:data attributes:nil];
}
स्क्रॉल दृश्य नियंत्रक कोड
यहाँ कोड है कि मैं अपने स्क्रॉल दृश्य नियंत्रकों में छवियों को प्रदर्शित करने के लिए उपयोग की एक प्रासंगिक टुकड़ा है।
- (void)scrollViewDidScroll:(UIScrollView *)theScrollView {
CGFloat pageWidth = theScrollView.frame.size.width;
NSUInteger index = floor((theScrollView.contentOffset.x - pageWidth/2)/pageWidth) + 1;
[self loadImageFor:[NSNumber numberWithInt:index]];
[self loadImageFor:[NSNumber numberWithInt:index + 1]];
[self loadImageFor:[NSNumber numberWithInt:index - 1]];
}
- (void)loadImageFor:(NSNumber *)index {
if ([index intValue] < 0 || [index intValue] >= [self.photoData count]) {
return;
}
// ... initialize an image loader object that accesses the disk image cache or makes a network request
UIView *iew = [self.views objectForKey:index];
UIImageView *imageView = (UIImageView *) [view viewWithTag:kImageViewTag];
if (imageView.image == nil) {
NSDictionary *photo = [self.photoData objectAtIndex:[index intValue]];
[loader loadImage:[photo objectForKey:@"url"]];
}
}
छवि लोडर वस्तु सिर्फ एक हल्के उद्देश्य यह है कि डिस्क कैश की जाँच करता है और चाहे या नहीं डिस्क या नेटवर्क से एक छवि को लाने के लिए फैसला करता है।
- (void)imageLoadedFor:(NSNumber *)index image:(UIImage *)image {
// Cache image in memory
// ...
UIView *view = [self.views objectForKey:index];
UIImageView *imageView = (UIImageView *) [view viewWithTag:kImageViewTag];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.image = image;
}
अद्यतन
मैं एप्लिकेशन के साथ प्रयोग कर रहा था, और मैं छवि कैश अक्षम और पुनः बदला हमेशा बनाने के लिए: एक बार यह किया है, यह छवि प्रदर्शित करने के लिए स्क्रॉल दृश्य नियंत्रक पर एक प्रणाली को बुलाती है नेटवर्क अनुरोध ऐसा लगता है कि छवियों को लाने के लिए बस नेटवर्क अनुरोधों का उपयोग करना स्क्रॉल दृश्यों और तालिका दृश्यों के माध्यम से स्क्रॉल करते समय एक ही अंतराल का कारण बनता है! यही है, जब एक नेटवर्क अनुरोध समाप्त होता है और स्क्रॉल व्यू पेज या टेबल सेल में छवि दिखायी जाती है, तो यूआई थोड़ी देर लगती है और इसमें कुछ हिस्सों के अंतराल होते हैं क्योंकि मैं इसे खींचने की कोशिश करता हूं।
डिस्क कैश का उपयोग करते समय अंतराल अधिक ध्यान देने योग्य प्रतीत होता है, क्योंकि अंतराल पृष्ठ संक्रमण पर हमेशा होता है। संभवतः मैं लोड की गई छवि को उपयुक्त UIImageView में निर्दिष्ट करते समय कुछ गलत कर रहा हूं?
इसके अलावा - मैंने छोटी छवियों (50x50 थंबनेल) का उपयोग करने की कोशिश की है और अंतराल में सुधार हुआ है। तो ऐसा लगता है कि प्रदर्शन हिट या तो डिस्क से बड़ी छवि लोड करने या एक बड़ी छवि को UIImage ऑब्जेक्ट में लोड करने के कारण है। मुझे लगता है कि स्क्रॉल व्यू और टेबल व्यू में लोड होने वाली छवियों के आकार को कम करने के लिए एक सुधार होगा, जो कि मैं फिर भी करने की योजना बना रहा था। हालांकि, मैं समझ नहीं पा रहा हूं कि अन्य फोटो-गहन ऐप कैसे प्रदर्शित करने में सक्षम हैं, जो प्रदर्शन की समस्याओं के बिना डिस्क या नेटवर्क पर जाने के बिना स्क्रॉल करने योग्य दृश्यों में सुंदर उच्च-रेज फ़ोटो की तरह दिखता है।
हमें बड़ी छवियों वाले आईपैड पर एक ही समस्या है। अगर आपको कोई समाधान मिल जाए तो मैं आपको बता दूंगा –
प्रदर्शन स्क्रॉल करने के लिए मुख्य कुंजी में से एक मुख्य धागा को कभी भी अवरुद्ध नहीं करना है। मुख्य धागा यूआई थ्रेड है, जिसे स्क्रीन पर उच्च फ़्रेमेट अपडेट और आपके कंट्रोलर से संबंधित ईवेंट कॉलबैक प्रबंधित करना होता है। अपने NSUURLConnection कोड को देखे बिना मैं यह नहीं कह सकता कि आप इसे एक अलग थ्रेड में कर रहे हैं या नहीं, हालांकि, यह मेरा पहला झटका होगा। क्या आप अपना नेटवर्क हैंडलिंग कोड पोस्ट कर सकते हैं? – Yetanotherjosh
टीसीआईमेज व्यू जिथब परियोजना की जांच करें। आलसी लोडिंग छवियों और डिस्क कैशिंग के लिए उनके पास एक सुंदर साफ कार्यान्वयन है https://github.com/totocaster/TCImageView/blob/master/TCImageView.m –