在 swift 中使用 while 来检查状态会使 iOS 手机过热

问题描述 投票:0回答:1

我正在尝试使用 swift 在 iOS 中实现一个简单的游戏。游戏为回合制;第一个玩家移动,然后是第二个玩家,然后是第一个…… 我为此使用了一个协议:

class PersonAgent: AgentProtocol {
    let agentType: AgentType = .person
    let color: UIColor
    var points: Int = 0
    private var tappedLine: Line?

    init(color: UIColor) {
        self.color = color
    }

    func action() async -> Line {
        while self.tappedLine == nil {}
        guard let tappedLine = self.tappedLine else { fatalError() }
        self.tappedLine = nil
        return tappedLine
    }

    func tapped(line: Line) {
        self.tappedLine = line
    }
}

当用户点击按钮时,视图控制器调用点击的函数,之后,操作方法可以返回一些内容。问题是,对于这样一个简单的游戏来说,手机会变得过热。我可以在不使用 while 的情况下达到相同的功能吗?有什么建议可以提高CPU和内存虎钳的效率吗?

为了让事情更清楚,我在视图控制器中有这段代码:

extension BoardViewController {
    private func game() {
        print(#function)
        Task {
            print("inside task")
            while self.shouldResumeGame() {
                print("Turn Iteration")
                var shouldChangeTurn = true
                let currentAgent: AgentProtocol
                switch self.turn {
                case .first:
                    currentAgent = self.firstAgent
                case .second:
                    currentAgent = self.secondAgent
                }

                let actionResult = await currentAgent.action()
                // some logic here
            }

            let message: String
            if self.firstAgent.points > self.secondAgent.points {
                message = "First Player Won"
            } else if self.firstAgent.points < self.secondAgent.points {
                message = "Second Player Won"
            } else {
                message = "Draw"
            }

            // MARK: Game finished

            let alert = UIAlertController(title: "Game Finished", message: message, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { [weak self] _ in
                self?.navigationController?.popViewController(animated: true)
            }))
            self.present(alert, animated: true)
        }
    }

    private func shouldResumeGame() -> Bool {
        return self.firstAgent.points + self.secondAgent.points != 60
    }
}
ios swift async-await while-loop cpu-usage
1个回答
0
投票

不要使用

while
循环。这是投票

现代应用程序使用事件驱动的方法,其中用户交互或计时器触发等事件会触发操作。

例如,

while self.tappedLine == nil {}
将执行每秒数百万次

您没有提供足够的信息让我给您一个完整的答案,但是重构

PersonAgent
的一种方法是使用
CheckedContinuation
:

class PersonAgent:AgentProtocol {
    let agentType: AgentType = .person
    let color: UIColor
    var points: Int = 0
    var continuation: CheckedContinuation<Line,Never>?

    init(color: UIColor) {
        self.color = color
    }
    
    func action() async -> Line {
        guard self.continuation == nil else {
            fatalError("Action called while already awaiting")
        }
        let tappedLine = await withCheckedContinuation { continuation in
            self.continuation=continuation
        }
        self.continuation = nil
        return tappedLine
    }
    
    func tapped(line: Line) {
        self.continuation?.resume(returning:line)
    }
}

现在该线路没有轮询。

action
函数创建一个延续并等待它被恢复。
tapped
函数恢复所点击的线的延续。

© www.soinside.com 2019 - 2024. All rights reserved.