मैं स्विफ्ट में एक UIViewController उपवर्ग के लिए एक कस्टम इनिशियलाइज़र कैसे बनाऊं?


95

माफी अगर यह पहले पूछा गया है, मैंने बहुत खोज की है और कई जवाब पहले के स्विफ्ट बेटों से हैं जब चीजें अलग थीं। मुझे निश्चित उत्तर नहीं मिल रहा है।

मैं उप-वर्ग करना चाहता हूं UIViewControllerऔर एक कस्टम इनिशियलाइज़र है जो मुझे इसे आसानी से कोड में सेट करने की अनुमति देता है। मुझे स्विफ्ट में ऐसा करने में परेशानी हो रही है।

मुझे एक init()फंक्शन चाहिए जिसे मैं एक विशिष्ट पास करने के लिए उपयोग कर सकता NSURLहूं, फिर मैं व्यू कंट्रोलर के साथ उपयोग करूंगा। मेरे दिमाग में यह कुछ-कुछ दिखता है init(withImageURL: NSURL)। अगर मैं उस फ़ंक्शन को जोड़ता हूं तो मुझे init(coder: NSCoder)फ़ंक्शन जोड़ने के लिए कहता है ।

मेरा मानना ​​है कि यह इसलिए है क्योंकि यह requiredकीवर्ड के साथ सुपरक्लास में चिह्नित है ? तो मुझे इसे उपवर्ग में करना होगा? मैं इसे जोड़ता हूं:

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

अब क्या? क्या मेरे विशेष इनिशियलाइज़र को एक माना जाता है convenience? एक नामित? क्या मैं सुपर इनिशियलाइज़र कहलाता हूँ? एक ही कक्षा से एक इनिलाइज़र?

मैं एक UIViewControllerउपवर्ग पर अपने विशेष इनिशलाइज़र को कैसे जोड़ूँ ?


शुरुआती प्रोग्रामर क्रिएट किए गए व्यूअंट्रोलर्स के लिए अच्छे हैं, लेकिन स्टोरीबोर्ड के माध्यम से बनाए गए व्यू-कंट्रोल्स के लिए आप किस्मत से बाहर हैं और इसके चारों ओर अपना काम करना है
Honey

जवाबों:


161
class ViewController: UIViewController {

    var imageURL: NSURL?

    // this is a convenient way to create this view controller without a imageURL
    convenience init() {
        self.init(imageURL: nil)
    }

    init(imageURL: NSURL?) {
        self.imageURL = imageURL
        super.init(nibName: nil, bundle: nil)
    }

    // if this view controller is loaded from a storyboard, imageURL will be nil

    /* Xcode 6
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    */

    // Xcode 7 & 8
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

इसके बजाय imageURL एक स्थिर हो सकता है? ("आईएएसयूआरयूआरएल: एनएसयूआरएल?)
वान डू ट्रान

2
काम नहीं कर रहा है xCode 7, आवश्यक निर्माणकर्ता वर्ग स्तर की संपत्ति को शुरू करने में विफल हो रहा है, मेरे मामले में एक इंट, एनएसयूआरएल नहीं?
क्रिस हैस

1
@NikolaLukic - हम फोन करके वर्ग का एक नया उदाहरण बनाता है सकते हैं ViewController(), ViewController(imageURL: url)या यह एक स्टोरीबोर्ड से लोड हो रहा है।
ylin0x81

3
मुझे मेरा लिखना था, required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }अन्यथा super.init(coder: aDecoder)मुझे संपत्तिself.somePropertysuper.init
हनी

1
यकीन नहीं है कि यह कैसे संबंधित है। यदि आप शुद्ध कोड कर रहे हैं, तो आपको अपने गुणों को अंदर रखने की आवश्यकता नहीं है init(coder: aDecoder)fatalErrorइच्छा पर्याप्त
हनी

26

उन लोगों के लिए जो कोड में UI लिखते हैं

class Your_ViewController : UIViewController {

    let your_property : String

    init(your_property: String) {
        self.your_property = your_property
        super.init(nibName: nil, bundle: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) is not supported")
    }
}

12

यह अन्य उत्तरों के समान है, लेकिन कुछ स्पष्टीकरण के साथ। स्वीकृत उत्तर भ्रामक है क्योंकि इसकी संपत्ति वैकल्पिक है और इस तथ्य को उजागर नहीं करता है कि आपका init?(coder: NSCoder)एमयूएस प्रत्येक संपत्ति को इनिशियलाइज़ करता है और इसका एकमात्र समाधान है fatalError()। अंततः आप अपने गुणों को वैकल्पिक बनाकर दूर हो सकते हैं, लेकिन यह वास्तव में ओपी के सवाल का जवाब नहीं देता है।

// Think more of a OnlyNibOrProgrammatic_NOTStoryboardViewController
class ViewController: UIViewController {

    let name: String

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // I don't have a nib. It's all through my code.
    init(name: String) {
        self.name = name

        super.init(nibName: nil, bundle: nil)
    }

    // I have a nib. I'd like to use my nib and also initialze the `name` property
    init(name: String, nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle? ) {
        self.name = name
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    // when you do storyboard.instantiateViewController(withIdentifier: "ViewController")
    // The SYSTEM will never call this!
    // it wants to call the required initializer!

    init?(name: String, coder aDecoder: NSCoder) {
        self.name = "name"
        super.init(coder: aDecoder)
    }

    // when you do storyboard.instantiateViewController(withIdentifier: "ViewController")
    // The SYSTEM WILL call this!
    // because this is its required initializer!
    // but what are you going to do for your `name` property?!
    // are you just going to do `self.name = "default Name" just to make it compile?!
    // Since you can't do anything then it's just best to leave it as `fatalError()`
    required init?(coder aDecoder: NSCoder) {
        fatalError("I WILL NEVER instantiate through storyboard! It's impossible to initialize super.init?(coder aDecoder: NSCoder) with any other parameter")
    }
}

आपको मूल रूप से स्टोरीबोर्ड से इसे लोड करना है। क्यों?

क्योंकि जब आप viewController कहते हैं storyboard.instantiateViewController(withIdentifier: "viewController")तो UIKit अपनी बात और कॉल करेगा

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

आप कभी भी पुनर्निर्देशित नहीं कर सकते हैं कि किसी अन्य init विधि को कॉल करें

इस पर डॉक्स instantiateViewController(withIdentifier:):

प्रोग्रामेटिक रूप से प्रस्तुत करने के लिए व्यू कंट्रोलर ऑब्जेक्ट बनाने के लिए इस विधि का उपयोग करें। हर बार जब आप इस विधि को कहते हैं, तो यह विधि का उपयोग करके दृश्य नियंत्रक का एक नया उदाहरण बनाता है init(coder:)

अभी तक प्रोग्रामेटिक रूप से बनाए गए व्यूकंट्रोलर या नीब के लिए व्यूक्रंट्रोलर्स बनाए गए हैं जिन्हें आप ऊपर बताए अनुसार कॉल रिडायरेक्ट कर सकते हैं।


5

सुविधा इनिशियलाइज़र माध्यमिक हैं, एक वर्ग के लिए इनिशियलाइज़र का समर्थन करते हैं। आप एक सुविधा इनिशियलाइज़र को एक ही वर्ग से निर्दिष्ट इनिशियलाइज़र को कॉल करने के लिए परिभाषित कर सकते हैं क्योंकि सुविधा इनिशियलाइज़र कुछ निर्धारित इनिशियलाइज़र के मापदंडों के साथ डिफ़ॉल्ट मान पर सेट है। आप विशिष्ट उपयोग के मामले या इनपुट मूल्य प्रकार के लिए उस वर्ग का उदाहरण बनाने के लिए एक सुविधा इनिशियलाइज़र को भी परिभाषित कर सकते हैं।

वे यहाँ प्रलेखित हैं


0

यदि आपको उदाहरण के लिए पॉपओवर के लिए एक कस्टम init की आवश्यकता है, तो आप निम्नलिखित दृष्टिकोण का उपयोग कर सकते हैं:

एक कस्टम init बनाएँ जो nibName और बंडल के साथ सुपर init का उपयोग करता है और उसके बाद दृश्य पदानुक्रम के भार को बाध्य करने के लिए दृश्य गुण तक पहुँचें।

फिर viewDidLoad फ़ंक्शन में आप आरंभ में दिए गए मापदंडों के साथ विचारों को कॉन्फ़िगर कर सकते हैं।

import UIKit

struct Player {
    let name: String
    let age: Int
}

class VC: UIViewController {


@IBOutlet weak var playerName: UILabel!

let player: Player

init(player: Player) {
    self.player = player
    super.init(nibName: "VC", bundle: Bundle.main)
    if let view = view, view.isHidden {}
}

override func viewDidLoad() {
    super.viewDidLoad()
    configure()
}

func configure() {
    playerName.text = player.name + "\(player.age)"
}
}

func showPlayerVC() {
    let foo = Player(name: "bar", age: 666)
    let vc = VC(player: foo)
    present(vc, animated: true, completion: nil)
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.