程序调试 (二) —— Xcode Simulator的高级功能
版本记录
版本号 | 时间 |
---|---|
V1.0 | 2021.01.04 星期一 |
前言
程序总会有bug,如果有好的调试技巧和方法,那么就是事半功倍,这个专题专门和大家分享下和调试相关的技巧。希望可以帮助到大家。感兴趣的可以看下面几篇文章。
1. 程序调试 (一) —— App Crash的调试和解决示例(一)
开始
首先看下主要内容:
在本教程中,您将学习Xcode Simulator的高级功能,以改善您的日常开发经验。内容来自翻译。
下面看下写作环境:
Swift 5, iOS 14, Xcode 12
接着就是正文了。
Xcode Simulator
是开发人员使用最广泛的工具之一。 在模拟器上运行和测试应用程序已成为每个开发人员日常工作的一部分。 熟悉各种模拟器选项对于任何开发人员都是至关重要的。 您知道您也可以从命令行创建和配置模拟器吗? 在本教程中,您将学习:
- 什么是模拟器
- 深入了解有用的模拟器选项
- 从命令行创建和配置模拟器
- 使用命令行流式传输和捕获日志
- 创建
Bash
脚本以在不同区域设置的模拟器上自动启动应用程序。
打开RayWonders
项目。 构建并运行。

这个程序有两个tab
— Photo and Map
。 Photo tab
显示了世界奇观的照片。 点击照片可显示其详细说明。 Map tab
将世界奇观的照片显示为地图上的注释。 这是raywenderlich.com
教程之一,您无需修改项目。 相反,您将使用此应用程序作为基础来学习各种模拟器选项。 在开始世界巡回演唱之前,您需要了解什么是模拟器。
What Is a Simulator?
该模拟器是在Mac上模拟iOS,iPadOS,tvOS和watchOS的绝佳工具。 它通过模拟不同的设备来帮助快速进行原型设计和测试。 从技术上讲,模拟器是在macOS
内核上运行的独立用户空间。

User space是分配给运行应用程序的系统内存,而内核空间是分配给运行OS内核和设备驱动程序的系统内存。启动新的模拟器会创建一个单独的用户空间。
内核(kernel)
是操作系统的核心组件。它促进了硬件和软件组件之间的交互。它负责管理硬件,分配内存并在进程之间进行仲裁。
这些进程之一 —— ** Daemon** —— 在后台运行。launchd,cfprefsd,distnoted是一些系统daemons
程序。
在设备和模拟器上运行的应用程序是否相同?接下来,您将学到。
Running App on a Device vs. a Simulator
在模拟器上测试应用程序非常方便。但是,在设备和模拟器上运行的应用程序之间存在一些关键差异。
1. Computing Performance
模拟器与Mac共享相同的计算资源。这包括内存,CPU和网络连接。相反,与Mac相比,物理设备具有更少的内存和计算能力。同样,网络可能是物理设备上不可预测的野兽。

2. Display
Mac和物理设备上的分辨率和色域可能会不同,从而导致图像和文本出现锯齿。 在本教程的后面,您将学习如何模拟确切的物理设备大小。
3. Hardware Limitations
模拟器不支持某些硬件组件。 这些包括:
- 蓝牙
- 相机
- 运动传感器,例如加速度计和陀螺仪
- 接近传感器
4. Framework Limitations
模拟器不支持某些框架。 这些包括:
ARKit
HomeKit
IOSurface
MessageUI
有关所有差异的更详尽列表,请通过在“模拟器”菜单中选择Help ▸ Simulator Help
来参考文档。
接下来,您将学习如何组织模拟器。
Organizing Simulators Using Xcode
Xcode
附带了一组默认的模拟器。 要查看这些模拟器的列表,请按照下列步骤操作:
- 1) 打开
Xcode
。 - 2) 选择
Window
菜单选项。 - 3) 选择
Devices and Simulators
菜单。

- 4) 选择
Simulators
选项卡。
您会看到Xcode随附的模拟器列表。 如果您过去曾经下载过其他运行时,那么也会看到这些相关的模拟器。
现在,您将使用自定义名称创建一个新的模拟器。

按着这些次序:
- 1) 按下左下方的
+
按钮。 - 2) 将模拟器名称设置为
Demo
。 - 3) 选择
iPhone 12 Pro
作为设备类型。 - 4) 选择
iOS 14.2
作为操作系统版本。 - 5) 按
Create
。
这将创建一个名为Demo
的新模拟器,您现在可以在模拟器列表中找到它。
取消选中Demo simulator
的Show as runtime destination
复选框。

这隐藏了模拟器。 它不会显示在该app scheme
旁边的模拟器列表中。
按住Control键并单击Demo
模拟器。 出现几个选项,例如Delete
和Rename
。

继续并通过单击Delete
来删除Demo simulator
。 不用担心 您很快就会使用其他方法创建它。
1. Running Older Runtimes
有时,您必须在旧版运行时上运行您的应用。

创建新的模拟器时,可以通过在OS版本下拉菜单中选择Download more runtimes
来下载较早的运行时。
您也可以从Components
窗口下载更多运行时。 选择Xcode ▸ Preferences ▸ Components
选项。

该窗口显示下载的模拟器运行时以及其他可供下载的运行时的列表。
接下来,您将学习创建模拟器的另一种方法。
2. Creating Simulators From the Simulator Menu
构建并运行。
当模拟器正在运行时,请按照下列步骤操作:
- 1) 从模拟器菜单中选择
File ▸ New Simulator
。

- 2) 输入
Demo
作为模拟器名称。 - 3) 选择
iPhone 12 Pro
作为Device Type
。 - 4) 选择
iOS 14.2
作为版本。 - 5) 单击
Create
。
请按照以下步骤打开模拟器:
- 1) 从菜单中选择
File ▸ Open Simulator
。 - 2) 选择
iOS 14.2
运行时。 - 3) 选择
Demo
模拟器。

这将启动Demo
模拟器。
那又快又简单! 接下来,您将了解模拟器中的各种尺寸选项。
Comparing Simulator Size Options
您可以通过在四个角之一中单击并拖动来调整模拟器的大小。 Window menu
选项提供四个缩放选项。
1. Physical Size

物理大小会调整模拟器的大小,以匹配实际的设备大小。 这可以直观地显示您的应用在不同屏幕尺寸下的外观。
2. Point Accurate

点精确模式可调整窗口大小,以便在具有不同比例因子的设备上内容具有相同大小。 结果,显示为3x
的设备上的图像与2x
显示器的尺寸相同。
3. Pixel Accurate

在此模式下,窗口大小更改为与物理设备相同的像素数。 模拟设备上的每个像素都映射到Mac显示器上的一个像素。 如果Mac显示器的像素密度低于模拟设备的像素密度,这会使模拟器在屏幕上显得更大。 您可以使用此模式检查应用程序中图像和控件的对齐方式。
4. Fit Screen

这会将模拟器的大小调整为Mac
显示器的大小。
接下来,您将学习模拟器中提供的各种选项。
Slow Animations
动画是应用程序体验不可或缺的一部分。 在Demo
模拟器中构建并运行RayWonders
。
点击Photos
选项卡。 接下来,点击一张世界奇观的照片,以呈现有关该地方的详细信息。 向下滑动以消除视图。
要模拟慢速动画,请在Simulator
菜单中选择Debug ▸ Slow Animations
选项。

再次点击图片。 现在,视图动画缓慢。

缓慢查看动画有助于提高清晰度。 另外,它可以帮助检查渲染和性能方面的问题。
接下来,您将学习模拟Dark Mode
。 在继续之前,通过取消选择Debug ▸ Slow Animations
菜单选项来禁用慢动画。
1. Dark Mode
Dark Mode可在弱光环境下提供出色的观看体验。 模拟器提供了在黑暗模式下查看您的应用程序的选项。

选择Features ▸ Toggle Appearance
。 这会将外观切换为Dark Mode
。 现在,点击RayWonders
中的Map
选项卡。

您会注意到地图已更改为深色外观。 很简单,不是吗? 这是在黑暗模式下测试应用程序的便捷方法。
要将外观改回默认设置,请取消选择Features ▸ Toggle appearance
。 要了解如何支持暗模式,请查看Supporting Dark Mode: Adapting You App to Support Dark Mode tutorial。
接下来,您将学习如何模拟推送通知!
Simulating Push Notifications
推送通知是一种让用户知道应用程序中新内容更新的好方法。 过去,测试推送通知是一个挑战。 您需要物理设备来测试推送通知。 从Xcode 11.4
开始,您可以在模拟器上模拟推送通知。
使用以下命令创建一个名为RayWondersPushNotification.apns
的文件:
{
"Simulator Target Bundle": "com.raywenderlich.RayWonders",
"aps": {
"alert": {
"title": "Hindi language support added!",
"body": "Checkout RayWonders in Hindi!"
}
}
}
这是带有title
和body
的简单可见的推送通知有效内容。 Simulator Target Bundle
是一个特殊的键。 它指定应接收通知的应用程序的bundle ID
。
在尝试有payload
之前,您需要首先在应用程序中授予通知权限。

按着这些次序:
- 1) 在
Demo
模拟器中打开RayWonders
。 - 2) 在
Photos
选项卡中,点击右上角的响铃图标。 - 3) 在通知权限提示中选择
Allow
。 - 4) 从
Simulator menu
中选择Device ▸ Home
,将应用程序置于后台。

接下来,将RayWondersPushNotification.apns
文件拖放到Demo
模拟器上。

出现一个可见的推送通知。 那很简单! 请记住,模拟器只能模拟推送通知。 要测试从Apple推送通知服务器收到的实际推送通知,需要使用物理设备。
要更深入地了解推送通知,请阅读 Push Notifications Tutorial: Getting Started。
接下来,您将学习如何缩放。
Zooming In and Out
在模拟器中打开RayWonders
。 切换到Map
标签。 地图以世界奇观为中心并放大。 世界其他奇迹在哪里?
您需要缩小以查看全景。 在按住Option
键的同时单击并拖动。

单击和拖动很棒,但是很快就会变得很累。 接下来,您将学到一种更快的去往某个地点的方法。
Simulating a Location
模拟器提供了一种简单的方法来模拟位置。 首先,您需要在RayWonders
中授予位置权限。

按着这些次序:
- 1) 在模拟器中打开
RayWonders
并切换到Map
选项卡。 - 2) 点击
Map
选项卡中的Start Location Services
按钮。 - 3) 选择
Allow While Using App
权限。
现在,要模拟位置:
- 1) 从模拟器菜单中选择
Features ▸ Location ▸ Custom Location
。

- 2) 输入
41.8902142
作为纬度,输入12.4900422
作为经度。 - 3) 单击
OK
。

这会将您直接带到地图上的罗马竞技场-您有史以来最快的旅程!

但是,输入要模拟的每个位置的坐标都需要占用大量内存,即您的内存即任务。 接下来,您将学到解决此问题的简便方法。
1. Sharing Locations From the Maps App
macOS
上的Maps
应用程序提供了一种与模拟器共享位置的简便方法。

按着这些次序:
- 1) 打开
Maps
应用。 - 2) 在搜索文本中输入
Machu Picchu
。 - 3) 单击搜索字段旁边的
Share
按钮。 - 4) 从下拉菜单中选择
Simulator
。 - 5) 在位置提示中,选择
Demo
作为模拟器。

- 6) 单击
Send
。
您现在位于模拟器的地图视图中的Machu Picchu
。

恭喜你! 您刚刚创造了从罗马斗兽场到Machu Picchu
旅行最快的世界纪录!
要了解有关更深入地处理应用中位置的信息,请查看 MapKit and Core Location。
现在,该改变一下了。
Simulating Shake Gesture
摇动手势(Shake gestures)
是提示用户在应用程序中提供反馈的绝佳线索。 但是,如何摇动模拟器? 幸运的是,严格摇动Mac
不是解决方案。 模拟器提供了一种简单的方法。
在Demo
模拟器上打开RayWonders
。 从Simulator
菜单中选择Device ▸ Shake
。

这模拟了摇动手势。

RayWonders
会检测到晃动并向用户提示alert
。 您可以通过实现motionEnded(_:with :)
方法来检测和处理应用中的摇动手势。 要了解更多信息,请查阅Apple documentation。
接下来,您将学习如何模拟内存警告。
Simulating a Memory Warning
当iOS的内存使用量接近设备的上限时,iOS会向该应用发送警告。 应用程序需要通过清除缓存数据做出响应,该数据可以在以后重新创建。
在演示模拟器上打开RayWonders
。 从菜单中选择Debug ▸ Simulate Memory Warning
。

这模拟了内存警告。

RayWonders
显示alert
。 您可以在Responding to Memory Warnings Apple文档中了解有关处理内存警告的更多信息。
到目前为止,您已经看到了一些有用的模拟器选项。 本教程未涵盖其他几项。 您应该根据自己的应用需求将其签出。 其中一些选项包括:
- 使用
Features ▸ Trigger iCloud Sync
来模拟iCloud
同步。 - 使用
Features ▸ Authorize Apple Pay
来模拟Apple Pay
授权。 - 使用
Device ▸ Siri
触发Siri
。 - 使用
Debug ▸ Open System Log
检查系统日志。
接下来,您将学习使用命令行与模拟器进行交互。
Organizing Simulators Using the Command Line
到目前为止,您已经使用Xcode
创建和管理了模拟器。 此外,您还了解了各种Simulator
菜单选项。 现在,您将学习从命令行管理和使用模拟器。
打开终端。 输入以下命令:
xcrun simctl --help
然后按Enter
。
help
选项提供了使用simctl
可用的所有子命令的列表。

Simctl
是帮助管理模拟器并以编程方式与模拟器交互的工具。 您可以使用xcrun
命令行工具访问simctl
。
现在,您将探索其中的几个子命令。 运行以下命令:
xcrun simctl list
list
命令显示所有可用设备和运行时的列表。

它还显示了设备的当前状态,无论是Booted
还是Shutdown
。
接下来,您将学习从命令行创建和启动模拟器。
1. Creating Simulator From the Command Line
在创建新模拟器之前,请删除通过Xcode
创建的Demo
模拟器。 输入以下内容:
xcrun simctl delete Demo
delete
命令标识一个模拟器并将其删除。 现在,从命令行创建一个新的模拟器。
输入以下内容:
xcrun simctl create Demo "iPhone 12 Pro" "iOS14.2"
create
命令接受设备类型和运行时,并创建模拟器。 这将创建具有iOS 14.2
运行时的iPhone 12 Pro
模拟器。
现在,终端显示新设备的唯一标识符。

输入以下内容:
xcrun simctl boot Demo
启动演示模拟器。 默认情况下,它处于关机(Shutdown)
状态。
现在,使用命令行安装RayWonders
。 您首先需要该app bundle
。 按着这些次序:
- 1) 打开“项目”导航器,然后选择
Products
文件夹中的RayWonders.app

- 2) 右键单击并选择在
Finder
中显示。

- 3) 将
RayWonders
复制到您的主目录。
打开终端并通过输入以下内容导航到主目录:
cd ~
接下来,运行以下命令:
xcrun simctl install Demo RayWonders.app
install
命令将RayWonders
安装在模拟器上。 很好!
您甚至可以使用simctl
启动该应用程序。 输入以下内容:
xcrun simctl launch Demo com.raywenderlich.RayWonders
启动(launch)
命令将app bundle ID
作为参数。 RayWonders
在Demo
模拟器中启动。
恭喜你! 现在,您已经从命令行创建,启动,安装并启动了模拟器。 您可以尝试以下其他选项:
-
terminate:这将使用
bundle identifier
终止应用程序。 - erase:这将擦除设备内容。
-
uninstall:这将卸载应用程序。 您需要指定应用程序的
bundle identifier
。
接下来,您将学习一些适用于您的应用的出色命令。
2. Taking Screenshots
您的应用的屏幕截图在几种情况下很有用。 例如,在AppStore
中提交应用程序时需要截图。
输入以下命令:
xcrun simctl io Demo screenshot screenshot.png --type="png"
这将获取当前屏幕的屏幕截图,并将其保存到文件screenshot.png
中。 除了png
外,screenshot
命令还支持其他文件格式,例如TIFF,BMP,GIF和JPEG
。
屏幕快照可以显示您的应用程序的外观,而一张图片值一千字。 但是,视频的价值更高。
3. Recording Video
您可以使用simctl
录制应用程序的视频。 要开始记录,请输入以下命令:
xcrun simctl io Demo recordVideo Demo.mov --codec="h264"
在模拟器上与RayWonders
进行交互。 完成后,在终端中按Control-C
。 这会将视频保存在Demo.mov
中。
另外,您可以在录制时指定所需的编解码器。 默认编解码器为hevc
。

recordVideo
命令有助于避免使用QuickTime
播放器录制应用程序的视频。
4. Customizing the Status Bar
在模拟器中检查应用程序的状态栏。 您会看到电池已充满,设备具有最佳信号,并且模拟器上的时间是本地Mac时间。 如果要覆盖这些内容怎么办?
在终端中输入以下命令:
xcrun simctl status_bar Demo override \
--dataNetwork 4g --cellularBars 2 --batteryState charging \
--batteryLevel 25 --time 12:05
这会覆盖要设置的状态栏:
- 数据网络为4G
- 蜂窝信号到两个条形图
- 电池状态为充电状态,电池电量为25%
- 在模拟器上的时间为12:05

在自己的项目中执行此操作时,可以将状态栏信息设置为所需的任何内容。
当您要自定义应用屏幕截图和视频的外观时,status_bar
命令可能非常方便。
完成后,通过输入以下命令将状态栏恢复为默认外观:
xcrun simctl status_bar Demo clear
Debugging and Diagnosing
Simctl
还提供了一些命令来帮助调试和诊断问题。
返回终端,然后输入以下内容:
xcrun simctl get_app_container Demo com.raywenderlich.RayWonders
get_app_container
打印app bundle
的路径。

您可以使用此路径检查应用容器中的数据。 此外,在调试问题时,模拟器日志确实非常有用。
现在,在终端中键入以下内容:
xcrun simctl spawn Demo log stream
这将开始从Demo
模拟器流式传输所有日志。

但是,这可能是要检查的数据过多。 按Control-C
停止流。
请尝试以下操作:
xcrun simctl spawn Demo log stream | grep com.raywenderlich.RayWonders
这将过滤日志并仅显示来自RayWonders
的日志。

与应用互动时,您会在终端中看到更多日志。 在提交bug
或向Apple提供反馈时,这些日志非常有用。
输入以下内容:
xcrun simctl diagnose
diagnose
命令收集一堆数据,包括日志和崩溃。 它还会生成可帮助Apple调试问题的文件。 默认情况下,收集的日志用于引导的设备。 通过指定设备的UDID
,您可以将日志收集限制到该特定设备。
您现在已成为模拟器命令行专家! 您可以通过使用Bash
脚本自动执行常见操作来更进一步。
Automating Using a Bash Script
现在,您将创建一个脚本来克隆模拟器并在其他区域启动RayWonders
。
首先,打开终端,然后输入以下内容:
touch sim_utility.sh
这将创建一个名为sim_utility
的新文件。 .sh
扩展名表示它是一个shell
脚本。
注意:您可以在文件系统中的任何位置创建脚本。 为了便于示例项目的组织,该脚本位于
“Scripts”
文件夹下。
接下来,运行:
chmod +x sim_utility.sh
这使sim_utility.sh
可执行,因此您可以运行它。
在编辑器中打开sim_utility.sh
,并添加以下内容:
#!/bin/bash
#1
COMMAND="$1"
SIMULATOR_NAME="$2"
#2
get_id_of_simulator() {
#TODO
}
get_status_of_simulator() {
#TODO
}
launch() {
#TODO
}
#3
case $COMMAND in
"launch") launch "$3" "$4" "$5" ;;
*)
launch_help
exit 1
;;
esac
这是怎么回事:
- 1) 该脚本采用命令名称和模拟器名称作为命令行参数。
- 2)
get_id_of_simulator,get_status_of_simulator
和launch
是接下来要实现的空存根。 - 3) 该脚本当前支持一个名为
launch
的命令。 此launch
使用三个附加参数,您将很快实现这些参数。
在get_id_of_simulator
中,将#TODO
替换为以下内容:
xcrun simctl list | grep "$SIMULATOR_NAME" | \
awk 'match($0, /\(([-0-9A-F]+)\)/) {print substr( $0, RSTART + 1, RLENGTH-2 )}'
get_id_of_simulator
搜索模拟器列表以匹配指定为参数的名称。 如果找到匹配项,则子字符串操作将获得模拟器的唯一标识符。
在get_status_of_simulator
方法中,将#TODO
替换为以下内容:
xcrun simctl list | grep "$SIMULATOR_NAME" | \
awk 'match($0, /\(([a-zA-Z]+)\)/) {print substr( $0, RSTART + 1, RLENGTH - 2 )}'
get_status_of_simulator
在设备列表中搜索名称匹配的模拟器。 如果找到匹配项,它将获得模拟器的状态 —— booted
或shutdown
。 您将在launch
中使用它们。
1. Implementing Launch
在launch
时,将#TODO
替换为以下内容:
#1
BUNDLE_ID="$1"
LOCALE="$2"
LANGUAGE="$3"
CLONE_NAME="$LOCALE"
#2
SIMULATOR_ID=$(get_id_of_simulator)
if [ -z "$SIMULATOR_ID" ]; then
echo "No device matching the name: $SIMULATOR_NAME"
return
fi
echo "Simulator id: $SIMULATOR_ID"
echo "Bundle id: $BUNDLE_ID"
echo "Locale: $LOCALE"
#3
SIMULATOR_STATUS=$(get_status_of_simulator)
echo "Simulator Status: $SIMULATOR_STATUS"
if [ "$SIMULATOR_STATUS" = "Booted" ]; then
echo "Making sure the device is shutdown first..."
xcrun simctl shutdown "$SIMULATOR_NAME"
fi
#4
echo "Cloning the device with name $LOCALE..."
xcrun simctl clone "$SIMULATOR_NAME" "$CLONE_NAME"
#5
echo "Booting device..."
xcrun simctl boot "$SIMULATOR_NAME"
xcrun simctl boot "$CLONE_NAME"
#6
echo "Launching app..."
xcrun simctl launch "$SIMULATOR_NAME" "$BUNDLE_ID"
#7
xcrun simctl launch "$CLONE_NAME" "$BUNDLE_ID" -AppleLocale "$LOCALE" \
-AppleLanguages "($LANGUAGE)"
保存文件。这是逐步执行的操作。它:
- 1) 提供其他
launch
参数,包括应用程序的bundle ID
,语言环境和启动应用程序所使用的语言。它声明一个本地变量CLONE_NAME
,它是克隆设备的名称。在这种情况下,克隆设备的名称就是您指定的语言环境; - 2) 通过调用
get_id_of_simulator
来获取模拟器的ID。然后,将结果存储在SIMULATOR_ID
中。如果没有匹配的模拟器,则退出程序。 - 3) 通过调用
get_status_of_simulator
获取模拟器的状态。如果状态为Booted
,则它将运行shutdown
命令将其关闭。要克隆,必须关闭设备。 - 4) 使用
clone
命令克隆模拟器; - 5) 使用
boot
命令引导原始模拟器和克隆的模拟器; - 6) 使用
launch
命令在原始模拟器上启动应用程序; - 7) 使用克隆的模拟器上的
launch
命令启动应用程序。它指定启动应用程序的语言环境和语言。
2. Launching RayWonders in a Different Locale
打开终端,然后运行以下命令:
./sim_utility.sh launch Demo com.raywenderlich.RayWonders hi_IN hi
RayWonders
在印地语上使用克隆的模拟器hi_IN
启动。

无需再进行设置并切换设备语言来测试您的应用。 现在,您可以同时以多种语言查看您的应用。 很好!
注意:如果在运行脚本时遇到问题,请确保只有一个名为
Demo
的模拟器。 您可以通过运行xcrun simctl list | grep Demo
检查可用的模拟器数量。删除所有重复的模拟器,然后重试。
RayWonders
还支持其他几种语言。 运行以下命令:
./sim_utility.sh launch Demo com.raywenderlich.RayWonders ja_Jp ja
RayWonders
现在在新的模拟器上以日语启动。

作为一个有趣的挑战,在sim_utility
脚本中实现另外两个命令。
- Cleanup:这将删除给定模拟器名称的模拟器。
- Help:这将打印脚本支持的所有命令的菜单。
您可以在下载资料的Scripts
文件夹中找到该脚本的最终版本以及所有这些选项。
在本教程中,您学习了很多有用的模拟器和命令行选项。 要了解更多信息,请观看以下WWDC视频:
后记
本篇主要讲述了
Xcode Simulator
的高级功能,感兴趣的给个赞或者关注~~~
