Skip to content

Instantly share code, notes, and snippets.

@fcanas
Created May 29, 2019 02:09
Show Gist options
  • Save fcanas/258a9f70a390598e330ba8e6aef04f29 to your computer and use it in GitHub Desktop.
Save fcanas/258a9f70a390598e330ba8e6aef04f29 to your computer and use it in GitHub Desktop.
Loading AVAssets from Asset Catalogs
//
// AVAsset+Catalog.swift
// Micro Album
//
// Created by Fabian Canas on 5/28/19.
// Copyright © 2019 Fabian Canas. All rights reserved.
//
import AVFoundation
import MobileCoreServices
import UIKit
fileprivate let AssetCache = NSCache<NSString, AVAsset>()
extension AVAsset {
/// This method looks in in-memory and on-disk caches for an AVAsset with
/// the specified name. If a matching AVAsset is not already in the cache,
/// this method locates and loads the video data from disk or from an
/// asset catalog, and then caches and returns the resulting object.
///
/// - Parameter name: The name of the video asset
/// - Returns: The video asset for the specified asset name, or nil if the
/// method could not find the specified image.
class func named(_ name: String) -> AVAsset? {
if let avAsset = AssetCache.object(forKey: name as NSString) {
return avAsset
}
// NSDataAsset lets us have arbitrary data in Asset Catalogs
guard let dataAsset = NSDataAsset(name: name) else {
return nil
}
let temporaryFilename = "avasset-\(name.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ProcessInfo().globallyUniqueString)"
let cfExtension = UTTypeCopyPreferredTagWithClass(dataAsset.typeIdentifier as CFString, kUTTagClassFilenameExtension)?.takeRetainedValue()
guard let fileExtension = cfExtension as String? else {
// AVAsset is picky about the file extension when dealing with local
// files. If the extension doesn't match what's expected, it's not
// worth making the asset.
return nil
}
let fileManager = FileManager.default
let url = fileManager.temporaryDirectory.appendingPathComponent(temporaryFilename).appendingPathExtension(fileExtension)
if !fileManager.fileExists(atPath: url.path) {
do {
try dataAsset.data.write(to: url, options: .atomicWrite)
} catch {
return nil
}
}
let avAsset = AVAsset(url: url)
AssetCache.setObject(avAsset, forKey: name as NSString)
return avAsset
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment