IOS 7 में UICollectionView ReloadData ठीक से काम नहीं कर रहा है


93

मैं iOS 7 पर चलने के लिए अपने ऐप्स अपडेट कर रहा हूं जो कि अधिकांश भाग के लिए सुचारू रूप से चल रहा है। मैंने एक से अधिक ऐप पर ध्यान दिया है कि एक का reloadDataतरीका UICollectionViewControllerयह काम नहीं करता है कि यह कैसे उपयोग करता है।

मैं लोड करूँगा UICollectionViewController, UICollectionViewसामान्य रूप से कुछ डेटा के साथ पॉपुलेट करता हूं । यह पहली बार में शानदार काम करता है। हालाँकि अगर मैं नए डेटा का अनुरोध करता हूं (पॉप्युलेट करता हूं UICollectionViewDataSource), और फिर कॉल करता हूं , तो reloadDataयह डेटा स्रोत के लिए क्वेरी करेगा numberOfItemsInSectionऔर numberOfSectionsInCollectionView, लेकिन यह cellForItemAtIndexPathउचित संख्या में कॉल करने के लिए प्रतीत नहीं होता है ।

अगर मैं कोड को केवल एक सेक्शन को फिर से लोड करने के लिए बदलता हूं, तो यह ठीक से काम करेगा। इनको बदलने के लिए मेरे लिए यह कोई समस्या नहीं है, लेकिन मुझे नहीं लगता कि मुझे ऐसा करना चाहिए। reloadDataप्रलेखन के अनुसार सभी दृश्यमान कोशिकाओं को पुनः लोड करना चाहिए।

क्या किसी और ने इसे देखा है?


5
यहाँ, इसके iOS7GM में, पहले ठीक काम किया था। मैंने देखा है कि reloadDataviewDidAppear के बाद कॉल करने से समस्या, उसके भयानक हल और समस्या को हल करने की जरूरत महसूस होती है। मुझे उम्मीद है कि कोई यहां मदद करेगा।
jasonIM

1
एक ही समस्या होने। IOS6 में कोड ठीक काम करता था। अब ना बुलाने की कोशिकाओं के समुचित संख्या लौटने भले ही cellforitematindexpath
Avner बर्र

क्या यह 7.0 की रिलीज़ के बाद तय किया गया था?
विलियम जोकस

मैं अभी भी इस मुद्दे से संबंधित मुद्दों का सामना कर रहा हूं।
अनिल

चेंज करने के बाद इसी तरह की समस्या [संग्रह देखें सेटफ्रेम] ऑन-द-फ्लाई; हमेशा एक ही सेल को डिलीट करता है और वह डेटा स्रोत में संख्या की परवाह किए बिना है। यहाँ और सब कुछ करने की कोशिश की, और इसके आसपास नहीं मिल सकता।
RegularExpression

जवाबों:


72

इसे मुख्य सूत्र पर रखें:

dispatch_async(dispatch_get_main_queue(), ^ {
    [self.collectionView reloadData];
});

1
मुझे यकीन नहीं है कि मैं और समझा सकता हूं। खोज, शोध, परीक्षण और जांच के बाद। मुझे लगता है कि यह एक iOS 7 बग है। मजबूरन मुख्य धागा सभी UIKit संबंधित संदेश चलाएगा। जब दूसरे व्यू कंट्रोलर से दृश्य पॉपिंग होता है तो मैं इसमें भागता हूं। मैं viewWillAppear पर डेटा ताज़ा करता हूं। मैं डेटा और संग्रह दृश्य पुनः लोड कॉल देख सकता था, लेकिन UI अपडेट नहीं किया गया था। मुख्य थ्रेड (UI थ्रेड) को मजबूर किया, और यह जादुई रूप से काम करना शुरू कर देता है। यह केवल IOS 7.
शॉनटी फोंद्रिसि

6
इसका कोई मतलब नहीं है क्योंकि आप पुनः लोडडॉट को मुख्य थ्रेड से बाहर नहीं कर सकते हैं (आप मुख्य थ्रेड से बाहर के विचारों को अपडेट नहीं कर सकते हैं) इसलिए यह एक साइड इफेक्ट है, जिसके परिणामस्वरूप आप कुछ दौड़ स्थितियों के कारण चाहते हैं।
राफेल ओलिवेरा

7
मुख्य कतार से मुख्य कतार में डिस्पैच करना अगले रन लूप तक निष्पादन को विलंबित करता है, जिससे वर्तमान में पहले निष्पादित होने का मौका पाने वाली हर चीज की अनुमति मिलती है।
जॉनी

2
धन्यवाद!! अभी भी समझ में नहीं आता है कि क्या जॉनी तर्क सही है क्योंकि कोर डेटा अनुरोध का समय लगता है और इसका उत्तर देने में देरी हो रही है या क्योंकि मैं विलडिसप्लेसेल पर डेटा पुनः लोड कर रहा हूं।
फिदेल लोपेज

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

64

मेरे मामले में, डेटा स्रोत में कोशिकाओं / वर्गों की संख्या कभी नहीं बदली और मैं स्क्रीन पर दृश्य सामग्री को फिर से लोड करना चाहता था।

मैंने कॉल करके इसे प्राप्त करने में सफलता प्राप्त की:

[self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]];

फिर:

[self.collectionView reloadData];

6
उस पंक्ति के कारण मेरा ऐप क्रैश हो गया - "*** जोरदार विफलता - [UICollectionView _endItemAnimations], /SourceCache/UIKit_Sim/UIKit-2935.137/UICLlectionView.m:3840"
लुगब्रीस

@Lugubrious आप शायद एक ही समय में अन्य एनिमेशन प्रदर्शन कर रहे हैं .. उन्हें एक performBatchUpdates:completion:ब्लॉक में डालने का प्रयास करें ?
liamnichols

यह मेरे लिए काम करता है, लेकिन मुझे यकीन नहीं है कि मैं समझता हूं कि यह आवश्यक क्यों है। किसी भी विचार क्या मुद्दा है?
जॉन इवांस

@JonEvans दुर्भाग्य से मुझे कोई पता नहीं है .. मेरा मानना ​​है कि यह आईओएस में किसी प्रकार का बग है, यह सुनिश्चित नहीं है कि इसे बाद के संस्करणों में हल किया गया है या नहीं, क्योंकि मैंने परीक्षण नहीं किया है और जिस परियोजना में मेरा मुद्दा था वह नहीं है अब मेरी समस्या :)
liamnichols

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

26

मेरे पास बिल्कुल वही मुद्दा था, हालांकि मैं यह खोजने में कामयाब रहा कि क्या गलत हो रहा है। मेरे मामले में मैं संग्रह से reloadData कॉल कर रहा था : cellForItemAtIndexPath: जो सही नहीं लगता है।

पुन: लोड करने की कॉल को मुख्य कतार में भेजने से समस्या एक बार और हमेशा के लिए ठीक हो गई।

  dispatch_async(dispatch_get_main_queue(), ^{
    [self.collectionView reloadData];
  });

1
क्या आप मुझे बता सकते हैं कि यह लाइन क्या है [self.collectionData.collectionViewLayout अमान्यateLayout] के लिए;
iOSDeveloper

इसने इसे मेरे लिए भी हल कर दिया - मेरे मामले reloadDataमें एक परिवर्तन पर्यवेक्षक द्वारा बुलाया जा रहा था।
सुडो

यह भी इस पर लागू होता हैcollectionView(_:willDisplayCell:forItemAtIndexPath:)
स्टीफन अराम्बशिक

20

कुछ आइटम्स को पुनः लोड करना मेरे लिए काम नहीं आया। मेरे मामले में, और केवल इसलिए कि मेरे द्वारा उपयोग किए जा रहे संग्रह दृश्य में सिर्फ एक अनुभाग है, मैं बस उस विशेष अनुभाग को पुनः लोड करता हूं। इस बार सामग्री को सही ढंग से पुनः लोड किया गया है। अजीब है कि यह केवल iOS 7 (7.0.3) पर हो रहा है

[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];

12

IOS पर पुनः लोडडैट के साथ एक ही मुद्दा था 7. लंबे डिबग सत्र के बाद, मुझे समस्या मिली।

IOS7 पर, UICollectionView पर reloadData पिछले अपडेट को रद्द नहीं करता है, जो अभी तक पूरा नहीं हुआ है (अपडेट्स जो performBatchUpdates: ब्लॉक के अंदर कहा जाता है)।

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


जहाँ आप अपने सभी अपडेट को PerformBatchUpdate के अंदर कर रहे हैं? कुछ में कुछ बाहर? सब बाहर जाएं? बहुत ही रोचक पोस्ट।
VaporwareWolf

मैं CoreData से डेटा दिखाने के लिए NSFetchedResultsController के साथ संग्रह दृश्य का उपयोग कर रहा हूं। जब NSFetchedResultsController प्रतिनिधि बदलाव पर सूचित करते हैं, तो मैं सभी अपडेट इकट्ठा करता हूं और उन्हें PerformBatchUpatesates के अंदर कॉल करता हूं। जब NSFetchedResultsController अनुरोध विधेय को बदल दिया जाता है, तो पुनः लोड किया जाना चाहिए।
user2459624

यह वास्तव में सवाल का एक अच्छा जवाब है। यदि आप एक reloadItems () चलाते हैं (जो एनिमेटेड है) और फिर reloadData () यह कोशिकाओं को छोड़ देगा।
बायो

12

स्विफ्ट 5 - 4 - 3

// GCD    
DispatchQueue.main.async(execute: collectionView.reloadData)

// Operation
OperationQueue.main.addOperation(collectionView.reloadData)

स्विफ्ट 2

// Operation
NSOperationQueue.mainQueue().addOperationWithBlock(collectionView.reloadData)

4

मुझे भी यह समस्या थी। संयोग से मैंने परीक्षण के लिए फिर से लोड करने के लिए मजबूर करने के लिए संग्रह के शीर्ष पर एक बटन जोड़ा - और अचानक तरीकों को बुलाया जाने लगा।

इसके अलावा बस के रूप में सरल रूप में कुछ जोड़ने

UIView *aView = [UIView new];
[collectionView addSubView:aView];

कारणों को बुलाया जाएगा

इसके अलावा मैं फ्रेम आकार के साथ चारों ओर खेला - और आवाज के तरीकों को बुलाया जा रहा था।

IOS7 UICollectionView के साथ बहुत सारे बग हैं।


मुझे यह देखकर खुशी हुई (प्रमाणित तरीकों से) कि दूसरों को भी इस समस्या का सामना करना पड़ रहा है। वर्कअराउंड के लिए धन्यवाद।
वेपरवेयर वुल्फ

3

आप इस विधि का उपयोग कर सकते हैं

[collectionView reloadItemsAtIndexPaths:arayOfAllIndexPaths];

आप सभी को जोड़ सकते हैं indexPathअपने की वस्तुओं UICollectionViewमें सरणी arrayOfAllIndexPathsबार-बार दोहराना द्वारा विधि नीचे के उपयोग के साथ सभी वर्गों और पंक्तियों के लिए पाश

[aray addObject:[NSIndexPath indexPathForItem:j inSection:i]];

मुझे उम्मीद है कि आप समझ गए होंगे और यह आपकी समस्या को हल कर सकता है। यदि आपको किसी और स्पष्टीकरण की आवश्यकता है तो कृपया उत्तर दें।


3

शॉनटी फोंद्रिसि द्वारा दिया गया समाधान लगभग सही है। लेकिन की कतारबद्ध करें निष्पादन की तरह कोड या कोड के इस तरह के एक टुकड़े UICollectionViewके reloadData()लिए NSOperationQueueहै mainQueueवास्तव में रन पाश में अगली घटना पाश है, जो कर सकता है की शुरुआत करने के लिए निष्पादन समय डालता है UICollectionViewएक झटका के साथ अद्यतन।

इस मुद्दे को हल। हमें वर्तमान ईवेंट लूप के अंत में कोड के एक ही टुकड़े का निष्पादन समय देना चाहिए, लेकिन अगले की शुरुआत नहीं। और हम इसका उपयोग करके प्राप्त कर सकते हैं CFRunLoopObserver

CFRunLoopObserver सभी इनपुट स्रोत प्रतीक्षा गतिविधियों और रन लूप की प्रविष्टि और निकास गतिविधि का अवलोकन करता है।

public struct CFRunLoopActivity : OptionSetType {
    public init(rawValue: CFOptionFlags)

    public static var Entry: CFRunLoopActivity { get }
    public static var BeforeTimers: CFRunLoopActivity { get }
    public static var BeforeSources: CFRunLoopActivity { get }
    public static var BeforeWaiting: CFRunLoopActivity { get }
    public static var AfterWaiting: CFRunLoopActivity { get }
    public static var Exit: CFRunLoopActivity { get }
    public static var AllActivities: CFRunLoopActivity { get }
}

उन गतिविधियों के बीच, .AfterWaitingजब वर्तमान ईवेंट लूप समाप्त होने वाला होता है, और .BeforeWaitingतब देखा जा सकता है जब अगला ईवेंट लूप अभी शुरू हुआ हो।

जैसा कि NSRunLoopप्रति केवल एक उदाहरण है NSThreadऔर NSRunLoopवास्तव में ड्राइव करता है NSThread, हम विचार कर सकते हैं कि एक्सेस एक ही NSRunLoopउदाहरण से आते हैं जो हमेशा थ्रेड को पार नहीं करते हैं।

पहले उल्लेख किए गए बिंदुओं के आधार पर, हम अब कोड लिख सकते हैं: एक NSRunLoop- आधारित कार्य प्रेषण:

import Foundation
import ObjectiveC

public struct Weak<T: AnyObject>: Hashable {
    private weak var _value: T?
    public weak var value: T? { return _value }
    public init(_ aValue: T) { _value = aValue }

    public var hashValue: Int {
        guard let value = self.value else { return 0 }
        return ObjectIdentifier(value).hashValue
    }
}

public func ==<T: AnyObject where T: Equatable>(lhs: Weak<T>, rhs: Weak<T>)
    -> Bool
{
    return lhs.value == rhs.value
}

public func ==<T: AnyObject>(lhs: Weak<T>, rhs: Weak<T>) -> Bool {
    return lhs.value === rhs.value
}

public func ===<T: AnyObject>(lhs: Weak<T>, rhs: Weak<T>) -> Bool {
    return lhs.value === rhs.value
}

private var dispatchObserverKey =
"com.WeZZard.Nest.NSRunLoop.TaskDispatcher.DispatchObserver"

private var taskQueueKey =
"com.WeZZard.Nest.NSRunLoop.TaskDispatcher.TaskQueue"

private var taskAmendQueueKey =
"com.WeZZard.Nest.NSRunLoop.TaskDispatcher.TaskAmendQueue"

private typealias DeallocFunctionPointer =
    @convention(c) (Unmanaged<NSRunLoop>, Selector) -> Void

private var original_dealloc_imp: IMP?

private let swizzled_dealloc_imp: DeallocFunctionPointer = {
    (aSelf: Unmanaged<NSRunLoop>,
    aSelector: Selector)
    -> Void in

    let unretainedSelf = aSelf.takeUnretainedValue()

    if unretainedSelf.isDispatchObserverLoaded {
        let observer = unretainedSelf.dispatchObserver
        CFRunLoopObserverInvalidate(observer)
    }

    if let original_dealloc_imp = original_dealloc_imp {
        let originalDealloc = unsafeBitCast(original_dealloc_imp,
            DeallocFunctionPointer.self)
        originalDealloc(aSelf, aSelector)
    } else {
        fatalError("The original implementation of dealloc for NSRunLoop cannot be found!")
    }
}

public enum NSRunLoopTaskInvokeTiming: Int {
    case NextLoopBegan
    case CurrentLoopEnded
    case Idle
}

extension NSRunLoop {

    public func perform(closure: ()->Void) -> Task {
        objc_sync_enter(self)
        loadDispatchObserverIfNeeded()
        let task = Task(self, closure)
        taskQueue.append(task)
        objc_sync_exit(self)
        return task
    }

    public override class func initialize() {
        super.initialize()

        struct Static {
            static var token: dispatch_once_t = 0
        }
        // make sure this isn't a subclass
        if self !== NSRunLoop.self {
            return
        }

        dispatch_once(&Static.token) {
            let selectorDealloc: Selector = "dealloc"
            original_dealloc_imp =
                class_getMethodImplementation(self, selectorDealloc)

            let swizzled_dealloc = unsafeBitCast(swizzled_dealloc_imp, IMP.self)

            class_replaceMethod(self, selectorDealloc, swizzled_dealloc, "@:")
        }
    }

    public final class Task {
        private let weakRunLoop: Weak<NSRunLoop>

        private var _invokeTiming: NSRunLoopTaskInvokeTiming
        private var invokeTiming: NSRunLoopTaskInvokeTiming {
            var theInvokeTiming: NSRunLoopTaskInvokeTiming = .NextLoopBegan
            guard let amendQueue = weakRunLoop.value?.taskAmendQueue else {
                fatalError("Accessing a dealloced run loop")
            }
            dispatch_sync(amendQueue) { () -> Void in
                theInvokeTiming = self._invokeTiming
            }
            return theInvokeTiming
        }

        private var _modes: NSRunLoopMode
        private var modes: NSRunLoopMode {
            var theModes: NSRunLoopMode = []
            guard let amendQueue = weakRunLoop.value?.taskAmendQueue else {
                fatalError("Accessing a dealloced run loop")
            }
            dispatch_sync(amendQueue) { () -> Void in
                theModes = self._modes
            }
            return theModes
        }

        private let closure: () -> Void

        private init(_ runLoop: NSRunLoop, _ aClosure: () -> Void) {
            weakRunLoop = Weak<NSRunLoop>(runLoop)
            _invokeTiming = .NextLoopBegan
            _modes = .defaultMode
            closure = aClosure
        }

        public func forModes(modes: NSRunLoopMode) -> Task {
            if let amendQueue = weakRunLoop.value?.taskAmendQueue {
                dispatch_async(amendQueue) { [weak self] () -> Void in
                    self?._modes = modes
                }
            }
            return self
        }

        public func when(invokeTiming: NSRunLoopTaskInvokeTiming) -> Task {
            if let amendQueue = weakRunLoop.value?.taskAmendQueue {
                dispatch_async(amendQueue) { [weak self] () -> Void in
                    self?._invokeTiming = invokeTiming
                }
            }
            return self
        }
    }

    private var isDispatchObserverLoaded: Bool {
        return objc_getAssociatedObject(self, &dispatchObserverKey) !== nil
    }

    private func loadDispatchObserverIfNeeded() {
        if !isDispatchObserverLoaded {
            let invokeTimings: [NSRunLoopTaskInvokeTiming] =
            [.CurrentLoopEnded, .NextLoopBegan, .Idle]

            let activities =
            CFRunLoopActivity(invokeTimings.map{ CFRunLoopActivity($0) })

            let observer = CFRunLoopObserverCreateWithHandler(
                kCFAllocatorDefault,
                activities.rawValue,
                true, 0,
                handleRunLoopActivityWithObserver)

            CFRunLoopAddObserver(getCFRunLoop(),
                observer,
                kCFRunLoopCommonModes)

            let wrappedObserver = NSAssociated<CFRunLoopObserver>(observer)

            objc_setAssociatedObject(self,
                &dispatchObserverKey,
                wrappedObserver,
                .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    private var dispatchObserver: CFRunLoopObserver {
        loadDispatchObserverIfNeeded()
        return (objc_getAssociatedObject(self, &dispatchObserverKey)
            as! NSAssociated<CFRunLoopObserver>)
            .value
    }

    private var taskQueue: [Task] {
        get {
            if let taskQueue = objc_getAssociatedObject(self,
                &taskQueueKey)
                as? [Task]
            {
                return taskQueue
            } else {
                let initialValue = [Task]()

                objc_setAssociatedObject(self,
                    &taskQueueKey,
                    initialValue,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

                return initialValue
            }
        }
        set {
            objc_setAssociatedObject(self,
                &taskQueueKey,
                newValue,
                .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

        }
    }

    private var taskAmendQueue: dispatch_queue_t {
        if let taskQueue = objc_getAssociatedObject(self,
            &taskAmendQueueKey)
            as? dispatch_queue_t
        {
            return taskQueue
        } else {
            let initialValue =
            dispatch_queue_create(
                "com.WeZZard.Nest.NSRunLoop.TaskDispatcher.TaskAmendQueue",
                DISPATCH_QUEUE_SERIAL)

            objc_setAssociatedObject(self,
                &taskAmendQueueKey,
                initialValue,
                .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

            return initialValue
        }
    }

    private func handleRunLoopActivityWithObserver(observer: CFRunLoopObserver!,
        activity: CFRunLoopActivity)
        -> Void
    {
        var removedIndices = [Int]()

        let runLoopMode: NSRunLoopMode = currentRunLoopMode

        for (index, eachTask) in taskQueue.enumerate() {
            let expectedRunLoopModes = eachTask.modes
            let expectedRunLoopActivitiy =
            CFRunLoopActivity(eachTask.invokeTiming)

            let runLoopModesMatches = expectedRunLoopModes.contains(runLoopMode)
                || expectedRunLoopModes.contains(.commonModes)

            let runLoopActivityMatches =
            activity.contains(expectedRunLoopActivitiy)

            if runLoopModesMatches && runLoopActivityMatches {
                eachTask.closure()
                removedIndices.append(index)
            }
        }

        taskQueue.removeIndicesInPlace(removedIndices)
    }
}

extension CFRunLoopActivity {
    private init(_ invokeTiming: NSRunLoopTaskInvokeTiming) {
        switch invokeTiming {
        case .NextLoopBegan:        self = .AfterWaiting
        case .CurrentLoopEnded:     self = .BeforeWaiting
        case .Idle:                 self = .Exit
        }
    }
}

पहले कोड के साथ, हम अब प्रेषण कर सकते हैं के निष्पादन UICollectionView'एस reloadData()कोड के इस तरह के एक टुकड़े से वर्तमान घटना पाश के अंत तक:

NSRunLoop.currentRunLoop().perform({ () -> Void in
     collectionView.reloadData()
    }).when(.CurrentLoopEnded)

वास्तव में, इस तरह के एक NSRunLoop आधारित कार्य डिस्पैचर पहले से ही मेरे व्यक्तिगत इस्तेमाल किए गए ढांचे में से एक में रहा है: नेस्ट। और यहाँ GitHub पर इसका भंडार है: https://github.com/WeZZard/Nest


2
 dispatch_async(dispatch_get_main_queue(), ^{

            [collectionView reloadData];
            [collectionView layoutIfNeeded];
            [collectionView reloadData];


        });

यह मेरे लिए काम किया।


1

इस धागे के लिए सबसे पहले धन्यवाद, बहुत मददगार। मेरे पास रीलोड डेटा के साथ एक समान मुद्दा था सिवाय इस बात के कि विशिष्ट कोशिकाएं अब स्थायी रूप से नहीं चुनी जा सकती हैं जबकि अन्य हो सकती हैं। IndexPathsForSelectedItems विधि या समकक्ष के लिए कोई कॉल नहीं। डीबगिंग ने रिलोड डेटा की ओर संकेत किया। मैंने ऊपर दोनों विकल्पों की कोशिश की; और समाप्त हो गया ReloadItemsAtIndexPaths विकल्प को अपनाने के रूप में अन्य विकल्प मेरे मामले में काम नहीं करते थे या मिलि सेकंड या तो संग्रह दृश्य को फ्लैश कर रहे थे। नीचे दिया गया कोड अच्छा काम करता है:

NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; 
NSIndexPath *indexPath;
for (int i = 0; i < [self.assets count]; i++) {
         indexPath = [NSIndexPath indexPathForItem:i inSection:0];
         [indexPaths addObject:indexPath];
}
[collectionView reloadItemsAtIndexPaths:indexPaths];`

0

यह मेरे साथ आईओएस 8.1 एसडीके में भी हुआ था, लेकिन मुझे यह सही लगा जब मैंने देखा कि datasourceविधि numberOfItemsInSection:को अपडेट करने के बाद भी वस्तुओं की नई गिनती नहीं लौट रही थी। मैंने गिनती को अपडेट किया और इसे काम कर रहा हूं।


आपने कैसे अपडेट किया है कि कृपया गणना करें .. उपरोक्त सभी विधियाँ मेरे लिए तेजी से काम करने में विफल रही हैं 3.
nyxee

0

क्या आप UICollectionView.contentInset को सेट करते हैं? बाएँ और दाएँ किनारे को हटा दें। सब कुछ ठीक है, जब मैं उन्हें हटाता हूं, तो बग अभी भी iOS8.3 में मौजूद है।


0

जाँच करें कि हर एक UICollectionView प्रतिनिधि विधि वह करती है जो आप उससे करने की अपेक्षा करते हैं। उदाहरण के लिए, यदि

collectionView:layout:sizeForItemAtIndexPath:

एक मान्य आकार नहीं लौटाता, पुनः लोड नहीं होगा ...


0

इस कोड को आज़माएं।

 NSArray * visibleIdx = [self.collectionView indexPathsForVisibleItems];

    if (visibleIdx.count) {
        [self.collectionView reloadItemsAtIndexPaths:visibleIdx];
    }

0

यहाँ है कि यह कैसे मेरे लिए स्विफ्ट 4 में काम किया

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = campaignsCollection.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell

cell.updateCell()

    // TO UPDATE CELLVIEWS ACCORDINGLY WHEN DATA CHANGES
    DispatchQueue.main.async {
        self.campaignsCollection.reloadData()
    }

    return cell
}

-1
inservif (isInsertHead) {
   [self insertItemsAtIndexPaths:tmpPoolIndex];
   NSArray * visibleIdx = [self indexPathsForVisibleItems];
   if (visibleIdx.count) {
       [self reloadItemsAtIndexPaths:visibleIdx];
   }
}else if (isFirstSyncData) {
    [self reloadData];
}else{
   [self insertItemsAtIndexPaths:tmpPoolIndex];
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.