作为iOS独立开发者,我做了一个把城市探索变成「战争迷雾」的App——雁过留痕

uni-app 和 Flutter 打包上架 iOS 频繁触发 4.3 (a):原因拆解与合规处理路径 跨端方案让 iOS 上架的门槛降低了,但也带来一个明显的副作用 ——4.3 (a) 的命中率显著高于原生项目。很多开发者不理解:业务代码明明是自己写的,为什么还会被判为重复应用。这篇专门讲跨端场景,把原因和可走的路径讲清楚。 阅读详情

前言:一个搁置了两年的想法

我大学时候喜欢骑车在城市里乱逛,每到一个新地方就在手绘地图上涂一小块,像玩现实版的战争迷雾游戏。后来工作了,偶尔用运动App记轨迹,但看着那些线叠在地图上,总觉得缺了点什么。

直到有一天我盯着跑步App里密密麻麻的轨迹线发了会儿呆,突然想明白一件事:线是线,面积是面积。你沿着同一条路跑了一百遍,轨迹记录得再漂亮,你真正"探索"过的地方其实没增加。

我想要的不是"记录我走过哪条路",而是**“我到底覆盖了多少土地”**。

这两个问题看着像,其实差别很大。于是我做了「雁过留痕」——一个iOS App,核心概念只有一句话:把你走过的地方换算成探索面积,单位是 km²。

25米网格:听起来简单粗暴,调起来真不简单

实现"面积"这个概念比我预期难得多。

最早我试过用轨迹围成的多边形来算面积,结果发现你走个来回根本围不成像样的形状,算出来的数字毫无意义。后来换了思路:把地图切成 25m × 25m 的小格子,人经过一个格子就算"点亮"一个。探索面积 = 点亮的格子数 × 每个格子的面积。

这个方案效果出奇地好——你在街上走,地图上会像素画一样慢慢铺开一片颜色,直觉上就是"这块地方我踩过了"。

25米这个精度是一轮轮试出来的:

  • 50米:太粗,你明明没走到对面那条街,格子已经亮了
    • 10米:数据量爆炸,手机存储扛不住
    • 25米:刚好是精度和性能的平衡点
      GPS 轨迹记录本身用的是 iOS 的 CoreLocation 后台定位能力,这套 API 比较成熟,关键是在电量和精度之间找平衡。我在内部的指标追踪模块里监控了很多维度——总距离、总时长、记录天数、连续打卡天数、夜间出行次数、周末记录天数等等,这些数据最后都会喂给成就系统。

这里分享一下核心的网格计算逻辑,思路不复杂但很关键:

struct GridCell: Hashable {
    let x: Int
        let y: Int
        }
func gridCell(for coordinate: CLLocationCoordinate2D, gridSize: Double = 25.0) -> GridCell {
    // 将经纬度投影到平面坐标后,按 gridSize 取整
        let metersPerDegreeLat = 111_320.0
            let metersPerDegreeLon = 111_320.0 * cos(coordinate.latitude * .pi / 180)
                
                    let x = Int(floor(coordinate.longitude * metersPerDegreeLon / gridSize))
                        let y = Int(floor(coordinate.latitude * metersPerDegreeLat / gridSize))
                            return GridCell(x: x, y: y)
                            }
// 探索面积 = 去重后的格子数 × 单格面积
let exploredArea = Double(uniqueGridCells.count) * 0.000625 // 25×25 = 625m² = 0.000625km²

逻辑不难理解:把每个 GPS 坐标点映射到对应的网格,用 Set 去重,最后乘以单格面积就是总探索面积。真正麻烦的是工程层面的问题——后台定位的频率控制、大量格子数据的持久化性能、以及地图渲染时怎么高效绘制数万个已点亮格子。

省份解锁:比想象中上头

做着做着发现,光有面积数字还不够"爽"。你告诉用户"你探索了 12.7km²",他可能没什么概念。但如果你说**“你已经解锁了 3 个省份、15 个城市”**,感觉就完全不一样了。

所以我内置了中国行政区的边界数据,做了省市解锁的玩法。轨迹落在哪个省、哪个市,系统自动识别,地图上对应区域被染上颜色。

这里有个经典的坑:国内地图的坐标偏移问题(GCJ-02)。GPS 拿到的是 WGS-84 坐标,不做转换的话你在上海走的路可能"飘"到黄浦江里去。这个适配花了不少时间,做国内地图相关开发的同学应该都踩过这个。

成就徽章也是自然长出来的功能。我在代码里按不同维度分了好几个 track:

Track含义示例
exploration探索类累计探索面积达到 10km²
consistency坚持类连续记录 30 天
china中国版图类解锁 10 个省份
world世界探索类足迹覆盖 3 个国家

每个 track 下面又分多个系列,每个系列有多个层级。比如连续记录 7 天解锁一个徽章,30 天又是一个,90 天又是一个。做这套东西的时候自己都上瘾了——有一次周末专门绕远路走了一段没去过的巷子,就为了多亮几个格子。

数据安全:数据是用户的,不是我的

做这种长期积累型的 App,最怕数据丢失。你攒了大半年的探索面积,换个手机没了,用户肯定跟你急。

所以我做了本地备份导出,格式是自定义的 .wingprintBackup(底层是 JSON),同时也支持 GPX 格式导出,方便用户在其他平台使用。

这个决定其实挺纠结的。GPX 导出意味着用户可以把数据带走,对"留存"来说不是好事。但我觉得数据是用户的,不是我的。独立开发者跟大厂不一样,没必要靠锁数据留人。

一些做得还不错的功能,和坦白的问题

做得还不错的:

  • 桌面 Widget:显示当日进度和累计面积,这个好评率挺高
    • 路线回放:选一条历史轨迹,在地图上像看动画一样回放你的路线。去年十一出去玩回来看了一遍自己的行程回放,有点像用上帝视角重走了一遍
      坦白说的问题:

现在下载量不大。一个没有推广预算的新 App,在 App Store 里就是沧海一粟。而且"探索面积"这个概念需要解释成本,不像"记步"或者"打卡"那么直觉。

社交分享卡片一直想做——让用户一键生成好看的探索报告图,比如"2024年我走过了 XX km²,解锁了 XX 个城市"——还在打磨中。

写在最后

有个用户评论说:“人生总要留下一些什么,走过的路,见过的人,看过的风景。”

我看到这条评论的时候愣了一下,觉得这个 App 没白做。

如果你也是那种喜欢在城市里乱逛、走没走过的路、发现犄角旮旯小地方的人,可以在 App Store 搜「雁过留痕」试试。它是一个纯 iOS 原生 App,Swift 开发,目前还是我一个人在做。

另外也想和社区里的开发者交流几个技术方向:大规模网格数据的存储优化(目前用的 Core Data,数据量上去之后查询性能是个挑战)、后台定位的省电策略、以及地图上大量自定义图层的渲染性能。如果你有相关经验,欢迎评论区聊聊。

你所在的城市,你觉得自己探索了百分之几?

【信息科学与工程学】计算机科学与自动化——第六十三篇 人机交互之前端交互参数知识库02 每个分支下又细分了四个关键方向,并按照“研究对象/焦点、基本问题、核心理论/概念、研究方法、应用/目标、前沿/发展”的框架进行阐述,严格遵循了六级编码体系。在最终整合时,应建立唯一的学科分类编码表(例如,用两位数字或“ART”、“MED”、“ECO”等字母前缀),并确保所有下级编码(尺度、层次、类别、子类、具体项)的逻辑一致性。此回答中的编码为示例,实际系统需据此调整。控制过程(前馈、同期、反馈)、全面质量管理(TQM)、平衡计分卡(BSC)定量(调查、实验)、定性(访谈、民族志)、混合方法、大数据。 阅读详情

相关推荐

瑞芯微rk3568移植openbmc(一)----关于ob移植的优缺点

基于rock3a的单板,CPU为瑞芯微rk3568的环境,移植了openbmc

feixiang3839的专栏 5537

[iOS]Runtime2

为了让你在父类中依然能访问当前对象(也就是子类的实例),编译器在底层会生成一个结构体,叫 : 当调用 时,底层调用的函数是 : 拿着(也就是当前的子类对象)作为消息接收者,但是把方法查找的起点定位在了 (父类)这里需要注意的就是仍然是调用者自己,即先讲一下上篇没讲过的,我们如果缓存未命中,那我们就会进入慢速查找,现在我们来详细的讲解在进入慢速查找的瞬间会再看一遍方法列表,然后立刻调用加锁,因为多线程下别人正在动态添加方法或者扩容,不加锁会崩溃类就绪OC的机制就是在编译期只生成了 结构,当类首次被发送消息时(

wzm20070304的博客 262

Vue3多级路由缓存失效的深度解析与实战解决方案

本文深度解析了Vue3项目中多级路由下keep-alive缓存失效的根本原因,并提供了三种实战解决方案:通过路由扁平化根治问题、利用状态管理精细模拟缓存效果,以及借助keep-alive-vue3插件快速修复。文章旨在帮助开发者彻底理解Vue Router与keep-alive的协作机制,从而根据项目情况选择最佳策略,有效解决页面状态丢失的难题。

weixin_29015801的博客 285

VS Code + KXApp 开发 iOS 报错排查指南,工程、签名、真机、补全、配置

在 VS Code 里用 KXApp 开发 iOS,报错常不在代码而在环境。本文按失败阶段分五类排查:工程没出现 Xcode 视图(查 .xcodeproj 与 xcode-select)、构建失败(No profiles、Team 签名、CocoaPods 用 .xcworkspace)、真机调试失败(信任、开发者模式、设备未准备好)、没补全或 No such module(等索引、清 clangd 冲突)、设置保存不了(装 xcodeproj gem),每类给现象、日志通道和修法。

2501_91590906的博客 208

实战避坑:泛微E9流程接口与单点登录(SSO)开发全解析(含自定义Action、Restful API与免密登录)

本文深入解析泛微E9流程接口与单点登录(SSO)开发中的关键技术与避坑指南,涵盖自定义Action开发、Restful API鉴权机制及跨系统单点登录实现。通过实战案例与代码示例,帮助开发者高效完成二次开发,解决系统集成中的数据孤岛问题,提升企业信息化建设效率。

weixin_42549451的博客 674

ZYNQ学习:PL端DDR3 读写测试

DDR SDRAM 的最大特点是双沿触发,即在时钟的上升沿和下降沿都能进行数据采集和发送,同样的工作时钟, DDR SDRAM 的读写速度可以比传统的 SDRAM 快一倍。本次实验使用的 DDR3 芯片是南亚的 NT5CC256M16ER-EKI, NT5CC256M16ER-EKI 的 bank 位宽为 3,行位宽为 15,列位宽为 10,所以它的地址大小等于 2^3*2^15*2^10(即 2^28=256M),数据位宽为 16bit,所以容量大小为 256M*16bit,也就是 512MByte。

shuidiQAQ的博客 3031

flutter ios 4.3.a被拒整改方案

本文分享了团队首次推进Flutter项目iOS上架时遭遇4.3.a审核被拒的全过程。历经四次提审失败,因未深入分析根本原因,仅做局部优化,导致问题反复。最终通过复盘、整理被拒文档、结合元数据与IPA-Diff工具分析,发现核心问题是二进制代码相似度过高,源于Flutter项目未深度重构。遂开展为期两周的系统性整改:重构Dart代码、清理冗余、升级Flutter版本、优化元数据与UI设计,降低二进制指纹至0.23,成功通过审核。强调海外上架需环境隔离、专用设备,并愿免费协助解决同类问题。

zdgdq的专栏 154

gRPC之gRPC开发流程与入门案例

gRPC之gRPC开发流程与入门案例

YIYIYI 3759

Appuploader 创建 iOS 描述文件详解,Development / Ad Hoc / App Store

搞不清 iOS 描述文件(Provisioning Profile)该选 Development、Ad Hoc 还是 App Store?本文讲清四种类型各装到哪、哪些要绑设备、能不能上架,重点辨析最容易混的 Development 与 Ad Hoc,说明设备或证书变动后为什么要重建、重建后要重新导入签名,并给出不用 Mac 在 Windows/Linux 上用 Appuploader 新建与重建描述文件的实操步骤,附装机"描述文件不匹配"等常见问题排查。

2501_91373349的博客 237

上网第二课:办了百兆宽带,为什么测速只有一半?

最慢的那一环。

qq_36765170的博客 110

深入理解 DDR5 Bank Group 与并行调度机制

Bank Group架构和并行调度机制,是DDR5性能跃升的核心秘密!理解它们才能写出高效调度程序,设计出性能强劲又稳定的DDR5系统。🎯记住:Bank Group不是简单的分组,而是高速并行的“魔法钥匙”,巧用它,你的DDR5设计将爆发惊人性能!

weixin_43199439的博客 313

VS Code 开发 iOS 工程,KXApp 与 Xcode 分工,双工具协同实操

想用 VS Code 写 iOS 又担心脱离 Xcode、搞乱团队工程?本文讲清 KXApp 和 Xcode 的并用关系:它是 Mac 上的 VS Code 扩展、必须装 Xcode 并调用它构建签名,两边共用编译结果(一边编过另一边不用重编)、共用同一份工程文件不迁移,补全用的 buildServer.json 可 gitignore 不影响同事,签名沿用 Xcode 登录的账户,Cmd+B/R/. 快捷键一致,Interface Builder 和 Instruments 仍回 Xcode。

2501_91592143的博客 71

【雕爷学编程】Arduino动手做(75)---TTL转RS-485模块之二线制可以实现真正的多点双向通信

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来---小小的进步或是搞不掂的问题,希望能够抛砖引玉。 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程) 实验七十五:TTL转RS-485模块 MAX485 RS485模块 MAX485 是一个8.

雕爷学编程 1万+

苹果的内核跑上了安卓手机:2,631 Star 的 HakiOS 让 XNU 在 Adreno GPU 上画出 118 帧

HakiOS 把苹果开源的 XNU 内核搬上 Android 手机:自研引导器与驱动、RAM 内运行重启即还原,Metal 在 Adreno GPU 上跑出 118 帧。本文拆解其分层架构、双路线性能对比与法律边界。

话梅糖の优快云 Blog 341

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Windows 开发 iOS,Sign in with Apple 苹果登录,KXBuild 真机调试全流程

Sign in with Apple 接入分四步:App ID 开能力并重新生成描述文件,entitlements 加 com.apple.developer.applesignin,用 SignInWithAppleButton 拿 identityToken 交服务端验签,删账号时调 revoke。本文讲清审核指南 4.8 为什么要你提供它、姓名邮箱只给一次、用 user 当主键,并在 Windows 上用 KXBuild 真机测登录,附 1000 报错排查。

2501_91373349的博客 234

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Appuploader 配置 iOS Bundle ID,开启推送、iCloud,解决描述文件失效问题

App 代码没动,去开发者后台取消勾选一个能力,再打包就签名失败、描述文件失效——为什么?本文讲清 iOS Bundle ID(App ID)的注册规矩(反向域名、创建后 Identifier 不可改、通配符、App Clip)、用 Appuploader 配置推送/iCloud/App Groups 等 Capabilities 的方法,重点说明能力配置与 Apple 门户实时同步、描述文件是能力的快照,以及取消能力为何导致描述文件失效、怎么重建修复,附改名、删除、通配符等常见问题。

2501_91591841的博客 156

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

iOS 深度链接配置教程,URL Scheme 与 Universal Links,KXBuild 真机验证

深度链接两种:URL Scheme(myapp://)只改 Info.plist 的 CFBundleURLTypes;Universal Links(https://)要开 Associated Domains、在 entitlements 写 applinks 域名、网站放 /.well-known/apple-app-site-association。讲清两者怎么选、onOpenURL 处理代码,在 Windows 上用 KXBuild 装 Debug 包真机验证,附 CDN 缓存和十个不跳转排查。

2501_91600747的博客 297

手机远程控制电脑哪家强?2026年iOS/安卓/鸿蒙横评实测,ToDesk/向日葵谁更流畅

手机远程控制电脑已成刚需,ToDesk凭借全平台覆盖、低延迟、无广告、免费不限速等优势,成为最佳选择。其iOS、安卓、鸿蒙及Mac系统均支持,实测连接快、操作流畅,虚拟键盘、外接键鼠、互动批注等功能体验出色。相较之下,向日葵存在限时踢线、传输慢、广告多等痛点。选购建议:无论用何种手机,首选ToDesk,实现高效便捷的远程办公与协助。

lx08113的博客 307

uni-app iOS 离线打包教程,Windows KXBuild 本地生成 IPA,页面秒推真机

uni-app 云打包老排队、次数受限、改一次 manifest 原生配置就得重打?用 KXBuild 的 HBuilderX 插件在 Windows 本地做 uni-app 离线打包 iOS:导入同版本离线 SDK、填好 AppKey 和证书,就能运行到 iPhone 真机,改页面用"推送"几秒生效,最后生成可上传 App Store Connect 的 ipa,全程不用云打包。附 AppKey 错误、版本不匹配白屏、相机闪退等 9 个常见问题排查。

2501_91510632的博客 207

go消息推送之极光推送 (JPush REST API + SDK,覆盖安卓与iOS)

使用 gorush有个绕不开的问题:国内安卓设备上 FCM 基本不可达,华为、小米、OPPO、vivo 各自为政——此时可用极光推送(JPush)作解决方案。它的思路和前面几家都不一样:App 集成极光 SDK 后拿到统一的 RegistrationID,服务端发一条 REST 请求,极光云端自动把消息路由到 APNs、各家厂商通道或极光自有长连接。这里给出了:一个用纯标准库直接调用极光的;另一个用社区维护的,类型化参数,接口注释与官方文档逐条对应。两个功能相同,可放在一起对比学习。

qq_40467670的博客 187

Cocos Creator3.8.8 + Xcode27.2 编译运行失败

Cocos Creator3.8构建IOS工程后,使用最新的Xcode27.2版本进行真机调试,遇到C++标准库冲突,如is_floating_point、is_arithmetic和is_signed失败,以及webp对齐失败等问题。

HYNN12的博客 421

IPD咨询洞察:华为项目管理:分析价值创造的来源

华为项目管理中,价值交付不是笼统的完成任务,而是从两个角度拆解:价值的形态和归属。价值有三个维度——当期商业价值、未来战略目标、整体能力提升。价值归属四类对象:客户、企业、伙伴、团队。先定义价值,再对齐对象,项目才算真正交付了价值。

weixin_58096508的博客 232

IPD咨询洞察:华为项目文化:让胜利成为一种信仰

华为“让胜利成为信仰”的本质是使命必达,落地为五项内核:开放创新、勇于担当、团队协同、契约精神、善思善结。使命必达不能停留在墙面标语,须转化为可落地、可考核的行为准则,胜利才能真正成为团队习惯。

weixin_58096508的博客 120

【2026-11-06】华为研发机试三道编程题解

本文整理了华为11月6日研发岗三道编程题解法:第一题为按列填充句子,通过枚举行数模拟列宽计算,求最小行数;第二题为生鲜库存优化,利用动态分配思想,预处理“采购-销售”成本,贪心选择最便宜来源满足需求;第三题涉及AC自动机与动态规划结合的序列化奖励问题。代码均以Java实现,思路清晰,适合笔试刷题参考。关注公众号【TechGuide】获取更多真题解析。

试问道几许 375

华为运维面试题

华为面试注重真实经历与价值观契合,主管面采用STAR+价值观锚点+反思闭环框架,强调“我”的决策与量化结果。运维手撕题重思路表达与边界处理,需清晰复述、分步讲解、主动验证。云场景设计题须先澄清需求,再分层设计,兼顾可靠性与成本,突出取舍意识。通用心法:聚焦“我”、结构先行、主动说明边界与改进,以数字和反思收尾,展现复盘能力与华为文化匹配度。

dp340823的博客 179

鸿蒙手机远程控制Windows电脑:华为手机控电脑实操完全指南

对于鸿蒙(HarmonyOS)用户来说,用华为手机/平板远程控制Windows电脑,ToDesk是目前最佳选择

球球!? 253
上一篇: iOS 专注 App 架构实践:用 struct ViewModel 全面替代 ObservableObject,代码量砍掉三分之一
下一篇: 我用 ArkTS 做了一个精力管理 App:用「电量」隐喻追踪一天的精力消耗
SameX-4869
博客等级 码龄18年 3354粉丝 657原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值