ইউআইটিএবলভিউ পুনরায়লোডডাটাটি সম্পূর্ণ করার পরে কীভাবে বলবেন?


183

আমি কোনও ইউআইটিএবলভিউ সম্পাদন করার পরে নীচে স্ক্রোল করার চেষ্টা করছি [self.tableView reloadData]

আমি আসলে ছিল

 [self.tableView reloadData]
 NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection: ([self.tableView numberOfSections]-1)];

[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

কিন্তু তারপর আমি পড়তে যে reloadData, অ্যাসিঙ্ক্রোনাস তাই স্ক্রলিং যেহেতু ঘটে না self.tableView, [self.tableView numberOfSections]এবং [self.tableView numberOfRowsinSectionসব 0 হয়।

ধন্যবাদ!

কি অদ্ভুত যে আমি ব্যবহার করছি:

[self.tableView reloadData];
NSLog(@"Number of Sections %d", [self.tableView numberOfSections]);
NSLog(@"Number of Rows %d", [self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1);

কনসোলে এটি বিভাগগুলি = 1 প্রদান করে, সারি = -1;

আমি যখন ঠিক একই এনএসএলগগুলি করি তখন আমি cellForRowAtIndexPathবিভাগগুলি = 1 এবং সারি = 8 পাই; (8 সঠিক)


এই প্রশ্নের সম্ভাব্য সদৃশ: stackoverflow.com/questions/4163579/...
pmk

2
সেরা সমাধান আমি দেখেছি। stackoverflow.com/questions/1483581/...
খালেদ Annajar

নিম্নলিখিতগুলির জন্য আমার উত্তর আপনাকে সহায়তা করতে পারে, stackoverflow.com/questions/4163579/…
সুহাস আইথাল

আমার উত্তরটি এখানে চেষ্টা করুন - stackoverflow.com/questions/4163579/…
সুহাস আইথাল

উত্তর:


288

পুনরায় লোডটি পরবর্তী লেআউট পাসের সময় ঘটে, যা সাধারণত আপনি যখন রান লুপটিতে নিয়ন্ত্রণ ফিরে আসেন তখন ঘটে (পরে, বলুন, আপনার বোতামের ক্রিয়া বা যা কিছু ফিরে আসে)।

টেবিল ভিউ পুনরায় লোড করার পরে কিছু চালানোর এক উপায় হ'ল টেবিল ভিউটিকে অবিলম্বে বিন্যাস সম্পাদন করতে বাধ্য করা:

[self.tableView reloadData];
[self.tableView layoutIfNeeded];
 NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection: ([self.tableView numberOfSections]-1)];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

অন্য উপায়টি হ'ল আপনার পরে-লেআউট কোডটি পরে ব্যবহার করে চালানোর জন্য সময় নির্ধারণ করা dispatch_async:

[self.tableView reloadData];

dispatch_async(dispatch_get_main_queue(), ^{
     NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection:([self.tableView numberOfSections]-1)];

    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
});

হালনাগাদ

আরও তদন্ত করার পরে, আমি টেবিল ভিউ পাঠায় এটি tableView:numberOfSections:এবং tableView:numberOfRowsInSection:থেকে ফেরার আগে তার ডেটা উৎস reloadData। যদি ডেলিগেট প্রয়োগ করে tableView:heightForRowAtIndexPath:তবে টেবিল ভিউ এটি থেকে ফিরে আসার আগে এটি (প্রতিটি সারির জন্য) প্রেরণ করে reloadData

যাইহোক, সারণী দর্শনটি লেআউট পর্ব অবধি প্রেরণ tableView:cellForRowAtIndexPath:বা প্রেরণ করে না tableView:headerViewForSection, যা আপনি রান লুপে নিয়ন্ত্রণ ফিরিয়ে আনলে পূর্বনির্ধারিতভাবে ঘটে।

আমিও যে একটি ক্ষুদ্র পরীক্ষা প্রোগ্রামে আপনার প্রশ্নের কোড সঠিকভাবে টেবিল ভিউ নীচে স্ক্রোল ছাড়া আমাকে কিছু বিশেষ করছেন (প্রেরণ মত layoutIfNeededবা ব্যবহার dispatch_async)।


3
@rob, আপনার টেবিলের ডেটা উত্সটি কতটা বড় তার উপর নির্ভর করে আপনি একই রান লুপে টেবিলভিউয়ের নীচে যেতে প্রাণবন্ত করতে পারেন। যদি আপনি একটি বিশাল টেবিল দিয়ে আপনার টেস্ট কোডটি ব্যবহার করে থাকেন, তবে পরবর্তী রান লুপটি অবধি স্ক্রোলিং বিলম্বিত করতে জিসিডি ব্যবহারের আপনার কৌশলটি তত্ক্ষণাত স্ক্রোলিং ব্যর্থ হবে। তবে যাইহোক, এই কৌশলটির জন্য ধন্যবাদ !!
মিঃ টি

7
পদ্ধতি 2 অজানা কারণে আমার জন্য কাজ করে না, পরিবর্তে প্রথম পদ্ধতিটি বেছে নিয়েছিল।
রাজ পবন গমদল

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

3
dispatch_async(dispatch_get_main_queue())সর্বদা কাজ না করার সাথে সম্মত হন । এখানে এলোমেলো ফলাফল দেখে।
ভোজ্টো

1
মূল থ্রেড একটি চালায় NSRunLoop। একটি রান লুপের বিভিন্ন ধাপ রয়েছে এবং আপনি একটি নির্দিষ্ট পর্বের জন্য (একটি ব্যবহার করে CFRunLoopObserver) কলব্যাক নির্ধারণ করতে পারেন । আপনার ইভেন্ট হ্যান্ডলার ফিরে আসার পরে, পরবর্তী পর্যায়ে হওয়ার জন্য ইউআইকিট শিডিউল লেআউট।
রব মেওফ

106

সুইফট:

extension UITableView {
    func reloadData(completion:@escaping ()->()) {
        UIView.animateWithDuration(0, animations: { self.reloadData() })
            { _ in completion() }
    }
}

...somewhere later...

tableView.reloadData {
    println("done")
}

উদ্দেশ্য গ:

[UIView animateWithDuration:0 animations:^{
    [myTableView reloadData];
} completion:^(BOOL finished) {
    //Do something after that...
}];

16
এটি "নিকট ভবিষ্যতে" মূল থ্রেডে কিছু প্রেরণের সমান। মূল থ্রেডটি সমাপ্তি ব্লকটি আবিষ্কার করার আগে সম্ভবত আপনি কেবল টেবিলের দৃশ্যগুলি অবজেক্টগুলি রেন্ডার করে দেখছেন। প্রথমে এই ধরণের হ্যাক করার পরামর্শ দেওয়া হয়নি, তবে যে কোনও ক্ষেত্রে, আপনি প্রেরণ_পরে ব্যবহার করা উচিত যদি আপনি এটি চেষ্টা করে যাচ্ছেন।
SEO

1
রবের সমাধানটি ভাল তবে টেবিলভিউতে কোনও সারি না থাকলে কাজ করে না। টেবিলের কোনও লাইন না থাকলেও কেবল বিভাগগুলি থাকা অবস্থায়ও অ্যাভিয়েলের সমাধানটিতে কাজ করার সুবিধা রয়েছে।
Chrstph SLN

@ ক্রিস্টোফ এখন অবধি, আমি আমার মক ভিউ নিয়ামক tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Intপদ্ধতিটিতে ওভাররাইড করে এবং আমার ওভাররাইডে যা লিখতে চেয়েছিলাম যা পুনরায় লোড শেষ হয়েছে তা byুকিয়ে কোনও টেবিল ভিউতে রবের আপডেটটি ব্যবহার করতে সক্ষম হয়েছি।
গোব

49

এক্সকোড 8.2.1, আইওএস 10 এবং দ্রুত 3,

আপনি tableView.reloadData()সহজেই একটি ক্যাটারসেকশন ব্লক ব্যবহার করে শেষটি নির্ধারণ করতে পারেন:

CATransaction.begin()
CATransaction.setCompletionBlock({
    print("reload completed")
    //Your completion code here
})
print("reloading")
tableView.reloadData()
CATransaction.commit()

উপরেরগুলি ইউআইকোলিকেশনভিউ'র পুনঃলোডডাটা () এবং ইউআইপিকারকারভিউর পুনরায়লোডঅলকোম্পোনেন্টস () এর শেষ নির্ধারণের জন্যও কাজ করে।


You're আপনি যদি কাস্টম পুনরায় লোড করছেন, যেমন ম্যানুয়ালি সন্নিবেশ করানো, সারণি সারণীতে সারিগুলি সরাতে বা মুছে ফেলার মতো, beginUpdatesএবং এর মধ্যে endUpdatesকল করা।
দারারস্কি

আমি বিশ্বাস করি এটি আসলে আধুনিক সমাধান। আসলে এটি আইওএসের সাধারণ প্যাটার্ন, উদাহরণস্বরূপ ... স্ট্যাকওভারফ্লো
47536770/

আমি এই চেষ্টা করেছিলাম। আমি একটি খুব বিজোড় আচরণ পেয়েছিলাম। আমার টেবিলভিউটি সঠিকভাবে দুটি হেডারভিউ দেখায়। ইনসাইড setCompletionBlockআমার numberOfSectionsশো 2 ... এ পর্যন্ত সব ঠিকই। তবুও যদি ভিতরে setCompletionBlockকরি তবে tableView.headerView(forSection: 1)তা ফিরবে nil!!! তাই আমি মনে করি এই ব্লকটি হয় পুনরায় লোড হওয়ার আগেই ঘটছে বা কিছু ক্যাপচার করার আগে বা আমি কিছু ভুল করছি। এফওয়াইআই আমি টাইলারের উত্তর চেষ্টা করেছিলাম এবং এটি কার্যকর হয়েছিল! @ ফ্যাটি
মধু

32

dispatch_async(dispatch_get_main_queue())উপরে পদ্ধতি কাজ নিশ্চিত করা হয় না । আমি এটির সাথে অ-বিড়ম্বনামূলক আচরণটি দেখছি, যার মধ্যে কখনও কখনও সিস্টেমটি লেআউটসুভিউগুলি এবং সেল রেন্ডারিং সম্পূর্ণ হওয়ার আগে এবং কখনও কখনও পরে সম্পন্ন করে।

আইওএস ১০-এ আমার জন্য 100% কাজ করে এমন একটি সমাধান এখানে দেওয়া হয়েছে এটির জন্য কাস্টম সাবক্লাস হিসাবে ইউআইটিএবলভিউ বা ইউআইসি কলিকেশনভিউ ইনস্ট্যান্ট করার দক্ষতা প্রয়োজন। এখানে ইউআইকোলিকেশনভিউ সমাধানটি রয়েছে তবে এটি ইউআইটিএবলভিউয়ের জন্য হুবহু:

CustomCollectionView.h:

#import <UIKit/UIKit.h>

@interface CustomCollectionView: UICollectionView

- (void)reloadDataWithCompletion:(void (^)(void))completionBlock;

@end

CustomCollectionView.m:

#import "CustomCollectionView.h"

@interface CustomCollectionView ()

@property (nonatomic, copy) void (^reloadDataCompletionBlock)(void);

@end

@implementation CustomCollectionView

- (void)reloadDataWithCompletion:(void (^)(void))completionBlock
{
    self.reloadDataCompletionBlock = completionBlock;
    [self reloadData];
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    if (self.reloadDataCompletionBlock) {
        self.reloadDataCompletionBlock();
        self.reloadDataCompletionBlock = nil;
    }
}

@end

ব্যবহারের উদাহরণ:

[self.collectionView reloadDataWithCompletion:^{
    // reloadData is guaranteed to have completed
}];

এই উত্তরের একটি সুইফ্ট সংস্করণের জন্য এখানে দেখুন


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

2
আপনি ব্লকটি কল করার পরে layoutSubviewsএটি nilপরবর্তী কল হিসাবে সেট করা উচিত layoutSubviews, কল করার কারণে অগত্যা নয় reloadData, ফলে ব্লকটি কার্যকর করা হবে কারণ সেখানে দৃ strong় রেফারেন্স রাখা হচ্ছে, যা পছন্দসই আচরণ নয়।
মার্ক বোর্কে

আমি কেন এটি ইউআইটিএবলভিউয়ের জন্য ব্যবহার করতে পারি না? এটি কোনও দৃশ্যমান ইন্টারফেস দেখাচ্ছে না। আমি হেডার ফাইলটি আমদানি করেছিলাম তবে এখনও একই
জুলফিকার

2
এই উত্তরের সংযোজন হ'ল একমাত্র বিদ্যমান কলব্যাক ক্লোবার করা সম্ভব, যার অর্থ একাধিক কলারদের রেস-কন্ডিশন থাকবে। সমাধানটি হ'ল reloadDataCompletionBlockব্লকগুলির একটি অ্যারে তৈরি করা হবে এবং তাদের প্রয়োগের সময় পুনরুক্তি করা হবে এবং তার পরে অ্যারে খালি করা হবে।
টাইলার শেফার

1) এটি রবের প্রথম উত্তরের সমতুল্য নয়, তবে কি লেআউটআইফিডেড ব্যবহার করতে হবে? 2) আপনি আইওএস 10 উল্লেখ করেছেন কেন, এটি আইওএস 9 এ কাজ করে না ?!
মধু

30

টাইলার শেফারের মতো আমারও একই সমস্যা ছিল।

আমি সুইফটে তার সমাধানটি প্রয়োগ করেছি এবং এটি আমার সমস্যার সমাধান করেছে।

সুইফট 3.0:

final class UITableViewWithReloadCompletion: UITableView {
  private var reloadDataCompletionBlock: (() -> Void)?

  override func layoutSubviews() {
    super.layoutSubviews()

    reloadDataCompletionBlock?()
    reloadDataCompletionBlock = nil
  }


  func reloadDataWithCompletion(completion: @escaping () -> Void) {
    reloadDataCompletionBlock = completion
    self.reloadData()
  }
}

সুইফট 2:

class UITableViewWithReloadCompletion: UITableView {

  var reloadDataCompletionBlock: (() -> Void)?

  override func layoutSubviews() {
    super.layoutSubviews()

    self.reloadDataCompletionBlock?()
    self.reloadDataCompletionBlock = nil
  }

  func reloadDataWithCompletion(completion:() -> Void) {
      reloadDataCompletionBlock = completion
      self.reloadData()
  }
}

ব্যবহারের উদাহরণ:

tableView.reloadDataWithCompletion() {
 // reloadData is guaranteed to have completed
}

1
চমৎকার! ছোট নাইট-পিক, আপনি এই if letকথাটি দ্বারা মুছে ফেলতে পারবেন reloadDataCompletionBlock?()যা কল করবে যদি না il
টাইলার শেফার

Ios9
Matjan 5'17

self.reloadDataCompletionBlock? { completion() }হওয়া উচিত ছিলself.reloadDataCompletionBlock?()
ইমাম

আমি কীভাবে টেবিল দেখার উচ্চতার আকার পরিবর্তন করতে পারি? আমি পূর্বে টেবিল ভিউ.বেগিনআপটেটস () টেবিল ভিউ.এলআউটআইফনেডিড () টেবিল ভিউ.অ্যান্ডআপেটস ()
পার্থ তামানে

10

এবং একটি UICollectionViewসংস্করণ, কোলাওয়ার্ল্ডের উত্তরের উপর ভিত্তি করে:

https://stackoverflow.com/a/43162226/1452758

পরীক্ষার প্রয়োজন। এখন পর্যন্ত আইওএস 9.2, এক্সকোড 9.2 বিটা 2 তে কোনও সংগ্রহ সংগ্রহ করে স্ক্রোলিং সহ একটি সূচি হিসাবে দেখুন হিসাবে বন্ধ রয়েছে Works

extension UICollectionView
{
    /// Calls reloadsData() on self, and ensures that the given closure is
    /// called after reloadData() has been completed.
    ///
    /// Discussion: reloadData() appears to be asynchronous. i.e. the
    /// reloading actually happens during the next layout pass. So, doing
    /// things like scrolling the collectionView immediately after a
    /// call to reloadData() can cause trouble.
    ///
    /// This method uses CATransaction to schedule the closure.

    func reloadDataThenPerform(_ closure: @escaping (() -> Void))
    {       
        CATransaction.begin()
            CATransaction.setCompletionBlock(closure)
            self.reloadData()
        CATransaction.commit()
    }
}

ব্যবহার:

myCollectionView.reloadDataThenPerform {
    myCollectionView.scrollToItem(at: indexPath,
            at: .centeredVertically,
            animated: true)
}

6

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

When [tableView reloadData]রিটার্ন দেয়, টেবিলভিউর পিছনে অভ্যন্তরীণ ডেটা স্ট্রাকচার আপডেট করা হয়েছে। সুতরাং, যখন পদ্ধতিটি সম্পূর্ণ হয় আপনি নিরাপদে নীচে স্ক্রোল করতে পারেন। আমি এটি আমার নিজের অ্যাপে যাচাই করেছি। @ রব-মায়োফ দ্বারা বহুল স্বীকৃত উত্তর, যদিও পরিভাষায় বিভ্রান্তিকর, তার সর্বশেষ আপডেটে এটি স্বীকার করে।

যদি tableViewআপনি নীচে স্ক্রল না করে থাকেন তবে অন্য পোস্টে আপনার পোস্ট করা হয়নি এমন একটি সমস্যা থাকতে পারে। সম্ভবত আপনি স্ক্রোলিং সম্পূর্ণ হয়ে যাওয়ার পরে ডেটা পরিবর্তন করছেন এবং আপনি আবার লোড করছেন না এবং / অথবা নীচে স্ক্রোলিং করছেন?

টেবিলের ডেটার পরে সঠিক কিনা তা যাচাই করতে নীচে কিছু লগিং যুক্ত করুন reloadData। আমার একটি নমুনা অ্যাপে নিম্নলিখিত কোড রয়েছে এবং এটি পুরোপুরি কার্যকর হয় works

// change the data source

NSLog(@"Before reload / sections = %d, last row = %d",
      [self.tableView numberOfSections],
      [self.tableView numberOfRowsInSection:[self.tableView numberOfSections]-1]);

[self.tableView reloadData];

NSLog(@"After reload / sections = %d, last row = %d",
      [self.tableView numberOfSections],
      [self.tableView numberOfRowsInSection:[self.tableView numberOfSections]-1]);

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[self.tableView numberOfRowsInSection:[self.tableView numberOfSections]-1]-1
                                                          inSection:[self.tableView numberOfSections] - 1]
                      atScrollPosition:UITableViewScrollPositionBottom
                              animated:YES];

আমি আমার প্রশ্ন আপডেট। আপনি কি জানেন যে আমার এনএসলোগগুলি কেন এভাবে আউটপুট দেয়?
অ্যালান

8
reloadDataসিঙ্ক্রোনাস নয়। এই উত্তরটি দেখুন - এটি ব্যবহার করা হয়: stackoverflow.com/a/16071589/193896
bendytree

1
এটি সিনক্রোনাস। একটি নমুনা অ্যাপ্লিকেশন দিয়ে এটি পরীক্ষা করা এবং এটি দেখতে খুব সহজ। আপনি এই প্রশ্নের @ রব এর উত্তরের সাথে লিঙ্ক করেছেন। আপনি নীচে তার আপডেটটি পড়লে, তিনি এটিও যাচাই করেছেন। সম্ভবত আপনি ভিজ্যুয়াল লেআউট পরিবর্তনের কথা বলছেন। এটি সত্য যে টেবিলভিউ দৃশ্যমানভাবে সুসংগতভাবে আপডেট হয় না তবে ডেটা হয়। এজন্য ওপি-র প্রয়োজনীয় মানগুলি reloadDataরিটার্নের সাথে সাথেই সঠিক হয় ।
এক্স জোনেস

1
কী ঘটবে বলে আপনি বিভ্রান্ত হতে পারেন reloadData। আমার পরীক্ষার কেসটি বি / সি লাইনের viewWillAppearজন্য স্বীকার করতে ব্যবহার করুন scrollToRowAtIndexPath:যা tableViewপ্রদর্শিত না হলে তা অর্থহীন । আপনি দেখতে পাবেন যে ইনস্ট্যান্সে reloadDataক্যাশেড ডেটা আপডেট করেছে tableViewএবং এটি reloadDataসিঙ্ক্রোনাস। আপনি যদি অন্য tableViewডেলিগেট পদ্ধতিগুলির উল্লেখ করছেন যখন যখন tableViewলেআউটটি আউট হচ্ছে তখন কল করা হবে না যদি tableViewপ্রদর্শিত হয় না। আমি যদি আপনার পরিস্থিতি ভুল বুঝতে পারি তবে দয়া করে ব্যাখ্যা করুন।
এক্স জোনেস 21

3
কি মজা সময়। এটি ২০১৪, এবং কোনও পদ্ধতি সিঙ্ক্রোনাস এবং অ্যাসিনক্রোনাস কিনা তা নিয়ে তর্ক রয়েছে। অনুমান করার মতো লাগে। সমস্ত প্রয়োগের বিশদটি সেই পদ্ধতির নামের পিছনে সম্পূর্ণ অস্বচ্ছ is প্রোগ্রামিং দুর্দান্ত না?
ফতুহোকু

5

আমি এই কৌশলটি ব্যবহার করি, বেশ নিশ্চিত যে আমি ইতিমধ্যে এটি এই প্রশ্নের সদৃশটিতে পোস্ট করেছি:

-(void)tableViewDidLoadRows:(UITableView *)tableView{
    // do something after loading, e.g. select a cell.
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // trick to detect when table view has finished loading.
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tableViewDidLoadRows:) object:tableView];
    [self performSelector:@selector(tableViewDidLoadRows:) withObject:tableView afterDelay:0];

    // specific to your controller
    return self.objects.count;
}

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

1
কোনও জাল অ্যানিমেশনটির উপর নির্ভর করে? কোন উপায় যে একটি ভাল ধারণা। নির্বাচক বা জিসিডি সম্পাদন শিখুন এবং এটি সঠিকভাবে করুন। বিটিডব্লিউ এখন একটি টেবিল লোড পদ্ধতি রয়েছে যা আপনি কেবল এটি ব্যবহার করতে পারেন যদি আপনি কোনও প্রাইভেট প্রোটোকল ব্যবহার করতে আপত্তি করেন না যা সম্ভবত এটির সূক্ষ্ম কারণ এটি আপনার কোডটিকে চারপাশের চেয়ে বরং অন্য দিকে কল করে।
মালহাল

3

আসলে এই আমার সমস্যার সমাধান করেছে:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

NSSet *visibleSections = [NSSet setWithArray:[[tableView indexPathsForVisibleRows] valueForKey:@"section"]];
if (visibleSections) {
    // hide the activityIndicator/Loader
}}

2

এটি কাজ করবে এইভাবে চেষ্টা করুন

[tblViewTerms performSelectorOnMainThread:@selector(dataLoadDoneWithLastTermIndex:) withObject:lastTermIndex waitUntilDone:YES];waitUntilDone:YES];

@interface UITableView (TableViewCompletion)

-(void)dataLoadDoneWithLastTermIndex:(NSNumber*)lastTermIndex;

@end

@implementation UITableView(TableViewCompletion)

-(void)dataLoadDoneWithLastTermIndex:(NSNumber*)lastTermIndex
{
    NSLog(@"dataLoadDone");


NSIndexPath* indexPath = [NSIndexPath indexPathForRow: [lastTermIndex integerValue] inSection: 0];

[self selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];

}
@end

টেবিল সম্পূর্ণ লোড হয়ে গেলে আমি কার্যকর করব

অন্যান্য সমাধান আপনি ইউআইটিএবলভিউ সাবক্লাস করতে পারেন


1

শানের সমাধানের বিভিন্নতা ব্যবহার করে আমি শেষ করেছি:

একটি প্রতিনিধি সহ একটি কাস্টম ইউআইটিএবল ভিউ ক্লাস তৈরি করুন:

protocol CustomTableViewDelegate {
    func CustomTableViewDidLayoutSubviews()
}

class CustomTableView: UITableView {

    var customDelegate: CustomTableViewDelegate?

    override func layoutSubviews() {
        super.layoutSubviews()
        self.customDelegate?.CustomTableViewDidLayoutSubviews()
    }
}

তারপরে আমার কোডে, আমি ব্যবহার করি

class SomeClass: UIViewController, CustomTableViewDelegate {

    @IBOutlet weak var myTableView: CustomTableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.myTableView.customDelegate = self
    }

    func CustomTableViewDidLayoutSubviews() {
        print("didlayoutsubviews")
        // DO other cool things here!!
    }
}

এছাড়াও আপনি ইন্টারফেস নির্মাতার কাস্টম টেবিলভিউতে আপনার টেবিলের দৃশ্যটি সেট করেছেন তা নিশ্চিত করুন:

এখানে চিত্র বর্ণনা লিখুন


এটি কাজ করে তবে সমস্যাটি হ'ল পদ্ধতিটি প্রতিবারই কোনও একক সেল লোড করার পরে হিট হয়ে যায়, পুরো টেবিল ভিউটি বিক্রি হবে না, তাই পরিষ্কারভাবে উত্তরটি জিজ্ঞাসা করা প্রশ্নের ক্ষেত্রে নয়।
যশ বেদী

সত্য, এটি একাধিকবার কল হয় তবে প্রতিটি কক্ষে নয়। সুতরাং আপনি প্রথম প্রতিনিধিটির কথা শুনতে এবং বাকীটিকে উপেক্ষা করতে পারবেন যতক্ষণ না আপনি আবার রিলোডডাটা কল করেন।
স্যাম

1

সুইফট 3.0 + + আমরা জন্য একটি একটি এক্সটেনশন তৈরি করতে পারেন UITableViewএকটি সঙ্গে escaped Closureনিচের মত:

extension UITableView {
    func reloadData(completion: @escaping () -> ()) {
        UIView.animate(withDuration: 0, animations: { self.reloadData()})
        {_ in completion() }
    }
}

আপনি যেখানে চান সেখানে নীচের মতো এটি ব্যবহার করুন:

Your_Table_View.reloadData {
   print("reload done")
 }

আশা করি এটি কারও সাহায্য করবে। চিয়ার্স!


উজ্জ্বল ধারণা..একটি বিষয়, কেবল বিভ্রান্তি এড়াতে, আমি ফাংশনটির নাম টি পুনরায় লোড করেছি, রিলোডডেটা () এর পরিবর্তে। ধন্যবাদ
বিজয় কুমার এবি

1

বিস্তারিত

  • এক্সকোড সংস্করণ 10.2.1 (10E1001), সুইফট 5

সমাধান

import UIKit

// MARK: - UITableView reloading functions

protocol ReloadCompletable: class { func reloadData() }

extension ReloadCompletable {
    func run(transaction closure: (() -> Void)?, completion: (() -> Void)?) {
        guard let closure = closure else { return }
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)
        closure()
        CATransaction.commit()
    }

    func run(transaction closure: (() -> Void)?, completion: ((Self) -> Void)?) {
        run(transaction: closure) { [weak self] in
            guard let self = self else { return }
            completion?(self)
        }
    }

    func reloadData(completion closure: ((Self) -> Void)?) {
        run(transaction: { [weak self] in self?.reloadData() }, completion: closure)
    }
}

// MARK: - UITableView reloading functions

extension ReloadCompletable where Self: UITableView {
    func reloadRows(at indexPaths: [IndexPath], with animation: UITableView.RowAnimation, completion closure: ((Self) -> Void)?) {
        run(transaction: { [weak self] in self?.reloadRows(at: indexPaths, with: animation) }, completion: closure)
    }

    func reloadSections(_ sections: IndexSet, with animation: UITableView.RowAnimation, completion closure: ((Self) -> Void)?) {
        run(transaction: { [weak self] in self?.reloadSections(sections, with: animation) }, completion: closure)
    }
}

// MARK: - UICollectionView reloading functions

extension ReloadCompletable where Self: UICollectionView {

    func reloadSections(_ sections: IndexSet, completion closure: ((Self) -> Void)?) {
        run(transaction: { [weak self] in self?.reloadSections(sections) }, completion: closure)
    }

    func reloadItems(at indexPaths: [IndexPath], completion closure: ((Self) -> Void)?) {
        run(transaction: { [weak self] in self?.reloadItems(at: indexPaths) }, completion: closure)
    }
}

ব্যবহার

UITableView

// Activate
extension UITableView: ReloadCompletable { }

// ......
let tableView = UICollectionView()

// reload data
tableView.reloadData { tableView in print(collectionView) }

// or
tableView.reloadRows(at: indexPathsToReload, with: rowAnimation) { tableView in print(tableView) }

// or
tableView.reloadSections(IndexSet(integer: 0), with: rowAnimation) { _tableView in print(tableView) }

UICollectionView

// Activate
extension UICollectionView: ReloadCompletable { }

// ......
let collectionView = UICollectionView()

// reload data
collectionView.reloadData { collectionView in print(collectionView) }

// or
collectionView.reloadItems(at: indexPathsToReload) { collectionView in print(collectionView) }

// or
collectionView.reloadSections(IndexSet(integer: 0)) { collectionView in print(collectionView) }

সম্পূর্ণ নমুনা

সমাধান কোডটি এখানে যুক্ত করতে ভুলবেন না

import UIKit

class ViewController: UIViewController {

    private weak var navigationBar: UINavigationBar?
    private weak var tableView: UITableView?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupNavigationItem()
        setupTableView()
    }
}
// MARK: - Activate UITableView reloadData with completion functions

extension UITableView: ReloadCompletable { }

// MARK: - Setup(init) subviews

extension ViewController {

    private func setupTableView() {
        guard let navigationBar = navigationBar else { return }
        let tableView = UITableView()
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: navigationBar.bottomAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        tableView.dataSource = self
        self.tableView = tableView
    }

    private func setupNavigationItem() {
        let navigationBar = UINavigationBar()
        view.addSubview(navigationBar)
        self.navigationBar = navigationBar
        navigationBar.translatesAutoresizingMaskIntoConstraints = false
        navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        navigationBar.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        navigationBar.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        let navigationItem = UINavigationItem()
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "all", style: .plain, target: self, action: #selector(reloadAllCellsButtonTouchedUpInside(source:)))
        let buttons: [UIBarButtonItem] = [
                                            .init(title: "row", style: .plain, target: self,
                                                  action: #selector(reloadRowButtonTouchedUpInside(source:))),
                                            .init(title: "section", style: .plain, target: self,
                                                  action: #selector(reloadSectionButtonTouchedUpInside(source:)))
                                            ]
        navigationItem.leftBarButtonItems = buttons
        navigationBar.items = [navigationItem]
    }
}

// MARK: - Buttons actions

extension ViewController {

    @objc func reloadAllCellsButtonTouchedUpInside(source: UIBarButtonItem) {
        let elementsName = "Data"
        print("-- Reloading \(elementsName) started")
        tableView?.reloadData { taleView in
            print("-- Reloading \(elementsName) stopped \(taleView)")
        }
    }

    private var randomRowAnimation: UITableView.RowAnimation {
        return UITableView.RowAnimation(rawValue: (0...6).randomElement() ?? 0) ?? UITableView.RowAnimation.automatic
    }

    @objc func reloadRowButtonTouchedUpInside(source: UIBarButtonItem) {
        guard let tableView = tableView else { return }
        let elementsName = "Rows"
        print("-- Reloading \(elementsName) started")
        let indexPathToReload = tableView.indexPathsForVisibleRows?.randomElement() ?? IndexPath(row: 0, section: 0)
        tableView.reloadRows(at: [indexPathToReload], with: randomRowAnimation) { _tableView in
            //print("-- \(taleView)")
            print("-- Reloading \(elementsName) stopped in \(_tableView)")
        }
    }

    @objc func reloadSectionButtonTouchedUpInside(source: UIBarButtonItem) {
        guard let tableView = tableView else { return }
        let elementsName = "Sections"
        print("-- Reloading \(elementsName) started")
        tableView.reloadSections(IndexSet(integer: 0), with: randomRowAnimation) { _tableView in
            //print("-- \(taleView)")
            print("-- Reloading \(elementsName) stopped in \(_tableView)")
        }
    }
}

extension ViewController: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int { return 1 }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 20 }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = "\(Date())"
        return cell
    }
}

ফলাফল

এখানে চিত্র বর্ণনা লিখুন


0

'শেষবারের দৃশ্যমান' সেলটি পাঠানো হবে এমন সমাপ্তির ধারণার ভিত্তিতে, কেবলমাত্র অন্য পদ্ধতির প্রস্তাব দেওয়া cellForRow

// Will be set when reload is called
var lastIndexPathToDisplay: IndexPath?

typealias ReloadCompletion = ()->Void

var reloadCompletion: ReloadCompletion?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    // Setup cell

    if indexPath == self.lastIndexPathToDisplay {

        self.lastIndexPathToDisplay = nil

        self.reloadCompletion?()
        self.reloadCompletion = nil
    }

    // Return cell
...

func reloadData(completion: @escaping ReloadCompletion) {

    self.reloadCompletion = completion

    self.mainTable.reloadData()

    self.lastIndexPathToDisplay = self.mainTable.indexPathsForVisibleRows?.last
}

একটি সম্ভাব্য সমস্যা হ'ল: সেট আপ reloadData()হওয়ার আগে যদি এটি শেষ হয়ে যায় lastIndexPathToDisplay, সেট করার আগে 'সর্বশেষ দৃশ্যমান' ঘরটি প্রদর্শিত হবে lastIndexPathToDisplayএবং সমাপ্তি বলা হবে না (এবং এটি 'অপেক্ষার' অবস্থায় থাকবে):

self.mainTable.reloadData()

// cellForRowAt could be finished here, before setting `lastIndexPathToDisplay`

self.lastIndexPathToDisplay = self.mainTable.indexPathsForVisibleRows?.last

আমরা যদি বিপরীত হই, আমরা পূর্বে স্ক্রোলিং দ্বারা ট্রিগার ট্রিপিং সমাপ্তির সাথে শেষ হতে পারে reloadData()

self.lastIndexPathToDisplay = self.mainTable.indexPathsForVisibleRows?.last

// cellForRowAt could trigger the completion by scrolling here since we arm 'lastIndexPathToDisplay' before 'reloadData()'

self.mainTable.reloadData()

0

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

tableView.backgroundColor = .black

tableView.reloadData()

DispatchQueue.main.async(execute: {

    tableView.backgroundColor = .green

})

reloadData()ফাংশনটি সম্পূর্ণ হওয়ার পরে টেবিলভিউ রঙটি কালো থেকে সবুজ হয়ে যাবে।


0

আপনি ইউটিবেলভিউয়ের পারফরম্যান্সবাচআপডেটস ফাংশনটি ব্যবহার করতে পারেন

আপনি কীভাবে অর্জন করতে পারেন তা এখানে

self.tableView.performBatchUpdates({

      //Perform reload
        self.tableView.reloadData()
    }) { (completed) in

        //Reload Completed Use your code here
    }

0

CATransaction এর পুনরায় ব্যবহারযোগ্য এক্সটেনশন তৈরি করা:

public extension CATransaction {
    static func perform(method: () -> Void, completion: @escaping () -> Void) {
        begin()
        setCompletionBlock {
            completion()
        }
        method()
        commit()
    }
}

এখন ইউআইটিএবলভিউয়ের একটি এক্সটেনশন তৈরি করা যা CATransaction এর এক্সটেনশন পদ্ধতিটি ব্যবহার করবে:

public extension UITableView {
    func reloadData(completion: @escaping (() -> Void)) {
       CATransaction.perform(method: {
           reloadData()
       }, completion: completion)
    }
}

ব্যবহার:

tableView.reloadData(completion: {
    //Do the stuff
})

-2

আপনি ডেটা পুনরায় লোড করার পরে এটি কিছু করার জন্য ব্যবহার করতে পারেন:

[UIView animateWithDuration:0 animations:^{
    [self.contentTableView reloadData];
} completion:^(BOOL finished) {
    _isUnderwritingUpdate = NO;
}];

-20

বিলম্ব স্থাপনের চেষ্টা করুন:

[_tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.2];
[_activityIndicator performSelector:@selector(stopAnimating) withObject:nil afterDelay:0.2];

14
এটা বিপজ্জনক. আপনার বিলম্বের চেয়ে পুনরায় লোড করতে বেশি সময় নিলে কী হবে?
ছিনতাই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.