skip to Main Content

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

2

Answers


  1. Chosen as BEST ANSWER

    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
    }
    

  2. The accepted types for httpsCallable are:

    • nil or NSNull
    • String
    • NSNumber, or any Swift numeric type bridgeable to NSNumber
    • [Any], where the contained objects are also one of these types.
    • [String: Any] where the values are also one of these types.

    You are attempting to send JSON encoded as Data, which is not on the list

    You could convert your JSON Data back to a String and send that, then in your cloud function parse that JSON string back to an object.

    Alternatively you could use GCP cloud run rather than Firebase functions. This is a much more flexible environment, but it does need more set up and you don’t get some of the in-built functionality of cloud functions.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search