UITableView के लोडिंग के अंत का पता कैसे लगाएं


141

मैं लोड समाप्त होने पर तालिका की ऑफसेट बदलना चाहता हूं और यह तालिका पर लोड की गई कोशिकाओं की संख्या पर निर्भर करता है।

यह वैसे भी एसडीके पर है जब यह पता चलता है कि जब एक यूटिटेव लोडिंग समाप्त हो गई है? मुझे न तो प्रतिनिधि और न ही डेटा स्रोत प्रोटोकॉल पर कुछ दिखाई देता है।

मैं केवल दृश्य कोशिकाओं के लोड होने के कारण डेटा स्रोतों की गिनती का उपयोग नहीं कर सकता।


डेटासोर्स काउंट और '
indexPathsForVanishRows

1
ध्वज में आगे की जानकारी के आधार पर फिर से खोला गया: "यह डुप्लिकेट नहीं है। यह दृश्य कोशिकाओं को लोड करने के बारे में पूछता है, डेटा के समापन के बारे में नहीं पूछ रहा है। स्वीकृत उत्तर के लिए अपडेट देखें"
केव

यह समाधान मेरे लिए ठीक काम करता है। आप इसकी जांच करते हैं। stackoverflow.com/questions/1483581/…
खालिद अन्नजर

जवाबों:


224

@RichX उत्तर में सुधार करें: lastRowदोनों हो सकते हैं [tableView numberOfRowsInSection: 0] - 1या ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row। तो कोड होगा:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

अद्यतन: ठीक है, @ htafoya की टिप्पणी सही है। यदि आप चाहते हैं कि यह कोड स्रोत से सभी डेटा लोड करने के अंत का पता लगाए, तो यह नहीं होगा, लेकिन यह मूल प्रश्न नहीं है। यह कोड यह पता लगाने के लिए है कि कब दिखाई देने वाली सभी कोशिकाएं प्रदर्शित होती हैं। willDisplayCell:चिकनी UI के लिए यहां उपयोग किया जाता है (एकल सेल आमतौर पर willDisplay:कॉल के बाद तेजी से प्रदर्शित होती है )। आप इसके साथ भी प्रयास कर सकते हैं tableView:didEndDisplayingCell:


यह जानने के लिए बहुत बेहतर है कि सभी कोशिकाएं दिखाई देती हैं।
एरिक

14
हालाँकि, यह तब कहा जाएगा जब उपयोगकर्ता अधिक सेल देखने के लिए स्क्रॉल करेगा।
एचटीएफ़ॉइया

इसके साथ समस्या यह है कि यह पाद दृश्य के लिए जिम्मेदार नहीं है। अधिकांश के लिए एक मुद्दा नहीं हो सकता है, लेकिन अगर यह है कि आप एक ही विचार लागू कर सकते हैं लेकिन viewForFooterInSectionविधि में।
काइल क्लेग

1
@KyleClegg patric.schenke ने आपके उत्तर में टिप्पणी के कारणों में से एक का उल्लेख किया है। इसके अलावा, क्या होगा यदि पाद सेल के लोडिंग के अंत में दिखाई नहीं देता है?
फ़्लेक्स

27
tableView: didEndDisplayingCell: वास्तव में किसी सेल को दृश्य से हटाते समय कहा जाता है, न कि जब दृश्य में इसका प्रतिपादन पूरा होता है तो यह काम नहीं करेगा। अच्छी पद्धति का नाम नहीं। होगा डॉक्स पढ़ा।
एंड्रयू राफेल

34

स्विफ्ट 3 और 4 और 5 संस्करण:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let lastVisibleIndexPath = tableView.indexPathsForVisibleRows?.last {
        if indexPath == lastVisibleIndexPath {
            // do here...
        }
    }
}

1
जब हम पहली बार डेटा लोड करते हैं तो यह विधि कहलाती है। मेरे मामले में केवल 4 दृश्य कोशिकाएं हैं। मैंने 8 पंक्तियों को लोड किया था लेकिन फिर भी यह फ़ंक्शन कहा जा रहा था। जब मैं चाहता हूं कि अधिक डेटा लोड किया जाए जब उपयोगकर्ता अंतिम पंक्ति तक पहुंच जाए
मुहम्मद नायब

हाय मुहम्मद नायब, शायद आप "अगर indexPath == lastVanishIndexPath" को "अगर indexPath.row == yourDataSource.count" से बदल सकते हैं
Daniele Ceglia

1
@DanieleCeglia इस बात के लिए धन्यवाद। अगर indexPath == lastVanishIndexPath && indexPath.row == yourDataSource.count - 1 यह मेरे लिए काम करने वाला है। चीयर्स !!!
योगेश पटेल

28

मैं हमेशा इस बहुत ही सरल उपाय का उपयोग करता हूं:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == lastRow){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

अंतिम पंक्ति का पता कैसे लगाएं? मेरे लिए समस्या यही है .. क्या आप बता सकते हैं कि उस स्थिति में आप उस पर कैसे टिकते हैं।
समीरा चतुर्भुज

6
अंतिम पंक्ति है [tableView numberOfRowsInSection: 0] - 1। आपको 0आवश्यक मान से प्रतिस्थापित करना चाहिए । लेकिन यह समस्या नहीं है। समस्या यह है कि UITableView केवल दृश्यमान लोड करता है। हालाँकि ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).rowसमस्या हल करती है।
15

1
अगर हम पूर्णता की तलाश में हैं तो इसका उपयोग करना सबसे अच्छा नहीं होगा - (शून्य) tableView: (UITableView *) tableView didEndDisplayingCell: (UITableViewCell *) सेल forRowAtIstexPath: (NSIndexPath *) indexPath?
morcutt

10

यहाँ एक और विकल्प है जो मेरे लिए काम करता है। ViewForFooter प्रतिनिधि विधि में यह जाँच करें कि यह अंतिम खंड है और अपना कोड वहाँ जोड़ें। यह दृष्टिकोण दिमाग में आने के बाद पता चलता है कि विलडिसप्ले फेलर के लिए खाता नहीं है यदि आपके पास है।

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 
{
  // Perform some final layout updates
  if (section == ([tableView numberOfSections] - 1)) {
    [self tableViewWillFinishLoading:tableView];
  }

  // Return nil, or whatever view you were going to return for the footer
  return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
  // Return 0, or the height for your footer view
  return 0.0;
}

- (void)tableViewWillFinishLoading:(UITableView *)tableView
{
  NSLog(@"finished loading");
}

मुझे लगता है कि यह दृष्टिकोण सबसे अच्छा काम करता है यदि आप संपूर्ण के लिए अंत लोडिंग ढूंढ रहे हैं UITableView, और केवल दृश्यमान कोशिकाएं नहीं। अपनी आवश्यकताओं के आधार पर आप केवल दिखाई देने वाली कोशिकाओं को चाहते हैं, जिस स्थिति में फॉक्सलेक्स का उत्तर एक अच्छा मार्ग हो सकता है।


रिटर्निंग nilसे tableView:viewForFooterInSection:आईओएस 7 में अपने लेआउट ऑटो लेआउट का उपयोग कर के साथ गड़बड़।
ma11hew28

दिलचस्प। क्या होगा यदि आप इसे ऊंचाई और चौड़ाई 0 के साथ एक फ्रेम पर सेट करते हैं? return CGRectMake(0,0,0,0);
काइल क्लेग

मैंने कोशिश की और सेट भी कर दिया self.tableView.sectionFooterHeight = 0। किसी भी तरह से, यह लगभग 10. की ऊंचाई के साथ एक अनुभाग पाद लेख दृश्य सम्मिलित करने के लिए लगता है। मुझे यकीन है कि मैं इसे 0-ऊंचाई की बाधा को जोड़कर देख सकता हूं जो मैं लौटता हूं। वैसे भी, मैं अच्छा हूँ क्योंकि मैं वास्तव में यह जानना चाहता था कि अंतिम सेल पर UITableView कैसे शुरू करें लेकिन यह पहली बार देखा।
ma11hew28

1
@MattDiPasquale यदि आप viewForFooterInSection को लागू करते हैं, तो आपको heightForFooterInSection को भी लागू करना होगा। यह एक शून्य पाद के साथ वर्गों के लिए 0 वापस करना है। यह अब तक आधिकारिक डॉक्स में भी है।
patric.schenke

viewForFooterInSection यदि आप 0 heightForFooterInSection सेट कहा जाता है नहीं प्राप्त करता है
Oded Harth

10

स्विफ्ट 2 समाधान:

// willDisplay function
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let lastRowIndex = tableView.numberOfRowsInSection(0)
    if indexPath.row == lastRowIndex - 1 {
        fetchNewDataFromServer()
    }
}

// data fetcher function
func fetchNewDataFromServer() {
    if(!loading && !allDataFetched) {
        // call beginUpdates before multiple rows insert operation
        tableView.beginUpdates()
        // for loop
        // insertRowsAtIndexPaths
        tableView.endUpdates()
    }
}

9

निजी API का उपयोग करना:

@objc func tableViewDidFinishReload(_ tableView: UITableView) {
    print(#function)
    cellsAreLoaded = true
}

सार्वजनिक API का उपयोग करना:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // cancel the perform request if there is another section
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tableViewDidLoadRows:) object:tableView];

    // create a perform request to call the didLoadRows method on the next event loop.
    [self performSelector:@selector(tableViewDidLoadRows:) withObject:tableView afterDelay:0];

    return [self.myDataSource numberOfRowsInSection:section];
}

// called after the rows in the last section is loaded
-(void)tableViewDidLoadRows:(UITableView*)tableView{
    self.cellsAreLoaded = YES;
}

एक संभावित बेहतर डिज़ाइन दृश्य कोशिकाओं को एक सेट में जोड़ना है, फिर जब आपको यह जांचने की आवश्यकता होती है कि क्या तालिका लोड है तो आप इस सेट के चारों ओर लूप के लिए कर सकते हैं, जैसे

var visibleCells = Set<UITableViewCell>()

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.insert(cell)
}

override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.remove(cell)
}

// example property you want to show on a cell that you only want to update the cell after the table is loaded. cellForRow also calls configure too for the initial state.
var count = 5 {
    didSet {
        for cell in visibleCells {
            configureCell(cell)
        }
    }
}

दूसरों की तुलना में बहुत बेहतर समाधान। यह एक tableView पुनः लोड की आवश्यकता नहीं है। यह बहुत सरल है और viewDidLoadRows: हर बार अंतिम सेल लोड होने पर कॉल नहीं किया जाता है।
मैट हडसन

यह अब तक का सबसे अच्छा समाधान है, क्योंकि अन्य समाधानों में कई वर्गों को ध्यान में नहीं रखा गया है
न्यायपीठ

मुझे भद्दी टिप्पणी के लिए खेद है, लेकिन वास्तव में यह 'जादू' कैसे है? प्रतिनिधि से किसी अन्य विधि के लिए कॉल करना। मुझे नहीं मिला।
लुकास पेट्र

@LukasPetr कैंसिल और आफ्टरलेड पर एक नज़र। वे अंतिम को छोड़कर हर अनुभाग के लिए रद्द किए जाने वाले विधि कॉल को सक्षम करते हैं, जो तब होता है जब तालिका पूरी तरह से लोड हो चुकी होती है।
मलहल

@ हेमल ओह, ठीक है। यह पहली नज़र में मैंने जितना सोचा था उससे कहीं अधिक चतुर है।
लुकास पेट्र

8

स्विफ्ट 3 में चुने गए उत्तर संस्करण के लिए:

var isLoadingTableView = true

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if tableData.count > 0 && isLoadingTableView {
        if let indexPathsForVisibleRows = tableView.indexPathsForVisibleRows, let lastIndexPath = indexPathsForVisibleRows.last, lastIndexPath.row == indexPath.row {
            isLoadingTableView = false
            //do something after table is done loading
        }
    }
}

मुझे isLadingTableView चर की आवश्यकता थी क्योंकि मैं यह सुनिश्चित करना चाहता था कि मैं एक डिफ़ॉल्ट सेल चयन करने से पहले तालिका को लोड कर रहा हूं। यदि आप इसे शामिल नहीं करते हैं, तो हर बार जब आप तालिका को स्क्रॉल करते हैं तो यह आपके कोड को फिर से आमंत्रित करेगा।


6

सबसे अच्छा तरीका है जो मुझे पता है कि एरिक का जवाब है: जब यूआईटेबल व्यू ने डेटा के लिए पूछना समाप्त कर लिया तो सूचित करें

अपडेट: इसे काम करने के लिए मुझे इन कॉल्स को करना होगा -tableView:cellForRowAtIndexPath:

[tableView beginUpdates];
[tableView endUpdates];

इस लायक के लिए, मैं महीनों के लिए अपनी सभी परियोजनाओं पर इस बहुत ही सरल विधि का उपयोग कर रहा हूं और यह पूरी तरह से काम करता है।
एरिक मोरैंड

3

यह जानने के लिए कि जब तालिका दृश्य अपनी सामग्री लोड करना समाप्त करता है, तो हमें सबसे पहले इस बात की बुनियादी समझ होनी चाहिए कि विचारों को स्क्रीन पर कैसे रखा जाता है।

किसी ऐप के जीवन चक्र में 4 महत्वपूर्ण क्षण होते हैं:

  1. एप्लिकेशन को एक घटना (स्पर्श, टाइमर, ब्लॉक प्रेषण आदि) प्राप्त होती है
  2. एप्लिकेशन ईवेंट को संभालता है (यह एक बाधा को संशोधित करता है, एक एनीमेशन शुरू करता है, पृष्ठभूमि बदलता है आदि)
  3. एप्लिकेशन नए दृश्य पदानुक्रम की गणना करता है
  4. ऐप दृश्य पदानुक्रम को प्रस्तुत करता है और इसे प्रदर्शित करता है

2 और 3 बार पूरी तरह से अलग हो गए हैं। क्यों ? प्रदर्शन कारणों से, हम हर बार एक संशोधन किए जाने के बाद हर पल 3 की गणना करना नहीं चाहते हैं।

इसलिए, मुझे लगता है कि आप इस तरह के एक मामले का सामना कर रहे हैं:

tableView.reloadData()
tableView.visibleCells.count // wrong count oO

यहाँ क्या गलत है?

किसी भी दृश्य की तरह, एक टेबल दृश्य अपनी सामग्री को आलसी तरीके से पुनः लोड करता है। दरअसल, यदि आप reloadDataकई बार कॉल करते हैं तो यह प्रदर्शन समस्याओं को पैदा नहीं करेगा। तालिका दृश्य अपने प्रतिनिधि कार्यान्वयन के आधार पर केवल इसकी सामग्री के आकार को फिर से प्रदर्शित करता है और इसकी कोशिकाओं को लोड करने के लिए पल 3 की प्रतीक्षा करता है। इस समय को लेआउट पास कहा जाता है।

ठीक है, लेआउट पास में कैसे जाएं?

लेआउट पास के दौरान, ऐप दृश्य पदानुक्रम के सभी फ़्रेमों की गणना करता है। शामिल हो के लिए, आपको समर्पित तरीकों ओवरराइड कर सकते हैं layoutSubviews, updateLayoutConstraintsआदि एक में UIViewऔर एक दृश्य नियंत्रक उपवर्ग में बराबर तरीकों।

ठीक वैसा ही एक टेबल व्यू करता है। यह ओवरराइड करता है layoutSubviewsऔर आपके प्रतिनिधि कार्यान्वयन के आधार पर कोशिकाओं को जोड़ता या हटाता है। यह cellForRowनए सेल को जोड़ने और बिछाने से ठीक पहले कॉल करता है, willDisplayठीक उसके बाद। यदि आपने reloadDataपदानुक्रम में तालिका दृश्य को कॉल किया या जोड़ा है, तो इस महत्वपूर्ण क्षण में इसके फ़्रेम को भरने के लिए तालिकाओं के दृश्य में उतनी कोशिकाएँ शामिल हैं जितनी आवश्यक हैं।

ठीक है, लेकिन अब, कैसे पता चलेगा जब एक टेबल व्यू ने अपनी सामग्री को फिर से लोड करना समाप्त कर दिया है?

अब हम इस सवाल को फिर से उठा सकते हैं: कैसे पता करें कि जब एक टेबल व्यू ने अपने सबव्यू को खत्म कर दिया है?

टेबल व्यू के लेआउट में आने का सबसे आसान तरीका है:

class MyTableView: UITableView {
    func layoutSubviews() {
        super.layoutSubviews()
        // the displayed cells are loaded
    }
}

ध्यान दें कि तालिका दृश्य के जीवन चक्र में इस विधि को कई बार कहा जाता है। स्क्रॉल और तालिका दृश्य के विचलन व्यवहार के कारण, कोशिकाओं को संशोधित, हटा दिया जाता है और अक्सर जोड़ा जाता है। लेकिन यह काम करता है, ठीक इसके बाद super.layoutSubviews(), कोशिकाओं को लोड किया जाता है। यह समाधान willDisplayअंतिम इंडेक्स पथ की घटना की प्रतीक्षा करने के बराबर है । प्रत्येक ईवेंट को layoutSubviewsजोड़े गए कक्षों के लिए तालिका दृश्य के निष्पादन के दौरान यह ईवेंट कहा जाता है ।

एक अन्य तरीका यह है कि ऐप को लेआउट पास समाप्त होने पर बुलाया जाए।

जैसा कि प्रलेखन में वर्णित है , आप निम्न विकल्प का उपयोग कर सकते हैं UIView.animate(withDuration:completion):

tableView.reloadData()
UIView.animate(withDuration: 0) {
    // layout done
}

यह समाधान काम करता है, लेकिन लेआउट के समय और ब्लॉक को प्राप्त करने के समय के बीच स्क्रीन एक बार ताज़ा हो जाएगी। यह DispatchMain.asyncसमाधान के बराबर है लेकिन निर्दिष्ट है।

वैकल्पिक रूप से, मैं टेबल व्यू के लेआउट को मजबूर करना पसंद करूंगा

किसी भी दृश्य को अपने सबव्यू फ्रेम की गणना करने के लिए मजबूर करने के लिए एक समर्पित तरीका है layoutIfNeeded:

tableView.reloadData()
table.layoutIfNeeded()
// layout done

हालांकि सावधान रहें, ऐसा करने से सिस्टम द्वारा उपयोग किए जाने वाले आलसी लोडिंग को हटा दिया जाएगा। उन तरीकों को बार-बार कॉल करने से प्रदर्शन समस्याएं पैदा हो सकती हैं। सुनिश्चित करें कि टेबल व्यू के फ्रेम की गणना होने से पहले उन्हें कॉल नहीं किया जाएगा, अन्यथा टेबल व्यू फिर से लोड हो जाएगा और आपको सूचित नहीं किया जाएगा।


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



1

यहाँ है कि मैं इसे स्विफ्ट 3 में कैसे करता हूं

let threshold: CGFloat = 76.0 // threshold from bottom of tableView

internal func scrollViewDidScroll(_ scrollView: UIScrollView) {

    let contentOffset = scrollView.contentOffset.y
    let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;

    if  (!isLoadingMore) &&  (maximumOffset - contentOffset <= threshold) {
        self.loadVideosList()
    }
}

1

यहां है जो मुझे करना होगा।

  1. आपके आधार वर्ग में (rootVC BaseVc आदि हो सकते हैं),

    A. "DidFinishReloading" कॉलबैक भेजने के लिए एक प्रोटोकॉल लिखें।

    @protocol ReloadComplition <NSObject>
    @required
    - (void)didEndReloading:(UITableView *)tableView;
    @end

    B. तालिका दृश्य को पुनः लोड करने के लिए एक सामान्य विधि लिखें।

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController;
  2. बेस क्लास मेथड इम्प्लीमेंटेशन में, प्रतिनिधि के साथ रीलोडडाटा और उसके बाद देरी से कॉल करें।

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController{
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [tableView reloadData];
            if(aViewController && [aViewController respondsToSelector:@selector(didEndReloading:)]){
                [aViewController performSelector:@selector(didEndReloading:) withObject:tableView afterDelay:0];
            }
        }];
    }
  3. सभी व्यू कंट्रोलर में पुनः लोडिंग प्रोटोकॉल की पुष्टि करें जहां आपको कॉलबैक की आवश्यकता है।

    -(void)didEndReloading:(UITableView *)tableView{
        //do your stuff.
    }

संदर्भ: https://discussions.apple.com/thread/2598339?start=0&tstart=0


0

@folex जवाब सही है।

लेकिन यह विफल हो जाएगा यदि टेबल व्यू में एक बार में एक से अधिक अनुभाग प्रदर्शित हों।

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
   if([indexPath isEqual:((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject])]){
    //end of loading

 }
}

0

स्विफ्ट में आप ऐसा कुछ कर सकते हैं। हर बार जब आप तालिका के अंत तक पहुँचते हैं, तो निम्नलिखित शर्त सही होगी

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}

0

मुझे पता है कि यह उत्तर दिया गया है, मैं सिर्फ एक सिफारिश जोड़ रहा हूं।

निम्नलिखित दस्तावेज के अनुसार

https://www.objc.io/issues/2-concurrency/thread-safe-class-design/

Dispatch_async के साथ समयावधि के मुद्दों को ठीक करना एक बुरा विचार है। मेरा सुझाव है कि हमें FLAG या कुछ और जोड़कर इसे संभालना चाहिए।


0

यदि आपके पास कई खंड हैं, तो यहां अंतिम खंड में अंतिम पंक्ति कैसे प्राप्त करें (स्विफ्ट 3):

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let visibleRows = tableView.indexPathsForVisibleRows, let lastRow = visibleRows.last?.row, let lastSection = visibleRows.map({$0.section}).last {
        if indexPath.row == lastRow && indexPath.section == lastSection {
            // Finished loading visible rows

        }
    }
}

0

काफी गलती से मैं इस समाधान में टकरा गया:

tableView.tableFooterView = UIView()
tableViewHeight.constant = tableView.contentSize.height

आपको सामग्री देखने से पहले footerView सेट करने की आवश्यकता है, जैसे viewDidLoad में। Btw। FooteView सेट करने से आप "अप्रयुक्त" विभाजकों को हटा सकते हैं


-1

क्या आप उन वस्तुओं की कुल संख्या की तलाश कर रहे हैं जिन्हें तालिका में प्रदर्शित किया जाएगा या वर्तमान में दिखाई देने वाली वस्तुओं की कुल संख्या? किसी भी तरह से .. मेरा मानना ​​है कि सभी डेटा स्रोत विधियों को कॉल करने के बाद 'viewDidLoad' विधि निष्पादित होती है। हालाँकि, यह केवल डेटा के पहले लोड पर काम करेगा (यदि आप एकल आवंटन ViewController का उपयोग कर रहे हैं)।


-1

मैं एंड्रयू के कोड की नकल कर रहा हूं और इसे उस मामले के लिए विस्तारित कर रहा हूं जहां आपके पास तालिका में सिर्फ 1 पंक्ति है। यह मेरे लिए अब तक काम कर रहा है!

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// detect when all visible cells have been loaded and displayed
// NOTE: iOS7 workaround used - see: http://stackoverflow.com/questions/4163579/how-to-detect-the-end-of-loading-of-uitableview?lq=1
NSArray *visibleRows = [tableView indexPathsForVisibleRows];
NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
BOOL isPreviousCallForPreviousCell = self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
BOOL isFinishedLoadingTableView = isLastCell && ([tableView numberOfRowsInSection:0] == 1 || isPreviousCallForPreviousCell);

self.previousDisplayedIndexPath = indexPath;

if (isFinishedLoadingTableView) {
    [self hideSpinner];
}
}

नोट: मैं एंड्रयू के कोड से सिर्फ 1 अनुभाग का उपयोग कर रहा हूं, इसलिए इसे ध्यान में रखें ..


SO @ jpage4500 पर आपका स्वागत है। मैंने आपके उत्तर को कम प्रतिनिधि बिंदुओं और प्रश्न बम्प के बारे में निकालने के लिए संपादित किया है। किसी अन्य उपयोगकर्ता के उत्तर पर विस्तार करना अपने आप में पूरी तरह से मान्य उत्तर है, इसलिए आप उस सामान को छोड़ कर अव्यवस्था को कम कर सकते हैं। यह अच्छा है कि आपने एंड्रयू को श्रेय दिया, ताकि वह रुके।
skrrgwasme

-3

IOS7.0x में समाधान थोड़ा अलग है। यहां वह है जो मैंने जुटाया।

    - (void)tableView:(UITableView *)tableView 
      willDisplayCell:(UITableViewCell *)cell 
    forRowAtIndexPath:(NSIndexPath *)indexPath
{
    BOOL isFinishedLoadingTableView = [self isFinishedLoadingTableView:tableView  
                                                             indexPath:indexPath];
    if (isFinishedLoadingTableView) {
        NSLog(@"end loading");
    }
}

- (BOOL)isFinishedLoadingTableView:(UITableView *)tableView 
                         indexPath:(NSIndexPath *)indexPath
{
    // The reason we cannot just look for the last row is because 
    // in iOS7.0x the last row is updated before
    // looping through all the visible rows in ascending order 
    // including the last row again. Strange but true.
    NSArray * visibleRows = [tableView indexPathsForVisibleRows];   // did verify sorted ascending via logging
    NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
    // For tableviews with multiple sections this will be more complicated.
    BOOL isPreviousCallForPreviousCell = 
             self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
    BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
    BOOL isFinishedLoadingTableView = isLastCell && isPreviousCallForPreviousCell;
    self.previousDisplayedIndexPath = indexPath;
    return isFinishedLoadingTableView;
}

-3

उद्देश्य सी

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

तीव्र

self.tableView?.reloadData()
self.tableView?.performBatchUpdates({ () -> Void in

                            }, completion: { (Bool finished) -> Void in
                                /// table-view finished reload
                            })

1
यह विधि केवल UICollectionViewजहाँ तक मैं समझता हूँ, पर उपलब्ध है ।
विस्मय-ओ

हाँ आप सही है। UITableView का आरंभ UICollectionView के प्रदर्शन के बराबर है। stackoverflow.com/a/25128583/988169
pkc456

इसलिए प्रश्न का उचित और मान्य उत्तर दें।
G.Abhisek
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.