Skip to content

Instantly share code, notes, and snippets.

@AnnieNinaJoyceV
Created April 29, 2017 06:10
Show Gist options
  • Save AnnieNinaJoyceV/e61f3bb68e7126f54cfa0ac3d41e5df8 to your computer and use it in GitHub Desktop.
Save AnnieNinaJoyceV/e61f3bb68e7126f54cfa0ac3d41e5df8 to your computer and use it in GitHub Desktop.
On-Demand Resources - ODR : AppThinning
// Steps to mark ODR resources
// Select file(image, audio, etc) - File inspector - On Demand Resource Tags - Give it a name
class ODR_ViewController: UIViewController {
var tubbyRequest : NSBundleResourceRequest?
@IBOutlet weak var resourceDownloadProgress: UIProgressView! //to show download progress
// fileName is the name of the file's ODR tag
// if you want to download more than 1 file, change String to [String]
func fetchODRResourceWithName(fileName: String) {//to be called when the file needs to be accessed
guard self.tubbyRequest == nil else {return}
self.tubbyRequest = NSBundleResourceRequest(tags: [fileName])
self.resourceDownloadProgress.isHidden = false
self.resourceDownloadProgress.progress = Float((tubbyRequest?.progress.fractionCompleted)!)
self.tubbyRequest!.progress.addObserver(self, forKeyPath: "fractionCompleted", options: .new, context: nil)
self.tubbyRequest?.conditionallyBeginAccessingResources(completionHandler: { (resourceAvailable) in
if !resourceAvailable { //resource not available locally
self.tubbyRequest!.beginAccessingResources { err in
guard err == nil else {//an error occured while downloading
print(err as Any)
return
}
DispatchQueue.main.async {//file downloaded
self.resourceDownloadProgress.isHidden = true
//Do the next steps
}
}
} else { //resource available locally
DispatchQueue.main.async {
self.resourceDownloadProgress.isHidden = true
//DO the next steps
}
}
})
}
func stopDownloadingFile() {//to be called to cancel on-going download process, or to be called on 'viewWillDisappear' to be sure
guard self.tubbyRequest != nil else {
return
}
self.tubbyRequest!.endAccessingResources()
self.tubbyRequest!.progress.removeObserver(self, forKeyPath: "fractionCompleted")
self.tubbyRequest!.progress.cancel()
self.tubbyRequest = nil
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "fractionCompleted" {
DispatchQueue.main.async { [weak self] in
self?.resourceDownloadProgress.progress = Float((self?.tubbyRequest!.progress.fractionCompleted)!)
}
}
}
}
@yo1995
Copy link

yo1995 commented Apr 2, 2021

FYI: it seems the conditionallyBeginAccessingResources(completionHandler:) has to be called prior to beginAccessingResources(completionHandler:) even if the resource already exists on local disk.

Otherwise the resource file is inaccessible.

Ref: https://developer.apple.com/documentation/foundation/nsbundleresourcerequest/1614840-beginaccessingresources#discussion

Maybe Apple is sandboxing these resource files somehow... 🤔

@ibuprofane
Copy link

Also, these files can be purged at any time by the system so you'll need to retain it if you expect it to be around when you want to access it later: https://stackoverflow.com/questions/50063305/ios-is-purging-on-demand-resources-downloaded-mp3-how-to-prevent-this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment