UITableViewCell में iOS7 पर ऑटो लेआउट की कमी की समस्या


104

मैं अपने कस्टम UITableView कोशिकाओं को लेआउट करने के लिए प्रोग्रामेटिक रूप से ऑटो लेआउट बाधाओं का उपयोग कर रहा हूं और मैं सेल आकारों को सही ढंग से परिभाषित कर रहा हूं tableView:heightForRowAtIndexPath:

यह iOS6 पर ठीक काम कर रहा है और यह iOS7 में भी ठीक दिखता है

लेकिन जब मैं iOS7 पर ऐप चलाता हूं, तो कंसोल में मुझे इस तरह का संदेश दिखाई देता है:

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-10-02 09:56:44.847 Vente-Exclusive[76306:a0b] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
        "<NSLayoutConstraint:0xac4c5f0 V:|-(15)-[UIImageView:0xac47f50]   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
        "<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>",
        "<NSLayoutConstraint:0xac43680 V:[UIView:0xac4d0f0(1)]>",
        "<NSLayoutConstraint:0xac436b0 V:[UIView:0xac4d0f0]-(0)-|   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>

और वास्तव में उस सूची में एक बाधा है जो मुझे नहीं चाहिए:

"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"

और मैं NO => की translatesAutoresizingMaskIntoConstraintsसंपत्ति सेट नहीं कर सकता, contentViewयह पूरे सेल को गड़बड़ कर देगा।

44 डिफ़ॉल्ट सेल ऊंचाई है, लेकिन मैंने अपने कस्टम हाइट को टेबल व्यू डेलिगेट में परिभाषित किया है कि सेल कंटेंट व्यू में यह बाधा क्यों है? इसका क्या कारण हो सकता है?

IOS6 में ऐसा नहीं हो रहा है और iOS6 और iOS7 दोनों पर ही सब कुछ ठीक है।

मेरा कोड काफी बड़ा है इसलिए मैं इसे यहां पोस्ट नहीं करूंगा, लेकिन अगर आपको इसकी आवश्यकता है, तो एक पास्टबिन के लिए पूछने के लिए स्वतंत्र महसूस करें।

यह निर्दिष्ट करने के लिए कि मैं यह कैसे कर रहा हूँ, सेल पर

  • मैं अपने सभी लेबल, बटन आदि बनाता हूं
  • मैंने उनकी translatesAutoresizingMaskIntoConstraintsसंपत्ति NO पर सेट की
  • मैं उन्हें contentViewसेल के साक्षात्कार के रूप में जोड़ता हूं
  • मैं इसमें अड़चनें जोड़ता हूं contentView

मुझे यह समझने में भी गहरी दिलचस्पी है कि यह केवल iOS7 पर ही क्यों होता है।


आपके कस्टम सेल की ऊँचाई कितनी है?
माइक पोलार्ड

मेरे कस्टम सेल की ऊँचाई 90
एलेक्सिस

एक सहकर्मी के पास कल भी यही मुद्दा था, लेकिन डिफ़ॉल्ट चौड़ाई 320 (एक आईपैड ऐप के लिए) थी।
jrturton

इसी मुद्दे को प्रदर्शित करते हुए यहां एक नमूना परियोजना है: github.com/Alex311/TableCellWithAutoLayout यहां मेरी कुछ टिप्पणियां इस प्रकार हैं: github.com/Alex311/TableCellWithAutoLayout/commit/…
smileyborg

मैं उसी त्रुटि में भाग गया, लेकिन यह इसलिए था क्योंकि मैंने अपने कस्टम सेल की ऊँचाई का पता लगाने के लिए जिस अतिरिक्त प्रोटोटाइप सेल का उपयोग कर रहा था, उसे कभी भी इनिशियलाइज़ नहीं किया था।
स्टीव मोजर

जवाबों:


132

मुझे भी यह समस्या थी .. ऐसा प्रतीत होता है कि ContentView का फ्रेम अपडेट नहीं होता है layoutSubviews जाता है कि सेल के फ्रेम को जाता है, लेकिन कंट्रोवर्सी का {0, 0, 320, 44}मूल्यांकन किया जाता है , उस समय contentView के फ्रेम को छोड़ते समय इसे अपडेट किया जाता है।

कंटेंट व्यू को अधिक विस्तार से देखने के बाद, ऐसा प्रतीत होता है कि ऑटोरेस्पोन्डिंग मास्क अब सेट नहीं किए जा रहे हैं।

अपने विचारों में बाधा डालने से पहले ऑटोराइज़िंग मास्क सेट करना इस मुद्दे को हल कर सकता है:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self)
    {
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
        [self loadViews];
        [self constrainViews];
    }
    return self;
}

यह काम धन्यवाद आदमी करता है। संपादन शैलियों का उपयोग करते समय क्या हो सकता है?
एलेक्सिस

11
@ L14M333 इस टिप्पणी में मेरे द्वारा पोस्ट किया गया कोड यहां देखें - मूल रूप से, आपको self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);अपनी बाधाओं को जोड़ने से पहले बस सेट करने में सक्षम होना चाहिए, जो समस्या को हल करना चाहिए।
स्माइबॉर्ग

2
autoresizingMask मेरे लिए काम नहीं करता है: शुरुआती बाधा दूर हो गई है, लेकिन 3 नए जोड़े गए हैं "<NSAutoresizingMaskLayoutConstraint: 0x8b79740 h = - & - v = & - UITableViewCellContentView: 0x8b44010.height ==ITITViewView" ” 0x8ac19d0 (0)]> "
कैटमफेटामाइन

1
मेरे लिए भी काम करता है, मैं इस पर एक घंटे के लिए संघर्ष कर रहा हूँ! धन्यवाद! <3
मोकागियो

2
अन्य ऑटो लेआउट समस्याओं (आईओएस 7 / आईओएस 8) से छुटकारा पाने के बाद मुझे पता चला कि उपयोग करने के self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);रूप में अच्छा काम करता है self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;। मैंने updateConstraintsअपनी सामग्री दृश्य में बाधाओं को जोड़ने से पहले इसे रखा ।
परीक्षण

35

जाहिरा तौर पर iOS 7 SDK का उपयोग करके iOS 7 पर UITableViewCell और UICollectionViewCell के साथ कुछ गड़बड़ है।

जब सेल पुन: उपयोग किया जाता है तो आप सेल के contentView को अपडेट कर सकते हैं:

स्थैतिक UITableViewController के लिए:

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }

    //your code goes here

    return cell;
}

#endif
#endif

चूंकि स्टेटिक टेबल व्यू कंट्रोलर नाजुक होते हैं और आसानी से तोड़े जा सकते हैं यदि आप कुछ डेटा स्रोत या डिलीटगेट तरीकों को लागू करते हैं - ऐसे चेक हैं जो यह सुनिश्चित करेंगे कि यह कोड केवल iOS 7 पर संकलित किया जाएगा और चलाया जाएगा

यह मानक गतिशील UITableViewController के लिए समान है:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"CellID";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }
    //your code goes here       
    return cell;
}

इस विधि के लिए इस संकलन की आवश्यकता नहीं है, क्योंकि इस पद्धति को लागू करना आवश्यक है।

विचार दोनों मामलों के लिए और UICollectionViewCell के लिए समान है, जैसे कि इस थ्रेड में टिप्पणी की गई है: स्टोरीबोर्ड प्रोटोटाइप सेल (Xcode 6, iOS 8KK) में UICollectionViewCell contentView के फ्रेम का ऑटोरेस्ज़िंग मुद्दा केवल iOS 7 पर चलने पर होता है


1
यह सबसे अच्छा जवाब है, या कम से कम मेरे लिए सबसे अच्छा समाधान है। मेरे सेल (ऑटोलॉययूट नियम) ने iOS8 में XCode6 के साथ बहुत अच्छा काम किया और iOS7 और 6 के साथ XCode 5. के साथ शानदार काम किया। मैं XCode6 में XCode को अपडेट करता हूं और यह अब iOS6 और 7. में काम नहीं कर रहा है। धन्यवाद !!!!
xarly

यह अब Xcode 6.1 के साथ कोई समस्या नहीं है। इसके अलावा, NSFoundationVersionNumber का उपयोग न करें, कृपया nshipster.com/swift-system-version-checking
onmyway133

1
@ onmyway133: Xcode 6.1 में अब यह समस्या क्यों नहीं है? मुझे अभी भी समस्या है, भले ही मैं Xcode 6.1 और iOS 8.1 SDK का उपयोग करूं। समस्या केवल आईओएस 7 पर होती है। सीमा बदलने या ऑटोरेस्पोन्डिंग मास्क स्थापित करने से समस्या हल हो जाती है। लेकिन मैंने सबसे अधिक वोट दिए गए उत्तर में या उसके टिप्पणियों में बताए गए दृष्टिकोण का उपयोग किया।
परीक्षण

हाँ, यह मेरे 3-घंटे के googling के आधार पर सबसे अच्छा उत्तर है। अन्य समान "समाधान" cell.contentView.autoresizingMask की पूरी सूची प्रदान नहीं करते हैं। Xcode 6 में बनाए गए मेरे iPad 7.1 प्रोजेक्ट के लिए केवल यही एक काम करता है
Golden Thumb

13

जैसा कि कोशिकाओं का पुन: उपयोग किया जा रहा है और सामग्री के आधार पर ऊंचाई बदल सकती है, मुझे लगता है कि सामान्य तौर पर यह आवश्यक होगा कि स्पैकिंग की प्राथमिकता को कम से कम निर्धारित किया जाए।

आपके मामले में UIImageView में शीर्ष पर 15 का अंतर है और नीचे के दृश्य में 0 से नीचे तक का अंतर है। यदि आप उन बाधाओं की प्राथमिकता 999 (1000 के बजाय) निर्धारित करते हैं, तो ऐप क्रैश नहीं होगा, क्योंकि बाधाओं की आवश्यकता नहीं है।

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


आप एक प्रतिभाशाली हैं! अच्छा और साफ समाधान आपको धन्यवाद :)
Blacky

9

मुझे अभी भी स्टोरीबोर्ड के लिए एक अच्छा समाधान नहीं मिला ... कुछ जानकारी यहां भी: https://github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac34654dd2f2ff9775f163#commitcomment-4633188

वे वहाँ क्या सलाह देते हैं:

self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);

मैंने अपना समाधान प्रेरित किया है:

  • स्टोरीबोर्ड पर राइट क्लिक करें
  • Open As -> सोर्स कोड
  • स्ट्रिंग "44" के लिए वहाँ खोजें
  • यह पसंद है

<tableView hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="44" ...
    <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ChatMessageCell" id="bCG-aU-ivE" customClass="ChatMessageCell">
        <rect key="frame" x="0.0" y="22" width="320" height="44"/>

  • rowHeight = "44" को rowHeight = "9999" और ऊंचाई = "44" के साथ ऊँचाई = 9999/ के साथ बदलें
  • स्टोरीबोर्ड पर राइट क्लिक करें
  • ओपन इस प्रकार -> इंटरफ़ेस बिल्डर
  • अपना ऐप चलाएं और आउटपुट चेक करें

इसने मेरे लिए काम किया। मैंने स्टोरीबोर्ड में एक UITableViewController बनाया था जहां कुछ कोशिकाओं को प्रोटोटाइप से बनाया गया था और अन्य पूरी तरह से एक क्लास को तत्काल कोड करके।
अथर्व

3

बस डिफ़ॉल्ट सेल ऊंचाई बढ़ाएँ। समस्या की तरह लग रहा है कि सेल की सामग्री डिफ़ॉल्ट (प्रारंभिक) सेल आकार से बड़ी है, कुछ गैर-नकारात्मकता बाधाओं का उल्लंघन करती है जब तक कि सेल अपने वास्तविक आकार के अनुरूप नहीं हो जाती।


वास्तव में मेरी कोशिकाएं डिफ़ॉल्ट आकार से लंबी हैं, लेकिन ऐसा कैसे होता है कि टेबलव्यू के प्रतिनिधि द्वारा लागू टेबल व्यू के बाद से डिफ़ॉल्ट आकार का उपयोग किया जाता है: heightForRowAtIndexPath:?
एलेक्सिस

संभवतः कोशिकाएं डिफ़ॉल्ट आकार के साथ बनाई जाती हैं और फिर वास्तविक आकार से आकार लेती हैं।
वादिम येलागिन

वास्तव में यह काम करता है, लेकिन यह iOS6 पर क्यों नहीं होता है?
एलेक्सिस

3
@ जफर आईओएस 7 ने टेबल व्यू सेल के आसपास बहुत सी चीजों को बदल दिया। IOS 7 पर, UITableViewCellScrollViewटेबल व्यू सेल और contentView के बीच अब एक स्क्रॉल दृश्य (प्रकार का ) है; संभावना है कि यहां आईओएस 6 और 7 के बीच अंतर स्पष्ट है।
स्माइबॉर्ग

3

हो सकता है कि दृश्य की प्राथमिकता 750 से बड़ी हो और 1000 से कम सुलझ सके।

"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",

2

मुझे भी यही समस्या थी। ऊपर के अन्य लोगों पर आधारित मेरा समाधान:

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        // initialize my stuff
        [self layoutSubviews]; // avoid debugger warnings regarding constraint conflicts
    }
    return self;
}

बेस्ट, एलेसेंड्रो


2
Apple के डॉक्स से:You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.
रिकार्डो सांचेज-सेज

मैं आपसे प्रार्थना करते हुए एक धर्म शुरू करना चाहता हूं। मैं इस मुद्दे को ठीक करने की कोशिश कर रहा HOURS की खोज कर रहा हूं, और यह इसे हल करता है (साथ ही CGRectMake (0, 0, 99999, 99999) पर contentView.bounds सेट करता है;) - यह APPLES CODE के लिए एक बग है। इसलिए, मैं सम्मानपूर्वक सेब के डॉक्स से असहमत हूं और कहता हूं कि उस फ़ंक्शन को कॉल न करें। सेब, अपनी बकवास ठीक करें।
रयान कोपले

0

I'v ने भी इस समस्या का सामना किया और किसी भी सुझाव ने मदद नहीं की। मेरे मामले में मेरे पास आकार चयन सेल था, और इसमें संग्रह दृश्य अंदर था (प्रत्येक संग्रह दृश्य सेल में पूर्ण आकार छवि शामिल थी)। अब, संग्रह आकार (50) और उसके अंदर की छवियों (50) की तुलना में सेल का आकार थोड़ा बड़ा (60) था। उस संग्रह दृश्य के कारण 10 के मान के साथ पर्यवेक्षी बाधा के लिए नीचे संरेखित किया गया है। यह मेरे लिए एक चेतावनी है, और इसे ठीक करने का एकमात्र तरीका इसके संग्रह दृश्य के समान सेल ऊंचाई बनाना था।


0

मैं डिजाइनर में UITableViewCell का उपयोग नहीं करने से समाप्त हुआ ... मैं वहां कस्टम दृश्य बनाता हूं और इसे सेल प्रोग्राम के सामग्री दृश्य में जोड़ देता हूं ... कुछ सहायता श्रेणियों के साथ कोई कोड बॉयलरप्लेट भी नहीं है ...


0

यदि यह iOS8 में ठीक काम करता है, और iOS7 में चेतावनी प्राप्त करता है, तो आप स्टोरीबोर्ड स्रोत कोड खोज सकते हैं, और सही टेबलव्यूसेल खोज सकते हैं, फिर टेबलव्यूसेल लाइन के बाद रूट विशेषता को जोड़ सकते हैं। कुकुमोवन को धन्यवाद ।

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" .../>
                                <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.