ইউআইকোলিকেশনভিউ পুনরায়লোডডোটা আইওএস 7 এ সঠিকভাবে কাজ করছে না


93

আমি iOS 7 এ চালানোর জন্য আমার অ্যাপ্লিকেশনগুলি আপডেট করছি যা বেশিরভাগ অংশে সুচারুভাবে চলছে। আমি একাধিক অ্যাপে লক্ষ্য করেছি যে এর reloadDataপদ্ধতিটি UICollectionViewControllerঠিক তেমনভাবে অভিনয় করে না।

আমি লোড করব UICollectionViewController, UICollectionViewসাধারণ হিসাবে কিছু ডেটা দিয়ে পপুলেট করব । এটি প্রথমবার দুর্দান্ত কাজ করে। তবে আমি যদি নতুন ডেটার জন্য অনুরোধ করি (এটি জনবহুল করুন UICollectionViewDataSource), এবং তারপরে কল করুন reloadData, এটি ডেটা উত্সটির জন্য জিজ্ঞাসা করবে numberOfItemsInSectionএবং এর জন্য numberOfSectionsInCollectionView, তবে এটি cellForItemAtIndexPathযথাযথ সংখ্যায় কল করবে বলে মনে হয় না ।

যদি আমি কোডটি কেবল একটি বিভাগে পুনরায় লোড করতে পরিবর্তন করি তবে এটি সঠিকভাবে কাজ করবে। এগুলি পরিবর্তন করা আমার পক্ষে কোনও সমস্যা নয়, তবে আমার মনে হয় না আমার উচিত should reloadDataডকুমেন্টেশন অনুযায়ী সমস্ত দৃশ্যমান ঘর পুনরায় লোড করা উচিত।

এটা কি আর কেউ দেখেছে?


5
এখানে একই, এটি আইওএস 7 জিএম এর আগে ঠিক আছে before আমি লক্ষ্য করেছি যে reloadDataভিউডিড অ্যাপের পরে কল করা সমস্যাটি সমাধান করছে বলে মনে হচ্ছে, এর ভয়াবহ পরিশ্রম, এবং ঠিক করা দরকার। আমি আশা করি কেউ এখানে সাহায্য করবে।
জেসনআইএম

4
একই সমস্যা হচ্ছে। কোড iOS6 এ সূক্ষ্মভাবে কাজ করত। যথাযথ সংখ্যক কোষ ফিরিয়ে দিলেও এখন সেলফোরাইটেমেটিনেক্সপথকে কল দিচ্ছেন না
আভনার বার

এটি কি 7-পরবর্তী পোস্টে প্রকাশ করা হয়েছিল?
উইলিয়াম জকুশ

আমি এখনও এই সমস্যা সম্পর্কিত সমস্যা সম্মুখীন।
অনিল

ফ্লাইট-অন ফ্লাই [কালেকশনভিউ সেটফ্রেম] পরিবর্তন করার পরে একই সমস্যা; সর্বদা একটি কক্ষের প্রাপ্য এবং এটি ডেটা উত্সের সংখ্যা নির্বিশেষে। এখানে আরও অনেক কিছুর চেষ্টা করেছিলেন এবং এর কাছাকাছি যেতে পারছেন না।
নিয়মিতভাবে এক্সপ্রেসনে

উত্তর:


72

এটিকে মূল থ্রেডে চাপ দিন:

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

4
আমি আরও ব্যাখ্যা করতে পারি কিনা তা নিশ্চিত নই। অনুসন্ধান, গবেষণা, পরীক্ষা এবং পরীক্ষার পরে। আমি অনুভব করি এটি একটি আইওএস 7 বাগ। মূল থ্রেড জোর করে সমস্ত UIKit সম্পর্কিত বার্তা চালিত হবে। অন্য ভিউ কন্ট্রোলার থেকে ভিউতে পপ করার সময় আমি এটিকে চালিত করব বলে মনে হচ্ছে। আমি ভিউউইল অ্যাপয়ারে ডেটা রিফ্রেশ করি। আমি ডেটা এবং সংগ্রহ ভিউ রিলোডলোড কলটি দেখতে পেলাম, তবে ইউআই আপডেট হয়নি। মূল থ্রেড (ইউআই থ্রেড) জোর করে, এবং এটি যাদুতে কাজ শুরু করে। এটি কেবল আইওএস
in-এ রয়েছে

6
এটি এতটা অর্থবহ করে না কারণ আপনি মূল থ্রেডের বাইরে পুনরায় লোডডাটাটি কল করতে পারবেন না (আপনি মূল থ্রেডের বাইরে মতামত আপডেট করতে পারবেন না) তাই এটি সম্ভবত এমন একটি পার্শ্ব প্রতিক্রিয়া যা কিছু জাতিগত অবস্থার কারণে আপনি যা চান তার ফলাফল দেয়।
রাফেল অলিভিরা

7
মূল সারি থেকে মূল কাতারে প্রেরণ কেবল পরবর্তী রান লুপ অবধি মৃত্যুদন্ড কার্যকর করতে বিলম্ব করে, বর্তমানে সারিবদ্ধ যে সমস্ত কিছু প্রথমে কার্যকর করার সুযোগ দেয়।
জুনি

4
ধন্যবাদ !! জনি যুক্তিটি সঠিক কিনা তা এখনও বুঝতে পারছেন না কারণ মূল ডেটা অনুরোধটি সময় নেয় এবং এর উত্তর বিলম্বিত হয় বা কারণ আমি উইলডিসপ্লেলে ডেটা পুনরায় লোড করছি।
ফিদেল লোপেজ

4
বাহ এই সমস্ত সময় এবং এটি এখনও উঠে আসে। এটি প্রকৃতপক্ষে একটি রেসের শর্ত, বা দর্শন ইভেন্ট লাইফাইসাইকেলের সাথে সম্পর্কিত। "উইল" প্রদর্শিত হবে ইতিমধ্যে আঁকা হত। শুভ অন্তর্দৃষ্টি জুনি, ধন্যবাদ। ভাবুন আমরা এই আইটেমটি শেষ পর্যন্ত "জবাব দেওয়া" করতে পারি?
শাওন্টি ফন্ড্রিসি

64

আমার ক্ষেত্রে, ডাটাসোর্সে সেল / বিভাগগুলির সংখ্যা কখনই পরিবর্তিত হয়নি এবং আমি কেবল পর্দায় দৃশ্যমান সামগ্রী পুনরায় লোড করতে চেয়েছিলাম ..

আমি কল করে এই কাছাকাছি পেতে পরিচালিত:

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

তারপরে:

[self.collectionView reloadData];

6
এই লাইনটি আমার অ্যাপ্লিকেশনটি বিধ্বস্ত করেছে - "*** দৃ failure় ব্যর্থতা - - [ইউআইসোক্লেশনভিউ _ইন্ডআইটেমনিস্ট্রেশন], / সোর্সক্যাচি / ইউআইকিট_সিম / ইউআইকিট-2935.137/UICollectionView.m:3840"
লুগব্রিয়াস

@ লুগব্রিয়াস আপনি সম্ভবত একই সাথে অন্যান্য অ্যানিমেশনগুলি সম্পাদন করছেন .. এগুলি একটি performBatchUpdates:completion:ব্লকে রাখার চেষ্টা করছেন ?
লায়ামনিচলস 15

এটি আমার পক্ষে কাজ করেছিল তবে আমি কেন নিশ্চিত তা নিশ্চিত যে আমি বুঝতে পারি না। কোন ধারণা কি সমস্যা?
জন ইভান্স

@ জোনাভানস দুর্ভাগ্যক্রমে আমার কোনও ধারণা নেই .. আমি বিশ্বাস করি এটি আইওএস-এ কোনও এক প্রকারের বাগ, এটি পরবর্তী সংস্করণে সমাধান হয়েছে কিনা তা নিশ্চিত নই যদিও যদিও আমি পরীক্ষা করে দেখিনি এবং যে প্রকল্পটি আমার ইস্যুতে এসেছিল তা হ'ল না no আমার সমস্যা আর দীর্ঘ নয় :)
লিয়ামনিচল

4
এই বাগটি কেবল খাঁটি বুলিশিট! আমার সমস্ত ঘরগুলি ছিল - এলোমেলোভাবে - যখন আমি আমার সংগ্রহ ভিউটি পুনরায় লোড করি তখনই অদৃশ্য হয়ে যায়, কেবল যদি আমার সংগ্রহে আমার কাছে একটি নির্দিষ্ট ধরণের ঘর থাকে। আমি এতে দু'দিন হারিয়েছি কারণ কী হচ্ছে তা আমি বুঝতে পারি না এবং এখন আমি আপনার সমাধানটি প্রয়োগ করেছি এবং এটি কার্যকর হয়েছে, কেন এটি এখন কাজ করছে তা এখনও বুঝতে পারি না। এতো হতাশার! যাইহোক, সাহায্যের জন্য ধন্যবাদ: ডি !!
সাইবারড্যান্ডি

26

আমার ঠিক একই সমস্যা ছিল, তবে আমি কী ভুল হচ্ছে তা সন্ধান করতে পেরেছি। আমার ক্ষেত্রে আমি সংগ্রহ থেকে রিলোডলোড ডেটা কল করছিলাম : সেলফোর আইটেমটিডেক্সপথ: যা সঠিক বলে মনে হচ্ছে না।

পুনরায় লোডডাটাটির মূল কাতারে কল পাঠানো সমস্যাটি একবার এবং চিরতরে স্থির করে।

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

4
আপনি কি আমাকে বলতে পারেন যে এই লাইনটি [সেল্ফ-ক্লেকশনডাটা ক্যালকশন ভিউলয়আউট অবৈধ লেআউট] এর জন্য;
আইওএস ডেভেলপার

এটি আমার জন্যও এটি সমাধান করেছে - আমার ক্ষেত্রে reloadDataএকজন পরিবর্তন পর্যবেক্ষক ডেকেছিলেন।
sudo

এছাড়াও এটি প্রযোজ্যcollectionView(_:willDisplayCell:forItemAtIndexPath:)
স্টেফান আরামবাশিচ

20

কিছু আইটেম রিলোড করা আমার পক্ষে কাজ করে না। আমার ক্ষেত্রে, এবং শুধুমাত্র সংগ্রহ ভিউটি ব্যবহার করছি বলে কেবল একটি বিভাগ রয়েছে, আমি কেবল সেই বিশেষ বিভাগটি পুনরায় লোড করি। এবার বিষয়বস্তুগুলি সঠিকভাবে পুনরায় লোড করা হয়েছে। আশ্চর্যের বিষয় যে এটি কেবল আইওএস 7 এ ঘটছে (7.0.3)

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

12

আইওএস re-এ রিলোডলোড ডেটা নিয়ে আমার একই সমস্যা ছিল long দীর্ঘ ডিবাগ সেশনের পরে, আমি সমস্যাটি পেয়েছি।

আইওএস On-তে, ইউআইকোলিকেশনভিউতে পুনরায়লোড ডেটা আগের আপডেটগুলি বাতিল করে না যা এখনও সম্পূর্ণ হয়নি (আপডেটগুলি যার মধ্যে পারফরম্যাচব্যাচআপেটস: ব্লক বলা হয়)।

এই বাগটি সমাধানের সর্বোত্তম সমাধান হ'ল বর্তমানে প্রক্রিয়া করা সমস্ত আপডেট এবং রিলোডডাটা কল করে। পারফেক্টব্যাচআপেটসগুলির ব্লক বাতিল বা বন্ধ করার কোনও উপায় আমি খুঁজে পাইনি। সুতরাং, বাগটি সমাধান করার জন্য, আমি একটি পতাকা সংরক্ষণ করেছি যা ইঙ্গিত করে যে যদি বর্তমানে কোনও প্রক্রিয়াধীন পারফর্মব্যাচআপডেটস ব্লক রয়েছে। যদি বর্তমানে আপডেট হওয়া কোনও আপডেট ব্লক না থাকে তবে আমি অবিলম্বে রিলোডডাটা কল করতে পারি এবং প্রত্যাশা অনুযায়ী সবকিছুই কাজ করে। যদি বর্তমানে আপডেট হওয়া কোনও আপডেট ব্লক থাকে তবে আমি পারফর্মব্যাচআপের সম্পূর্ণ ব্লকে রিলোডলোডটি কল করব।


আপনি পারফর্মব্যাচআপেটের ভিতরে আপডেট হওয়া সমস্তগুলি কোথায় সম্পাদন করছেন? কিছু কিছু বাইরে? আউট আউট? খুব আকর্ষণীয় পোস্ট।
ভ্যাপারওয়ারওয়াল্ফ

আমি কোরেডাটা থেকে ডেটা দেখানোর জন্য এনএসফ্যাচড্রেসাল্টস কন্ট্রোলারের সাথে সংগ্রহের ভিউটি ব্যবহার করছি। যখন NSFetchedResultsController প্রতিনিধি পরিবর্তনগুলি সম্পর্কে অবহিত করে, আমি সমস্ত আপডেটগুলি সংগ্রহ করি এবং তাদের পারফরম্যাচব্যাচআপেটে কল করি। যখন NSFetchedResultsController অনুরোধ প্রিকিকেট পরিবর্তন করা হয়, পুনরায় লোডডাটা কল করা আবশ্যক।
user2459624

এটি আসলে প্রশ্নের উত্তরের উত্তর। আপনি যদি পুনরায় লোড আইটেমগুলি () চালিত করেন (যা অ্যানিমেটেড হয়) এবং তারপরে পুনরায় লোডডাটা () এটি কক্ষগুলি এড়িয়ে যাবে।
বায়ো

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];

পদ্ধতিগুলি কল করার কারণ হবে

এছাড়াও আমি ফ্রেমের আকারের সাথে চারপাশে খেলেছি - এবং ভয়েলা পদ্ধতিগুলি ডাকছিল।

আইওএস 7 ইউআইকোলিকেশনভিউ সহ প্রচুর বাগ রয়েছে।


অন্যরাও এই সমস্যাটি অনুভব করছে তা দেখে আমি প্রত্যেকে (প্রত্যয়ন পদ্ধতিতে) আনন্দিত। কর্মক্ষেত্রের জন্য ধন্যবাদ।
ভ্যাপারওয়ারওয়াল্ফ

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সর্বদা থ্রেডকে অতিক্রম করে না।

পূর্বে উল্লিখিত পয়েন্টগুলির ভিত্তিতে, আমরা এখন কোডটি লিখতে পারি: একটি এনএসআরনলুপ-ভিত্তিক টাস্ক প্রেরণকারী:

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)

প্রকৃতপক্ষে, এই জাতীয় এনএসআরনলুপ ভিত্তিক টাস্ক ডিসপাচার ইতিমধ্যে আমার ব্যক্তিগত ব্যবহৃত কাঠামোর মধ্যে রয়েছে: নেস্ট। এবং এখানে গিটহাবে এটির সংগ্রহস্থল: https://github.com/WeZZard/ নীস্ট


2
 dispatch_async(dispatch_get_main_queue(), ^{

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


        });

এটা আমার জন্য কাজ করে।


1

এই থ্রেডটির জন্য সবার আগে ধন্যবাদ, খুব সহায়ক। আমার পুনরায় লোড ডেটাতে একইরকম সমস্যা ছিল লক্ষণ ব্যতীত নির্দিষ্ট কোষগুলিকে আর স্থায়ী উপায়ে নির্বাচন করা যায় না অন্যরা পারে। ইনডেক্সপ্যাথসফোর্টসলেক্টড আইটেমস পদ্ধতি বা সমতুল্য কোনও কল নেই। ডিবাগিং ডেটা পুনরায় লোডের দিকে নির্দেশিত। আমি উপরের দুটি বিকল্প চেষ্টা করেছিলাম; এবং অন্যান্য বিকল্পগুলি আমার ক্ষেত্রে কাজ করে না বা মিলি-সেকেন্ড বা তার জন্য সংগ্রহের ভিউ ফ্ল্যাশ তৈরি করায় রিলোডআইটেমসআইটিএন্ডেক্সপ্যাথস বিকল্পটি গ্রহণ করা শেষ হয়েছিল। নীচের কোডটি ভাল কাজ করে:

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:আইটেমগুলির নতুন গণনাটি ফিরিয়ে আনা হয়নি it আমি গণনা আপডেট করেছি এবং এটি কাজ করে চলেছি।


আপনি কীভাবে এই গণনাটি আপডেট করেছিলেন দয়া করে .. উপরের সমস্ত পদ্ধতি আমার পক্ষে দ্রুত 3 এ কাজ করতে ব্যর্থ হয়েছে
nyxee

0

আপনি কি ইউআইসি কলিকেশনভিউ.কন্টেন্টইনসেট সেট করেন? বাম এবং ডান প্রান্তটি সরানআইসেট করুন, আমি তাদের সরিয়ে দেওয়ার পরে সবকিছু ঠিক আছে, iOS8.3 এ বাগটি এখনও বিদ্যমান exists


0

ইউআইসিকলিকেশনভিউ ডেলিগেট পদ্ধতিগুলির প্রত্যেকটি আপনার দ্বারা এটি প্রত্যাশা করে তা করে। উদাহরণস্বরূপ, যদি

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];
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.