0

I am trying to download some images and found a solution on Stack Overflow

It is using some closure syntax I don't understand.

func getDataFromUrl(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
    URLSession.shared.dataTask(with: url) { data, response, error in
        completion(data, response, error)
        }.resume()
}

It creates a function, and it is allowed to escape the completion argument, right? Ths function then returns a URLSession? where is the return statement?

What does the "data, response, error in" statement mean?

Then it calls a function called completion(...) where is it defined and implemented?

I guess this is some syntax I don't know. Any hint on where to read about this?

I then called the function:

    getDataFromUrl(url: url){ data, response, error in
        guard let data = data, error == nil else {return}
        DispatchQueue.main.async {
            let image = UIImage(data: data)
            print(image!)
            self.m_images?.append(image!)
            print(self.m_images!.count)
        }
    }

self.m_images is an Array: [Any], declared like this at the top of my viewController:

var m_images:[Any]?=nil

I am getting an error when unwrapping it, it is still nil: Why? I just appended an image. The image does exist, I print it and it works fine.

DavidVV
  • 225
  • 1
  • 4
  • 12

1 Answers1

2

completion is declared as a closure taking 3 parameters and with no return value in the getDataFromUrl function.

 ... completion: @escaping (Data?, URLResponse?, Error?) -> () ...

The closure can be represented by

{ (data, response, error) -> Void in 
  // code 
}

In the function completion is called passing the parameters

completion(data, response, error)

The error in your question occurs because var m_images is declared but not initialized. At the moment you are appending objects to nil to code crashes.

Basically never declare an array as [Any] if the type is actually much more specific.

Declare and initialize the image array as a non-optional array of UIImage

var mImages = [UIImage]()

Then check if the images could be created with optional bindings

if let image = UIImage(data: data) {
    print(image)
    self.mImages.append(image)
    print(self.mImages.count)
}

Note : Unlike PHP or JavaScript variables are supposed to be camelCased rather than snake_cased in Swift.

vadian
  • 274,689
  • 30
  • 353
  • 361