用途:为 NativeScript iOS 应用添加 CoreSpotlight/系统搜索索引,并避免直接调用时出现的永久主线程死锁。资料指出,应用启动看似正常,但在数据加载后约 1–2 秒会永久冻结,通常表现为首次安装后滚动即卡死、重启后仍然冻结。
死锁原因:向原生接口传入 JS 数组时不会复制,而是包装成由活动 V8 数组支撑的 ArrayAdapter。CoreSpotlight 的 indexSearchableItems 使用 dispatch_apply 并行枚举,工作线程调用 count/objectAtIndex 时需重新进入 V8 并获取 isolate 锁,而调用线程在同步原生调用期间一直持有该锁,主线程也会在下一个 JS 回调处阻塞,形成三方死锁,最终被 watchdog 终止。另一加重因素是 CoreSpotlight 在自身后台队列调用完成回调,JS 回调在那里执行会持有 V8 锁。
两条规则:其一,传给 CoreSpotlight 的每个集合都要物化,例如先在 JS 线程构建真实 NSMutableArray 再传入,嵌套集合同样处理,如 attrs.keywords = NSArray.arrayWithArray(keywords as any);其二,完成回调先跳回主线程再继续操作,使用 Utils.dispatchToMainThread 包装后续逻辑。这两条规则也适用于其他可能在非主线程枚举集合的原生 API。
推荐集成形态:每次数据刷新先 deleteAllSearchableItems 再全量重建索引,并做约 1.5 秒防抖;唯一标识采用 <kind>:<id> 形式,kind 兼作 domainIdentifier;用 CSSearchableItemAttributeSet.alloc().initWithContentType(UTTypeText) 构建条目,设置标题、描述、物化的关键词及可选起止时间;将 expirationDate 设为 NSDate.distantFuture,否则条目 30 天后过期;重复系列先去重;点击通过应用委托中的 applicationContinueUserActivityRestorationHandler 处理 CSSearchableItemActionType,读取 CSSearchableItemActivityIdentifier 映射到深链。
验证与诊断:任何索引改动后都要测试全新安装;用 xcrun simctl spawn booted log show --last 2m --predicate 'processImagePath CONTAINS "<appname>"' | grep -i spotlight 查看成功日志;卡死时用 sample <pid> 查找 v8::Locker::Initialize 签名;在模拟器主屏搜索索引标题并点击验证路由。资料基于 iOS 26 模拟器与 @nativescript/core 9.1.0-alpha.11 验证,其他版本行为暂未提供。