0

I am trying to get remote images to show for Apple CarPlay.

I know I need to make an extension as it does not work by default.

I have tried to add the following and I get No exact matches in call to initializer Which I don't know what that means or how to fix.

extension UIImage {

    func imageFromBase64(_ base64: String) -> UIImage? {
        if let url = URL(string: base64), let data = try? Data(contentsOf: url) {
            return UIImage(data: data)
        }
        return nil
    }
}

 let item = CPListItem(text: station.name,
                                    detailText: station.name,
                                    image:  station.imageurl.imageFromBase64()
              )
Shawn Frank
  • 4,381
  • 2
  • 19
  • 29
Russell Harrower
  • 778
  • 1
  • 6
  • 20
  • `station.imageurl.imageFromBase64()`, so I guess that `station.imageurl` is a String. So does `String` have a method called `imageFromBase64()`? No. You added on for `UIImage` instances, and it has a parameter. Plus, this is a sync code, so it will freeze the current thread with `Data(contentsOf:)`. – Larme Mar 29 '22 at 07:39
  • @Larme The imagery just points to a URL where the image is hosted. – Russell Harrower Mar 29 '22 at 07:43

1 Answers1

1

Your station image url is probably a String or a URL type, however your extension is for a UIImage type so there is a type mismatch.

You might be better off just creating a simple function rather than an extension

func imageFromBase64(_ base64: String) -> UIImage? {
    if let url = URL(string: base64),
       let data = try? Data(contentsOf: url) {
        return UIImage(data: data)
    }
    return nil
}

let item = CPListItem(text: station.name,
                      detailText: station.name,
                      image: imageFromBase64(station.imageurl))

If you do want to make it a UIImage extension, I think you need to initialize a UIImage with a URL so this is an option:

extension UIImage {
    convenience init?(url: URL?) {
        
        guard let url = url,
              let data = try? Data(contentsOf: url)
        else {
            self.init()
            return
        }
         
        self.init(data: data)
    }
}

let url = URL(string: station.imageurl)
let stationImage = UIImage(url: url)

let item = CPListItem(text: station.name,
                      detailText: station.name,
                      image: stationImage)

However, this will block the main thread while loading so I suggest looking at the comment on your previous question's answer by a user called fruitcoder

He shows how to load data asynchronously for CarPlay. Here is the code and he has another article for the same.

Shawn Frank
  • 4,381
  • 2
  • 19
  • 29