Swift 1.2: Compiler forces immutable (let) properties to be initialized in phase 1 of object initialization before super.init is called
Swift 1.2 Release notes: "Previously, immutable (let) properties were completely mutable within the body of initializers. Now, they are only allowed to be assigned to once to provide their value". Fails to mention that they can only be initialized once AND only during phase 1 of initialization, before super.init is called. My guess is that due to their mutability within the initializer body, they were actually set to nil before super.init in phase 1 and then set to an actual value when self was usable in phase 2.
Code in Documentation now fails: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID55
Dev Forum Discussions:
- https://devforums.apple.com/message/1104945#1104945
- https://devforums.apple.com/message/1109362#1109362
- https://devforums.apple.com/message/1117014#1117014
- https://devforums.apple.com/thread/264001?tstart=150
Current workaround is to turn these constants into implicitly unwrapped privately set variables since
- Variables can be mutated at any point during initialization
- Implicitly unwrapped means they can be nil before self is reference but can be safely assumed to contain something afterwards
- Privately set as to keep them from being set outside of the class similarly to being constant.
// from
public let serviceID: String!
// to
public private(set) var serviceID: String!
required public init?(usn: UniqueServiceName, descriptionURL: NSURL, descriptionXML: NSData) {
super.init(usn: usn, descriptionURL: descriptionURL, descriptionXML: descriptionXML)
// self is referenced for the parser
let serviceParser = UPnPServiceParser(upnpService: self, descriptionXML: descriptionXML)
let parsedService = serviceParser.parse().value
if let serviceID = parsedService?.serviceID {
self.serviceID = serviceID
}
else { return nil }
...