2012-12-12 18 views
28

मेरे पास कुछ डेटा है जो किसी अन्य थ्रेड में लाया जाता है जो UICollectionView के शीर्षलेख को अद्यतन करता है। हालांकि, मुझे हेडर या पाद लेख जैसे पूरक दृश्य को पुनः लोड करने का एक प्रभावी तरीका नहीं मिला है।UICollectionView हेडर या फ़ूटर को दोबारा लोड करें?

मैं collectionView reloadSections: पर कॉल कर सकता हूं, लेकिन यह पूरे अनुभाग को फिर से लोड करता है जो अनावश्यक है। collectionView reloadItemsAtIndexPaths: केवल कोशिकाओं को लक्षित करने लगता है (पूरक विचार नहीं)। और हेडर पर setNeedsDisplay को कॉल करना या तो काम नहीं करता है। क्या मैं कुछ भूल रहा हूँ?

उत्तर

2

यहां दो तरीके हैं जो आप कर सकते हैं।

1. अंततः उपलब्ध डेटा को वापस करने के लिए एक परिवर्तनीय मॉडल बनाएं। परिवर्तनों का निरीक्षण करने के लिए UICollectionReusableView के विरासत वर्ग में केवीओ का उपयोग करें और उपलब्ध होने पर नए डेटा के साथ हेडर व्यू अपडेट करें।

[model addObserver:headerView 
     forKeyPath:@"path_To_Header_Data_I_care_about" 
      options:(NSKeyValueObservingOptionNew | 
        NSKeyValueObservingOptionOld) 
      context:NULL]; 

तो हैडर ध्यान में रखते हुए श्रोता विधि को लागू

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 

2. देखने के लिए अधिसूचना श्रोता जोड़ सकते हैं और एक सूचना पोस्ट जब डेटा को सफलतापूर्वक उपलब्ध आ गया है। नकारात्मकता यह है कि यह आवेदन व्यापक है और एक साफ डिजाइन नहीं है।

// place in shared header file 
#define HEADER_DATA_AVAILABLE @"Header Data Available Notification Name" 

// object can contain userData property which could hole data needed. 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(headerDataAvailable:) name:HEADER_DATA_AVAILABLE object:nil]; 

[[NSNotificationCenter defaultCenter] postNotificationName:HEADER_DATA_AVAILABLE object:nil]; 
+0

मैं KVO का उपयोग किया है, लेकिन मैं, डेटा के अपडेट के लिए बात सुनी है मेरी कस्टम हेडर वर्ग पर क्षेत्रों की स्थापना की, और उस पर setNeedsDisplay कहा जाता है, लेकिन कुछ भी नहीं बदला । मुझे हेडर को रीफ्रेश करने के लिए और अधिक परेशानी हो रही है, क्योंकि मैं आर्किटेक्टिंग के साथ इसे अपडेट करना चाहता हूं। – akaru

+0

क्या आपने अवैध लेटआउट को कॉल करने का प्रयास किया है। क्या यह आपके हेडर को रीफ्रेश करता है? – Samuel

+0

जो कि काम नहीं करता था। सबसे आसान स्तर पर – akaru

11

मैं सिर्फ एक ही समस्या में पड़ गए, और मैं अपने टैग का उपयोग कर किसी लेबल को संपादित करने के लिए दृश्य को देख समाप्त हो गया:

UICollectionReusableView *footer = (UICollectionReusableView*)[self.collectionView viewWithTag:999]; 
UILabel *footerLabel = (UILabel*)[footer viewWithTag:100]; 

जैसे तुमने कहा यह एक पूरा खंड को फिर से लोड करने के लिए अनावश्यक है, जो कोशिकाओं पर किसी भी एनीमेशन को रद्द करता है। मेरा समाधान आदर्श नहीं है, लेकिन यह काफी आसान है।

+0

मुझे डरना होगा कि हेडर पुन: उपयोग को रोक देगा, या स्मृति समस्याओं का कारण बन जाएगा। – akaru

+3

@akaru यह मेरे लिए ठीक काम करता है। निश्चित नहीं है कि स्मृति समस्या क्यों होगी क्योंकि यह सिर्फ एक टैग है। –

+2

केवीओ – TheCodingArt

3

मुझे एक ही समस्या मिली। मैंने @ बॉबवॉर्क्स के जवाब की कोशिश की और यह ठीक काम कर रहा है, अगर केवल सेल का पुन: उपयोग किया गया तो यह नहीं होगा। इसलिए, मैंने इसे प्राप्त करने के लिए एक और अधिक क्लीनर तरीका खोजने का प्रयास किया और मैं निष्पादन बैचअपडेट (समापन ब्लॉक) के बाद पूरे यूआईसीओलेक्शन व्यू को पुनः लोड कर रहा हूं और यह बहुत अच्छा काम कर रहा है। यह insertItemsAtIndexPath में एनीमेशन को रद्द करने के बिना संग्रह को फिर से लोड करता है। असल में मैंने हाल ही में 2 उत्तरों का वोट दिया क्योंकि मुझे यह काम मिल रहा है लेकिन मेरे मामले में, यह करने का सबसे साफ तरीका है।

[self.collectionView performBatchUpdates:^{ 
    // perform indexpaths insertion 
} completion:^(BOOL finished) { 
    [self.collectionView reloadData]; 
}]; 
19

तुम भी उपयोग कर सकते हैं

[[_collectionView collectionViewLayout] invalidateLayout] 
+3

के बगल में सबसे खराब जवाब यह वास्तव में स्वीकार्य उत्तर – tropicalfish

+1

सही उत्तर होना चाहिए ..! –

+1

जो पूरे लेआउट को पुनः लोड करता है। पूरक विचारों के बावजूद या नहीं। – TheCodingArt

1

यहाँ मैं केवल अनुभाग शीर्ष लेख है कि वर्तमान में स्मृति में लोड किए गए हैं अद्यतन करने के लिए किया था है:

  • एक weakToStrong NSMapTable जोड़ें। जब आप हेडर बनाते हैं, तो इंडेक्सपाथ ऑब्जेक्ट के साथ हेडर को कमजोर रूप से दबाए गए कुंजी के रूप में जोड़ें। अगर हम हेडर का पुन: उपयोग करते हैं तो हम इंडेक्सपाथ अपडेट करेंगे।
  • जब आपको हेडर अपडेट करने की आवश्यकता होती है, तो अब आप आवश्यकतानुसार NSMapTable से ऑब्जेक्ट्स/चाबियों की गणना कर सकते हैं।

    @interface YourCVController() 
     @property (nonatomic, strong) NSMapTable *sectionHeaders; 
    @end 

    @implementation YourCVContoller 

    - (void)viewDidLoad { 
     [super viewDidLoad]; 
     // This will weakly hold on to the KEYS and strongly hold on to the OBJECTS 
     // keys == HeaderView, object == indexPath 
     self.sectionHeaders = [NSMapTable weakToStrongObjectsMapTable]; 
    } 

    // Creating a Header. Shove it into our map so we can update on the fly 
    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 
    { 
     PresentationSectionHeader *header = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"presentationHeader" forIndexPath:indexPath]; 
     // Shove data into header here 
     ... 
     // Use header as our weak key. If it goes away we don't care about it 
     // Set indexPath as object so we can easily find our indexPath if we need it 
     [self.sectionHeaders setObject:indexPath forKey:header]; 
     return header; 
    } 

    // Update Received, need to update our headers 
    - (void) updateHeaders { 
     NSEnumerator *enumerator = self.sectionHeaders.keyEnumerator; 
     PresentationSectionHeader *header = nil; 
     while ((header = enumerator.nextObject)) { 
      // Update the header as needed here 
      NSIndexPath *indexPath = [self.sectionHeaders objectForKey:header]; 
     } 
    } 

    @end 
1

यह सवाल बहुत पुरानी लेकिन यह सिर्फ एक देरी उस समय आपके विचार एनिमेट और जब तक आप दृश्य को अपडेट एनीमेशन अक्षम करने है ... आमतौर पर एक हटाने को शामिल किया गया स्थापित करने के लिए है करने के लिए एक आसान तरीका है या डालने के बारे में लेता है।इसलिए 35 सेकंड बस करो:

delay(0.35){ 
      UIView.performWithoutAnimation{ 
      self.collectionView.reloadSections(NSIndexSet(index: 1)) 
      } 
0
[UIView performWithoutAnimation:^{ 
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:4]]; 
}]; 

[UIView performWithoutAnimation:^{ 
[self.collectionView reloadData]; 
}]; 
संबंधित मुद्दे