【问题标题】:Class 'ViewController' has no initializers in swift'ViewController' 类在 swift 中没有初始化器
【发布时间】:2014-09-12 15:20:29
【问题描述】:

当我这样做时从编译器那里得到投诉

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 关键字。

【问题讨论】:

    标签: swift xcode6 swift-playground


    【解决方案1】:

    该错误可以改进,但您的第一个版本的问题是您有一个成员变量delegate,它没有默认值。 Swift 中的所有变量都必须始终有一个值。这意味着您必须在您没有的初始化程序中对其进行设置,或者您可以在线为其提供默认值。

    当您将其设为可选时,默认情况下您允许它为 nil,从而无需显式地为其赋值或对其进行初始化。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        有时,当您有尚未初始化的 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
        }
        

        【讨论】:

        • 那么有什么解决办法呢?
        • 可以在初始化函数中初始化它们吗?
        【解决方案4】:

        当您的变量之一没有值时,通常会出现此问题 或者当您忘记添加“!”时强制此变量存储 nil 直到它被设置。

        在你的情况下,问题就在这里:

        var delegate: AppDelegate
        

        应将其定义为var delegate: AppDelegate!,以使其成为存储 nil 的可选项,并且在使用该值之前不要解包变量。

        很遗憾,Xcode 将整个类作为错误突出显示,而不是突出显示导致它的特定代码行,因此需要一段时间才能弄清楚。

        【讨论】:

        • 在 IBOutlet 的情况下,这确实消除了我的错误消息,但在标准变量的情况下却没有。
        • 这解决了我的问题。当我尝试这样做时: var fetchedResultsController: NSFetchedResultsController 我得到了编译错误。通过增加 ”!”错误消失了,就像这样 var fetchedResultsController: NSFetchedResultsController!
        • 感谢您的回答!这对我很有帮助,我刚刚知道“?”为可选值,但“!”我以前不知道。我设置 ”!”像这样:var time: NSTimer!
        【解决方案5】:

        如果您丢失了“!”在你的代码中,就像下面的这段代码,你也会得到这个错误。

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

        【讨论】:

          【解决方案6】:

          var appDelegate : AppDelegate? 替换为 let appDelegate = UIApplication.sharedApplication().delegateviewDidLoad() 中的第二条注释行中有所暗示。

          关键字“可选”完全是指?的使用,更多细节见this

          【讨论】:

            【解决方案7】:

            我使用 Xcode 7 和 Swift 2。最后,我做了:

            类 ViewController: UIViewController{ var time: NSTimer //这里出错 }

            然后我修复: 类视图控制器: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)
            }
            

            }

            【讨论】:

            • 你的答案并不完全清楚,但这是我的问题;我没有指定成员变量的可选性(强制/可选);一旦我这样做了,后来又调整了代码,ViewController 就不再抱怨没有初始化器了。
            【解决方案8】:

            对我来说,声明是不完整的。例如:

            var isInverted: Bool
            

            改为正确的方式:

            var isInverted: Bool = false
            

            【讨论】: