คลาส 'ViewController' ไม่มี initializers อย่างรวดเร็ว


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คำหลักที่เกี่ยวข้องกับข้อผิดพลาดนี้เว้นแต่ฉันจะผิด

คำตอบ:


240

ข้อผิดพลาดสามารถปรับปรุงได้ แต่ปัญหาในเวอร์ชันแรกของคุณคือคุณมีตัวแปรสมาชิกdelegateซึ่งไม่มีค่าเริ่มต้น ตัวแปรทั้งหมดใน Swift ต้องมีค่าเสมอ นั่นหมายความว่าคุณต้องตั้งค่าในโปรแกรมเริ่มต้นที่คุณไม่มีหรือคุณสามารถระบุค่าเริ่มต้นในบรรทัดได้

เมื่อคุณกำหนดให้เป็นทางเลือกคุณจะอนุญาตให้เป็นnilค่าเริ่มต้นโดยไม่จำเป็นต้องระบุค่าหรือกำหนดค่าเริ่มต้นอย่างชัดเจน


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

พวกเขาสามารถ inited ในฟังก์ชัน init แทนได้หรือไม่?
Martian2049

13

ปัญหานี้มักจะปรากฏขึ้นเมื่อตัวแปรตัวใดตัวหนึ่งของคุณไม่มีค่าหรือเมื่อคุณลืมใส่ "!" เพื่อบังคับให้ตัวแปรนี้เก็บค่าศูนย์จนกว่าจะมีการตั้งค่า

ในกรณีของคุณปัญหาอยู่ที่นี่:

var delegate: AppDelegate

ควรกำหนดvar delegate: AppDelegate!ให้เป็นทางเลือกที่เก็บค่าศูนย์และห้ามแกะตัวแปรจนกว่าจะใช้ค่า

เป็นเรื่องน่าเศร้าที่ Xcode เน้นทั้งคลาสว่าเป็นข้อผิดพลาดแทนที่จะเน้นบรรทัดเฉพาะของโค้ดที่ทำให้เกิดดังนั้นจึงต้องใช้เวลาสักพักในการคิดออก


สิ่งนี้จะกำจัดข้อความแสดงข้อผิดพลาดสำหรับฉันในกรณีของ IBOutlet แต่ไม่ใช่ในกรณีของตัวแปรมาตรฐาน
Tim Vermeulen

วิธีนี้ช่วยแก้ปัญหาของฉันได้ เมื่อฉันพยายามทำสิ่งนี้: var fetchedResultsController: NSFetchedResultsController ฉันได้รับข้อผิดพลาดในการคอมไพล์ โดยการเพิ่ม "!" ข้อผิดพลาดหายไปเช่น so var fetchedResultsController: NSFetchedResultsController!
Jervisbay

ขอบคุณสำหรับคุณ ans! นี่เป็นประโยชน์สำหรับฉันฉันเพิ่งรู้จัก "?" เป็นค่าที่ไม่บังคับ แต่ "!" ฉันไม่รู้จักมาก่อน ฉันตั้งค่า "!" เช่นนั้น: 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().delegateviewDidLoad()

คำหลัก "ตัวเลือก" หมายตรงกับการใช้งานของ?ดูนี้สำหรับรายละเอียดเพิ่มเติม


1

ฉันใช้ Xcode 7 และ Swift 2 ล่าสุดฉันทำ:

คลาส ViewController: UIViewController {var time: NSTimer // error this here}

จากนั้นฉันจะแก้ไข: 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)
}

}


คำตอบของคุณไม่ได้ชัดเจนทั้งหมด แต่นี่เป็นปัญหาของฉัน ฉันไม่ได้ระบุตัวเลือกของสมาชิก var (บังคับ / ไม่บังคับ); เมื่อฉันทำและปรับโค้ดในภายหลัง ViewController ไม่บ่นอีกต่อไปว่าไม่มีตัวเริ่มต้น
James Perih

0

สำหรับฉันคือการประกาศที่ไม่สมบูรณ์ ตัวอย่างเช่น:

var isInverted: Bool

แทนวิธีที่ถูกต้อง:

var isInverted: Bool = false
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.