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

Swift:等待阻塞用户数组加载完成后再调用FireStore获取用户函数

解决方案:串行加载并过滤用户数据

我来帮你搞定这个问题!核心问题在于当前两个异步请求是并行执行的,导致获取全量用户的请求先完成时,阻塞用户数组还没加载好,没法实时过滤。而didSet的问题是它会在数组每次变更时触发,导致重复发起请求,自然就出现了重复用户。

具体实现方案(分两种常见场景)

1. 用Swift 5.5+的async/await(推荐)

这种方式代码更简洁易读,能天然保证请求的串行顺序:

// 定义一个专门负责加载并过滤用户的方法
func loadAndFilterUsers() async {
    do {
        // 第一步:先获取阻塞用户数组,等待请求完成
        let blockedUsers = try await fetchArrayOfUsersBlockingTheCurrentUser()
        
        // 第二步:拿到阻塞数组后,再请求全量用户
        let allUsers = try await fireStoreFetchUsers()
        
        // 第三步:剔除阻塞用户,得到最终要展示的列表
        let filteredUsers = allUsers.filter { user in
            !blockedUsers.contains(user.id) // 这里假设用户有唯一标识id,根据你的实际字段调整
        }
        
        // 回到主队列更新UI(必须保证UI操作在主线程)
        DispatchQueue.main.async {
            self.displayedUsers = filteredUsers
        }
    } catch {
        // 处理请求失败的情况,比如打印错误、显示提示弹窗
        print("加载用户数据失败:\(error.localizedDescription)")
    }
}

然后在页面的生命周期里只调用一次这个方法:

  • 如果是SwiftUI,用.task修饰符(只会在视图出现时执行一次,消失时自动取消):
    var body: some View {
        UserListView(users: displayedUsers)
            .task {
                await loadAndFilterUsers()
            }
    }
    
  • 如果是UIKit,在viewWillAppear里判断列表为空时才加载,避免每次进入页面都重复请求:
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if displayedUsers.isEmpty {
            Task {
                await loadAndFilterUsers()
            }
        }
    }
    

2. 用传统的Completion Handler(兼容老版本Swift)

如果你还没升级到支持async/await的版本,可以用嵌套的闭包保证串行顺序:

func loadAndFilterUsers() {
    // 第一步:先请求阻塞用户数组
    fetchArrayOfUsersBlockingTheCurrentUser { [weak self] blockedUsers in
        guard let self = self else { return }
        
        // 第二步:拿到阻塞数组后再请求全量用户
        self.fireStoreFetchUsers { allUsers in
            // 过滤阻塞用户
            let filteredUsers = allUsers.filter { !blockedUsers.contains($0.id) }
            
            // 主线程更新UI
            DispatchQueue.main.async {
                self.displayedUsers = filteredUsers
            }
        }
    }
}

调用时机和上面一样,在页面初始化/出现时只执行一次即可。

为什么didSet会导致重复用户?

didSet会在displayedUsers每次被赋值时触发,如果在didSet里调用fireStoreFetchUsers(),会导致:

  1. 第一次加载时设置数组,触发didSet再次发起请求
  2. 新请求返回后又赋值数组,再次触发didSet,形成循环
  3. 多次请求返回的用户列表叠加,就出现了重复用户

所以一定要避免在didSet里触发数据请求,把加载逻辑放在专门的方法里,只在合适的时机执行一次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:22:37