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

如何在UIDevice旋转后生成适配重定位节点的新UIBezierPath?

解决方案

1. 确保节点布局完成后再计算路径

viewDidLayoutSubviews是UIKit层的回调,SKView内部的节点布局可能未同步完成。计算路径前先强制SKView完成布局:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    guard let skView = view as? SKView else { return }
    // 强制SKView完成子节点布局
    skView.layoutIfNeeded()
    
    // 仅在设备方向变化时执行更新,避免重复调用
    let currentOrientation = UIDevice.current.orientation
    guard currentOrientation != previousOrientation else { return }
    previousOrientation = currentOrientation
    
    skView.isPaused = true
    
    // 更新节点位置与尺寸,确保基于当前view尺寸计算
    updateSpriteNodesLayout()
    
    // 重新生成路径
    setTrackPaths()
    
    skView.isPaused = false
}

2. 修正createTrainPath的计算逻辑

确保路径计算时直接使用节点的实时属性,而非缓存的旧值:

func createTrainPath() -> UIBezierPath {
    let path = UIBezierPath()
    
    // 直接取当前节点的实时位置
    let startNode = trainStartNode
    path.move(to: startNode.position)
    
    // 遍历节点时,实时获取每个节点的位置与尺寸
    for node in trackNodes {
        path.addLine(to: node.position)
        // 基于节点当前尺寸绘制路径
        path.addArc(withCenter: node.position, radius: node.size.width/2, startAngle: 0, endAngle: .pi*2, clockwise: true)
    }
    
    return path
}

3. 确保路径被正确替换

如果是给SKShapeNode用路径,直接替换path属性;如果是用于节点跟随动作,需重新创建动作并替换:

func setTrackPaths() {
    let newPath = createTrainPath()
    
    // 更新路径显示节点
    trackShapeNode.path = newPath.cgPath
    
    // 重新创建跟随动作,替换旧动作
    let followAction = SKAction.follow(newPath.cgPath, asOffset: false, orientToPath: true, speed: 100)
    trainNode.removeAllActions()
    trainNode.run(followAction)
}

4. 避免布局循环或重复触发

若更新节点布局时会再次触发viewDidLayoutSubviews,可添加标记控制:

private var isUpdatingLayout = false

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    guard !isUpdatingLayout else { return }
    isUpdatingLayout = true
    
    // 执行所有更新逻辑...
    
    isUpdatingLayout = false
}

额外排查点

  • 检查是否在路径计算中使用了固定的屏幕尺寸(如UIScreen.main.bounds),旋转后应改用skView.bounds来计算节点位置。
  • 若节点使用Auto Layout约束,确保旋转后约束已更新完成,或在updateSpriteNodesLayout中手动基于新view尺寸计算位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:52:34