【iOS】通过Xcode任意指定iPhone/iPad的地理位置

Posted by 西维蜀黍 on 2017-09-27, Last Modified on 2022-10-10

需求

  • 在开发地图类应用时,经常需要模拟地理位置。如开发者位于上海,需要模拟App的使用者位于北京时的场景;
  • 为iOS设置一个特定的地理位置。

开箱即用

我已经将一个可在iPhone真机上运行的iOS Project存放于https://github.com/swsmile/LocationModifierForiOS。

开箱即用:

  • 直接git clone https://github.com/swsmile/LocationModifierForiOS
  • 在Xcode中打开这个项目;
  • 直接修改项目中.gpx文件中的经纬度坐标数据;
  • 在真机上运行这个项目。

最终,所有真机的软件获取到的位置(GPS信息),就是你刚才指定的位置。

效果展示

在设备中运行(真机 or 模拟器均可),此时打开一个地图App进行定位。毫无疑问,此时显示的必然是你的实际地理位置。

模拟地理位置后,再次打开一个地图App并进行定位,此时显示的定位将是我手动设定的一个地理位置(瞬间飞到了日本)。

手工实现

其实,Xcode本身给我们提供了设置地理位置的方法。进入【Product】 - 【Scheme】 - 【Edit Scheme】,选择【Options】,在【Core Location】处,我们可以指定当前设备的地理位置(而不只是当前运行的App获取到的地理位置)。

展开列表后,发现Xcode已经为我们提供了一些地理位置。

当然,还可以通过Add GPX File to Project来手动设定一个特定的地理位置。


**GPX (GPS eXchange Foramt)**是一个表示GPS数据的XML数据格式,专门用来存储地理信息,可用于描述路点(waypoint)、轨迹(track)、路程(route)。

  • 路点:通过经度、维度等描述某一个具体的点
  • 轨迹:描述曾经走过的轨迹
  • 路程:推荐可以走的路径,常用于导航

很多blog推荐通过 http://gpx-poi.com/ 选定地图上的点,生成.gpx文件。然而,我通过gpx-poi.com生成的.gpx文件导入Xcode后并不能被正常识别(可能是Xcode对.gpx文件的解析与gpx-poi.com的生成规则不一致)。

其实,Xcode本身就提供了创建.gpx文件的方法:在Xcode中,【File】-【New】-【File】以创建一个GPX file

生成后:

<?xml version="1.0"?>
<gpx version="1.1" creator="Xcode">

    <!--
     Provide one or more waypoints containing a latitude/longitude pair. If you provide one
     waypoint, Xcode will simulate that specific location. If you provide multiple waypoints,
     Xcode will simulate a route visiting each waypoint.
     -->
    <wpt lat="37.331705" lon="-122.030237">
        <name>Cupertino</name>

        <!--
         Optionally provide a time element for each waypoint. Xcode will interpolate movement
         at a rate of speed based on the time elapsed between each waypoint. If you do not provide
         a time element, then Xcode will use a fixed rate of speed.

         Waypoints must be sorted by time in ascending order.
         -->
        <time>2014-09-24T14:55:37Z</time>
    </wpt>

</gpx>

注意,这里的<wpt lat="37.331705" long="-122.030237">即是用纬度和经度来描述这个地理位置点。


于是,采用一个讨巧的办法,先在http://gpx-poi.com/ 地图上选择要模拟的地理位置点,获得其纬度和经度值(如Longitude: -2.243958,Latitude: 53.480491):

或者,我们也可以在Google Map中,通过鼠标左键单击以选择一个点,然后在该点上单机右键,并选择"What’s here",就会在下方显示出该点的经纬度信息(下图中:Longitude: -2.965337,Latitude: 53.407010)。

无论你通过什么方式获取,最终,将该经纬度数据,复制到Xcode生成的GPX file模板中:


注意:在Xcode中创建这个.gpx文件后,就会自动添加到Default Location的列表中(名为Location):

选择这个文件作为要模拟的地理位置点,再次运行App,打开任意地图工具,发现我们设置的点就是此时的地理位置定位了(Longitude: -2.243958,Latitude: 53.480491):


在App运行后,通过【Debug】 - 【Simulate Location】或Debug中的工具栏,我们还可以随时动态修改本设备的地理位置(不需要重新run当前App,而位置修改立即生效)。

比如此时我修改为【San Francisco】,在地图工具中发现当前的定位会立刻变化:

Troubleshooting

Xcode 13: Build hangs with “iPhone is busy: making Apple Watch ready for development

I have been struggling with this for some time now. If you don’t need the Apple Watch, instead of turning it off completely, you can also turn on airplane mode if configured correctly.

On your watch, go to Settings AppAirplane Mode. Make sure that both WIFI and Bluetooth switches are turned off!

When the bluetooth switch is turned on, a connection will still be established even if your watch is in airplane mode AND bluetooth is turned off on the phone from Control Center. It took me some time to figure this out…

Ref

Failed to prepare device for development.

This operation can fail if the version of the OS on the device is incompatible with the installed version of Xcode. You may also need to restart your mac and device in order to correctly detect compatibility.

  1. Check /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ for directory name 15.4 (your iOS version).
  2. If the directory is missing download support files for 15.4 (your iOS version) from https://github.com/filsv/iPhoneOSDeviceSupport and place it in the above path.
  3. Restart Xcode.

Ref