2012-07-12 9 views
13

मेरे पास कुछ नियंत्रकों और कुछ विचारों के साथ UIViewController है। इनमें से दो विचार (ग्रिड सेल) अन्य निब हैं। मुझे ग्रिड सेल से फाइल के मालिक को आउटलेट मिल गए हैं, लेकिन वे स्वचालित रूप से लोड नहीं होते हैं।अनंत लूप जब initWithCoder ओवरराइडिंग

तो मैं GridCell.m के initWithCoder को ओवरराइड करने का प्रयास करता हूं। यह एक अनंत लूप शुरू करता है।

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

मैं इसे प्राप्त करने के बारे में कैसे जा सकता हूं?

संपादित करें 1

मैं इसे सिकंदर की मदद से काम कर प्राप्त करने की कोशिश कर रहा हूँ। इस प्रकार मैंने इसे स्थापित कर लिया है: मेन व्यू में कस्टम क्लास सेट के साथ ग्रिडसेल के रूप में UIView है। इसे मेनव्यू/फाइल के मालिक में आउटलेट मिला।

Pic 1

GridCell.m से सभी init-कोड निकाला गया और अपने कस्टम वर्ग

Pic 2

Pic 3

MainView अभी भी GridCell प्रदर्शित नहीं करते के लिए एक दुकान की स्थापना हालांकि। कोई त्रुटि नहीं है, केवल एक अकेला, खाली जगह जहां लाल स्विच होना चाहिए। मैं क्या गलत कर रहा हूं?

मैं इस प्रोग्रामेटिक तरीके से करने के बहुत करीब हूं। मुझे सीखना अच्छा लगेगा कि यह कैसे निब्स के साथ है।

+0

'[NSBundle loadNibNamed]' 'BOOL 'देता है! – trojanfoe

+2

आपके उत्तर के लिए धन्यवाद। एनएसबंडल loadNibNamed एक सरणी लौटाता है जिसे मुझे पहली वस्तु मिलती है: [ऐप्पल डेवलपर] (https://developer.apple.com/library/ios/#documentation/UIKit/Reference/NSBundle_UIKitAdditions/Introduction/Introduction.html) –

+1

आह अच्छा बिंदु - मैं ओएस एक्स संदर्भ देख रहा था :) – trojanfoe

उत्तर

42

उम्मीद निब लोड हो रहा है का कारण बनता है initWithCoder फिर से के नाम से जाना काम करना चाहिए, ताकि आप केवल ऐसा करना चाहते हैं, तो उपवर्ग वर्तमान में किसी भी subviews जरूरत नहीं है।

-(id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 
    if (self) { 
     if (self.subviews.count == 0) { 
      UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil]; 
      UIView *subview = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0]; 
      subview.frame = self.bounds; 
      [self addSubview:subview]; 
     } 
    } 
    return self; 
} 
+1

यह विधि एआरसी के साथ संगत है - और यह भी एकमात्र उत्तर है जो subview.frame = self.bounds को सेट करने के लिए याद करता है। –

+0

धन्यवाद, यह मेरे लिए काम किया। –

+0

यह शानदार – Eugene

1

loadNibNamed :: initWithCoder कॉल करेगा:

आप इस पैटर्न क्यों पालन नहीं करते हैं?

-(id)initWithCoder:(NSCoder *)coder 
{ 

    if (self = [super initWithcoder:coder]) { 

     // do stuff here ... 

    } 

    return self;     
} 

[super initWithcoder:coder] चीजें हैं जो आप से बचने के लिए चाहते हैं करता है?

11

एक निब लोड हो रहा है कारण होगा एक

-(id) initWithCoder:(NSCoder *) coder; 

कॉल

इसलिए अपने इस पद्धति में coude में इसी मालिक:

self = [[[NSBundle mainBundle] loadNibNamed: @"GridCell" 
owner: self 
options: nil] objectAtIndex:0]; 

फिर initWithCoder विधि का एक कॉल का कारण होगा। ऐसा इसलिए है क्योंकि आप फिर से निब लोड करने का प्रयास करते हैं। यदि आप एक कस्टम UIView को परिभाषित करते हैं और इसके सबव्यूज़ को रखने के लिए एक निब फ़ाइल बनाते हैं तो आप केवल एक अन्य nib फ़ाइल में UIView नहीं जोड़ सकते हैं, आईबी में कक्षा का नाम अपनी कस्टम क्लास में बदल सकते हैं और उम्मीद कर सकते हैं कि निब लोडिंग सिस्टम इसे समझने के लिए। आप क्या कर सकते हैं निम्न है:

आपकी कस्टम व्यू की निब फ़ाइल को 'कस्टम का क्लास' क्लास आपके कस्टम व्यू क्लास पर सेट करने की आवश्यकता है और आपको 'toplevelSubView' नामक अपनी कस्टम क्लास में आउटलेट होना चाहिए आपके कस्टम व्यू nib फ़ाइल में एक दृश्य जो सभी सबव्यूज़ के लिए कंटेनर के रूप में कार्य कर रहा है।अपनी व्यू क्लास में अतिरिक्त आउटलेट जोड़ें और उप-दृश्यों को 'फ़ाइल के मालिक' (अपने कस्टम UIView) से कनेक्ट करें। निब फ़ाइल जहां उसे अपने साथ निब फ़ाइल यह नये नोट्स है कस्टम दृश्य शामिल करना चाहते हैं

जाओ: (https://stackoverflow.com/a/7589220/925622 देखें)

संपादित ठीक है, आपकी संपादित सवाल का जवाब देने मैं निम्नलिखित करना होगा। कस्टम दृश्य (GridCell) ही यह मत करो, बजाय एक दृश्य जो आपके ग्रिड सेल में शामिल होंगे बनाने (उदाहरण के लिए gridCellContainer है, लेकिन यह एक UIView होना चाहिए) अपने कस्टम दृश्य के भीतर अनुकूलित initWithFrame विधि की तरह आप initWithCoder में किया था :

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"GridCell" owner:self options:nil];  
     self = [nib objectAtIndex:0]; 
     self.frame = frame; 
    } 
    return self; 
} 

और फिर, ViewController जो दृश्य है जहाँ आप अपने कस्टम दृश्य (gridCellContainer दृश्य के साथ एक) शामिल करना चाहते हैं के लिए fileOwner है में viewDidLoad जैसे में ऐसा

//... 
GridCell *gridCell = [[GridCell alloc] initWithFrame:self.viewGridCellContainer.bounds]; 
[self.viewGridCellContainer addSubview:gridCell]; 

अब eveything के रूप में आप

+0

आपके उत्तर के लिए धन्यवाद। आपके लिंक में, रॉबिन initWithCoder में मेरे रूप में एक निब लोड कर रहा है; लेकिन यह अनंत लूप का कारण बनता है - यह मेरे लिए एक समस्या है लेकिन उसके लिए एक समाधान है? मैं अपने समाधान के साथ अपना प्रश्न अपडेट कर रहा हूं क्योंकि मुझे अभी भी कुछ परेशानी है। मैं तस्वीरें और सामान जोड़ सकता हूं .. –

+0

मेरा प्रश्न अपडेट किया गया। यदि आपके पास एक मिनट है, तो कृपया एक नज़र डालें। –

+0

मेरे संपादन देखें ... – Alexander

0

मैं एक ही मुद्दा है जब मैं initWithsomething विधि ओवरराइड करने के लिए कोशिश कर रहा हूँ था, हम

-(id)initWithsomething:(Something *)something 
{ 
    if (self = [super initWithsomething:something]) { 
     // do stuff here ... 
    } 

    return self; 
} 

जरूरत के बजाय

-(id)initWithsomething:(Something *)something 
{ 
    if (self = [super init]) { 
     // do stuff here ... 
    } 

    return self; 
} 
+0

यह वास्तव में एक प्रश्न नहीं है, लेकिन आप बहुत दूर हैं, इसलिए मैं आपकी मदद करना चाहता था। सुपर उस वर्ग को संदर्भित करता है जिसे आप विस्तारित कर रहे हैं: जब हेडर फ़ाइल MyCustomLabel के साथ शुरू होती है: UILabel, सुपर UILabel है। यही कारण है कि, जब आप अपनी खुद की वस्तु शुरू करते हैं, तो आपको सुपर को [सुपर इनिट] के साथ शुरू करने की भी आवश्यकता होती है। आपको कभी भी MyCustomLabel में initWithsomething का उपयोग नहीं करना चाहिए और सुपर के init के साथ कुछ भी कहना चाहिए, क्योंकि आप सुपर के तरीके को अपने आप से ओवरराइड कर रहे हैं, क्योंकि यह वही नाम है। यही है, आपकी विधि को initWithCoder और न ही initWithFrame कहा जाना चाहिए। कुछ नया के साथ आओ –

2

फ़ाइल के मालिक के लिए एक कॉल नहीं मिलेगा

-(id) initWithCoder:(NSCoder *) coder; 
एक xib लोड करते समय

हालांकि, हर राय यह है कि xib में परिभाषित किया गया है जब एक xib लोड हो रहा है

-(id) initWithCoder:(NSCoder *) coder; 

के लिए एक कॉल मिल जाएगा।

यदि आपके पास एक xib में परिभाषित एक UIView (यानी ग्रिडसेल) का उप-वर्ग है और आपके उपclass के initWithCoder में उसी xib को लोड करने का प्रयास भी करता है, तो आप एक अनंत लूप के साथ समाप्त हो जाएंगे। हालांकि, मैं नहीं देख सकता कि उपयोग का मामला क्या होगा।

आमतौर पर आप अपने यूआईवीव के सबक्लास (यानी ग्रिडसेल) को एक xib में डिज़ाइन करते हैं, फिर उदाहरण के लिए दृश्य नियंत्रक के xib में उस सबक्लास का उपयोग करें।

इसके अलावा, एक का उपयोग मामला नहीं देख सकते हैं, जहां आपके कस्टम दृश्य जब तक आप कुछ अन्य xib में मांग पर अपने दृश्य पदानुक्रम ओवरराइड करने के लिए सक्षम होना चाहते हैं एक subview यह initWithCoder

-(id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 
    if (self) { 
     if (self.subviews.count == 0) { 
      UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil]; 
      UIView *subview = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0]; 
      subview.frame = self.bounds; 
      [self addSubview:subview]; 
     } 
    } 
    return self; 
} 

है में, यानी होगा । कौन सा आईएमओ बाहरी निर्भरता मानता है (यानी एक अन्य xib में परिभाषित पदानुक्रम) और थोड़े पहले स्थान पर पुन: प्रयोज्य UIView रखने के उद्देश्य को हरा देता है।

ध्यान रखें कि एक xib लोड करते समय, फ़ाइल के स्वामी के रूप में एक उदाहरण पास करते समय, उसके सभी आईबीओलेट सेट होंगे। उस स्थिति में, आप स्वयं को (i.e. ग्रिडसेल) की जगह ले लेंगे, जो कि GridCell.xib में जो भी रूट व्यू है, प्रक्रिया में सभी आईबीओटलेट कनेक्शन खो रहा है।

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"GridCell" owner:self options:nil];  
     self = [nib objectAtIndex:0]; 
     self.frame = frame; 
    } 
    return self; 
} 

वहाँ "How to implement a reusable UIView." पर एक अधिक विस्तृत पोस्ट कि रूप में अच्छी तरह थोड़ा और अधिक विस्तार में चला जाता है और उम्मीद है कि चीजों को साफ करता है।