7

मैं एक कस्टम लेआउट के साथ एक UICollectionView का उपयोग कर रहा हूं जो एक ग्रिड प्रारूप में कोशिकाओं को बताता है। 50 से अधिक पंक्तियों और 50 कॉलम अच्छी तरह से हो सकते हैं। स्क्रॉलिंग लंबवत और क्षैतिज दोनों होता है। वर्तमान में, मैं prepareLayout में लेआउट सेटअप के सभी कर रहा हूँ और सरणियों में भंडारण:UICollectionView बहुत धीमी कस्टम लेआउट

- (void)prepareLayout { 

    NSMutableArray *newLayoutInfo = [[NSMutableArray alloc] init]; 
    NSMutableArray *newLinearLayoutInfor = [[NSMutableArray alloc] init]; 

    NSInteger sectionCount = [self.collectionView numberOfSections]; 
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; 

    self.heightForRows = [delegate collectionViewHeightForAllRows]; 

    self.totalWidthsForRows = [[NSMutableArray alloc] init]; 

    for (int i = 0; i < sectionCount; i++) { 
     [self.totalWidthsForRows addObject:[NSNumber numberWithInt:0]]; 
    } 
    for (NSInteger section = 0; section < sectionCount; section++) { 
     NSMutableArray *cellLayoutInfo = [[NSMutableArray alloc] init]; 


     NSInteger itemCount = [self.collectionView numberOfItemsInSection:section]; 

    for (NSInteger item = 0; item < itemCount; item++) { 
     indexPath = [NSIndexPath indexPathForItem:item inSection:section]; 

     UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
     itemAttributes.frame = [self frameForCellAtIndexPath:indexPath]; 

     [cellLayoutInfo addObject:itemAttributes]; 
     [newLinearLayoutInfor addObject:itemAttributes]; 
    } 
    [newLayoutInfo addObject:cellLayoutInfo]; 
} 
self.layoutInfo = newLayoutInfo; 
self.linearLayoutInfo = newLinearLayoutInfor; 
} 
फिर layoutAttributesForElementsInRect में

मेरे पास है:

- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { 
NSArray *rows = [self.linearLayoutInfo filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *evaluatedObject, NSDictionary *bindings) { 
    return CGRectIntersectsRect(rect, [evaluatedObject frame]); 
}]]; 

यह ठीक काम करता है, लेकिन यह laggy और चिड़चिड़ा है जब मैं 50 से अधिक कॉलम और 50 पंक्तियां हैं। समस्या मैं अब है कि मैं

-(BOOL)shouldInvalidateLayoutForBoundsChange { 
     return YES; 
} 

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

मुझे यकीन है कि मैं यह सही नहीं कर रहा हूं और यह एक बेहतर तरीका होना चाहिए। अग्रिम में मदद के लिए धन्यवाद।

+2

आप देखें कि आप कहां स्क्रॉल के दौरान अपने समय खर्च कर रहे हैं उपकरण का उपयोग करना चाहिए। – nielsbot

+0

मैं तत्वों को बिछाने की अनुशंसा करता हूं क्योंकि वे आपके संग्रह दृश्य में जोड़े गए हैं। लेआउट तत्वों की कोई आवश्यकता नहीं है जो पहले से ही हैं - वे सही स्थिति में हैं। यदि आप इसे इस तरह से करते हैं तो आप 'चाहिएInvalidateLayoutForBoundsChange' – nielsbot

+0

@nielsbot को बंद कर सकते हैं मेरे पास पूरक विचार हैं जो हेडर के रूप में कार्य कर रहे हैं जिन्हें हमेशा संग्रहदृश्य की सामग्री ऑफ़सेट पर सेट किया जाना चाहिए। ये दृश्य के शीर्ष और किनारे पर हैं। अगर मैं 'चाहिएइविलिडेट लेटआउटफॉरबाउंड चेंज' की बारी करता हूं तो हेडर अब "फ्लोट" नहीं करते हैं जहां उन्हें माना जाता है। क्या इसका कोई अलग समाधान है? –

उत्तर

0

ठीक है - अब मैं समझता हूं। यहां मैं अनुशंसा करता हूं: 3 संग्रह दृश्य बनाएं ... कॉलम हेडर के लिए एक (जहां प्रत्येक सेल कॉलम हेडर है), पंक्ति के नेताओं (प्रत्येक सेल = 1 पंक्ति नेता) और आपके कक्षों के लिए एक संग्रह दृश्य के लिए एक। फिर जब उपयोगकर्ता द्वारा किसी भी संग्रह दृश्य की स्क्रॉल स्थिति बदल दी जाती है, तो उचित रूप से अन्य 2 संग्रह दृश्यों के लिए स्क्रॉल स्थिति अपडेट करें।

enter image description here

+0

आपको स्क्रॉलिंग के दौरान अपने ऐप को प्रोफाइल करने के लिए इंस्ट्रूमेंट्स का उपयोग करना चाहिए और देखें कि आप अपना सीपीयू समय कहां खर्च कर रहे हैं। मुख्य थ्रेड पर सीपीयू गहन कुछ भी करना आपके स्क्रॉलिंग प्रदर्शन को मार सकता है। – nielsbot

+2

मैंने एक प्रोफाइलर भी बनाया है जिसका उपयोग आप अपने ड्रॉ/लेआउट रूटीन के दौरान कर सकते हैं जो मदद कर सकता है: https://github.com/nielsbot/Profiler – nielsbot

+4

क्या आप मजाक कर रहे हैं? 3 संग्रह विचार ?? संग्रह दृश्य किसी भी प्रकार के यूआई को अपने कस्टम लेआउट सबक्लासिंग के साथ डिजाइन करने के लिए है। 3 संग्रह विचारों का निर्माण करना बस ऐप के प्रदर्शन को मारना है। –

5
-(BOOL)shouldInvalidateLayoutForBoundsChange { 
     return YES; 
} 

हल करने के लिए यह है कि क्या वास्तव में जांच करने के लिए है prepareLayout() हर बार यह स्क्रॉल करने के लिए लेआउट, जो भारी कंप्यूटिंग के कुछ भी मतलब है में तैयार एक laggy अभ्यास को बढ़ावा मिलेगा, तो एक संभावित दिशा का कारण बनता है ज्यादा समय लेना लेआउट के लिए विशेषताओं को उत्पन्न करने के लिए

for (NSInteger section = 0; section < sectionCount; section++) 
{ 
    // generate attributes ... 
} 

के अंदर एक संभावना है। जब भी यह स्क्रॉल होता है, हर बार जब यह सामान्यीकरण फिर से चालू हो जाता है, तो यह स्क्रॉल पर असर डालता है और अजीब लगता है। इसलिए इस समस्या को हल करने के लिए, या कम से कम यह हल करें कि यह वास्तव में परेशानी नहीं है, मैं सुझाव देता हूं कि इस लेआउट एल्गोरिदम में एक ध्वज सेट करने का सुझाव है, स्क्रॉलिंग है, जिस स्थिति को लेआउट को तैयार करने की आवश्यकता है, उस स्थिति के लिए खड़ा है। prepareLayout() में हर बार ध्वज की जांच करें, यदि यह हाँ है, तो हमें पता चलेगा कि लूप के लिए सभी विशेषताओं को पुन: उत्पन्न करने की आवश्यकता नहीं है, जो पहले लेआउट शुरू होने के बाद से पहले से बाहर निकलते हैं।

+1

यही कारण है कि आपको यह देखना चाहिए कि लेआउट को अमान्य किया जाना है या नहीं, यह देखने के लिए आपको चाहिएInvalidateLayoutForBoundsChange में तर्क लागू करना चाहिए। वापस हाँ बुराई है। – Andy

9

कस्टम प्रवाह लेआउट में मैं यह कर और यह मदद करने के लिए लगता है:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { 
    return !(CGSizeEqualToSize(newBounds.size, self.collectionView.frame.size)); 
} 
+1

क्या यह काम करता है? इस बिंदु पर ऐसा लगता है कि संग्रह दृश्य में पहले से ही नया आकार है, इस प्रकार हमेशा नएबाउंड के आकार को बराबर करता है। – mattyohe

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