Uploading usdz model to AR Quick Look at https link

Good afternoon! Please tell me how to load the usdz model from the url link (https) in AR Quick Look, I am using the code from the listing of the Apple presentation, and I get an error "Fatal error: Unexpectedly found nil while unwrapping an Optional value", what am I doing wrong? I hope and really look forward to your reply. The application compiles correctly, the error occurs after pressing a button on the device itself.

Code Block language
import UIKit
import QuickLook
import ARKit
import RealityKit
class ViewController: UIViewController, QLPreviewControllerDataSource {
  override func viewDidLoad() {
    super.viewDidLoad()
  }
  @IBAction func startDecoratingButtonPressed(_ sender: Any) {
    let previewController = QLPreviewController()
    previewController.dataSource = self
    present(previewController, animated: true, completion: nil)
  }
  func numberOfPreviewItems(in controller: QLPreviewController) -> Int { return 1 }
   
  func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
    let fileUrl = Bundle.main.url(forResource: "toy_drummer", withExtension: "usdz")!
    let previewItem = ARQuickLookPreviewItem(fileAt: fileUrl)
    previewItem.canonicalWebPageURL = URL(string: "https://developer.apple.com/augmented-reality/quick-look/models/drummertoy/")
    previewItem.allowsContentScaling = false
    return previewItem
  }
}


Hi @cyber_dennis,

I would venture a guess that the toy_drummer.usdz file isn't actually saved in your bundle. I have created a project, copied your code exactly, added a button to my storyboard, attached it to the startDecoratingButtonPressed() method, downloaded the toy_drummer.usdz from Apple's website, dragged it into my application's files in Xcode, and ran the app. I was able to tap the button and successfully view the AR model.

I may be misreading your question, but it sounded like you are expecting to be able to load the .usdz model directly from a website URL, which is not going to work in this sense. If you have a .usdz model saved somewhere on the web (such as how the toy_drummer.usdz is really saved at https://developer.apple.com/augmented-reality/quick-look/models/drummertoy/toy_drummer.usdz), you would need to use something like a URLSession to download the model to local storage, then replace fileUrl in your code with the path to the downloaded file. Alternatively, if you would prefer to bundle your .usdz models with your app, you could download the .usdz models from the web, drag them into Xcode, and replace fileUrl with the relevant file names. For the former, downloading from the web, see Downloading Files from Websites, which should point you in the right direction.
@brandonK212 Thanks for the answer! For example, I download a usdz file using the command:

Code Block language
let fileUrl = URL(fileURLWithPath: "https://developer.apple.com/augmented-reality/quick-look/models/drummertoy/toy_drummer.usdz")
  let entity = try? Entity.load(contentsOf: fileUrl)

Is this file saved to local iPhone storage? How can I access this file from code to open it in AR Quick Look?
Hi @cyber_denis,

No, that sample you are providing is not actually downloading a file. When you are trying to load an Entity, as you indicate in your line
Code Block
let entity = try? Entity.load(contentsOf: fileUrl)

the loading of the file is expected to come from local storage on your device (either by way of an asset being bundled with the app when you compile it, or by downloading an asset).

For what you are trying to achieve, you will need to use some methodology of downloading the file from the web, saving to a location that you app has access to (such as the app's Documents directory), and then reference that path when trying to load your Entity or AR object. The first example in Apple's Downloading Files from Websites will get you there.

For example, here is an updated version of your ViewController.swift. See notations below;

Code Block
import UIKit
import ARKit
import QuickLook
class ViewController: UIViewController, QLPreviewControllerDataSource {
// 1
var modelURL: URL?
override func viewDidLoad() {
super.viewDidLoad()
// 2
self.downloadSampleUSDZ()
}
@IBAction func startDecoratingButtonPressed(_ sender: Any) {
// 3
guard modelURL != nil else { return }
let previewController = QLPreviewController()
previewController.dataSource = self
present(previewController, animated: true, completion: nil)
}
// 4
func downloadSampleUSDZ() {
let url = URL(string: "https://developer.apple.com/augmented-reality/quick-look/models/drummertoy/toy_drummer.usdz")!
let downloadTask = URLSession.shared.downloadTask(with: url) { urlOrNil, responseOrNil, errorOrNil in
guard let fileURL = urlOrNil else { return }
do {
let documentsURL = try
FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let savedURL = documentsURL.appendingPathComponent(url.lastPathComponent)
try FileManager.default.moveItem(at: fileURL, to: savedURL)
self.modelURL = savedURL
} catch {
print ("file error: \(error)")
}
}
downloadTask.resume()
}
func numberOfPreviewItems(in controller: QLPreviewController) -> Int { return 1 }
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
// 5
let previewItem = ARQuickLookPreviewItem(fileAt: self.modelURL!)
previewItem.canonicalWebPageURL = URL(string: "https://developer.apple.com/augmented-reality/quick-look/models/drummertoy/")
previewItem.allowsContentScaling = false
return previewItem
}
}

1) Add a new variable to your ViewController.swift file, which will hold the local URL of the file, once it's been downloaded and saved to storage.

2) Call a new function (discussed below), to download the file from a web URL.

3) Make sure that we've set the modelURL, hereby confirming the file was downloaded successfully. Otherwise, do not do anything, as we have nothing to preview.

4) Again, this is adapted from the Downloading Files from Websites documentation, but you are establishing the URL of the file you want to download, and configuring a task to download that file. Once the file is downloaded, we save it to the app's Documents directory, using the original file name, and set modelURL to be the path to the local URL of the downloaded file.

5) We set the URL of the ARQuickLookPreviewItem to the local URL of the file, then preview.

This is a very abstract example, which does not take into account things like error handling, keeping the user informed of what is happening (otherwise they are just tapping the button repeatedly until the file is ready), and a litany of other considerations to deliver an ideal user experience (including adding the ability to dynamically provide the web URL of the file(s) you wish to download, as this example is hard-coding the web URL to "toy_drummer.usdz"). However, this code does compile when I test on my device, and I can preview the AR model after it downloads from the web.
@brandonK212 Thanks for the answer! Two more questions:
  1. How to make sure that the file is loaded not when you open the application, but after clicking the button. So that when you click on a button, it loads and opens in turn?

  2. How to make sure that after closing AR Quick Look these files are deleted from memory? I found the code but it doesn't seem to delete files!

Code Block language
   @IBAction func removeAllFiles(){
    let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    do {
      let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsUrl,
                                    includingPropertiesForKeys: nil,
                                    options: .skipsHiddenFiles)
      for fileURL in fileURLs {
        if fileURL.pathExtension == "usdz" {
          try FileManager.default.removeItem(at: fileURL)
        }
      }
    } catch { print(error) }
  }


Uploading usdz model to AR Quick Look at https link
 
 
Q