Created
July 17, 2018 08:10
-
-
Save aornano/a27691b6b40994dc4d63ef40a9092be9 to your computer and use it in GitHub Desktop.
A good Swift 4.x example to store generic encodable/decodable objects to file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
class Storage { | |
fileprivate init() { } | |
enum Directory { | |
case documents | |
case caches | |
} | |
/// Returns URL constructed from specified directory | |
static fileprivate func getURL(for directory: Directory) -> URL? { | |
var searchPathDirectory: FileManager.SearchPathDirectory | |
switch directory { | |
case .documents: | |
searchPathDirectory = .documentDirectory | |
case .caches: | |
searchPathDirectory = .cachesDirectory | |
} | |
if let url = FileManager.default.urls(for: searchPathDirectory, in: .userDomainMask).first { | |
return url | |
} else { | |
print(" -E- Could not create URL for specified directory!") | |
return nil | |
} | |
} | |
/// Store an encodable struct to the specified directory on disk | |
/// | |
/// - Parameters: | |
/// - object: the encodable struct to store | |
/// - directory: where to store the struct | |
/// - fileName: what to name the file where the struct data will be stored | |
static func store<T: Encodable>(_ object: T, to directory: Directory, as fileName: String)->Bool { | |
if let root = getURL(for: directory) { | |
let url = root.appendingPathComponent(fileName, isDirectory: false) | |
let encoder = JSONEncoder() | |
do { | |
let data = try encoder.encode(object) | |
if FileManager.default.fileExists(atPath: url.path) { | |
try FileManager.default.removeItem(at: url) | |
} | |
FileManager.default.createFile(atPath: url.path, contents: data, attributes: nil) | |
return true | |
} catch { | |
print(error.localizedDescription) | |
return false | |
} | |
} else { | |
return false | |
} | |
} | |
/// Retrieve and convert a struct from a file on disk | |
/// | |
/// - Parameters: | |
/// - fileName: name of the file where struct data is stored | |
/// - directory: directory where struct data is stored | |
/// - type: struct type (i.e. Message.self) | |
/// - Returns: decoded struct model(s) of data | |
static func retrieve<T: Decodable>(_ fileName: String, from directory: Directory, as type: T.Type) -> T? { | |
if let root = getURL(for: directory) { | |
let url = root.appendingPathComponent(fileName, isDirectory: false) | |
if !FileManager.default.fileExists(atPath: url.path) { | |
print(" -W- File at path \(url.path) does not exist!") | |
return nil | |
} | |
if let data = FileManager.default.contents(atPath: url.path) { | |
let decoder = JSONDecoder() | |
do { | |
let model = try decoder.decode(type, from: data) | |
return model | |
} catch { | |
print(" -E- \(type) \(error.localizedDescription)") | |
return nil | |
} | |
} else { | |
print(" -W- No data at \(url.path)!") | |
return nil | |
} | |
} else { | |
return nil | |
} | |
} | |
/// Remove all files at specified directory | |
static func clear(_ directory: Directory)->Bool { | |
if let url = getURL(for: directory) { | |
do { | |
let contents = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: []) | |
for fileUrl in contents { | |
try FileManager.default.removeItem(at: fileUrl) | |
} | |
return true | |
} catch { | |
print(error.localizedDescription) | |
return false | |
} | |
} else { | |
return false | |
} | |
} | |
/// Remove specified file from specified directory | |
static func remove(_ fileName: String, from directory: Directory)->Bool { | |
if let root = getURL(for: directory) { | |
let url = root.appendingPathComponent(fileName, isDirectory: false) | |
if FileManager.default.fileExists(atPath: url.path) { | |
do { | |
try FileManager.default.removeItem(at: url) | |
return true | |
} catch { | |
print(error.localizedDescription) | |
return false | |
} | |
} else { | |
return false | |
} | |
} else { | |
return false | |
} | |
} | |
/// Returns BOOL indicating whether file exists at specified directory with specified file name | |
static func fileExists(_ fileName: String, in directory: Directory)-> Bool { | |
if let root = getURL(for: directory) { | |
let url = root.appendingPathComponent(fileName, isDirectory: false) | |
return FileManager.default.fileExists(atPath: url.path) | |
} else { | |
return false | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment