मैं स्विफ्ट में एक UIView उपवर्ग के लिए एक कस्टम init कैसे लिखूं?


125

कहते हैं कि मैं चाहता हूँ initएक UIViewएक साथ उपवर्ग Stringऔर एक Int

मैं स्विफ्ट में यह कैसे करूंगा अगर मैं सिर्फ उपवर्ग कर रहा हूं UIView? अगर मैं सिर्फ एक कस्टम init()फंक्शन बनाता हूं, लेकिन पैरामीटर एक स्ट्रिंग और एक इंट हैं, तो यह मुझे बताता है कि "सुपरइनिट () इनिशियलाइज़र से लौटने से पहले नहीं कहा जाता है"।

और अगर मुझे super.init()लगता है कि मुझे बताया गया है तो मुझे एक निर्दिष्ट इनिशियलाइज़र का उपयोग करना चाहिए। मुझे वहां क्या उपयोग करना चाहिए? फ्रेम संस्करण? कोडर संस्करण? दोनों? क्यों?

जवाबों:


207

init(frame:)वर्शन में डिफ़ॉल्ट प्रारंभकर्ता है। अपने इंस्टेंस वेरिएबल्स को इनिशियलाइज़ करने के बाद ही आपको इसे कॉल करना होगा। यदि यह दृश्य एक Nib से पुनर्गठित किया जा रहा है, तो आपके कस्टम इनिशलाइज़र को नहीं बुलाया जाएगा, और इसके बजाय init?(coder:)संस्करण को बुलाया जाएगा। चूंकि स्विफ्ट को अब आवश्यक कार्यान्वयन की आवश्यकता है init?(coder:), मैंने नीचे दिए गए उदाहरण को अपडेट किया है और letपरिवर्तनशील घोषणाओं को बदल दिया है varऔर वैकल्पिक है। इस स्थिति में, आप उन्हें awakeFromNib()बाद में या कुछ समय के लिए प्रारंभ कर देंगे ।

class TestView : UIView {
    var s: String?
    var i: Int?
    init(s: String, i: Int) {
        self.s = s
        self.i = i
        super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

5
फिर हर तरह से उन्हें बनाते हैं var। लेकिन स्विफ्ट में डिफ़ॉल्ट सबसे अच्छा अभ्यास चर घोषित करना है letजब तक कि उन्हें घोषित करने का कोई कारण नहीं है var। ऊपर मेरे कोड उदाहरण में ऐसा करने का कोई कारण नहीं था, इसलिए let
वुल्फ मैकनली

2
यह कोड संकलित नहीं करता है। आपको आवश्यक इनिशियलाइज़र को लागू करने की आवश्यकता है init(coder:)
दशक चंद्रमा

3
दिलचस्प यह कैसे संकलित साल पहले। आजकल यह init (कोडर :) के तहत शिकायत करता है कि "प्रॉपर्टी self.s initialized at super.init call"
mafiOSo

स्विफ्ट 3.1 के लिए निश्चित उदाहरण। UIKit आयात करने वाले एक खेल के मैदान के तहत संकलन।
वुल्फ मैकनली

1
@ लाइट नाइट मैंने चीजों को सरल रखने के लिए वैकल्पिक sऔर iवैकल्पिक बनाया । यदि वे वैकल्पिक नहीं थे, तो उन्हें आवश्यक इनिशियलाइज़र में आरंभीकृत करने की आवश्यकता होगी। उन्हें वैकल्पिक बनाने का मतलब है कि nilजब उन्हें super.init()बुलाया जाता है तो वे हो सकते हैं । यदि वे वैकल्पिक नहीं थे, तो उन्हें सुपरइनिट () कहने से पहले वास्तव में असाइन करने की आवश्यकता होगी।
वुल्फ मैकनेली

32

मैं नामित और आवश्यक के लिए एक सामान्य init बनाता हूं। सुविधा के लिए, मैं init(frame:)शून्य के फ्रेम के साथ प्रतिनिधि हूं ।

शून्य फ्रेम होने में कोई समस्या नहीं है क्योंकि आम तौर पर दृश्य ViewController के दृश्य के अंदर होता है; जब आपके पर्यवेक्षी कॉल करते हैं तो आपके कस्टम दृश्य को इसके सब-वेवेज़ को लेआउट करने का एक अच्छा, सुरक्षित मौका मिलेगाlayoutSubviews() याupdateConstraints() । इन दोनों कार्यों को सिस्टम द्वारा पुनरावर्ती रूप से पूरे पदानुक्रम में कहा जाता है। आप updateContstraints()या तो उपयोग कर सकते हैं या layoutSubviews()updateContstraints()पहले कहा जाता है, फिर layoutSubviews()। में updateConstraints()मेकअप यकीन है कि सुपर कॉल करने के लिए पिछले । में layoutSubviews(), पहले सुपर बुलाओ ।

यहाँ मैं क्या कर रहा हूँ:

@IBDesignable
class MyView: UIView {

      convenience init(args: Whatever) {
          self.init(frame: CGRect.zero)
          //assign custom vars
      }

      override init(frame: CGRect) {
           super.init(frame: frame)
           commonInit()
      }

      required init?(coder aDecoder: NSCoder) {
           super.init(coder: aDecoder)
           commonInit()
      }

      override func prepareForInterfaceBuilder() {
           super.prepareForInterfaceBuilder()
           commonInit()
      }

      private func commonInit() {
           //custom initialization
      }

      override func updateConstraints() {
           //set subview constraints here
           super.updateConstraints()
      }

      override func layoutSubviews() {
           super.layoutSubviews()
           //manually set subview frames here
      }

}

1
यह काम नहीं करना चाहिए: विधि कॉल 'commonInit' से पहले super.init initializes में 'स्वयं' का प्रयोग स्वयं
Surfrider

1
Self.init कॉल के बाद कस्टम तर्क आरंभ करें। मेरे उत्तर को अपडेट किया।
MH175

1
लेकिन क्या होगा यदि आप commonInitविधि में कुछ गुणों को इनिशियलाइज़ करना चाहते हैं , लेकिन आप इसे superइस मामले में जगह नहीं दे सकते क्योंकि आपको बीईएफ superकॉल के सभी गुणों को इनिशियलाइज़ करना चाहिए । लोल यह मृत लूप की तरह लगता है।
सूर्यास्त

1
यह कैसे स्विफ्ट इनिशियलाइज़ेशन अक्सर काम करता है: "दो-चरण इनिशियलाइज़ेशन" की खोज करें। आप अंतर्निहित अलिखित वैकल्पिक का उपयोग कर सकते हैं, लेकिन मैं इसके खिलाफ सलाह देता हूं। आपकी वास्तुकला, विशेष रूप से विचारों से निपटने के दौरान, सभी स्थानीय गुणों को शुरू करना चाहिए। मैंने अब सैकड़ों विचारों के लिए इस सामान्य () विधि का उपयोग किया है। यह काम करता हैं
MH175

17

यहाँ है कि मैं इसे स्विफ्ट में iOS 9 पर कैसे करूं -

import UIKit

class CustomView : UIView {

    init() {
        super.init(frame: UIScreen.mainScreen().bounds);

        //for debug validation
        self.backgroundColor = UIColor.blueColor();
        print("My Custom Init");

        return;
    }

    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented"); }
}

यहाँ उदाहरण के साथ एक पूर्ण परियोजना है:


2
यह दृश्य के लिए पूरे प्रदर्शन का उपयोग करेगा
RaptoX

1
हां! यदि आंशिक उप-भाग में रुचि है, तो मुझे बताएं और मैं इसे पोस्ट करूंगा
J-Dizzle

1
मुझे यह उत्तर सबसे अच्छा लगता है, क्योंकि घातक होने का मतलब है कि मुझे आवश्यक इनिट में कोई कोड नहीं डालना है।
कार्टर मेडलिन

1
@ J-Dizzle, मैं आंशिक विचारों के लिए समाधान देखना चाहता हूं।
अरी लैकेन्स्की

क्या आपका उत्तर स्वीकृत उत्तर के विपरीत नहीं है? मेरा मतलब है कि आप इसके बाद कस्टमाइज़ेशन कर रहे हैं super.init, लेकिन उन्होंने कहा कि यह पहले किया जाना चाहिए super.init...
हनी

11

यहां बताया गया है कि मैं स्विफ्ट में iOS पर सबव्यू कैसे करता हूं -

class CustomSubview : UIView {

    init() {
        super.init(frame: UIScreen.mainScreen().bounds);

        let windowHeight : CGFloat = 150;
        let windowWidth  : CGFloat = 360;

        self.backgroundColor = UIColor.whiteColor();
        self.frame = CGRectMake(0, 0, windowWidth, windowHeight);
        self.center = CGPoint(x: UIScreen.mainScreen().bounds.width/2, y: 375);

        //for debug validation
        self.backgroundColor = UIColor.grayColor();
        print("My Custom Init");

        return;
    }

    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented"); }
}

4
FatalError () कॉल का अच्छा उपयोग। मुझे एक इनिशियलाइज़र से मौन चेतावनियों के लिए अल्टरनेटिव्स का उपयोग करना पड़ रहा था, जिसका उपयोग भी नहीं किया जा रहा था। इसने इसे ठीक कर दिया! धन्यवाद।
माइक क्रिक्ले
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.