Class has no initializers

I have a simple class in a .swift file that will keep track of the user's info.


import Foundation
class User {
   
    var joinedBefore: Bool = false
   
    let joinDate: NSDate?
   
    var name: String?
   
}


But when I try to run my app on my iPad it gives me an error at line 2 that says: "Class 'User' has no initializers". What does this mean? At first, I thought it meant you had to add something like UIViewController after the class name but upon further investigation, Apple's description of classes doesn't have any of that. Does anyone know what this means and how I can fix it? Thanks in advance. Any help is appreciated.

Answered by Claude31 in 253256022

Your declaration is nearly OK, except the let :


class User {   
    var joinedBefore: Bool = false    
    let joinDate: NSDate?   
    var name: String?  
}


In fact, when you declare as optional, NSDate? or String?, they are initialized to nil automatically.

Adding = nil will not change anything.


But with a let, you will not be able to change and give a value later. Complier detects this. Hence the error.


If you replace by var, evrything will compile OK

class User {
    var joinedBefore: Bool = false
    var joinDate: NSDate?
    var name: String?
}


However, it is good to give real values in the init


   init() {
        joinDate = NSDate()
        name = ""
    }

It is often useful to create convenience init, so that you can initialize the object directly when you create:


    init(aDay: NSDate) {
        joinDate = aDay
        name = ""
    }

use:

let dateOfBirth = // give the date
let newUser = User(dateOfBirth)


You can have an init with date and name as well.


2 points :

- if you declared USER as a subClass (of NSObject for instance), the you need to override the init

class Test : NSObject {
    var joinedBefore: Bool = false   
    var joinDate: NSDate?   
    var name: String?
   
    override init() {
        joinDate = NSDate()
        name = ""
        super.init()            // sinon, on risque le bug quand on essaiera d'appeler encodeWithCoder:
   }


- This is for Swift2 ; in Swift3, use Date instead of NSDate

Swift requires that all properties of a type be initialized.


Since you have properties without default values, the implicit empty initializer 'init() { }' doesn't satisfy this requirement.


So you can either ensure all your properties have a default value:

class User { 
    
    var joinedBefore: Bool = false 
    
    let joinDate: NSDate?  = nil
    
    var name: String? = nil
    
}


or, you can provide an explicit initializer:


class User {
     var joinedBefore: Bool = false
     let joinDate: Date
     var name: String

     init(name: String, joinDate: Date) {
          self.name = name
          self.joinDate = joinDate
     }
}


Note that in this last case, you don't need joinDate and name to be optionals, because presumably you can provide them at time of user creation... and (maybe?) it's reasonable for a user's name and joinDate to never be nil, since presumably, they aren't a user if they have not joined or provided a name, but those are details for you to decide 🙂

Accepted Answer

Your declaration is nearly OK, except the let :


class User {   
    var joinedBefore: Bool = false    
    let joinDate: NSDate?   
    var name: String?  
}


In fact, when you declare as optional, NSDate? or String?, they are initialized to nil automatically.

Adding = nil will not change anything.


But with a let, you will not be able to change and give a value later. Complier detects this. Hence the error.


If you replace by var, evrything will compile OK

class User {
    var joinedBefore: Bool = false
    var joinDate: NSDate?
    var name: String?
}


However, it is good to give real values in the init


   init() {
        joinDate = NSDate()
        name = ""
    }

It is often useful to create convenience init, so that you can initialize the object directly when you create:


    init(aDay: NSDate) {
        joinDate = aDay
        name = ""
    }

use:

let dateOfBirth = // give the date
let newUser = User(dateOfBirth)


You can have an init with date and name as well.


2 points :

- if you declared USER as a subClass (of NSObject for instance), the you need to override the init

class Test : NSObject {
    var joinedBefore: Bool = false   
    var joinDate: NSDate?   
    var name: String?
   
    override init() {
        joinDate = NSDate()
        name = ""
        super.init()            // sinon, on risque le bug quand on essaiera d'appeler encodeWithCoder:
   }


- This is for Swift2 ; in Swift3, use Date instead of NSDate

Class has no initializers
 
 
Q