Search code examples
iosswiftgoogle-cloud-functions

Unsupported type error in FirebaseFunctions iOS SDK


I've integrated the Firebase SDK into my iOS app.

My issue is that when I try to call a callable cloud function passing in a Data instance or a dictionary with a Data instance as a value in a pair, it crashes.

import UIKit
import FirebaseFunctions

class ViewController: UIViewController {
    lazy var functions = Functions.functions()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let encoder = JSONEncoder()
        let item = A(i: "string")
        let encodedItem: Data = try! encoder.encode(item)
        
        functions.httpsCallable(
            "foo"
        ).call([
            "item": encodedItem
        ]) { _, _ in
            
        }
    }
}

struct A: Codable {
    let i: String
}

FirebaseFunctions.SerializerError.unsupportedType

If I don't encode the structure instance, it crashes in the same way.

If in call(_:completion:) I pass dictionaries with strings, integers or other dictionaries with strings and integers as key values, the app does not crash.

If I pass an encoded or a non-encoded A instance (not a dictionary with a key-value pair in which the encoded A instance is the value), the app crashes in a different way:

enter image description here

Is there a solution other than passing dictionaries instead of Data instances in call(_:completion:)?

Xcode 15.3, iPhone 15 Pro simulator on iOS 17.4 MacBook Air M1 8GB on macOS Sonoma 14.4.1 Firebase iOS SDK 10.22.1


Solution

  • Import FirebaseSharedSwift and set the requestAs parameter of httpsCallable(_:requestAs:responseAs:encoder:decoder:) to A.self:

    import UIKit
    import FirebaseFunctions
    
    import FirebaseSharedSwift
    
    class ViewController: UIViewController {
        lazy var functions = Functions.functions()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let item = A(i: "string")
            
            functions.httpsCallable(
                "foo",
                requestAs: A.self
            ).call([
                "item": encodedItem
            ]) { _, _ in
                
            }
        }
    }
    
    struct A: Codable {
        let i: String
    }