WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Day 68: Documents Directory challenge

Forums > 100 Days of SwiftUI

Hello,

i tryed to solve this challange but I don´t get it so far. Can someone share there solution with me and tell me how you did it?

Kind regards Maxi

   

This was my solution to that:

extension FileManager {
    func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }

    func decode<T: Codable>(_ fromFile: String) -> T? {
        let url = getDocumentsDirectory().appendingPathComponent(fromFile)
        let decoder = JSONDecoder()

        do {
            let savedData = try Data(contentsOf: url)
            do {
                let decodedData = try decoder.decode(T.self, from: savedData)
                return decodedData
            } catch {
                print(error.localizedDescription)
                print("Decoding Failed!")
            }
        } catch {
            print(error.localizedDescription)
            print("Read Failed!")
        }
        return nil
    }

    func encode<T: Codable>(_ data: T, toFile fileName: String) {
        let encoder = JSONEncoder()

        do {
            let encoded = try encoder.encode(data)
            let url = getDocumentsDirectory().appendingPathComponent(fileName)
            do {
                try encoded.write(to: url)
            } catch {
                print(error.localizedDescription)
                print("Write Failed!")
            }
        } catch {
            print(error.localizedDescription)
            print("Encoding Failed!")
        }
    }
}

I found this to be difficult to figure out as well. I used Paul's Bundle-Decodable that he had given us previously as template:

extension Bundle {
    func decode<T: Codable>(_ file: String) -> T {
        guard let fileUrl = self.url(forResource: file, withExtension: nil) else {
            fatalError("Failed to find \(file) in bundle.")
        }
        guard let data = try? Data(contentsOf: fileUrl) else {
            fatalError("Failed to load \(file) from bundle.")
        }
        guard let decodedData = try? JSONDecoder().decode(T.self, from: data) else {
            fatalError("Failed to decode \(file) from bundle.")
        }
        return decodedData
    }
}

I took it one step at a time and figured out the code for performing the encode and decode without using generics and without using an extension. Once I got that working, I implemented the generics. Once I got that working I implemented the extension. This is not a totally complete solution if you're decoding dates but that wasn't part of this particular challenge either. I also don't think you need to nest one do try catch inside the other but it was helpful to me to get the specific print messages that were more helpful to me than the error.localizedDescription.

That's another thing I did when I was trying to figure it out. I had print statements all over the place to see what was working and what wasn't working.

2      

This is another version of it I had done:

extension FileManager {
    func getDocumentsDirectory() -> URL {
        let paths = Self.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }
    func encode<T: Codable>(_ file: String, data: T) {
        if let encoded = try? JSONEncoder().encode(data) {
            let url = Self.default.getDocumentsDirectory().appendingPathComponent(file)
            do {
                try encoded.write(to: url)
            } catch {
                print(error.localizedDescription)
            }
        }
    }
    func decode<T: Codable>(_ file: String) -> T? {
        let url = Self.default.getDocumentsDirectory().appendingPathComponent(file)
        if let savedItems = try? Data(contentsOf: url) {
            if let decodedItems = try? JSONDecoder().decode(T.self, from: savedItems) {
                return decodedItems
            }
        }
        return nil
    }
}

This version doesn't give much error information if something goes wrong though.

2      

Thank you very much. I like the solution with many print statemants. Like you said you see exactly which line cause the program to crash and which line is good.

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.