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

展示其他SKView后SKView.presentScene带转场效果失效问题排查

更新

该问题由存在间接影响的循环引用(retain cycle)引发,完整的问题诊断过程已整理成文档记录。

我遇到了一个非常特殊的bug,表现为在其他UIView中展示过SKView后会产生副作用,看起来是旧iOS9版本中presentScene带转场失效bug的复现。

背景

Touchgram是一款iMessage应用扩展,支持创建和播放交互式消息,类似PowerPoint和游戏编辑器的结合体,基于消息体系运行。其界面采用UIKit构建,播放能力基于SpriteKit实现。

Touchgram引擎会创建SKScene对象,在多页面消息中可选择带转场或不带转场展示这些场景。

编辑界面初始为树状视图,可打开详情编辑页修改触摸检测、页面跳转动作、音效播放等配置。

部分详情编辑页也会展示SKView:其中触摸编辑器的特定模式下会展示SKView,用于录制bounding area(边界区域)或待匹配的手势;文本元素编辑器会展示SKView,用于预览样式对小段文本的影响,会在页面主背景(纯色或图片)上渲染文本元素。

问题描述

正常流程:启动应用(实际是iMessage内的应用扩展)后播放已保存的消息,所有功能正常,场景转场可以正常展示。

异常情况:只要进入文本元素编辑页,哪怕其内嵌的SKView没有绘制任何内容,后续的播放功能就会被破坏。此时播放任何带转场的消息都会卡住,前一个场景的节点会持续展示不消失。

我已经将问题范围缩小到该页面上SKView的存在本身:如果仅移除该SKView,问题就不会出现。当前该SKView甚至没有绑定输出口,也没有任何代码和它交互。

另一个触摸编辑页也包含SKView,但不会产生该副作用。

我花了数天才定位到该副作用,直到看到相关技术讨论帖才意识到,bug表现不一致是因为部分消息包含场景转场、部分不包含。该问题已经阻塞了我们历时一年多开发的核心引擎的首次产品发布。

正常页面 - 触摸编辑器

xib中视图层级的相关代码片段如下:

<objects>
    <view opaque="NO" contentMode="scaleToFill" id="Mia-xp-RE9">
        <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
        <subviews>
...
            <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rlf-kc-zvh" userLabel="RecordingOverlay">
                <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
                <subviews>
...
                    <skView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AnC-CG-Aqq" userLabel="RecordingArea">
                        <rect key="frame" x="57" y="191" width="300" height="543"/>
                        <constraints>
                            <constraint firstAttribute="width" secondItem="AnC-CG-Aqq" secondAttribute="height" multiplier="414:750" priority="950" id="zMg-Iv-5nu"/>
                        </constraints>
                    </skView>
                </subviews>
...
            </view>
        </subviews>
...
    </view>

异常页面 - 文本编辑器

xib中视图层级的相关代码片段如下:

<objects>
    <view opaque="NO" contentMode="scaleToFill" id="upw-ro-x1m">
        <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
        <subviews>
            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KTl-Xs-TIo" userLabel="MainContentView">
                <rect key="frame" x="0.0" y="44" width="375" height="734"/>
                <subviews>
...
                    <skView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Wch-3x-CLz" userLabel="preview">
                        <rect key="frame" x="91" y="307.33333333333326" width="193" height="349.66666666666674"/>
                        <constraints>
                            <constraint firstAttribute="width" secondItem="Wch-3x-CLz" secondAttribute="height" multiplier="414:750" priority="950" id="jeK-un-SXq"/>
                        </constraints>
                    </skView>
...
                </subviews>
...
            </view>
        </subviews>
...
    </view>

排查方向

我尝试找出两个页面的差异,以及触发该UIKit/SpriteKit异常行为的原因,以下是公开的思路梳理,无前置假设,仅排查正常/异常页面的差异带来的副作用,大部分选项看起来影响概率极低,但仍在逐一确认:

  1. 正常页面存在相邻/重叠的scrollView:正常页面有一个scrollView和另一个视图,会根据不同模式切换显隐。
  2. 排除 异常页面是UIViewController子类,之前绑定SKView时将其绑定到了父类的输出口。
  3. 排除 异常页面是SKSceneDelegate,在viewDidLoad中被设为代理,但是代理是通过可选值清空的,可能存在未清空的情况。
  4. 排除 存在其他VC代理混合:异常页面实现了第三方富文本字体选择的代理协议,同时是UIText相关代理。
  5. 排除 skView的嵌套层级问题:目前正常页面的SKView嵌套层级比异常页面更深,将SKView上移到和"MainContentView"平级也没有解决问题。
  6. 内存释放:在正常和异常页面中添加deinit方法,确认返回主树状视图后、播放前两个页面是否都被销毁。最终找到差异! - 异常页面从未调用deinit。

已排除的无关因素

以下因素基本确认对问题无影响:

  1. 是否绑定输出口:调试初期异常页面的SKView是绑定了输出口的,解绑后问题仍然存在。
  2. 是否可见:两个页面的SKView初始都是隐藏的,通过代码控制显示,无论是否显示都会触发问题。
  3. SKView是否有渲染内容:在SKView未绑定输出口、无任何代码交互的情况下,仅xib中存在该SKView就会触发副作用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:06:04