微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

进入后台时如何隐藏游戏状态

如何解决进入后台时如何隐藏游戏状态

我正在用 SpriteKit 编写一个逻辑益智游戏,该游戏可在 iPad 上玩,并且与时间赛跑,当应用程序进入后台时,我正在努力将拼图巧妙地隐藏起来。

问题是用户不应该双击主页按钮并在应用切换器中看到完整的拼图,因为这将允许他们在没有时钟运行的情况下完成它。

这是我想出的解决方案:

在单例 GameManager 中有一个 SKTexture() 变量,用于保存屏幕截图纹理,而在我的 AppDelegate 中,我有

func applicationWillResignActive(_ application: UIApplication) {
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "resigning"),object: self)
        
    let tempBackground = UIImageView(image: UIImage(cgImage: GameManager.shared.puzzleImage.cgImage()))
    tempBackground.frame = CGRect(x: 0,y: 0,width: 1024,height: 768)
    tempBackground.tag = 1000
    self.window?.addSubview(tempBackground)
    self.window?.bringSubviewToFront(tempBackground)
}

这会在即将退出焦点时发出通知,该通知由我的 GameScene 接收,然后创建屏幕截图并将其存储到我的 GameManager 中的变量中。然后将其作为 subview 添加AppDelegate 中。

class GameScene: SKScene {
    override func didMove(to view: SKView) {
        // Layout puzzle here
        
        NotificationCenter.default.addobserver(self,selector: #selector(appToBackground),name: NSNotification.Name(rawValue: "resigning"),object: nil)
    }

    @objc private func appToBackground() {
        // Save state of puzzle and hide it
        
        GameManager.shared.puzzleImage = SKView().texture(from: self)!
    }
}

这一切都有效。但并不出色。双击和添加 tempBackground 之间存在明显的时间延迟 - 应用切换器非常简短地显示拼图的细节,然后将图像更改为隐藏的拼图。

当应用重新获得焦点时,会在 AppDelegate调用以下内容

func applicationDidBecomeActive(_ application: UIApplication) {
    if let tempBackground = self.window?.viewWithTag(1000) {
        tempBackground.removeFromSuperview()
    }
}

但是当应用返回焦点时,会显示 tempBackground,然后在再次显示隐藏的拼图之前,可以非常简短地了解拼图的所有细节。

我可能完全错误解决了这个问题,但在阅读了互联网上的各种存档问题和文章后,这似乎是一条正确的道路。

我想知道的是:有什么办法可以让隐藏的拼图立即显示在应用切换器中,并避免在返回拼图时闪现拼图细节?

谢谢。

解决方法

添加子视图逻辑没有问题,但问题在于您在哪里触发它,根据 apple docs,您应该在 applicationDidEnterBackground 中添加子视图,并且应该删除您的子视图并准备您的应用显示在applicationWillEnterForeground

由于我在 Xcode 12 中创建了 Xcode 项目,我的项目有场景委托,这是我使用的代码,O/P 显示在下面的 gif 中

    func sceneWillResignActive(_ scene: UIScene) {
        guard let view = Bundle.main.loadNibNamed("HiddenView",owner: nil,options: [:])?[0] as? HiddenView else { return }
        view.tag = 1000
        view.frame = UIApplication.shared.windows[0].frame
        UIApplication.shared.windows[0].addSubview(view)
        UIApplication.shared.windows[0].bringSubviewToFront(view)
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        if let tempBackground = UIApplication.shared.windows[0].viewWithTag(1000) {
            tempBackground.removeFromSuperview()
        }
    }

enter image description here

编辑 1:

正如 OP 所提到的,他没有使用 Scene Delegate 我正在更新 AppDelegate

的答案
    func applicationWillResignActive(_ application: UIApplication) {
        guard let view = Bundle.main.loadNibNamed("HiddenView",options: [:])?[0] as? HiddenView else { return }
        view.tag = 1000
        view.frame = UIApplication.shared.windows[0].frame
        UIApplication.shared.windows[0].addSubview(view)
        UIApplication.shared.windows[0].bringSubviewToFront(view)
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        if let tempBackground = UIApplication.shared.windows[0].viewWithTag(1000) {
            tempBackground.removeFromSuperview()
        }
    }

enter image description here

,

我有一个解决方案,虽然感觉更像是一种变通方法,而不是一个合适的解决方案。

问题在于 iOS 在将应用程序发送到后台之前拍摄屏幕快照,并在应用程序返回前台时使用它。

可以使用预定义的视图(请参阅@Sandeep 的解决方案)或在隐藏拼图后创建屏幕的新快照(我最初尝试的解决方案)来替换此快照。

但是,在 applicationDidBecomeActive 中删除此虚拟对象意味着在更新屏幕之前会短暂显示 iOS 拍摄的原始快照。

有一个函数 UIApplication.shared.ignoreSnapshotOnNextApplicationLaunch() 可以输入到 applicationWillResignActive() 函数中,但它似乎并不是一直都在工作——只是大部分时间都在工作。事实上,在 Apple Developer 的论坛上,有一条评论说它是如何不一致的,并且报告了一个错误。但那是一年多前的事了,现在仍然不一致。

相反,在此函数中,不是直接将虚拟对象添加到 self.window?,而是添加到 rootViewController 的视图中,使用 self.window?.rootViewController!.view.addSubview(dummyImage)

然后当应用程序回到前台时实际上不要删除它。而是使用 Notification 来提醒 GameScene 该应用程序回到前台。然后可以运行一个方法,将 UITapGestureRecognizer 添加到场景中。这反过来可以链接到淡出虚拟图像的方法,然后在完成后将其和 UITapGestureRecognizer 移除。

也许不是最优雅的解决方案,但它似乎有效。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。