You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

ArcGIS Runtime SDK for Qt(100.2) iOS端MapView销毁崩溃问题求助

解决ArcGIS Runtime SDK for Qt 100.2中MapView销毁后崩溃的问题

我之前在处理ArcGIS Qt SDK的项目时也遇到过几乎一模一样的问题,结合官方文档和社区实践,给你整理几个靠谱的修复思路:

问题根源

你看到的这个ASSERT报错,核心是跨线程事件发送冲突QRTImpl::LocationDisplayImpl这个内部对象是在某个子线程创建的,但销毁MapView时,主线程尝试给它发送事件,因为线程归属不匹配,触发了Qt的断言检查导致崩溃。在100.2这种早期版本的ArcGIS Qt SDK中,LocationDisplay的线程管理确实存在已知的bug。

可尝试的解决方案

按顺序试试这几个方法,基本能解决问题:

  • 主动清理LocationDisplay再销毁MapView
    在销毁MapView之前,先手动停止LocationDisplay并解除关联,避免后续自动触发跨线程事件:

    // 假设你的MapView实例是mapView
    if (mapView && mapView->locationDisplay()) {
        mapView->locationDisplay()->stop();
        // 解除关联,切断事件传递路径
        mapView->setLocationDisplay(nullptr);
    }
    // 用deleteLater让Qt事件循环安全处理销毁
    mapView->deleteLater();
    

    别直接用delete销毁MapView,deleteLater()会让Qt在当前线程的事件循环空闲时执行销毁,大大降低线程冲突的概率。

  • 保证MapView的创建和销毁在同一线程
    检查你的代码逻辑:是不是在主线程创建了MapView,却在子线程里销毁它?或者反过来?一定要确保**MapView的创建和销毁操作都在同一个线程(一般是主线程)**执行。如果是在子线程创建的MapView,要么把销毁逻辑移到该子线程,要么提前调用mapView->moveToThread(QApplication::instance()->thread())把它移回主线程再销毁。

  • 升级SDK版本(最彻底的解决方法)
    100.2是2018年的老版本了,Esri在后续的100.x版本(比如100.15及以上)中修复了大量线程安全相关的问题,包括LocationDisplay的线程管理bug。如果项目允许的话,升级到稳定的新版本,这类问题基本都被官方解决了。

  • 清空所有相关引用和监听器
    检查有没有其他自定义类(比如定位状态监听器、地图加载回调)还持有MapView或者LocationDisplay的引用,导致MapView销毁后这些对象还在尝试发送事件。记得在销毁MapView前,断开所有connect的信号槽,清空相关指针引用。

额外调试技巧

如果还是找不到问题,可以加一段调试代码,打印线程ID确认归属:

qDebug() << "当前线程ID:" << QThread::currentThreadId();
if (mapView->locationDisplay()) {
    qDebug() << "LocationDisplayImpl所属线程ID:" << mapView->locationDisplay()->thread()->currentThreadId();
}

这样能精准定位到底是哪个线程不匹配,方便针对性调整。

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

火山引擎 最新活动