NSItemProvider iconProvider has a dynamic type rather than an image type

I'm using a LPMetadataProvider to get metadata for URLs.

If I do this

if itemProvider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
    let item = try? await itemProvider.loadItem(forTypeIdentifier: UTType.image.identifier)
    // continue with code to convert data to UIImage...
}

That seems to fail quite often, even on larger sites like Amazon where users will expect to see an icon.

I've noticed it's because sometimes the type is dyn.agq80w5pbq7ww88brrfv085u

I'm assuming this is because something about the website response or the image data does not let the system determine if it is actually an image.

If I just do this

let type: String = "dyn.agq80w5pbq7ww88brrfv085u"

if itemProvider.hasItemConformingToTypeIdentifier(type) {
    let item = try? await itemProvider.loadItem(forTypeIdentifier: type)
    // continue with code to convert data to UIImage...
}

Then I get the icon, so it is there and it is an image. The problem is, does this dynamic type cover everything? Should I even be doing that?

Does anyone know precisely what causes this and are there recommendations on better ways to handle it?

I know LPLinkView appears to do something to load these 'non-image' icons so I am assuming there are way.

My assumption is that it would be safe to look at the results of itemProvider.registeredTypeIdentifiers() and if it has something use that as the type rather than coming up with a hardcoded list of types to check for.

Thank you for suggesting that. It appears to behave the same way, assuming I have not made a mistake.

I should state this is on a simulator of an iPhone 15 Pro running iOS 17.2 and compiled with Xcode 15.2

This is what I tested. Obviously this just a quick and dirty code snippet.

_ = metadata?.iconProvider?.loadObject(ofClass: UIImage.self) { image, error in
    dump(error)
    dump(metadata?.iconProvider?.registeredTypeIdentifiers())

    if let iconImage = image as? UIImage {
        DispatchQueue.main.async {
            self.icon = iconImage
        }
    }
}

It's the same in that it works when it is one of these types:

  1. public.png
  2. com.microsoft.ico

And fails when it's the type

  1. dyn.agq80w5pbq7ww88brrfv085u

I'm still unsure if I am doing the right thing to blindly grab the first type as I've been testing (see below) but I have to say it seems to work pretty well so far and if it does not create an image it should just return nothing.

I'm guessing the URL check is probably unnecessary for an icon provider but if I keep that it can always go to the bottom where it'll not cause an additional check for the other cases but the performance seems reasonable.

if let type = itemProvider.registeredTypeIdentifiers().first {
 
    let item = try? await itemProvider.loadItem(forTypeIdentifier: type)

    if item is UIImage {
        ...
    }

    if item is URL {
        ...
    }

    if item is Data {
        ...
    }
}

I suspect I may be able to drop the URL check or at worst put the check at the bottom where it will likely never get hit.

NSItemProvider iconProvider has a dynamic type rather than an image type
 
 
Q