Swift Loaditem Closure Not Running

How do I load a URL using NSItemProvider's new Async loadItem method?

I had to cast to Data and then construct the URL from that:

if let data = try await urlProvider
.loadItem(forTypeIdentifier: UTType.fileURL.identifier) as? Data {
url = URL(dataRepresentation: data, relativeTo: nil) }

Accessing Website URL and Title in ShareExtension

Change your "loadItem" to "loadItemAsync" and run it that way. I ran into literally the EXACT same problem of the completion block not running, but when I call "loadItemAsync" instead of just "loadItem," it runs fine and I get all the output from my JS file.

Code outside loop being executed during loop

For this kind of async work you need something like DispatchGroup.

Edited your example to take use of it

    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)

itemProviders = results.map(\.itemProvider)
iterator = itemProviders.makeIterator()

let dispatchGroup = DispatchGroup()

while let itemProvider = iterator?.next(), itemProvider.canLoadObject(ofClass: UIImage.self) {

dispatchGroup.enter()

print("\n Entered while")
itemProvider.loadObject(ofClass: UIImage.self) { image, error in
DispatchQueue.main.async {
guard let image = image as? UIImage else { return }
self.images.append(image)
print("Image: \(image)")
print("Images: \(self.images)")

dispatchGroup.leave()
}
}
}
dispatchGroup.notify(queue: DispatchQueue.main) {
self.displayAndStoreImages()
}
}

func displayAndStoreImages(){
print("\n Entered displayAndStoreImages()")
print("Images: \(images) \n")

}

iOS YouTube Share Extension Not Providing URL

My first recommendation is to find out what types are actually provided by the
itemProvider:

if let item = extensionContext?.inputItems.first as? NSExtensionItem {
for (index, _) in (item.attachments?.enumerated())! {
if let itemProvider = item.attachments?[index] as? NSItemProvider {

// print out the registered type identifiers so we can see what's there
itemProvider.registeredTypeIdentifiers.forEach { print String(describing: $0) }

In this case, according to your comments, you are able to get plain text or kUTTypePlainText and that text contains a URL so:

if let item = extensionContext?.inputItems.first as? NSExtensionItem {
for (index, _) in (item.attachments?.enumerated())! {
if let itemProvider = item.attachments?[index] as? NSItemProvider {
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypePlainText) {
itemProvider.loadItem(forTypeIdentifier: kUTTypePlainText, options: nil, completionHandler: { (string, error) -> Void in
if let string = (string as? String), let shareURL = URL(string) {
// send url to server to share the link
print (shareURL.absoluteString!)

My second recommendation is to always use the kUTType constants instead of raw strings :-)

Swift - Using Async Method to Load PHPickerResult

I don't know why your code doesn't work. (It doesn't work for me either, for what it's worth.) However, I did determine code that does work, although you might not consider it to be an improvement over just using loadObject with a callback:

Task {
do {
let url = try await item.loadItem(forTypeIdentifier: "public.image") as! URL
let data = try Data(contentsOf: url)
if let image = UIImage(data: data) {
print("Image loaded: \(image)")
} else {
print("Error loading image!");
}
} catch let error {
print("async loadItem failed: \(error)")
}
}

Note: I tried to use UIImage(contentsOfFile: url.absoluteString) instead of loading the URL into a Data object and then loading the UIImage from that. That didn't work, and I don't know why. All I know is that UIImage(contentsOfFile:) returned nil.



Related Topics



Leave a reply



Submit