iOS 独立开发者转鸿蒙:我把足迹地图 App 迁移到 ArkTS 的全过程

起因:照片记不住你走过的路

上个月出差跑了三个城市,回来翻相册想回忆去过哪些地方,发现照片里全是会议室和酒店大堂。那些走过的街道、路过的江边、绕远路发现的小巷子,什么都没留下。

运动类 App 能记录轨迹,但每次都要手动开始、手动结束,忘按一次就白走了。我只是想给自己留个痕迹,不想发给任何人看,也不需要配速心率那套东西。

困扰久了就自己动手做了------雁过留痕,一个足迹地图 App。iOS 端用 SwiftUI 写的,今年把它迁移到了 HarmonyOS 原生。这篇文章聊聊迁移过程中的技术选型、踩坑经验,以及鸿蒙平台上那些让我觉得「还真不错」的能力。

为什么没选跨平台,而是 ArkTS 原生

最初考虑过跨平台方案,毕竟 iOS 端已经有一套完整的 SwiftUI 代码。但试了几天 ArkTS 之后改了主意。

原因很实际:ArkUI 的声明式语法和 SwiftUI 在思路上非常接近,迁移的心智成本比预想的低不少。Column、Row、Stack 和 SwiftUI 的 VStack、HStack、ZStack 几乎一一对应,我把 iOS 端的 UI 结构搬过来改改语法,大部分页面半天就跑起来了。既然迁移成本不高,那不如直接原生,把鸿蒙独有的能力吃透。

更关键的是,鸿蒙有两个能力是 iOS 生态里拿不到的,对足迹记录这个场景刚好命中要害。

后台持续定位。 iOS 的后台定位权限审核越来越严,而 HarmonyOS 的 continuous task(长时任务)机制让后台轨迹采集有了更清晰的系统级支持。用户授权一次,App 在后台安静记录,不需要反复弹窗确认。做轨迹类产品的同学应该懂这个痛点。

原子化服务卡片。 用户不用打开 App,桌面卡片上就能看到今天走过的轨迹缩略图。比 iOS 的 Widget 更适合做这种「瞄一眼就够」的信息展示,因为卡片本身可以承载更丰富的交互。

轨迹采集与地图渲染的核心实现

轨迹记录的核心逻辑不复杂,但细节很多------GPS 漂移过滤、低速状态下的降频采集、电量优化策略等等。地图渲染这块用了 HarmonyOS 的 MapComponent,把采集到的坐标点用 Polyline 画到地图上。骨架代码长这样:

arkts 复制代码
@Entry
@Component
struct TrackMapView {
  @State pathPoints: Array<mapCommon.LatLng> = []

  build() {
    Column() {
      MapComponent({
        mapOptions: { center: { latitude: 39.9, longitude: 116.4 }, zoom: 12 }
      })
        .onReady((map) => {
          let polylineOpt: mapCommon.MapPolylineOptions = {
            points: this.pathPoints,
            clickable: false,
            width: 8,
            color: 0xFF3A7DFF
          }
          map.addPolyline(polylineOpt)
        })
        .width('100%')
        .height('80%')
    }
  }
}

做的事情很直白:坐标数组丢给地图组件,画一条线。实际项目里还有轨迹平滑、分段着色之类的处理,但骨架就是这个样子。如果你做过高德或百度地图的 Polyline 渲染,上手 MapComponent 基本没有额外学习成本。

桌面卡片:鸿蒙版体验提升最明显的地方

原子化服务卡片的实现是我觉得鸿蒙版比 iOS 版体验拉开差距的点。每天凌晨自动截取前一天的轨迹缩略图,更新到卡片上。用户早上解锁手机,一眼就看到昨天的足迹轮廓。

arkts 复制代码
@Entry
@Component
struct TrackWidgetCard {
  @LocalStorageProp('todayDistance') todayDistance: string = '0 km'
  @LocalStorageProp('trackSnapshot') trackImg: string = ''

  build() {
    Column({ space: 8 }) {
      Text('昨日足迹')
        .fontSize(14)
        .fontColor('#666')
      Image(this.trackImg)
        .width('100%')
        .aspectRatio(1.6)
        .borderRadius(8)
      Text(this.todayDistance)
        .fontSize(20)
        .fontWeight(FontWeight.Medium)
    }
    .padding(12)
  }
}

卡片上只放两样东西:一张轨迹缩略图和一个距离数字。克制一点,信息密度刚刚好。这个卡片上线之后我自己每天都会看一眼,已经变成一种习惯了。

SwiftUI → ArkTS 迁移的真实体感

聊几个具体感受,可能对同样在考虑双端开发的同学有参考价值。

布局系统迁移成本很低。 前面提到了 Column/Row/Stack 的对应关系,这不是客气话,是真的能直接「翻译」过来。如果你有 SwiftUI 经验,ArkUI 的布局系统几乎零学习成本。

状态管理思路有差异,但差异是好的。 SwiftUI 用 @State、@ObservedObject 那套,ArkTS 的 @State、@Link、@Prop 的作用域划分更细。刚开始会有点不习惯,但写了两三个页面之后反而觉得鸿蒙这套更明确------谁持有数据、谁只是引用,代码里看得更清楚。对于多组件间状态同步比较复杂的场景(比如地图页面和轨迹列表页的数据联动),这种显式的数据归属划分写起来心智负担更小。

工具链成熟度还在追赶。 DevEco Studio 整体还行,但和 Xcode 比的话,断点调试、性能分析这些工具还有打磨空间。不过每个版本都能感觉到在进步,不是阻塞性问题。

设备适配是实打实的加分项。 同一套代码跑在手机、平板、折叠屏上,ArkUI 的自适应布局能力省了不少事。雁过留痕在 MatePad 上展开地图的效果比手机上好太多,大屏看轨迹图那种满足感是小屏给不了的。

产品上的一个决定:只做留痕

开发过程中最难的不是技术,是克制。

总有人建议加社交分享、加运动数据统计、加打卡排行榜。但我一直觉得这个 App 的价值恰恰在于它什么都不多做。你出门,它安静记录;你想看了,打开地图,所有去过的地方一目了然。没有点赞,没有评论,没有「今日步数打败了 98% 的用户」。它不是运动 App,不做配速心率那些事,定位就是「记录去过的地方」,仅此而已。

有次出差结束看了一眼全年轨迹图,发现自己居然去过三十多个城市。地图上那条慢慢延伸的线,就是你存在过的证据。那个瞬间比任何打卡成就都让人感慨。

后续计划和想交流的问题

鸿蒙版目前在持续迭代中,后面打算尝试跨设备流转------手机上录的轨迹在平板上查看大地图,在手表上快速看今日路线。这些场景在 HarmonyOS 的分布式架构下实现起来会比较自然。

从我个人体感来说,鸿蒙生态对独立产品而言是一个值得认真对待的平台了。ArkTS 的学习曲线对有 Swift/TypeScript 基础的人很友好,原子化服务、分布式能力这些特色确实能做出 iOS 上做不到的东西。

有两个问题特别想和大家交流:一个是后台定位的功耗优化策略,continuous task 在长时间运行下电量表现怎么压;另一个是地图渲染性能,大量 Polyline 叠加时的卡顿问题有没有好的解法。踩过这两个坑的朋友,评论区聊聊?

#HarmonyOS开发 #ArkTS #ArkUI #原子化服务 #鸿蒙原生应用

相关推荐
sakiko_15 小时前
Swift学习笔记42-SwiftUI的属性包装器(讲解+面试)
笔记·学习·ios·swiftui·swift
Patrick_Wilson1 天前
iOS Safari 按钮点击无响应问题修复指南
前端·ios·safari
随遇丿而安1 天前
第 3 周:UIButton 点了没反应,因为它默认就没有按压态
ios
思盛iOS签名上架2 天前
App苹果签名有什么作用?
macos·ios·cocoa
CocoaKier2 天前
Facebook广告后台收不到Adjust回传数据,我们排查了一个月终于找到了根因
ios·facebook
FairGuard手游加固3 天前
iOS 游戏加固技术解析:代码混淆、资源加密、内存保护与重签名检测
安全·游戏·macos·unity·ios·objective-c
思盛iOS签名上架3 天前
iOS企业签名原理是什么?
macos·ios·cocoa
Daniel_Coder3 天前
我用 SwiftUI + GRDB 做了一个「按时吃药·服药提醒」App
ios·swiftui·swift·widgetkit