UIDropSession.canLoadObjects(ofClass: NSItemProviderReading) not working correctly when using Universal Control in iOS 17

Originator:victor.pimentel
Number:rdar://FB13723251 Date Originated:12/04/2024
Status:Open Resolved:
Product:Continuity/Handoff Product Version:iOS 17
Classification:Incorrect/Unexpected Behavior Reproducible:Yes
 
Since iOS 17 UIDropSession.canLoadObjects(ofClass:) returns true no matter what you are dropping. I added an example project where this can be reproduced 100% of the time.

Steps to reproduce:
- Have a Mac and an iPad with iOS 17+ working with Universal Control enabled so the pointer can move between them.
- Open an app that supports UIDropInteraction, like the example app attached here. It needs to have a custom NSItemProviderReading.
- Drag any file that is not supported by that app from the Mac to that iPad.
- BUG: UIDropSession.canLoadObjects(ofClass: NSItemProviderReading) will return true for all files, but before iOS 17 this only returned true if the object was actually supported by that NSItemProviderReading class.

I’m using macOS Sonoma 14.0 and iPadOS 17.4.1, but other people in my team noticed this with other iOS 17 devices.

Comments

Workaround

For now you can replace these:

session.canLoadObjects(ofClass: aClass)

With:

session.hasItemsConforming(toTypeIdentifiers: aClass.readableTypeIdentifiersForItemProvider)

By victor.pimentel at April 12, 2024, 8:52 a.m. (reply...)

Info.plist

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>UIApplicationSceneManifest</key> <dict> <key>UIApplicationSupportsMultipleScenes</key> <false/> <key>UISceneConfigurations</key> <dict> <key>UIWindowSceneSessionRoleApplication</key> <array> <dict> <key>UISceneConfigurationName</key> <string>Default Configuration</string> <key>UISceneDelegateClassName</key> <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> <key>UISceneStoryboardFile</key> <string>Main</string> </dict> </array> </dict> </dict> <key>UTExportedTypeDeclarations</key> <array> <dict> <key>UTTypeConformsTo</key> <array> <string>public.composite-content</string> </array> <key>UTTypeDescription</key> <string>Example Document</string> <key>UTTypeIconFiles</key> <array/> <key>UTTypeIdentifier</key> <string>com.example.mydocument</string> <key>UTTypeTagSpecification</key> <dict/> </dict> </array> </dict> </plist>

By victor.pimentel at April 12, 2024, 8:47 a.m. (reply...)

ViewController.swift

import UIKit

class ViewController: UIViewController, UIDropInteractionDelegate {

override func viewDidLoad() {
    super.viewDidLoad()

    let interaction = UIDropInteraction(delegate: self)
    view.addInteraction(interaction)
}

func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
    true
}

func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
    UIDropProposal(operation: .copy)
}

func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
    if session.canLoadObjects(ofClass: ExampleProviderReading.self) {
        print("Can load objects")
        session.loadObjects(ofClass: ExampleProviderReading.self) { containers in
            guard let container = containers.first as? ExampleProviderReading else {
                fatalError("[BUG] Could not load object!")
            }
            print("Loaded an object: \(container)")
        }
    }
}

}

final class ExampleProviderReading: NSObject, NSItemProviderReading { static var readableTypeIdentifiersForItemProvider: [String] { return ["com.example.mydocument"] }

static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> ExampleProviderReading {
    ExampleProviderReading()
}

}

By victor.pimentel at April 12, 2024, 8:45 a.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!