Я интегрировал Firebase SDK в свое приложение для iOS.
Моя проблема в том, что когда я пытаюсь вызвать вызываемую облачную функцию, передающую экземпляр Data или словарь с экземпляром Data в качестве значения в паре, происходит сбой.
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
}
Если я не закодирую экземпляр структуры, он выйдет из строя таким же образом.
Если в call(_:completion:) я передаю словари со строками, целыми числами или другие словари со строками и целыми числами в качестве ключевых значений, приложение не аварийно завершает работу.
Если я передаю закодированный или незакодированный экземпляр A (а не словарь с парой ключ-значение, в котором закодированный экземпляр A является значением), приложение аварийно завершает работу по-другому:
Есть ли другое решение, кроме передачи словарей вместо экземпляров Data в call(_:completion:)?
Xcode 15.3, симулятор iPhone 15 Pro на iOS 17.4 MacBook Air M1 8 ГБ на macOS Sonoma 14.4.1 SDK Firebase для iOS 10.22.1





Принятые типы для httpsCallable:
nil или NSNullStringNSNumber или любой числовой тип Swift, соединяемый с NSNumber[Any], где содержащиеся объекты также относятся к одному из этих типов.[String: Any] где значения также относятся к одному из этих типов.Вы пытаетесь отправить JSON в кодировке Data, которого нет в списке.
Вы можете преобразовать свой JSON Data обратно в String и отправить его, а затем в своей облачной функции проанализировать эту строку JSON обратно в объект.
В качестве альтернативы вы можете использовать облачный запуск GCP, а не функции Firebase. Это гораздо более гибкая среда, но она требует дополнительной настройки, и вы не получаете некоторых встроенных функций облачных функций.
Импортируйте FirebaseSharedSwift и установите для параметра requestAs значение httpsCallable(_:requestAs:responseAs:encoder:decoder:):
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
}
Я использую это расширение для преобразования объектов Encodable в формат словаря ([String: Any]):
extension Encodable {
func toDictionary() -> [String: Any]? {
do {
let data = try JSONEncoder().encode(self)
if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
return jsonObject
}
} catch {
print(error.localizedDescription)
}
return nil
}
}