У класу "ViewController" немає швидких ініціалізаторів


123

Отримання скарги від компілятора, коли я це роблю

class ViewController: UIViewController {

    var delegate : AppDelegate
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        //self.appDelegate = UIApplication.sharedApplication().delegate;

    }

    @IBAction func getData(sender : AnyObject) {

    }

    @IBAction func LogOut(sender : AnyObject) {
    }
}

Однак якщо я просто додам ? наприкінці AppDelegate, як показано нижче, і помилка відсутня .

class ViewController: UIViewController {

    var delegate : AppDelegate?
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        //self.appDelegate = UIApplication.sharedApplication().delegate;

    }

    @IBAction func getData(sender : AnyObject) {

    }

    @IBAction func LogOut(sender : AnyObject) {
    }
}

Я не бачу optionalключового слова, яке стосується цієї помилки, якщо я не помиляюся.

Відповіді:


239

Помилку можна вдосконалити, але проблема з вашою першою версією полягає в тому, що у вас є змінна члена, delegate , яка не має значення за замовчуванням. Усі змінні у Swift завжди повинні мати значення. Це означає, що ви повинні встановити його в ініціалізаторі, якого у вас немає, або ви можете надати йому значення за замовчуванням в рядку.

Коли ви робите це необов’язковим, ви дозволяєте йому бути nilза замовчуванням, усуваючи необхідність явно надати йому значення або ініціалізувати його.


45

Швидка мова програмування стверджує:

Класи та структури повинні встановлювати всі їх збережені властивості до відповідного початкового значення до моменту створення екземпляра цього класу чи структури. Збережені властивості не можна залишити у невизначеному стані.

Ви можете встановити початкове значення для збереженої властивості в ініціалізаторі або призначити значення властивості за замовчуванням як частину визначення властивості.

Тому ви можете написати:

class myClass {

    var delegate: AppDelegate //non-optional variable

    init() {
        delegate = UIApplication.sharedApplication().delegate as AppDelegate
    }

}

Або:

class myClass {

    var delegate = UIApplication.sharedApplication().delegate as AppDelegate //non-optional variable

    init() {
        println("Hello")
    }

}

Або:

class myClass {

    var delegate : AppDelegate! //implicitly unwrapped optional variable set to nil when class is initialized

    init() {
        println("Hello")
    }

    func myMethod() {
        delegate = UIApplication.sharedApplication().delegate as AppDelegate
    }

}

Але ви не можете написати наступне:

class myClass {

    var delegate : AppDelegate //non-optional variable

    init() {
        println("Hello")
    }

    func myMethod() {
        //too late to assign delegate as an non-optional variable
        delegate = UIApplication.sharedApplication().delegate as AppDelegate
    }

}

22

Іноді ця помилка також з’являється, коли у вас є var або let, який не був ініціалізований.

Наприклад

class ViewController: UIViewController {
    var x: Double
    // or
    var y: String
    // or
    let z: Int
}

Залежно від того, що має робити ваша змінна, ви можете встановити тип var як необов'язковий або ініціалізувати його зі значенням, як наведено нижче

class ViewController: UIViewCOntroller {
    // Set an initial value for the variable
    var x: Double = 0
    // or an optional String
    var y: String?
    // or
    let z: Int = 2
}

так яке рішення для цього?
Martian2049

чи можна замість них запросити функцію init?
Martian2049

13

Ця проблема зазвичай з’являється, коли одна зі змінних не має значення або коли ви забудете додати "!" змусити цю змінну зберігати нуль, поки вона не буде встановлена.

У вашому випадку проблема тут:

var delegate: AppDelegate

Його слід визначити таким чином, var delegate: AppDelegate!щоб зробити його необов'язковим, що зберігає нуль і не розкручує змінну, поки не буде використане значення.

Сумно, що Xcode виділяє весь клас як помилку, замість того, щоб виділяти конкретний рядок коду, який його спричинив, тому потрібно розглянути час.


Це дозволяє позбутися повідомлення про помилку для мене у випадку IBOutlet, але не у випадку стандартних змінних.
Тім Вермеулен

Це вирішує мою проблему. Коли я намагався зробити це: var fetchedResultsController: NSFetchedResultsController, у мене з’явилася помилка компіляції. Додавши "!" помилка зникла, як-от так вар добудованіResultsController: NSFetchedResultsController!
Jervisbay

дякую за ур ан! Це корисно для мене, я просто знав "?" до необов'язкового значення, але "!" Я раніше не знав. Я встановив "!" так: var time: NSTimer!
AmyNguyen

10

якщо ви втратили "!" у вашому коді, як і цей код нижче, ви також отримаєте цю помилку.

import UIKit

class MemeDetailViewController : UIViewController {

    @IBOutlet weak var memeImage: UIImageView!

    var meme:Meme! // lost"!"

    override func viewWillAppear(animated: Bool) {

        super.viewWillAppear(animated)
        self.memeImage!.image = meme.memedImage
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)
    }

}

3

Замініть var appDelegate : AppDelegate?на, let appDelegate = UIApplication.sharedApplication().delegateяк натякано на другий коментований рядок уviewDidLoad() .

Ключове слово "необов'язково" відноситься саме до використання ?, див. Це детальніше.


1

Я використовую Xcode 7 і Swift 2. Останнє я зробив:

клас ViewController: UIViewController {var time: NSTimer // помилка тут}

Потім я виправляю: клас ViewController: UIViewController {

var time: NSTimer!
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func viewWillAppear(animated: Bool) {
    //self.movetoHome()
    time = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: #selector(ViewController.movetoHome), userInfo: nil, repeats: false)
    //performSegueWithIdentifier("MoveToHome", sender: self)
    //presentViewController(<#T##viewControllerToPresent: UIViewController##UIViewController#>, animated: <#T##Bool#>, completion: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>)
}

func movetoHome(){
    performSegueWithIdentifier("MoveToHome", sender: self)
}

}


Ясність не зовсім у вашій відповіді, але це була моя проблема; Я не вказав необов'язковість для учасника var (примусовий / необов'язковий); Як тільки я це зробив і пізніше відкоригував код, ViewController більше не скаржився на відсутність ініціалізатора.
Джеймс Перих

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.