Lớp 'ViewContoder' không có trình khởi tạo nhanh chóng


122

Nhận khiếu nại từ trình biên dịch khi tôi đang làm điều này

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) {
    }
}

Tuy nhiên, nếu tôi chỉ thêm ? ở cuối AppDelegate như bên dưới và lỗi không còn nữa.

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) {
    }
}

Tôi không thấy optionaltừ khóa liên quan đến lỗi này trừ khi tôi sai.

Câu trả lời:


238

Lỗi có thể được cải thiện, nhưng vấn đề với phiên bản đầu tiên của bạn là bạn có biến thành viên, delegatekhông có giá trị mặc định. Tất cả các biến trong Swift phải luôn có giá trị. Điều đó có nghĩa là bạn phải thiết lập nó trong một trình khởi tạo mà bạn không có hoặc bạn có thể cung cấp cho nó một giá trị mặc định trong dòng.

Khi bạn làm cho nó tùy chọn, bạn cho phép nó niltheo mặc định, loại bỏ sự cần thiết phải cung cấp cho nó một giá trị hoặc khởi tạo nó một cách rõ ràng.


45

Ngôn ngữ lập trình Swift nêu rõ:

Các lớp và cấu trúc phải đặt tất cả các thuộc tính được lưu trữ của chúng thành một giá trị ban đầu thích hợp vào thời điểm một thể hiện của lớp hoặc cấu trúc đó được tạo. Các thuộc tính được lưu trữ không thể để ở trạng thái không xác định.

Bạn có thể đặt giá trị ban đầu cho thuộc tính được lưu trữ trong bộ khởi tạo hoặc bằng cách chỉ định giá trị thuộc tính mặc định như một phần định nghĩa của thuộc tính.

Do đó, bạn có thể viết:

class myClass {

    var delegate: AppDelegate //non-optional variable

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

}

Hoặc là:

class myClass {

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

    init() {
        println("Hello")
    }

}

Hoặc là:

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
    }

}

Nhưng bạn không thể viết như sau:

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

Đôi khi, lỗi này cũng xuất hiện khi bạn có một var hoặc cho phép chưa được xác định.

Ví dụ

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

Tùy thuộc vào biến số của bạn được cho là gì, bạn có thể đặt loại var đó làm tùy chọn hoặc khởi tạo nó với giá trị như sau

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
}

Vậy giải pháp cho vấn đề này là gì?
Martian2049

thay vào đó họ có thể được kích hoạt trong một hàm init không?
Martian2049

12

Vấn đề này thường xuất hiện khi một trong các biến của bạn không có giá trị hoặc khi bạn quên thêm "!" để buộc biến này lưu trữ nil cho đến khi nó được đặt.

Trong trường hợp của bạn, vấn đề là ở đây:

var delegate: AppDelegate

Nó nên được định nghĩa là var delegate: AppDelegate!làm cho nó trở thành một tùy chọn lưu trữ nil và không mở khóa biến cho đến khi giá trị được sử dụng.

Thật đáng buồn khi Xcode làm nổi bật cả lớp là một lỗi thay vì làm nổi bật dòng mã cụ thể đã gây ra nó, vì vậy phải mất một thời gian để tìm ra nó.


Điều này không loại bỏ thông báo lỗi cho tôi trong trường hợp IBOutlet, nhưng không phải trong trường hợp biến tiêu chuẩn.
Tim Vermeulen

Điều này giải quyết vấn đề của tôi. Khi tôi cố gắng làm điều này: var fetchedResultsCont điều khiển: NSFetchedResultsControll Tôi đã gặp lỗi biên dịch. Bằng cách thêm "!" lỗi đã biến mất, như vậy var fetchedResultsCont điều khiển: NSFetchedResultsControll!
Jervvday

cảm ơn vì ans của bạn Điều này là hữu ích cho tôi, tôi chỉ biết "?" đến giá trị tùy chọn nhưng "!" Tôi chưa biết trước đây. Tôi đặt "!" như thế: var time: NSTimer!
AmyNguyen

10

nếu bạn mất "!" trong mã của bạn, như mã này bên dưới, bạn cũng sẽ gặp lỗi này.

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

Thay thế var appDelegate : AppDelegate?bằng let appDelegate = UIApplication.sharedApplication().delegatenhư gợi ý trên dòng nhận xét thứ hai trong viewDidLoad().

Từ khóa "tùy chọn" đề cập chính xác đến việc sử dụng ?, xem phần này để biết thêm chi tiết.


1

Tôi sử dụng Xcode 7 và Swift 2. Cuối cùng, tôi đã thực hiện:

class ViewContoder: UIViewControll {var time: NSTimer // lỗi này tại đây}

Sau đó, tôi sửa: class ViewContoder: UIViewControll {

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)
}

}


Sự rõ ràng không hoàn toàn có trong câu trả lời của bạn, nhưng đây là vấn đề của tôi; Tôi đã không chỉ định tùy chọn của thành viên var (bắt buộc / tùy chọn); một khi tôi đã làm và điều chỉnh mã sau đó, ViewContoder không còn phàn nàn về việc không có trình khởi tạo.
James Perih

0

Đối với tôi là một tuyên bố không đầy đủ. Ví dụ:

var isInverted: Bool

Thay vào đó là cách chính xác:

var isInverted: Bool = false
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.