Класс ViewController не имеет инициализаторов в Swift

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ключевого слова, относящегося к этой ошибке, если я не ошибаюсь.

tranvutuan
источник

Ответы:

240

Ошибка может быть исправлена, но проблема с вашей первой версией заключается в том, что у вас есть переменная-член delegate, которая не имеет значения по умолчанию. Все переменные в Swift всегда должны иметь значение. Это означает, что вы должны установить его в инициализаторе, которого у вас нет, или вы можете указать ему значение по умолчанию в строке.

Когда вы делаете его необязательным, вы разрешаете ему быть nilпо умолчанию, устраняя необходимость явно указывать ему значение или инициализировать его.

drewag
источник
45

Язык программирования Swift гласит:

Классы и структуры должны установить для всех своих сохраненных свойств соответствующее начальное значение к моменту создания экземпляра этого класса или структуры. Сохраненные свойства нельзя оставлять в неопределенном состоянии.

Вы можете установить начальное значение для сохраненного свойства в инициализаторе или назначив значение свойства по умолчанию как часть определения свойства.

Поэтому вы можете написать:

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
могут ли они быть вместо этого инициализированы в функции инициализации?
Martian2049
13

Эта проблема обычно возникает, когда одна из ваших переменных не имеет значения или когда вы забываете добавить "!" чтобы заставить эту переменную хранить ноль, пока она не будет установлена.

В вашем случае проблема здесь:

var delegate: AppDelegate

Он должен быть определен так, var delegate: AppDelegate!чтобы сделать его необязательным, который хранит nil и не разворачивает переменную, пока значение не будет использовано.

Печально, что Xcode выделяет весь класс как ошибку, вместо того, чтобы выделять конкретную строку кода, которая ее вызвала, поэтому требуется время, чтобы понять это.

Иван V
источник
Это избавляет меня от сообщения об ошибке в случае IBOutlet, но не в случае стандартных переменных.
Тим Вермёлен
Это решает мою проблему. Когда я попытался сделать это: var fetchedResultsController: NSFetchedResultsController, я получил ошибку компиляции. Добавляя "!" ошибка исчезла, например, var fetchedResultsController: NSFetchedResultsController!
Jervisbay 05
спасибо за ваш ответ! Для меня это полезно, я только что знал "?" на необязательное значение, но "!" Я не знал раньше. Ставлю "!" вот так: var time: NSTimer!
AmyNguyen 01
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)
    }

}
saneryee
источник
3

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

Ключевое слово «необязательно» относится именно к использованию ?, см это для более подробной информации.

user2118161
источник
1

Я использую Xcode 7 и Swift 2. Наконец, я сделал:

class ViewController: UIViewController {var time: NSTimer // ошибка здесь}

Потом исправляю: class 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)
}

}

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

Для меня декларация была неполной. Например:

var isInverted: Bool

Вместо правильного пути:

var isInverted: Bool = false
Алессандро Маттиуцци
источник