ios - 完成问题

标签 ios swift grand-central-dispatch

所以我正在尝试为我的初始 View Controller 实现一个 revelaingSplashView。我最初的 vc 有几个数据库调用似乎以奇怪的顺序完成。经过一些跟踪后,我将其缩小到完成 block 最后发生的特定功能。我在这里列出的

@objc func grabFriendsEvents(){
    print("Attempting to see where your friends are going")
    UserService.following { (user) in
        for following in user {
            print(following.username as Any)
            PostService.showFollowingEvent(for: following.uid, completion: { (event) in
                self.friendsEvents.append(event)
               // self.friendsEvents.append(contentsOf: event)
                // leave here
                self.friendsEvents = self.friendsEvents.removeDuplicates()
                print("ending in friends events")
                self.collectionView?.reloadData()
            })

        }  

    }
}

下面列出了我实现的服务方法中的两个支持函数。

static func following(for user: User = User.current, completion: @escaping ([User]) -> Void) {
    // 1
    let followingRef = Database.database().reference().child("following").child(user.uid)
    followingRef.observeSingleEvent(of: .value, with: { (snapshot) in
        // 2
        guard let followingDict = snapshot.value as? [String : Bool] else {
            return completion([])
        }

        // 3
        var following = [User]()
        let dispatchGroup = DispatchGroup()

        for uid in followingDict.keys {
            dispatchGroup.enter()

            show(forUID: uid) { user in
                if let user = user {
                    following.append(user)
                }

                dispatchGroup.leave()
            }
        }

        // 4
        dispatchGroup.notify(queue: .main) {
            completion(following)
        }
    })
}

第二个在这里列出

static func showFollowingEvent(for followerKey: String,completion: @escaping (Event) -> Void) {
    //getting firebase root directory
    let ref = Database.database().reference()

    ref.child("users").child(followerKey).child("Attending").observeSingleEvent(of: .value, with: { (attendingSnapshot) in
        print(attendingSnapshot)
        guard var eventKeys = attendingSnapshot.children.allObjects as? [DataSnapshot] else{return}
        for event in eventKeys{
            let dispatchGroup = DispatchGroup()
            dispatchGroup.enter()
            EventService.show(forEventKey: event.key, completion: { (event) in
                dispatchGroup.leave()
                completion(event!)
            })
        }
    }) { (err) in
        print("couldn't grab event info",err)

    }
}

现在 grabFriendsEvents 返回几次,具体取决于您拥有的 friend 数量和他们参加的事件。我试图找出知道什么时候完成的方法,这样我就可以忽略揭示性的观点。我认为调度组可能是可行的方法,但我不确定将它放在哪里。非常感谢任何帮助。

最佳答案

  1. 在 grabFriendsEvents 中:PostService.showFollowingEvent 也是一个循环调用的异步函数,因此您也需要为其添加一个调度队列。

    let dispatchGroup = DispatchGroup()
    for following in user {
        print(following.username as Any)
        dispatchGroup.enter()
        PostService.showFollowingEvent(for: following.uid, completion: { (event) in
            self.friendsEvents.append(event)
           // self.friendsEvents.append(contentsOf: event)
            // leave here
            self.friendsEvents = self.friendsEvents.removeDuplicates()
            print("ending in friends events")
            self.collectionView?.reloadData()
            dispatchGroup.leave()
        })
    
    } 
    dispatchGroup.notify(queue: .main) {
        // dismiss the revealing view
    }
    
  2. 在 showFollowingEvent 中你永远不会调用 dispatchGroup.notify,这就是它多次触发的原因

  3. 我知道可能不行,但最好重组API调用

关于ios - 完成问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50034336/

相关文章:

iOS - UI 自动化多个脚本与重置应用程序

ios - 由于 PanGesture,快速获取 EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP, subcode=0x0)

ios - sqlite3_prepare_v2 崩溃 - 已经在运行之前的查询

ios - IQKeyboardManager 从 UITextField 导航到 UITextView

ios - 如何在 IOS 5 上更改图层的分辨率

ios - Web View 为构建的应用程序加载页面,但不测试飞行部署的版本

Swift 游戏碰撞检测和物理 - Sprite 和背景

swift - Autolayout - 带有 ImageView 的 UITableViewCell - 边距?

iphone - 如何通过NSOperation实现并发任务?

swift - 如果在串行 DispatchQueue 中触发上下文切换会发生什么情况?