Here’s a quick file I/O example using Swift.
To load a file first we need a URL for the file to load. This will usually point to a local resource, either in your app’s bundle or from your documents folder.
Loading from (app) bundle
Include it in your bundle
First, include the file in your bundle by adding it in the Build Phases for your app’s target, under Copy Bundle Resources.
Then load the file
To load from your App’s bundle (or any other bundle), use
Bundle.url(forResource:withExtension:)
,
then initialize a Data
object using the
Data(contentsOf:)
initializer in a do ... catch
block:
enum File {
static func appData(from file: String, in bundle: Bundle = .main) -> Data? {
guard let path = bundle.url(forResource: file, withExtension: nil) else {
return nil
}
var data: Data?
do {
data = try Data(contentsOf: path)
}
catch {
print("Error reading data: \(error)")
}
return data
}
}
Loading from a local file
To load from a local file we can use FileManager
:
/// find user's home folder
private static var homeFolder: URL? {
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
}
static func data(from file: String) -> Data? {
guard let path = homeFolder?.appendingPathComponent(file) else {
return nil
}
var data: Data?
do {
data = try Data(contentsOf: path)
}
catch {
print("Error reading data: \(error)")
}
return data
}
Converting data
Now we can convert the data.
To string
Use String(data:encoding:)
:
func loadTextFile() {
let data = File.appData(from: File.Sample.text)!
let string = String(data: data, encoding: .utf8)
print(string)
}
Decoding JSON, or other Decodable
types:
Take the data from the file load and decode it using the appropriate decoder:
private static func decode<T: Decodable>(data: Data) -> T? {
do {
return try JSONDecoder().decode(T.self, from: data)
}
catch {
print("Error decoding file: \(error)")
}
return nil
}
Here I swallow exceptions and return an optional to make a simple example, cater to your own needs.
Writing a file
You can write files using Data.write(to:)
. You can
Example generic function to write to a json file:
func write<T: Encodable>(_ object: T, toJson file: String) {
guard let path = File.homeFolder?.appendingPathComponent(file) else {
return
}
do {
let data = try JSONEncoder().encode(object)
try data.write(to: path)
}
catch {
print("Could not write file \(path): \(error)")
}
}
Another approach could be to extend Encodable
and implement a new write(toJson:)
method:
extension Encodable {
/// writes object to json file in home folder
func write(toJson file: String) {
guard let path = File.homeFolder?.appendingPathComponent(file) else {
return
}
do {
let data = try JSONEncoder().encode(self)
try data.write(to: path)
}
catch {
print("Could not write file \(path): \(error)")
}
}
}