2012-03-31 23 views
37

मेरे पास UIScrollView में एक गैर स्क्रॉलिंग UITableView है। मैंने UITableView के फ्रेम आकार को इसके सामग्री आकार में सेट किया है।एक UITableView की सामग्री आकार कब सेट हो जाता है?

जब मैं UITableView पर एक पंक्ति जोड़ता हूं, तो मैं insertRowsAtIndexPaths:withRowAnimation पर कॉल करता हूं: UITableView पर। तब मैं UITableView के फ्रेम आकार बदलने के लिए एक विधि कॉल:

- (void)resizeTableViewFrameHeight 
{ 
    // Table view does not scroll, so its frame height should be equal to its contentSize height 
    CGRect frame = self.tableView.frame; 
    frame.size = self.tableView.contentSize; 
    self.tableView.frame = frame; 
} 

हालांकि यह है कि contentSize इस बिंदु पर अपडेट नहीं किया गया लगता है। यदि मैं पंक्तियों और खंडों की संख्या के आधार पर उपर्युक्त विधि में मैन्युअल रूप से फ्रेम की गणना करता हूं, तो विधि ठीक से काम करती है।

मेरा सवाल है, मैं contentSize को अपडेट करने के लिए UITableView कैसे प्राप्त कर सकता हूं? मुझे लगता है कि मैं reloadData पर कॉल कर सकता हूं और शायद यह ऐसा करेगा, लेकिन जब मैं केवल एक सेल डालने वाला हूं तो पूरी तालिका को फिर से लोड करने में अक्षम लगता है।

उत्तर

61

आप UITableView पर layoutIfNeeded फोन करके सामग्री के आकार की गणना करने के UITableView मजबूर कर सकते हैं। एक UITableViewController उपवर्ग कि चर आकार के साथ एक कंटेनर दृश्य में होना चाहिए के लिए

उदाहरण:

- (CGSize)preferredContentSize 
{ 
    // Force the table view to calculate its height 
    [self.tableView layoutIfNeeded]; 
    return self.tableView.contentSize; 
} 

अद्यतन 2016/07/28 यह एक ही बात का एक अपरीक्षित स्विफ्ट उदाहरण है। यह काम करना चाहिए, लेकिन अगर यह कोई टिप्पणी छोड़ नहीं है। ऐसा करने के लिए अच्छे या अधिक मूर्ख तरीके हो सकते हैं। दुर्भाग्य से मैं स्विफ्ट से बहुत परिचित नहीं हूं।

override var preferredContentSize: CGSize { 
    get { 
     self.tableView.layoutIfNeeded() 
     return self.tableView.contentSize 
    } 
    set {} 
} 
+0

मैंने कोशिश की, लेकिन यह मेरे लिए काम नहीं किया। लेकिन, मैं यहां एक और समाधान के साथ आने में सक्षम था जिसे मैंने यहां पोस्ट किया था: http://stackoverflow.com/questions/17634617/when-does-uitableview-content-size-update-with-row-insert-delete-animation/18665064 # 18665064 – Daren

+1

ओह, यह केवल प्रारंभिक सामग्री आकार के लिए है। जब आकार बदल रहा है तो आपका माइलेज अन्य मामलों के लिए भिन्न हो सकता है। – Farthen

+7

उन लोगों के लिए नोट जिनके लिए यह काम नहीं कर रहा है - tableView: अनुमानित हाइटफॉररोएट इंडेक्सपैथ सामग्री सामग्री के साथ गड़बड़ है, तो आप इसके कार्यान्वयन को हटाकर भाग्य प्राप्त कर सकते हैं। – weienw

13

इस प्रयास करें:

- (void)resizeTableViewFrameHeight 
{ 
    UITableView *tableView = self.tableView; 
    CGRect frame = tableView.frame; 
    frame.size.height = [tableView sizeThatFits:CGSizeMake(frame.size.width, HUGE_VALF)].height; 
    tableView.frame = frame; 
} 
+1

मैंने कोशिश की और यह काम किया, धन्यवाद! लेकिन हालांकि यह मेरी समस्या का समाधान करता है, यह वास्तव में मेरे प्रश्न का उत्तर नहीं देता है जब सामग्री का आकार सेट हो जाता है। – Darren

+1

मुझे संदेह है कि यह 'layoutSubviews' में सेट हो जाता है, लेकिन मुझे इस समय सत्यापित करने की तरह महसूस नहीं होता है। –

19

जब मैं KVO (मुख्य मान अवलोकन) प्यार नहीं करते, यह काफी अच्छा तरीका ठीक-ठीक पता करने के लिए जब अपनी मेज के contentSize (बस यादृच्छिक स्थानों में से एक गुच्छा में अपने अद्यतन तरीकों बुला के बजाय) बदल गया है । इसका उपयोग करना आसान है (हालांकि कुछ हद तक गुप्त और निहित)। अपनी मेज के contentSize पर परिवर्तन का पालन करने के लिए, निम्न करें:

1) इसलिए की तरह अपनी मेज के contentSize संपत्ति के एक पर्यवेक्षक बनें:

[self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL]; 

यह आमतौर पर (देखें नियंत्रक कि tableView रखती है में किया जाता है की तरह viewDidLoad: में, उदाहरण के लिए)।

2) विधि को देख KVO लागू करने और परिवर्तन की जरूरत है:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { 
    if(object == self.tableView && [keyPath isEqualToString:@"contentSize"]) { 
     // perform your updates here 
    } 
} 

3) कुछ तार्किक बिंदु (मैं dealloc में यह कहते हैं) पर एक पर्यवेक्षक के रूप में अपने दृश्य नियंत्रक निकालें।तुम इतनी तरह ऐसा करते हैं:

- (void)dealloc { 
    [self.tableView removeObserver:self forKeyPath:@"contentSize"]; 
} 
+1

मुझे केवीओ आदमी की याद दिलाने के लिए धन्यवाद। मैंने यह एकमात्र समाधान पाया जो मेरे काफी जटिल लेआउट पर काम करता है। – preams

+0

मुझे यहां एक नोट बनाने दें। जैसा कि आपने बताया है, मैं स्क्रॉलिंग में केवीओ का उपयोग करता था। हालांकि, यदि आप startUpdates और endUpdates का उपयोग कर रहे हैं तो यह आईओएस 11 के बाद ठीक से काम नहीं करेगा। आईओएस 11 में, सामग्री के दौरान सामग्री आकार बदलता है, यानी, यदि आप सामग्री के रूप में जल्द ही स्क्रॉल करते हैं आकार बदलते हैं, तो आप अपडेट के दौरान तालिका दृश्य की स्थिति बदल रहे होंगे, जो आपको बहुत अजीब बग पर ले जाएगा। मेरे प्रश्न की जांच करें [यहां] (https://stackoverflow.com/questions/46587878/uitableview-header-not-disappearing/46854828#46854828), केवीओ का उपयोग करके मेरी बग का कारण था। –

+0

यहां नोटिस की आवश्यकता है: रिकर्सिव रन से बचने के लिए रनलोप का उपयोग करके प्रमुख फेंक खराब अपवाद। – 0xDatou

0

यह मेरे लिए काम किया, जब tableview के मुद्दों को संबोधित जोड़ने/हटाने के पंक्तियों

tableView.layoutIfNeeded() 

का उपयोग करना और

सेट करने के बाद सही आकार हो रही
tableView.estimatedRowHeight = UITableViewAutomaticDimension 
3
  1. जोड़ें पर्यवेक्षक (मेरे नमूने में viewDidLoad

    tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil) 
    
  2. में निरीक्षण करें मूल्य

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
        if let obj = object as? UITableView { 
         if obj == self.tableView && keyPath == "contentSize" { 
          if let newSize = change?[NSKeyValueChangeKey.newKey] as? CGSize { 
           //do stuff here 
          } 
         } 
        } 
    } 
    
  3. पर्यवेक्षक निकालें

    deinit { 
        self.tableView.removeObserver(self, forKeyPath: "contentSize") 
    } 
    
0

आप पाद लेख के फ्रेम को बदल सकते हैं की जरूरत नहीं। मैं पाद लेख के एनिमेटेड उपस्थिति से पहले फोन करता हूं।

if self.newTableView.contentSize.height < self.newTableView.frame.height { 
     let additionalHeight: CGFloat = self.newTableView.frame.height - self.newTableView.contentSize.height 

     let tableFooterView = self.newTableView.tableFooterView! 

     let x = tableFooterView.frame.origin.x 
     let y = tableFooterView.frame.origin.y + additionalHeight 
     let width = tableFooterView.frame.width 
     let height = tableFooterView.frame.height 

     tableFooterView.frame = CGRect(x: x, y: y, width: width, height: height) 
    } 
संबंधित मुद्दे