I'm porting parts of an Objective-C framework to Swift, and I have an issue I can't think of how to fix. As part of one of the classes, I need to store a URLSession
to access a remote API, and I would like to be able to store it as an instance variable on the class which is to be its delegate. Unfortunately, I can't seem to figure out how to do this in Swift, as the compiler either decides I'm referencing self
before a call to super.init
or I'm calling super.init
before initializing all instance variables. Unfortunately, both of these conditions can't be simultaneously satisfied, which makes me wonder how to properly do this. People have asked this question with regard to other classes, but I haven't found anything specifically for URLSession
, which is unique in its inability to change delegates (that is, the delegate MUST be passed to the initializer).
Effectively, I wish that one of the two options worked:
class Foo
{
let session: URLSession
public init()
{
super.init()
// Compiler error on this line: Property 'self.session' not initialized at super.init call
self.session = URLSession(configuration: /* configuration object */, delegate: self, delegateQueue: nil)
}
}
OR
class Foo
{
let session: URLSession
public init()
{
// Compiler error on this line: 'self' used before super.init call
self.session = URLSession(configuration: /* configuration object */, delegate: self, delegateQueue: nil)
super.init()
}
}
The only workaround I can think of is changing the property to mutable and using an optional type, but this really is less than optimal, especially for behavior which is so straightforward in Objective-C.
CodePudding user response:
You can make it to computed property.
public class Foo: NSObject, URLSessionDelegate {
var session: URLSession {
URLSession(configuration: .default, delegate: self, delegateQueue: nil)
}
/*
// OR
lazy var session: URLSession = {
return URLSession(configuration: .default, delegate: self, delegateQueue: nil)
}()
*/
public override init() {
super.init()
}
}
CodePudding user response:
Initialise the variable lazily
class Foo
{
lazy var bar: Bar = {
return Bar(delegate: self)
}()
init()
{
}
}