TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: Day 68 Mini Challenge

Forums > 100 Days of SwiftUI

I was trying to do the mini challenge of creating an extension on FileManager based on the Bundle one from Project 8. I've been trying to do it, but I'm getting more confused as i continue.

Right now i have this but Im getting an error ("Generic parameter 'T' could not be inferred") when i try to use it, but i suspect i don't even know how to use this extension on the "onTapGesture"...

extension FileManager {

    func encode<T: Encodable> (data: T, file: String){
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentDirectory = paths[0]

        let url = documentDirectory.appendingPathComponent(file)

        let encoder = JSONEncoder()

        do {
            let encoded = try encoder.encode(data)
            try encoded.write(to: url)
        } catch {
            fatalError("Error encoding...")
        }
    }

    func decode<T: Decodable> (_ file: String) -> T {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentDirectory = paths[0]

        let url = documentDirectory.appendingPathComponent(file)

        guard let data = try? Data(contentsOf: url) else {
            fatalError("Failed to load \(file)")
        }

        let decoder = JSONDecoder()

        guard let loaded = try? decoder.decode(T.self, from: data) else {
            fatalError("Failed to decode \(file)")
        }

        return loaded
    }
}
struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .onTapGesture {
                FileManager.default.encode(data: "Test 222", file: "message.txt")
                do {
                    let result = FileManager.default.decode("message.txt")
                    print(String(contentsOf: result))
                }
            }
    }
}

2      

The code you provided seems to be an extension on the FileManager class in Swift, allowing you to encode and decode data using JSONEncoder and JSONDecoder respectively. It appears that you're encountering an error when trying to use the extension in the onTapGesture closure.

To fix the error ("Generic parameter 'T' could not be inferred"), you need to explicitly specify the type you want to decode when calling the decode method. In this case, since you're encoding a String, you should specify String as the type when decoding. Here's an updated version of your code:

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .onTapGesture {
                FileManager.default.encode(data: "Test 222", file: "message.txt")
                let result: String = FileManager.default.decode("message.txt")
                print(result)
            }
    }
}

In the updated code, we explicitly specify String as the type when calling the decode method. This resolves the "Generic parameter 'T' could not be inferred" error.

Please note that you should be cautious when force unwrapping and using fatalError in production code. These are used here for simplicity, but in real-world scenarios, you would want to handle errors more gracefully. ehsaasweb.com

3      

First of all i need to share some thoughts about generics -

Generics encourage you to avoid repeating yourself by packaging common operations into reusable functions. The goal is to write code that’s readable at a glance.

So now we look at the code you have used here

func decode<T: Decodable> (_ file: String) -> T

this funtion will be able to perform action on any type that is decodable but the input parameter being passed has to be string , also it will be able to return any type that is decodable.

Now the error come as you did not mention the type of what you are dealing with in regard to this funciton, it could be any where you might have missed.

So generics provide us the ability to not use a concrete type when defining a function , instead that concrete type like string can be used when we use this funciton, then we only have to be sure that it is in sync if it were be a function with concrete types.

Ofcourse the error messages you get will keep mentioning generics but that is natural.

3      

Thank you both for the explanation. Cleaned my code a bit and specified the type on the onTapGesture. It's working fine now.

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .onTapGesture {
                FileManager.default.encode(data: "Test 222", file: "message.txt")
                let result: String = FileManager.default.decode("message.txt")
                print(result)
            }
    }
}

extension FileManager {

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

    func encode<T: Encodable> (data: T, file: String){

        let url = getDocumentsDirectory().appendingPathComponent(file)

        let encoder = JSONEncoder()

        guard let encoded = try? encoder.encode(data) else {
            fatalError("Error encoding data")
        }

        do {
        try encoded.write(to: url)
        } catch {
            fatalError("Error writing data to \(url)")
        }
    }

    func decode<T: Decodable> (_ file: String) -> T {

        let url = getDocumentsDirectory().appendingPathComponent(file)

        guard let data = try? Data(contentsOf: url) else {
            fatalError("Failed to load \(file)")
        }

        let decoder = JSONDecoder()

        guard let loaded = try? decoder.decode(T.self, from: data) else {
            fatalError("Failed to decode \(file)")
        }

        return loaded
    }
}

2      

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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.