Valid file path for archiverootobject and unarchiverootobject
You can save it to a subdirectory folder named with your bundleID inside the application support folder or you can also save it to the preferences folder located inside the library directory:
let preferencesDirectoryURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!.appendingPathComponent("Preferences", isDirectory: true)
let fileURL = preferencesDirectoryURL.appendingPathComponent("fileName.plist")
print(fileURL.path) // "/var/folders/.../Library/Preferences/fileName.plist
How to get the url for a video saved in temporary directory
Since you don't seem to want your file to be visible to users or persisted between app launches, the Temporary directory
sounds perfectly fine for your use case:
var tempVideoFileUrl: URL {
return FileManager.default.temporaryDirectory.appendingPathComponent("my_video_name")
}
func storeVideoToTemporaryFolder(videoData: Data) {
guard !FileManager.default.fileExists(atPath: tempVideoFileUrl.path) else {
return
}
do {
try videoData.write(to: tempVideoFileUrl)
}
catch {
fatalError()
}
}
func loadVideoFromTemporaryFolder() -> Data? {
if let data = try? Data(contentsOf: tempVideoFileUrl) {
return data
}
return nil
}
Worth mentioning though, the system may (and most likely will) purge this directory after the app is exited. It's recommended that you remove any temporary directories/files after they're no longer needed.
So in your case, you can simply remove it once you finished uploading to Firebase Storage:
func deleteVideoFromTemporaryFolder() {
do {
try FileManager.default.removeItem(at: videoFileUrl)
}
catch {
fatalError()
}
}
If you prefer to keep your file around between app launches though, you could use Application Support directory
. But since Application Support and Documents directories gets automatically backed up, you may want to exclude your file from iCloud backup by setting its URL's isExcludedFromBackupKey
key:
var applicationSupportVideoFileUrl: URL {
let applicationSupportFolderUrl = try! FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
return applicationSupportFolderUrl.appendingPathComponent("my_video_name")
}
func excludeFromCloudBackup(url: URL) {
var targetUrl = url
var isAlreadyExcludedFromBackup: Bool
do {
let storedRessourceValues = try targetUrl.resourceValues(forKeys: [URLResourceKey.isExcludedFromBackupKey])
isAlreadyExcludedFromBackup = storedRessourceValues.isExcludedFromBackup ?? false
}
catch {
fatalError()
}
guard !isAlreadyExcludedFromBackup else {
return
}
var ressourceValues = URLResourceValues()
ressourceValues.isExcludedFromBackup = true
do {
try targetUrl.setResourceValues(ressourceValues)
}
catch {
fatalError()
}
}
Edit: To get the data from your PHAsset, this should work:
import Photos
func loadVideoData(phAsset: PHAsset, completion: @escaping (Data?)->()) {
guard phAsset.mediaType == .video else {
return completion(nil)
}
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = true
options.deliveryMode = .highQualityFormat
PHCachingImageManager().requestAVAsset(forVideo: phAsset, options: options) { (avAsset, _, _) in
guard let avUrlAsset = avAsset as? AVURLAsset else {
return
}
var videoData: Data?
do {
videoData = try Data(contentsOf: avUrlAsset.url)
} catch {
fatalError()
}
DispatchQueue.main.async {
completion(videoData)
}
}
}
Then simply call this method and store your video in the Temporary folder:
loadVideoData(phAsset: yourPhAsset) { [weak self] videoData in
guard let strongSelf = self else { return }
guard let videoData = videoData else {
return
}
strongSelf.storeVideoToTemporaryFolder(videoData: videoData)
}
Saving array using NSUserDefaults crashes app
Looks like your code should work fine even with some really weird forced casting going on in your decoder method. Try like this:
class Task: NSObject, NSCoding {
var name = String()
var notes = String()
var date: NSDate
var taskCompleted: Bool
init(name: String, notes: String, date: NSDate, taskCompleted: Bool){
self.name = name
self.notes = notes
self.date = date
self.taskCompleted = taskCompleted
}
required init(coder decoder: NSCoder){
self.name = decoder.decodeObjectForKey("name") as! String
self.notes = decoder.decodeObjectForKey("notes") as! String
self.date = decoder.decodeObjectForKey("date") as! NSDate
self.taskCompleted = decoder.decodeBoolForKey("taskCompleted")
}
func encodeWithCoder(coder: NSCoder) {
coder.encodeObject(name, forKey: "name")
coder.encodeObject(notes, forKey: "notes")
coder.encodeObject(date, forKey: "date")
coder.encodeBool(taskCompleted, forKey: "taskCompleted")
}
}
Testing with plist files:
let task1 = Task(name: "task1", notes: "note a", date: NSDate(), taskCompleted: false)
let task2 = Task(name: "task2", notes: "note b", date: NSDate(), taskCompleted: true)
let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
let fileURL = documentsDirectory.URLByAppendingPathComponent("data.plist")
if let filePath = fileURL.path {
NSKeyedArchiver.archiveRootObject([task1,task2], toFile: filePath)
if let loadedArray = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as? [Task] {
print(loadedArray.count)
print(loadedArray.first?.name ?? "")
print(loadedArray.first?.notes ?? "")
print(loadedArray.first!.date )
print(loadedArray.first!.taskCompleted)
print(loadedArray.last?.name ?? "")
print(loadedArray.last?.notes ?? "")
print(loadedArray.last!.date )
print(loadedArray.last!.taskCompleted)
}
}
Retrieve array function not working
The value of the parameter toFile
in the method archiveRootObject
and the parameter in unarchiveObjectWithFile
must be a valid file path..
archiveRootObject
returns true
if the operation was successful, otherwise false
Related Topics
How to Calculate Uilabel Width Based on Text Length
iOS Keeping Old Launch Screen and App Icon After Update
Uitableview Row Animation Duration and Completion Callback
Where's the Difference Between Setobject:Forkey: and Setvalue:Forkey: in Nsmutabledictionary
Developing for iOS Device in Windows Environment with Flutter
How to Remove the Default Navigation Bar Space in Swiftui Navigationview
Rsa Implementations in Objective C
Detect First Launch of iOS App
How to Change Locale Programmatically with Swift
How to Get an Iso 8601 Date on iOS
Use Multiple Font Colors in a Single Label
How to Get Unique Id in iOS Device
In iOS, How to Store a Secret "Key" That Will Allow Me to Communicate with My Server
How to Fix "No Valid 'Aps-Environment' Entitlement String Found for Application" in Xcode 4.3