首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UICollisionBehavior和UIGravityBehavior与DispatchQueue不能按预期工作

UICollisionBehavior和UIGravityBehavior与DispatchQueue不能按预期工作
EN

Stack Overflow用户
提问于 2019-04-15 01:54:12
回答 1查看 48关注 0票数 0

我目前正在为一个框架设计UI,这个框架可以播放Connect4。这个框架被封装在一个名为GameSession的类中。我不会描述它的API的细节和它是如何操作的。我不认为这很重要。

我相信我可能误解了分派队列,并且我没有正确地使用它们。但是,我无穷无尽地寻找,没有找到任何暗示我的问题的解决方案。

这里有一个关于正在发生的事情的简短解释。控制移动的方法是playGame(botStarts: Bool,atColumn: Int)。在此方法中,使用名为addBoundary(atRow: Int,atColumn: Int)的方法在正确的行和列处添加碰撞边界。然后,使用名为dropDisc(atColumn: Int,color: UIColor)的方法创建光盘。此方法创建自定义UIView,将其添加到屏幕上的视图中,并添加碰撞和重力行为。它会下降,直到到达之前添加的边界。

在playGame()中,我使用DispatchMain.Queue.async{dropDisc()}将光盘放到屏幕上。但是,每次我第二次或以后调用playGame()时,自定义圆盘都会绘制在屏幕顶部,但它们无法落下。在第一次迭代中,它们被绘制并按预期下降。

下面是我在上面引用的函数。

代码语言:javascript
复制
private func playGame(botStarts: Bool, dropPieceAt: Int) {
        DispatchQueue.global(qos: .userInitiated).async {
            if botStarts {
                if let move = gameSession.move {
                    let column = move.action % self.gameSession.boardLayout.columns
                    let row = move.action / self.gameSession.boardLayout.columns
                    self.addBoundary(atRow: row, atColumn: column)
                    DispatchQueue.main.async {
                        self.dropDisc(atColumn: column, color: move.color)
                    }
                }
            } else {
                let column = dropPieceAt
                if self.gameSession.userPlay(at: column) {
                    if let move = self.gameSession.move {
                        print(move)
                        let column = move.action % self.gameSession.boardLayout.columns
                        let row = move.action / self.gameSession.boardLayout.columns
                        self.addBoundary(atRow: row, atColumn: column)
                        DispatchQueue.main.async {
                            self.dropDisc(atColumn: column, color: move.color)
                        }
                    }
                    if let move = self.gameSession.move {
                        let column = move.action % self.gameSession.boardLayout.columns
                        let row = move.action / self.gameSession.boardLayout.columns
                        self.addBoundary(atRow: row, atColumn: column)
                        DispatchQueue.main.async {
                            self.dropDisc(atColumn: column, color: move.color)
                        }
                    }
                }
                if self.gameSession.done {
                    if let outcome = self.gameSession.outcome {
                        DispatchQueue.main.async {
                            self.gameLabel.text = outcome.message + "\n Winning pieces \(outcome.winningPieces)"
                        }
                    }
                }
            }
        }
    }


 private func dropDisc(atColumn: Int, color: UIColor) {
        var frame = CGRect()
        frame.origin = CGPoint.zero
        frame.size = Constants.bubbleSize
        let x = CGFloat(39) + CGFloat(47 * atColumn)
        frame.origin.x = x
        let bubbleView = DiscView(frame: frame, color: color)
        gameView.addSubview(bubbleView)
        collider.addItem(bubbleView)
        gravity.addItem(bubbleView)
    }



    // Adds a boundary using the row and column obtained from game session.
    private func addBoundary(atRow: Int, atColumn: Int) {
        let fromCoordX = CGFloat(16 + (boardView.initialX-boardView.radius)) + CGFloat(47 * atColumn)
        let toCoordX = fromCoordX + CGFloat(24)
        let coordY =  CGFloat(198.5 + (boardView.initialY+boardView.radius)) + CGFloat(45 * atRow)
        let fromPoint = CGPoint(x: fromCoordX, y: coordY+1)
        let toPoint = CGPoint(x: toCoordX, y: coordY+1)
        self.collider.addBoundary(withIdentifier: "boundary" as NSCopying, from: fromPoint, to: toPoint)
        self.drawLineFromPoint(start: fromPoint, toPoint: toPoint, ofColor: UIColor.red, inView: self.gameView)

    }

这是我的屏幕截图:https://imgur.com/7M3fklo

在底行,您可以看到users光盘(黄色)和机器人光盘(红色)。这些是在第一次调用playGame()时添加的。但是,在顶部,您可以看到在第二次调用playGame()时添加的两个磁盘。这些不会掉下来。

不管我试过什么

任何反馈都是非常感谢的!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-15 03:38:07

后台线程化很困难,应该只在绝对必要的时候使用(因为它是被迫的,或者因为你有一个耗时的活动要执行,而你不想冻结属于主线程的接口)。这里似乎没有必要这样做。你没有做任何耗时的事情。而且看起来DispatchQueue.global的使用可能会让您感到困惑;后台调度队列会导致您的代码无序运行,而您显然没有意识到这一点。

解决方案:去掉所有的DispatchQueue.globalDispatchQueue.main代码。(换句话说,删除这些行并匹配右大括号行。)然后一切都会在主队列上运行,没有理由不这样做。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55678315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档