簡體   English   中英

如何在 Swift 中編寫 UIViewController 的 init 方法

[英]How to write init methods of a UIViewController in Swift

我無法將 init 方法添加到以下 UIViewController 類。 我需要在 init 方法中編寫一些代碼。 我必須編寫 init(coder) 方法嗎? 即使我添加了編碼器和解碼器方法,我仍然會出錯。 我也嘗試使用不帶任何參數的 init 方法,但這似乎也不起作用。

class ViewController: UIViewController {

    var tap: UITapGestureRecognizer?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)   {
        super.init(nibName: nil, bundle: nil)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }

...
...
}

如果我不帶參數調用 super.init() 方法,則錯誤是“必須調用超類的指定初始化程序”,如果我傳遞參數 nib 和 bundle,則錯誤是“必需的初始化程序 init(coder)”。

即使我添加 init(coder) 和 init(decoder) 它也不起作用。

我用了:

convenience init() {
    self.init(nibName:nil, bundle:nil)
}

有人建議:

convenience init(){
    self.init()
}

但這給了你一個無限循環。

所有這些答案都是一半的答案。 有些人在相關帖子中遇到了無限循環,因為他們只是添加了convenience init() (如果您不提供獨特的init()方法來調用它,它會遞歸調用自己),而其他人則忽略了擴展超類。 這種格式結合了所有的解決方案來完全滿足問題。

// This allows you to initialise your custom UIViewController without a nib or bundle.
convenience init() {
    self.init(nibName:nil, bundle:nil)
}

// This extends the superclass.
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
}

// This is also necessary when extending the superclass.
required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented") // or see Roman Sausarnes's answer
}

編輯:另外,如果你想初始化使用傳遞給你的任何參數類的屬性convenience init()方法,無需全部重寫init()方法的抱怨,那么你可以設置所有這些屬性為隱含展開自選,這是一種模式通過使用蘋果自己

您需要覆蓋init(nibName:bundle:)初始化程序,提供init(coder:)所需的初始化程序,並在兩者中初始化tap

class ViewController: UIViewController {

    var tap: UITapGestureRecognizer?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)   {
        print("init nibName style")
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }

    // note slightly new syntax for 2017
    required init?(coder aDecoder: NSCoder) {
        print("init coder style")
        super.init(coder: aDecoder)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }
...
...
}

另外,請確保在調用超類初始值設定項時不要只為nibNamebundle傳遞nil 你應該放棄傳遞的任何東西。


請注意,某些答案中提到的“convenience init”方法僅在您實際“手動”初始化視圖控制器時才相關。 (很少有您會這樣做的情況。)如果您想“在正常初始化期間做某事” -例如創建手勢識別器或僅初始化一些變量-唯一可能的解決方案正是此答案中給出的解決方案.

您可以只創建一個便利初始值設定項,便利初始值設定項不會覆蓋 init() 而只是調用它使事情變得更容易。

class ViewController: UIViewController {
    var tap: UITapGestureRecognizer?
    convenience init(){
        self.init()
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }
}

我想你必須添加

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

或者

convenience init() {
    self.init()
}

你也必須寫init。 不要刪除它

var tap: UITapGestureRecognizer?

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)   {
    super.init(nibName: nil, bundle: nil)
}

希望能幫助到你

我遇到了這個你問很久的問題。 但沒有人對這個問題給出基本的答案。 這是 Swift 中的一個基本原則:- 子類必須在其超類初始化完成之前初始化其變量。

因此,正如Ankit Goel提到的崩潰:-“必須調用超類的指定初始值設定項”

因此更新的代碼將是:-

class ViewController: UIViewController {
    var tap: UITapGestureRecognizer?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)   {
        print("init nibName style")
        self.tap = nil
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.tap = UITapGestureRecognizer(target: self, action: Selector(("handleTap:")))
    }

    required init?(coder aDecoder: NSCoder) {
        print("init coder style")
        self.tap = nil
        super.init(coder: aDecoder)
        tap = UITapGestureRecognizer(target: self, action: Selector(("handleTap:")))
    }
}

我在 Xcode 12.0 中使用 Swift 5 時遇到了同樣的問題,這是我在 2020 年的解決方案。

class Foo: UIViewController {
    private var bar: Bar!

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

        setupController()
    }

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

        setupController()
    }
    
    private func setupController() {
        bar = Bar()
    }
}

我使用的另一種方法是在loadView函數中進行初始化。

class Foo: UIViewController {
    private var bar: Bar!
    
    override func loadView() {
        setupController()
    }

    private func setupController() {
        bar = Bar()
    }
}

正確的流程是,調用指定的初始化程序,在這種情況下是帶有 nibName 的初始化程序,

init(tap: UITapGestureRecognizer)
{
    // Initialise the variables
    tap = UITapGestureRecognizer(target: self, action: Selector(("handleTap:")))

    // Call the designated init of ViewController
    super.init(nibName: nil, bundle: nil)

    // Call your viewcontroller custom methods here
    setupViewControllers()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM