You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在SpriteKit场景中添加UITextField不显示,求正确实现方案

SpriteKit场景中UITextField不显示的问题解决

你的代码问题分析

UITextField不显示的核心原因是添加时机错误:
在init(size:)方法中尝试访问self.view并添加子视图时,Scene还未被附加到SKView上,self.view此时大概率为nil,导致添加UITextField的代码块完全没有执行。

另外还有坐标系的潜在问题:SpriteKit的坐标系原点在屏幕左下角,而UIKit的坐标系原点在左上角,直接用UIKit的frame计算位置,会导致控件位置和你预期的SpriteKit场景布局错位。

修正方案

1. 调整UITextField的添加时机

把添加UITextField的代码移到didMove(to view:)方法中,这个方法会在Scene被成功添加到SKView后调用,此时self.view已经有效:

override func didMove(to view: SKView) {
    let textFieldWidth: CGFloat = 200
    let textFieldHeight: CGFloat = 50
    
    // 转换SpriteKit居中坐标到UIKit坐标系
    let sceneCenter = CGPoint(x: size.width/2, y: size.height/2)
    let viewCenter = view.convert(sceneCenter, from: self)
    
    let textFieldFrame = CGRect(
        x: viewCenter.x - textFieldWidth/2,
        y: viewCenter.y - textFieldHeight/2,
        width: textFieldWidth,
        height: textFieldHeight
    )
    
    self.editCharName = UITextField(frame: textFieldFrame)
    self.editCharName.placeholder = "Enter character name"
    self.editCharName.borderStyle = .roundedRect
    self.editCharName.delegate = self
    view.addSubview(self.editCharName)
}

同时让CharacterCreatorView遵守UITextFieldDelegate协议,方便处理输入事件:

class CharacterCreatorView: SKScene, UITextFieldDelegate {
    // ... 原有代码 ...
    
    // 处理输入完成事件
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        if let name = textField.text {
            self.charName = name
        }
        return true
    }
}

2. 适配SpriteKit的替代方案(纯SpriteKit风格)

如果不想混用UIKit控件,可以用SKLabelNode配合点击触发弹窗的方式,更贴合SpriteKit的场景逻辑:

override func didMove(to view: SKView) {
    // 创建显示角色名的标签
    let nameLabel = SKLabelNode(text: charName)
    nameLabel.position = CGPoint(x: size.width/2, y: size.height/2)
    nameLabel.fontSize = 30
    nameLabel.name = "nameLabel"
    addChild(nameLabel)
    
    // 创建透明点击区域,覆盖标签范围
    let tapArea = SKShapeNode(rect: CGRect(x: -100, y: -20, width: 200, height: 40))
    tapArea.position = nameLabel.position
    tapArea.fillColor = .clear
    tapArea.strokeColor = .clear
    tapArea.name = "nameTapArea"
    addChild(tapArea)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let location = touch.location(in: self)
    let nodes = nodes(at: location)
    
    if nodes.contains(where: { $0.name == "nameTapArea" }) {
        let alert = UIAlertController(title: "修改角色名", message: nil, preferredStyle: .alert)
        alert.addTextField { textField in
            textField.text = self.charName
            textField.placeholder = "输入新名字"
        }
        alert.addAction(UIAlertAction(title: "确定", style: .default) { _ in
            if let newName = alert.textFields?.first?.text, !newName.isEmpty {
                self.charName = newName
                if let nameLabel = self.childNode(withName: "//nameLabel") as? SKLabelNode {
                    nameLabel.text = newName
                }
            }
        })
        alert.addAction(UIAlertAction(title: "取消", style: .cancel))
        self.view?.window?.rootViewController?.present(alert, animated: true)
    }
}

内容的提问来源于stack exchange,提问作者Andrew Nazareth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:55:26