V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
0littleboy
V2EX  ›  iOS

iOS 开发并发问题?

  •  
  •   0littleboy · 2023-03-22 17:32:43 +08:00 · 882 次点击
    这是一个创建于 646 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在编写用户列表模块中,后端需要并发的访问 users ,因此学了一段时间的并发,遇到了很多问题,解决了大部分,但仍然感觉代码似乎有不少问题,但由于水平不够,希望大家帮忙看看,感谢

    actor UsersModel {
        private(set) var users: [User]
        private(set) var userIDs: Set<User.UserIDType>
        
        init() async {
    //        users = Bundle.main.decode(file: "allUsers.json")
            userIDs = Set(["little-boy52", "0x3f", "mindexercise", "smilyt_", "zhui-ming-zhen-bai-1", "333"])
            // 升序排列
            users = (await loadAllUsers(userIDs: userIDs)).sorted { $0.contestResults?.rating ?? 0.0 > $1.contestResults?.rating ?? 0.0 }
        }
        
        func addUser(user: User) {
            
        }
        
        func addUserByID(id: User.UserIDType) async -> Bool {
            if let user = await loadUser(userid: id) {
                users.append(user)
                userIDs.insert(id)
                return true
            }
            return false
        }
        
        func deleteUser(user: User) {
            userIDs.remove(user.id)
            users.removeAll {
                return $0.id == user.id
            }
        }
        
        func contains(id: String) -> Bool {
            userIDs.contains(id)
        }
        
    }
    
    @MainActor
    class UsersViewModel: ObservableObject {
        @Published var model: UsersModel? = nil
        
        func loadModel() async {
            let model = await UsersModel()
            DispatchQueue.main.async {
                // Update the UI on the main thread
                self.model = model
            }
        }
        
        var users: [User] {
            get async {
                if let model = model {
                    return await model.users
                } else {
                    return []
                }
            }
        }
        
        func addUser(user: User) async {
            await model?.addUser(user: user)
        }
        
        func addUserByID(id: User.UserIDType) async -> Bool {
            if model == nil {
                return false
            }
            return await model!.addUserByID(id: id)
        }
        
        func deleteUser(user: User) async {
            await model?.deleteUser(user: user)
        }
        
        func contains(id: String) async -> Bool {
            if model == nil {
                return false
            }
            return await model!.contains(id: id)
        }
    }
    

    最后调用 loadModel

    // UsersView.swift
    
    VStack {...}
    .task {
        await usersVM.loadModel()
    }
    

    我在 UsersViewModel 中定义了计算字段 users,在 SwiftUI 中调用的话需要使用 ForEach(Task {await usersVM.users}.value) { user in ... },但这样的话又会报错'async' property access in a function that does not support concurrency,如何解决?

    MakHoCheung
        1
    MakHoCheung  
       2023-03-22 18:32:54 +08:00
    好绕啊,简洁点就是
    ```
    @State var users = []
    VStack {...}
    .task {
    user = await usersVM.loadUsers()
    }
    ```
    MakHoCheung
        2
    MakHoCheung  
       2023-03-22 18:47:23 +08:00 via iPhone
    class UsersViewModel: ObservableObject {
    @Published var users = []

    @MainActor
    func addUsers(users : [User]) {
    self.users = users
    }
    }

    这种可以的,你并发拿 user 最后在 adduser 方法汇聚并切到主 actor
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2573 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 01:36 · PVG 09:36 · LAX 17:36 · JFK 20:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.