You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift自定义数组追加元素后计数始终为0,求解决方案

问题原因
  • COLLECTION_USER.document(user).getDocument是异步网络请求,传入的闭包会在请求完成后才执行,而你在循环结束后立刻打印数组计数,这时候所有闭包里的append操作都还没触发,所以数组长度始终为0。
解决方案

方案1:用DispatchGroup跟踪异步任务

通过DispatchGroup标记每个异步任务的开始和结束,等所有请求完成后再处理数组:

func fetchLocations(usersID: [String]){
    var annotationsToReturn : [UserAnnotations] = []
    let group = DispatchGroup() // 创建调度组
    
    for user in usersID {
        group.enter() // 标记当前任务开始
        COLLECTION_USER.document(user).getDocument { snapshot, err in
            defer { group.leave() } // 确保任务结束时标记完成,不管成功失败
            
            if err != nil {
                print("ERROR")
                return
            }
            
            let data = snapshot?.data() as? [String:Any] ?? [:]
            
            // 安全解包,避免强制解包崩溃
            guard let latitude = data["latitude"] as? CLLocationDegrees,
                  let longitude = data["longitude"] as? CLLocationDegrees else {
                print("Invalid location data")
                return
            }
            
            print("latitude: \(latitude)")
            annotationsToReturn.append(UserAnnotations(user: User(dictionary: data), coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude)))
        }
    }
    
    // 等待所有任务完成后执行后续操作
    group.notify(queue: .main) {
        print("count: \(annotationsToReturn.count)")
        // 这里可以使用填充好的annotationsToReturn做其他业务操作
    }
}

方案2:用Async/Await(Swift 5.5+)

如果项目支持Swift 5.5及以上版本,用async/await写法更简洁,避免闭包嵌套:

func fetchLocations(usersID: [String]) async {
    var annotationsToReturn : [UserAnnotations] = []
    
    for user in usersID {
        do {
            let snapshot = try await COLLECTION_USER.document(user).getDocument()
            let data = snapshot.data() as? [String:Any] ?? [:]
            
            guard let latitude = data["latitude"] as? CLLocationDegrees,
                  let longitude = data["longitude"] as? CLLocationDegrees else {
                print("Invalid location data")
                continue
            }
            
            print("latitude: \(latitude)")
            annotationsToReturn.append(UserAnnotations(user: User(dictionary: data), coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude)))
        } catch {
            print("ERROR: \(error.localizedDescription)")
        }
    }
    
    print("count: \(annotationsToReturn.count)")
    // 后续可直接使用annotationsToReturn
}

调用该方法时需要在异步上下文里执行:

// 示例:在ViewController的viewDidLoad中调用
override func viewDidLoad() {
    super.viewDidLoad()
    Task {
        await fetchLocations(usersID: ["user_id_1", "user_id_2"])
    }
}

注意:原代码里的强制解包latitude as! CLLocationDegrees存在崩溃风险,建议换成上述代码中的guard let安全解包方式。

内容的提问来源于stack exchange,提问作者bruce_blake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 17:48:08