আমি কীভাবে জানতে পারি যে ইউআইসিকলিকেশনভিউ পুরোপুরি লোড হয়ে গেছে?


99

যখনই ইউআইসিকলিকশনভিউ পুরোপুরি লোড হয়ে গেছে তখনই আমাকে কিছু অপারেশন করতে হবে, অর্থাত্ সেই সময় ইউআইকোলিকেশনভিউয়ের সমস্ত ডেটাসোর্স / লেআউট পদ্ধতি কল করা উচিত। আমি কীভাবে জানব ?? ইউআইকোলিকেশনভিউ লোড হওয়া স্থিতি জানার জন্য কি কোনও প্রতিনিধি পদ্ধতি রয়েছে?

উত্তর:


63
// In viewDidLoad
[self.collectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary  *)change context:(void *)context
{
    // You will get here when the reloadData finished 
}

- (void)dealloc
{
    [self.collectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];
}

4
আমি ফিরে নেভিগেট করার সময় এটি আমার জন্য ক্র্যাশ হয়ে যায়, অন্যথায় ভাল কাজ করে।
এরিকসগ

4
@ericosg যোগ [self.collectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];করার -viewWillDisappear:animated:পাশাপাশি।
pxpographicics

উজ্জ্বল! আপনাকে অনেক ধন্যবাদ!
আবদো

41
স্ক্রোল করার সময় সামগ্রীর আকার পরিবর্তন হয় তাই এটি নির্ভরযোগ্য নয়।
রায়ান হিটনার

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

157

এটি আমার পক্ষে কাজ করেছে:

[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{}
                              completion:^(BOOL finished) {
                                  /// collection-view finished reload
                              }];

সুইফট 4 সিনট্যাক্স:

self.collectionView.reloadData()
self.collectionView.performBatchUpdates(nil, completion: {
    (result) in
    // ready
})

4
আইওএস 9
ম্যাগু

6
@ জি.আবিহেসেক এরর, অবশ্যই .... আপনার কি ব্যাখ্যা দেওয়ার দরকার? প্রথম লাইনটি reloadDataরিফ্রেশ করে collectionViewতাই এটি তার ডেটাসোর্স পদ্ধতিগুলির উপর আবার অঙ্কিত করে ... performBatchUpdatesএতে একটি সমাপ্তি ব্লক সংযুক্ত রয়েছে যাতে উভয়ই মূল থ্রেডে সঞ্চালিত হয় যদি আপনি জানেন যে কোনও স্থানে রাখা একটি কোড /// collection-view finished reloadএকটি নতুন এবং collectionView
বিছানো

8
যখন সংগ্রহ
ভিউতে

4
এই পদ্ধতিটি কোনও মাথা ব্যথা ছাড়াই নিখুঁত সমাধান।
arjavlad

4
@ ইংহাম এটি গতিশীল আকারের কোষগুলির সাথে আমার পক্ষে পুরোপুরি কাজ করে, সুইফট 4.2 আইওএস 12
রোমুলো বিএম

27

এটা আসলে খুব সহজ।

আপনি যখন উদাহরণস্বরূপ ইউআইকোলিকেশনভিউর পুনরায়লোড ডেটা পদ্ধতিটি কল করেন বা এটির বিন্যাসের অবৈধ লেআউট পদ্ধতিটি ব্যবহার করেন, আপনি নিম্নলিখিতটি করেন:

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

dispatch_async(dispatch_get_main_queue(), ^{
    //your stuff happens here
    //after the reloadData/invalidateLayout finishes executing
});

কেন এটি কাজ করে:

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

এখন মূল থ্রেড পাশাপাশি ব্লক করা হয়। সুতরাং যদি আপনি reloadDataকার্যকর করতে 3s সময় নেন তবে দ্বিতীয় ব্লকের প্রক্রিয়াকরণটি 3s দ্বারা পিছিয়ে যাবে।


4
আমি আসলে এটি পরীক্ষা করেছি, আমার অন্যান্য প্রতিনিধি পদ্ধতিগুলির আগে ব্লকটি কল হচ্ছে। সুতরাং এটি কাজ করে না?
টেলরসারসি

@ টেলোরক্র্যাসি আরে, আমি কোডটি আপডেট করেছি, এমন একটি জিনিস যা আমি এখন 2 টি প্রোডাকশন অ্যাপ্লিকেশনে ব্যবহার করছি। ব্যাখ্যাও অন্তর্ভুক্ত।
dezinezync

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

4
আপনি কি প্রথম ব্লকের কলটি প্রথমটির মধ্যে রেখে দেওয়ার চেষ্টা করতে পারেন? যাচাই করা হয়নি, তবে কাজ করতে পারে।
dezinezync

6
reloadDataএখন মূল থ্রেডে সেলগুলি লোডিংকে সজ্জিত করে (এমনকি মূল থ্রেড থেকে ডাকলেও)। সুতরাং সেলগুলি রিটার্নের cellForRowAtIndexPath:পরে আসলে লোড হয় না ( বলা হয় না) reloadData। আপনার ঘরগুলি লোড হয়ে যাওয়ার পরে আপনি কার্যকর করতে চান এমন র্যাপিং কোড dispatch_async(dispatch_get_main...এবং আপনার কল করার পরে কল reloadDataকরে কাঙ্ক্ষিত ফলাফল অর্জন করবে।
Tylerc230

12

কেবলমাত্র একটি দুর্দান্ত @ ডিজাইনজাইঙ্ক উত্তরে যুক্ত করতে:

সুইফ্ট 3+

collectionView.collectionViewLayout.invalidateLayout() // or reloadData()
DispatchQueue.main.async {
    // your stuff here executing after collectionView has been layouted
}

@ নিকাশ এটি দেখতে আমাদের যোগ করতে হবে হাজির !!
সারথ SASI

4
অগত্যা, লেআউটটি লোড হওয়ার পরে আপনি যেখান থেকে কিছু করতে চান সেখানে থেকে কল করতে পারেন।
নিকানস

আমি আইটেমগুলি সন্নিবেশ করার পরে আমার সংগ্রহভিউটি স্ক্রোলটি শেষের দিকে চেষ্টা করার জন্য স্ক্রোল ফ্লিকারগুলি পেয়ে যাচ্ছিলাম, এটি এটিকে ঠিক করেছে, ধন্যবাদ
স্কুয়া

6

এটা এভাবে করো:

       UIView.animateWithDuration(0.0, animations: { [weak self] in
                guard let strongSelf = self else { return }

                strongSelf.collectionView.reloadData()

            }, completion: { [weak self] (finished) in
                guard let strongSelf = self else { return }

                // Do whatever is needed, reload is finished here
                // e.g. scrollToItemAtIndexPath
                let newIndexPath = NSIndexPath(forItem: 1, inSection: 0)
                strongSelf.collectionView.scrollToItemAtIndexPath(newIndexPath, atScrollPosition: UICollectionViewScrollPosition.Left, animated: false)
        })

5

আরএক্সসুইফ্ট / আরএক্সকোচোয়া ব্যবহার করে একটি পৃথক আগমন:

        collectionView.rx.observe(CGSize.self, "contentSize")
            .subscribe(onNext: { size in
                print(size as Any)
            })
            .disposed(by: disposeBag)

4
আমি এটি পছন্দ করছি performBatchUpdatesআমার ক্ষেত্রে কাজ করছিল না, এইটি এটি করে। চিয়ার্স!
জোল্টন

@ মাইচাজিওব্রো, আপনি কি কোথাও আপনার কোড আপডেট করতে পারবেন? কন্টেন্টসাইজ পরিবর্তন হলেই পদ্ধতিটি কল করা উচিত? সুতরাং, আপনি যদি প্রতিটি স্ক্রোল এ পরিবর্তন না করেন তবে এটি কাজ করা উচিত!
চিনহ

4

পুনরায়লোডডাটা () কলের ঠিক পরে লেআউটআইফনেড () এর মাধ্যমে একটি সিঙ্ক্রোনাস লেআউট পাস জোর করে দেখুন। আইওএস 12-তে ইউআইকোলিকেশনভিউ এবং ইউআইটিএবলভিউ উভয়ের পক্ষে কাজ করার জন্য মনে হচ্ছে।

collectionView.reloadData()
collectionView.layoutIfNeeded() 

// cellForItem/sizeForItem calls should be complete
completion?()

ধন্যবাদ মানুষ! আমি দীর্ঘদিন ধরে এই সমস্যার সমাধান খুঁজছিলাম।
ট্রজি গ্রাজে

3

ডিজাইনাইজেনচের উত্তর হিসাবে , আপনার যা দরকার তা হ'ল প্রধান কাতারে reloadDataএকটি UITableViewবা পরে কোডের একটি ব্লক প্রেরণ করা UICollectionViewএবং তারপরে এই ব্লকটি নির্ধারিত কোষগুলির পরে কার্যকর করা হবে is

ব্যবহার করার সময় এটি আরও সোজা করার জন্য, আমি এটির মতো একটি এক্সটেনশন ব্যবহার করব:

extension UICollectionView {
    func reloadData(_ completion: @escaping () -> Void) {
        reloadData()
        DispatchQueue.main.async { completion() }
    }
}

এটি একটি থেকে বাস্তবায়ন করা যায় UITableViewপাশাপাশি


1

এটি আমার পক্ষে কাজ করে:

__weak typeof(self) wself= self;
[self.contentCollectionView performBatchUpdates:^{
    [wself.contentCollectionView reloadData];
} completion:^(BOOL finished) {
    [wself pageViewCurrentIndexDidChanged:self.contentCollectionView];
}];

4
বাজে কথা ... এটি কোনওভাবেই ফাঁসানো শেষ হয়নি।
মাগু

1

সংগ্রহ দৃশ্যটি ব্যবহারকারীর কাছে দৃশ্যমান হওয়ার আগে লোড হয়ে গেলে দৃশ্যমান সমস্ত কক্ষের জন্য আমার কিছু পদক্ষেপ নেওয়া দরকার ছিল, আমি ব্যবহার করেছি:

public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if shouldPerformBatch {
        self.collectionView.performBatchUpdates(nil) { completed in
            self.modifyVisibleCells()
        }
    }
}

মনোযোগ দিন যে সংগ্রহ ভিউয়ের মাধ্যমে স্ক্রোল করার সময় এটিকে ডাকা হবে, সুতরাং এই ওভারহেডটি রোধ করতে আমি যুক্ত করেছি:

private var souldPerformAction: Bool = true

এবং ক্রিয়া নিজেই:

private func modifyVisibleCells() {
    if self.shouldPerformAction {
        // perform action
        ...
        ...
    }
    self.shouldPerformAction = false
}

ক্রিয়াকলাপটি এখনও প্রাথমিক অবস্থায় দৃশ্যমান কক্ষগুলির সংখ্যা হিসাবে একাধিকবার সঞ্চালিত হবে। তবে এই সমস্ত কলগুলিতে, আপনার কাছে একই সংখ্যক দৃশ্যমান কক্ষ থাকবে (সেগুলি সমস্ত)। এবং সংগ্রহের দৃশ্যের সাথে ব্যবহারকারী ইন্টারঅ্যাক্ট করা শুরু করার পরে বুলিয়ান পতাকা এটি আবার চলতে বাধা দেবে।


1

সংগ্রহ ভিউটি পুনরায় লোড হওয়ার পরে আমি কিছু করার জন্য কেবল নিম্নলিখিতটি করেছি। আপনি এপিআই প্রতিক্রিয়াতেও এই কোডটি ব্যবহার করতে পারেন।

self.collectionView.reloadData()

DispatchQueue.main.async {
   // Do Task after collection view is reloaded                
}

1

আমি এখনও অবধি সবচেয়ে ভাল সমাধানটি পেয়েছি CATransactionসম্পূর্ণরূপে পরিচালনা করার জন্য ব্যবহার করা ।

সুইফট 5 :

CATransaction.begin()
CATransaction.setCompletionBlock {
    // UICollectionView is ready
}

collectionView.reloadData()

CATransaction.commit()

0

Def এটি করুন:

//Subclass UICollectionView
class MyCollectionView: UICollectionView {

    //Store a completion block as a property
    var completion: (() -> Void)?

    //Make a custom funciton to reload data with a completion handle
    func reloadData(completion: @escaping() -> Void) {
        //Set the completion handle to the stored property
        self.completion = completion
        //Call super
        super.reloadData()
    }

    //Override layoutSubviews
    override func layoutSubviews() {
        //Call super
        super.layoutSubviews()
        //Call the completion
        self.completion?()
        //Set the completion to nil so it is reset and doesn't keep gettign called
        self.completion = nil
    }

}

তারপরে আপনার ভিসির অভ্যন্তরে এ জাতীয় কল করুন

let collection = MyCollectionView()

self.collection.reloadData(completion: {

})

আপনি সাবক্লাস ব্যবহার করছেন তা নিশ্চিত করুন !!


0

এই কাজটি আমার জন্য:


- (void)viewDidLoad {
    [super viewDidLoad];

    int ScrollToIndex = 4;

    [self.UICollectionView performBatchUpdates:^{}
                                    completion:^(BOOL finished) {
                                             NSIndexPath *indexPath = [NSIndexPath indexPathForItem:ScrollToIndex inSection:0];
                                             [self.UICollectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
                                  }];

}


0

কেবল সংগ্রহটি পুনরায় লোড করুন ব্যাচের আপডেটের অভ্যন্তরে দেখুন এবং তারপরে এটি বুলিয়ান "ফিনিশিং" এর সাহায্যে শেষ হয়েছে কি না তা সমাপ্তি ব্লকটি দেখুন।

self.collectionView.performBatchUpdates({
        self.collectionView.reloadData()
    }) { (finish) in
        if finish{
            // Do your stuff here!
        }
    }

0

নীচে আমার পক্ষে কাজ করেছে এমন একমাত্র পন্থা।

extension UICollectionView {
    func reloadData(_ completion: (() -> Void)? = nil) {
        reloadData()
        guard let completion = completion else { return }
        layoutIfNeeded()
        completion()
    }
}

-1

আমি সুইফট 3.0.০ এর সাথে এইভাবে সমস্যার সমাধান করেছি:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if !self.collectionView.visibleCells.isEmpty {
        // stuff
    }
}

এটি কাজ করবে না। প্রথম সেলটি লোড হওয়ার সাথে সাথে ভিজিবল সেলগুলিতে সামগ্রী থাকবে ... সমস্যাটি আমরা শেষ কক্ষটি লোড হয়েছে তা জানতে চাই।
ট্র্যাভিস এম।

-9

এটা চেষ্টা কর:

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return _Items.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell;
    //Some cell stuff here...

    if(indexPath.row == _Items.count-1){
       //THIS IS THE LAST CELL, SO TABLE IS LOADED! DO STUFF!
    }

    return cell;
}

4
এটি সঠিক নয়, সেলফোর্ডটি কেবল তখনই কল করা হবে যখন সেই সেলটি দৃশ্যমান হতে চলেছে, সেই ক্ষেত্রে সর্বশেষ দৃশ্যমান আইটেমটি
সামগ্রীর

-10

আপনি এই মত করতে পারেন ...

  - (void)reloadMyCollectionView{

       [myCollectionView reload];
       [self performSelector:@selector(myStuff) withObject:nil afterDelay:0.0];

   }

  - (void)myStuff{
     // Do your stuff here. This will method will get called once your collection view get loaded.

    }

যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কেন এবং / অথবা এটি কীভাবে প্রশ্নের উত্তর দেয় সে সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করে এর দীর্ঘমেয়াদী মানকে উল্লেখযোগ্যভাবে উন্নতি করবে। কিছু ব্যাখ্যা যুক্ত করতে দয়া করে আপনার উত্তরটি সম্পাদনা করুন।
টবি স্পিড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.