Just started looking at Swift this weekend. I'm creating an id for my class to quickly compare objects. I want an immutable id, so should use let.
Using var and initialising id to "" will fix "use of self in method call before stored properties are initialised" but then of course it's mutable. Every other question i've seen similar to this is regarding a super class / calling super.init, which I don't have. It's very frustrating, I don't know why it's not straightforward.
class MagicCard {
let id:String
let name: String
let manaCost: Int
let description: String
let attack: Int
let defence: Int
init (name: String, manaCost: Int, description: String, attack: Int, defence: Int) {
self.name = name
self.manaCost = manaCost
self.description = description
self.attack = attack
self.defence = defence
id = generateRandomID()
}
private func generateRandomID() -> String {
let charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let charSetArray = Array(charSet.characters)
var id:String = ""
for _ in (0..<10) {
id.append(charSetArray[Int(arc4random()) % charSetArray.count])
}
return id
}
}
func == (lhs: MagicCard, rhs: MagicCard) -> Bool {
return lhs.id == rhs.id
}
Classes, structures and enumerations once declared in Swift 4 are initialized for preparing instance of a class. Initial value is initialized for stored property and also for new instances too the values are initialized to proceed further. The keyword to create initialization function is carried out by 'init()' method.
Variables and constants do not require initialization when declared. However, the variable or constant requires type annotation so that when the compiler reads the code line-by-line, it can determine the data type at the time of the build. A Use of undeclared type error will be thrown otherwise.
Initializers are called to create a new instance of a particular type. In its simplest form, an initializer is like an instance method with no parameters, written using the init keyword: init() { // perform some initialization here.
An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }
A hot-fix I can suggest is to make generateRandomID
a class func. So make it like so :
private class func generateRandomID() -> String {
And call like this :
id = MagicCard.generateRandomID()
The generateRandomID()
method does not use or modify any properties
of the instance, so one possible solution would be to make it a
type (class) method:
private class func generateRandomID() -> String {
// ...
return id
}
and use it like
id = MagicCard.generateRandomID()
(as also written in the other answer while I was writing this).
You could also drop the method and use an "immediately evaluated closure":
id = { () -> String in
// ...
return id
}()
But if the intention of the id property is to make the objects
Equatable
then you don't need it at all. Classes are reference
types and instances can be compared with the "identical to" operator:
func == (lhs: MagicCard, rhs: MagicCard) -> Bool {
return lhs === rhs
}
which makes the id
and the generateRandomID()
method obsolete.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With