skip to Main Content

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.

2

Answers


  1. 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()
        }
    }
    
    Login or Signup to reply.
  2. Initialise the variable lazily

    class Foo
    {
       lazy var bar: Bar = {
           return Bar(delegate: self)
       }()
    
       init()
       {
       }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search