[英]UICollisionBehavior and UIGravityBehavior not working as expected with DispatchQueue
我目前正在為一個已設計為可玩connect 4的框架設計UI。該框架封裝在一個名為GameSession的類中。 我不會描述它的API的來龍去脈以及它的運行方式。 我不認為這很重要。
我相信我可能會誤解調度隊列,並且使用不正確。 但是,我進行了無休止的搜索,沒有發現任何暗示解決我的問題的方法。
這里是對正在發生的事情的簡短解釋。 控制移動的方法是playGame(botStarts:Bool,atColumn:Int)。 在此方法中,使用稱為addBoundary(atRow:Int,atColumn:Int)的方法在正確的行和列處添加碰撞邊界。 然后,使用稱為dropDisc(atColumn:Int,color:UIColor)的方法創建光盤。 此方法創建一個自定義UIView,將其添加到屏幕上的視圖中,並添加碰撞和重力行為。 它下降直到到達先前添加的邊界。
在playGame()中,我使用DispatchMain.Queue.async {dropDisc()}將光盤放到屏幕上。 但是,每次第二次及以后調用playGame()時,自定義光盤都會繪制在屏幕頂部,但它們不會掉落。 在第一次迭代中,它們將按預期繪制並掉落。
以下是我上面引用的功能。
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 。
在底行,您可以看到用戶光盤(黃色)和機器人光盤(紅色)。 這些是在首次調用playGame()時添加的。 但是,在頂部,您可以看到在對playGame()的第二次調用中添加的兩張光盤。 這些不倒。
不管我嘗試了什么
任何反饋都非常感謝!
后台線程很難,並且僅在絕對必要時才使用(因為它被強加於您,或者因為您執行一項耗時的活動並且您不想凍結該主線程擁有的接口) )。 這里似乎沒有必要。 您沒有做任何耗時的事情。 看起來使用DispatchQueue.global
可能會使您感到困惑; 后台調度隊列會導致您的代碼亂序運行,顯然您並不知道這一點。
解決方案:刪除所有DispatchQueue.global
和DispatchQueue.main
代碼。 (換句話說,消除這些行並匹配正確的大括號行。)然后,所有內容將只在主隊列上運行,沒有理由不這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.