早上十点,东京,云量94%。我需要应用付费墙上的天空显示出一场清晰的日落。等下去是最直接的选择。我做的却是另一件事,只用了一条命令:把iOS模拟器挪到阿尔伯克基,那里是晚上七点,万里无云。等22秒,截图。没有假数据,没有改代码,没有修图。

这个办法后来还撑起了我的App Store截图。不过最终那组截图里的日落,来自离我更近的地方。下面说清楚它是怎么运作的、在哪里会失效,以及由此长出来的那个脚本。

打开网易新闻 查看精彩图片

为什么不能直接伪造天空

Amana是一款iOS应用,它根据时间、你的位置和当前天气,画出你窗外的天空,然后试图让你去看真正的天空。这个系列的前文里,我写过它为什么在设备端绘制天空,而不是用卫星图。

应用确实有调试开关,可以手动设定太阳高度和云量。问题在于诚实。有一张商店截图的文案写着"夜晚也一样——真实的月相,真实的天气"。如果在那句文案下面放一个手动摆上去的月亮,这张截图就在撒谎。付费墙上的小组件预览同样跑在实时天气上:阴天它渲染成灰色,而付费墙上一个灰色的预览,观感并不好。

所以天空必须是真的。只是不必是我头顶的那片天。

一条命令

我找到的关于 simctl location 的写法,都是拿它来测试定位功能:地图、地理围栏、权限弹窗。我没见人写下来的是它在下游会发生什么。

应用从不会为了自己而问"我在哪"。它向 CoreLocation 要坐标,然后把坐标交给 WeatherKit、交给用于取地名的反向地理编码、交给它的太阳位置计算。坐标一动,这些全都跟着动:云量、地名那一行,还有那句"天空可能很快烧起来"的提示。

我是靠数像素来验证的,而不是相信眼睛。在付费墙的小组件预览里,灰色预览的暖色像素只占几个百分点。跳转之后,测出来是30%到32%。

22秒是有讲究的

第一次尝试我只等了13秒,抓到的是应用的默认云量(0.40)——那是首次天气刷新完成之前显示的占位值。它看起来挺像回事,而这恰恰是问题所在。真实数据到得更晚,所以脚本现在等22秒。

三个旋钮,只有一个能拧

定位跑通之后,我以为模拟器能按需产出任意天空。它不能。原因值得讲清楚,因为它适用于任何界面依赖真实世界的应用。

一张截图的每一个输入,都来自三个地方之一:

  • 地点(纬度、经度):太阳高度、天气、地名、那句提示。可以用 simctl location 移动。
  • 日历(日期):决定太阳轨迹与月相。
  • 天气本身:由地点和日历共同决定,无法单独拧动。

所以能动的只有地点这一个旋钮。日历可以改,但那会连带改变太阳轨迹和月相,不是想要什么就有什么。天气则完全跟着前两者走,没有独立的开关。

这也解释了为什么"把模拟器搬到阿尔伯克基"这件事成立:它不是在伪造数据,而是让应用去一个真实存在、此刻恰好符合条件的地方取数。天空是真的,只是换了一片天。