2012-09-26 9 views
38

मैं स्टोरीबोर्ड में प्रोटोटाइप सेल का उपयोग कर कस्टम UITableViewCell को कॉन्फ़िगर कर रहा हूं। हालांकि, सभी UILabel एस (और अन्य यूआई तत्व) सेल के contentView में जोड़े जाने लगते नहीं हैं, इसके बजाय UITableViewCell सीधे सीधे जोड़ा जा रहा है। इससे समस्याएं उत्पन्न होती हैं जब सेल को संपादन मोड में रखा जाता है, क्योंकि सामग्री स्वचालित रूप से स्थानांतरित नहीं होती है/इंडेंट (जो यह करेगी, अगर वे contentView के अंदर थे)।सामग्री आईओएस 6 में इंडेंट नहीं दिख रहा है UITableViewCell प्रोटोटाइप सेल

इंटरफ़ेस बिल्डर/स्टोरीबोर्ड/प्रोटोटाइप कोशिकाओं का उपयोग कर सेल डालने पर UI12 तत्वों को contentView में जोड़ने का कोई तरीका है? मुझे मिला एकमात्र तरीका है कोड में सबकुछ बनाना और [cell.contentView addSubView:labelOne] का उपयोग करना जो बहुत अच्छा नहीं होगा, क्योंकि सेल को ग्राफिक रूप से लेआउट करना बहुत आसान है।

+1

क्या आप इसके बारे में निश्चित हैं? पिछली बार जब मैंने एक सेल को एक निब में रखा था, जबकि ऐसा नहीं लगता था कि मैं सामग्री दृश्य में उप-दृश्य जोड़ रहा था, डीबगर में रन टाइम पर सबकुछ सामग्री दृश्य में था। यदि आप पहले से नहीं हैं तो डीबगर में सत्यापित करने योग्य मूल्य ... –

+1

धन्यवाद कार्ल। आप सही थे - सभी दृश्यों को सामग्री दृश्य में जोड़ा गया है। समस्या आईओएस 6 autolayout से संबंधित थी। मैंने एक उत्तर शामिल किया है जो बताता है कि समस्या को कैसे ठीक किया गया था। – Skoota

उत्तर

66

आगे की जांच (सेल के सबव्यू पदानुक्रम को देखते हुए) इंटरफेस बिल्डर सेल के contentView के भीतर सबव्यूव्स रखता है, यह ऐसा नहीं लगता है।

इस मुद्दे का मूल कारण आईओएस 6 ऑटोलाउट था। जब कक्ष संपादन मोड (और इंडेंट) में रखा जाता है तो contentView भी इंडेंट किया जाता है, इसलिए इसका कारण यह है कि contentView के भीतर सभी सबव्यू contentView के भीतर होने के कारण (इंडेंट) स्थानांतरित हो जाएंगे। हालांकि, इंटरफेस बिल्डर द्वारा लागू सभी ऑटोलायआउट बाधा contentView के बजाय UITableViewCell के सापेक्ष प्रतीत होती है। इसका मतलब है कि contentView इंडेंट्स के बावजूद, सबव्यूज़ में शामिल नहीं है - बाधाएं चार्ज करती हैं।

उदाहरण के लिए, जब मैंने सेल में UILabel रखा (और सेल के बाएं हाथ से 10 अंक रखे) आईबी ने स्वचालित रूप से एक बाधा "क्षैतिज अंतरिक्ष (10)" लागू की। हालांकि, यह बाधा UITableViewCell से संबंधित है contentView नहीं। इसका मतलब यह है कि जब सेल इंडेंट किया जाता है, और contentView चाल चलता है, तो लेबल रहता है क्योंकि यह UITableViewCell के बाईं ओर से 10 अंक बने रहने के लिए बाध्यता का अनुपालन कर रहा है।

दुर्भाग्य से (जहां तक ​​मुझे पता है) आईबी के भीतर से इन आईबी निर्मित बाधाओं को दूर करने का कोई तरीका नहीं है, इसलिए यहां समस्या को हल किया गया है।

सेल के लिए UITableViewCell उप-वर्ग के भीतर, मैंने cellLabelHSpaceConstraint नामक उस बाधा के लिए IBOutlet बनाया। लेबल के लिए आपको IBOutlet की भी आवश्यकता है, जिसे मैंने cellLabel कहा था। मैं तो कार्यान्वित नीचे के अनुसार -awakeFromNib विधि:

- (void)awakeFromNib { 

    // ------------------------------------------------------------------- 
    // We need to create our own constraint which is effective against the 
    // contentView, so the UI elements indent when the cell is put into 
    // editing mode 
    // ------------------------------------------------------------------- 

    // Remove the IB added horizontal constraint, as that's effective 
    // against the cell not the contentView 
    [self removeConstraint:self.cellLabelHSpaceConstraint]; 

    // Create a dictionary to represent the view being positioned 
    NSDictionary *labelViewDictionary = NSDictionaryOfVariableBindings(_cellLabel); 

    // Create the new constraint 
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-10-[_cellLabel]" options:0 metrics:nil views:labelViewDictionary]; 

    // Add the constraint against the contentView 
    [self.contentView addConstraints:constraints]; 

} 

सारांश में, ऊपर क्षैतिज रिक्ति बाधा जो आईबी स्वचालित रूप से जोड़ निकाल देंगे (के रूप में नहीं बल्कि contentView से UITableViewCell के खिलाफ प्रभावी है) और फिर हम परिभाषित करने और जोड़ने contentView पर हमारी अपनी बाधा।

मेरे मामले में, सेल में अन्य सभी UILabelscellLabel की स्थिति के आधार पर स्थित थे, इसलिए जब मैंने इस तत्व की बाधा/स्थिति तय की, तो बाकी सभी सही ढंग से उपयुक्त और व्यवस्थित हुए। हालांकि, यदि आपके पास अधिक जटिल लेआउट है तो आपको अन्य सबव्यू के लिए भी ऐसा करने की आवश्यकता हो सकती है।

+2

+1 बहुत ही रोचक खोज और कामकाज! –

+0

अपने विस्तृत कामकाज को पोस्ट करने के लिए धन्यवाद। एक ही मुद्दा था! – Prine

+3

आप इंटरफ़ेस बिल्डर में ऑटोलायआउट बंद करके, या तो पूरे स्टोरीबोर्ड या केवल अपने सेल युक्त निब के लिए काम कर सकते हैं। विवरण के लिए यहां उत्तर देखें: http://stackoverflow.com/questions/12833176/indentation-not-working-on-custom-uitableviewcell – jrturton

6

सेलक्लोरएट इंडेक्सपैथ में बाधाओं को संशोधित करना सबक्लासिंग का एक विकल्प है।

कंटेनर व्यू के अंदर सेल की सभी सामग्री एम्बेड करें। फिर तालिका दृश्य कक्ष के बजाय सेल.contentView पर अग्रणी और पिछली बाधाओं को इंगित करें।

UIView *containerView = [cell viewWithTag:999]; 
    UIView *contentView = [cell contentView]; 

    //remove existing leading and trailing constraints 
    for(NSLayoutConstraint *c in [cell constraints]){ 
    if(c.firstItem==containerView && (c.firstAttribute==NSLayoutAttributeLeading || c.firstAttribute==NSLayoutAttributeTrailing)){ 
     [cell removeConstraint:c]; 
    } 
    } 

    NSLayoutConstraint *trailing = [NSLayoutConstraint 
           constraintWithItem:containerView 
           attribute:NSLayoutAttributeTrailing 
           relatedBy:NSLayoutRelationEqual 
           toItem:contentView 
           attribute:NSLayoutAttributeTrailing 
           multiplier:1 
           constant:0]; 

    NSLayoutConstraint *leading = [NSLayoutConstraint 
           constraintWithItem:containerView 
           attribute:NSLayoutAttributeLeading 
           relatedBy:NSLayoutRelationEqual 
           toItem:contentView 
           attribute:NSLayoutAttributeLeading 
           multiplier:1 
           constant:0]; 

    [cell addConstraint:trailing]; 
    [cell addConstraint:leading]; 
9

यहाँ एक उपवर्ग, अन्य उत्तर विचारों पर आधारित है, मैं पर अपने कस्टम कोशिकाओं के आधार के लिए जा रहा हूँ:

@interface FixedTableViewCell() 

- (void)initFixedTableViewCell; 

@end 

@interface FixedTableViewCell : UITableViewCell 

@end 

@implementation FixedTableViewCell 

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 
    if (nil != (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { 
     [self initFixedTableViewCell]; 
    } 
    return self; 
} 

- (void)awakeFromNib { 
    [super awakeFromNib]; 

    [self initFixedTableViewCell]; 
} 

- (void)initFixedTableViewCell { 
    for (NSInteger i = self.constraints.count - 1; i >= 0; i--) { 
     NSLayoutConstraint *constraint = [self.constraints objectAtIndex:i]; 

     id firstItem = constraint.firstItem; 
     id secondItem = constraint.secondItem; 

     BOOL shouldMoveToContentView = YES; 

     if ([firstItem isDescendantOfView:self.contentView]) { 
      if (NO == [secondItem isDescendantOfView:self.contentView]) { 
       secondItem = self.contentView; 
      } 
     } 
     else if ([secondItem isDescendantOfView:self.contentView]) { 
      if (NO == [firstItem isDescendantOfView:self.contentView]) { 
       firstItem = self.contentView; 
      } 
     } 
     else { 
      shouldMoveToContentView = NO; 
     } 

     if (shouldMoveToContentView) { 
      [self removeConstraint:constraint]; 
      NSLayoutConstraint *contentViewConstraint = [NSLayoutConstraint constraintWithItem:firstItem 
                        attribute:constraint.firstAttribute 
                        relatedBy:constraint.relation 
                         toItem:secondItem 
                        attribute:constraint.secondAttribute 
                        multiplier:constraint.multiplier 
                         constant:constraint.constant]; 
      [self.contentView addConstraint:contentViewConstraint]; 
     } 
    } 
} 

@end 
+0

लागू नहीं कर रहा हूं, मेरी राय में, initFixedTableViewCell को initWithStyle से कॉल करने में कोई उपयोग नहीं है: पुन: उपयोग करें: क्योंकि यह एक इंटरफ़ेस बिल्डर बग है, यह केवल तभी होता है जब आप लोड करते हैं एक निब फ़ाइल से सेल। उम्मीद है कि कोड में, किसी को इंटरफ़ेस बिल्डर की बग को पुन: पेश नहीं करना चाहिए ;-) मुझे यह भी नहीं पता कि बाधाओं की सूची में वंशजों की जांच क्यों करें। – Adrian

+2

यह मेरे लिए अच्छा काम करता है लेकिन आपको बाधा प्राथमिकता को भी संरक्षित करने की आवश्यकता है: "contentViewConstraint.priority = constraint.priority" –

32

जैसा कि बताया जा XCode के इंटरफ़ेस बिल्डर UITableViewCell के contentView छिपा है। हकीकत में, UITableViewCell में जोड़े गए सभी यूआई तत्व वास्तव में सामग्री दृश्य के सबव्यूज़ हैं।

फिलहाल, यह आईबी लेआउट बाधाओं के लिए एक ही जादू नहीं कर रहा है, जिसका अर्थ है कि वे सभी UITableViewCell स्तर पर व्यक्त किए गए हैं।

का संभावित हल एक उपवर्ग के awakeFromNib में है UITableViewCell से यह contentView है करने के लिए सभी NSAutoLayoutConstrains ले जाएँ और contentView के मामले में उन्हें व्यक्त करने के लिए:

-(void)awakeFromNib{ 
    [super awakeFromNib]; 
    for(NSLayoutConstraint *cellConstraint in self.constraints){ 
    [self removeConstraint:cellConstraint]; 
    id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem; 
    id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem; 
    NSLayoutConstraint* contentViewConstraint = 
    [NSLayoutConstraint constraintWithItem:firstItem 
           attribute:cellConstraint.firstAttribute 
           relatedBy:cellConstraint.relation 
            toItem:seccondItem 
           attribute:cellConstraint.secondAttribute 
           multiplier:cellConstraint.multiplier 
            constant:cellConstraint.constant]; 
    [self.contentView addConstraint:contentViewConstraint]; 
    } 
} 
+0

यह मेरे लिए काम करता है! धन्यवाद! – JimmyJammed

+0

यह बहुत अच्छा काम किया! समूहबद्ध तालिका दृश्य का उपयोग कर रहा था और इसे इंटरफ़ेस बिल्डर में सेल के सापेक्ष सबकुछ बनाना था, इसके बजाय यह दृष्टि से कैसे दिखता था, लेकिन यह इसे इंडेंट करने और ठीक से क्लिप करने के लिए काम करता था! – Gujamin

+0

+1 इसे मेरे आधार 'UITableViewCell' में जोड़ा गया है, इसलिए मुझे इसे फिर से सौदा नहीं करना पड़ेगा। – memmons

2

मुझे लगता है कि यह आईओएस 7 बीटा 3 समाधान अनावश्यक बना तय हो गई है उस बिंदु से (लेकिन शायद ज्यादातर मामलों में हानिरहित वे खाली संचालन बन जाएंगे)।

1

स्कूटा द्वारा कोड के आधार पर (मैं एक नौसिखिया हूं, आपने जो कुछ किया है, उसे नहीं जानते हैं, लेकिन उत्कृष्ट काम) मेरा सुझाव है कि आप अपनी सारी चीजें किनारे से किनारे के कंटेनर व्यू में डाल दें और जोड़ें निम्नलिखित:

सेल के हेडर फाइल में, मैं निम्नलिखित IBOutlets है:

@property (weak, nonatomic) IBOutlet UIView *container; 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *leftConstrain; 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *rightConstrain; 

कार्यान्वयन फ़ाइल में, मैं awakeFromNib में निम्नलिखित है:

// Remove the IB added horizontal constraint, as that's effective gainst the cell not the contentView 
[self removeConstraint:self.leftConstrain]; 
[self removeConstraint:self.rightConstrain]; 

// Create a dictionary to represent the view being positioned 
NSDictionary *containerViewDictionary = NSDictionaryOfVariableBindings(_container); 

// Create the new left constraint (0 spacing because of the edge-to-edge view 'container') 
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-0-[_container]" options:0 metrics:nil views:containerViewDictionary]; 
// Add the left constraint against the contentView 
[self.contentView addConstraints:constraints]; 

// Create the new constraint right (will fix the 'Delete' button as well) 
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"[_container]-0-|" options:0 metrics:nil views:containerViewDictionary]; 
// Add the right constraint against the contentView 
[self.contentView addConstraints:constraints]; 

फिर से, ऊपर स्कूटा द्वारा संभव बनाया गया था। धन्यवाद!!! अल क्रेडिट उसके पास जाते हैं।

संबंधित मुद्दे