Swift 5.0中Firestore数据转对象列表无法返回使用的问题
问题根源:异步操作的执行时机
Firestore的getDocuments是异步方法——它会在后台发起网络请求获取数据,只有当请求完成后,你传入的闭包才会被执行。而你在viewDidLoad里调用getUsers()后立刻执行print(ships.count),这时候闭包还没开始执行,ships数组自然是空的,所以输出0。闭包里的打印能正常输出,是因为那部分代码是在网络请求完成、数据解码后才运行的。
解决方案1:使用闭包回调(适配Swift 5.0)
修改getUsers方法,添加一个完成回调,当数据加载并处理完成后通知调用者,这样就能在数据准备好的时机安全使用ships数组。
修改后的代码示例:
class ViewController: UIViewController { lazy var usersCollection = Firestore.firestore().collection("ship") var ships: [MyShip] = [] override func viewDidLoad() { super.viewDidLoad() getUsers { [weak self] in guard let self = self else { return } // 这里闭包执行时,ships已经完成填充 print(self.ships.count) // 在这里执行需要使用ships的逻辑,比如刷新UI } } func getUsers(completion: @escaping () -> Void) { usersCollection.getDocuments { (snapshot, error) in guard let snapshot = snapshot, error == nil else { // 处理错误情况 print(error?.localizedDescription ?? "获取数据失败") completion() return } do { let myShip: [MyShip] = try snapshot.decoded() self.ships = myShip // 直接赋值替代循环append,更高效 print(self.ships[1].nlloyds) completion() // 通知调用者数据已准备完成 } catch { print("解码失败:\(error)") completion() } } } }
关键细节:
- 添加
completion逃逸闭包参数:因为闭包会在异步操作完成后执行,需要标记为@escaping。 - 替换强制解包和尝试:原来的
try!和snapshot!会在出错时直接崩溃,改用do-catch和可选绑定处理错误,让代码更健壮。 - 使用
[weak self]避免内存泄漏:在闭包中捕获self时,用弱引用避免ViewController被意外持有导致内存泄漏。
解决方案2:升级到Swift 5.5+使用async/await(更优雅)
如果你的项目可以升级到Swift 5.5或更高版本,推荐使用async/await处理异步操作,代码会更简洁易读:
class ViewController: UIViewController { lazy var usersCollection = Firestore.firestore().collection("ship") var ships: [MyShip] = [] override func viewDidLoad() { super.viewDidLoad() // 用Task启动异步任务 Task { await getUsers() print(ships.count) // 在这里执行需要使用ships的逻辑 } } func getUsers() async { do { let snapshot = try await usersCollection.getDocuments() let myShip: [MyShip] = try snapshot.decoded() self.ships = myShip print(self.ships[1].nlloyds) } catch { print("获取或解码数据失败:\(error)") } } }
关键细节:
- 将
getUsers标记为async方法,使用try await调用Firestore的异步API(需要iOS 15+支持)。 - 在
viewDidLoad中用Task包裹异步逻辑,等待getUsers执行完成后再处理ships数组。
内容的提问来源于stack exchange,提问作者Théo MARIE
相关产品推荐
相关产品推荐

