<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>App 开发 on Bruce&apos;s 博客</title><link>https://www.huangqixuan.com/categories/App%20%E5%BC%80%E5%8F%91/</link><description>Recent content in App 开发 on Bruce&apos;s 博客</description><generator>Recovered static publication</generator><language>zh-cn</language><lastBuildDate>Sun, 30 Aug 2026 21:30:00 +0800</lastBuildDate><atom:link href="https://www.huangqixuan.com/categories/App%20%E5%BC%80%E5%8F%91/index.xml" rel="self" type="application/rss+xml"/><item><title>我和 Codex 把一个包裹列表做成了 ParcelBoard：从 SwiftUI 到灵动岛与 Apple Watch</title><link>https://www.huangqixuan.com/p/parcelboard-ios-app-development/</link><pubDate>Sun, 30 Aug 2026 21:30:00 +0800</pubDate><guid>https://www.huangqixuan.com/p/parcelboard-ios-app-development/</guid><description>&lt;img src=&quot;https://www.huangqixuan.com/img/parcelboard/cover.webp&quot; alt=&quot;Featured image of post 我和 Codex 把一个包裹列表做成了 ParcelBoard：从 SwiftUI 到灵动岛与 Apple Watch&quot; /&gt;&lt;p&gt;ParcelBoard 最早并不是一个功能完整的快递 App。第一版能做的事情很少：添加一个包裹，在列表里看状态，点进去看几条物流动态，不需要的就删掉。&lt;/p&gt;
&lt;p&gt;真正开始在手机上使用以后，问题很快多了起来。单号从哪里来，能不能直接扫运单，状态怎样自动更新，取件码放在哪里最顺手，锁屏和 Apple Watch 能不能看，物流节点又该怎样画到地图上。每补上一块，工程都会牵出新的系统限制和交互问题。&lt;/p&gt;
&lt;p&gt;截至 2026 年 8 月 28 日，iOS 工程已经来到 &lt;code&gt;3.1.12 (35)&lt;/code&gt;。它仍然是一个没有上架的测试项目，但已经从本地列表变成了可以完整走通日常流程的原生 SwiftUI App。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/parcelboard/home.webp&quot; alt=&quot;ParcelBoard 当前主界面，画面使用本地演示包裹&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;我为什么想做一个包裹管理-app&quot;&gt;&lt;a href=&quot;#%e6%88%91%e4%b8%ba%e4%bb%80%e4%b9%88%e6%83%b3%e5%81%9a%e4%b8%80%e4%b8%aa%e5%8c%85%e8%a3%b9%e7%ae%a1%e7%90%86-app&quot; class=header-anchor&gt;&lt;/a&gt;我为什么想做一个包裹管理 App&lt;/h2&gt;
&lt;p&gt;我想要的并不只是“查一次快递”。我更希望有一个自己能控制的界面，把运单号、当前状态、最近动态、地图节点和取件码放到一起。打开以后先看到哪些包裹还在运输、哪些今天派送、哪些需要注意，而不是每次重新复制单号再查询。&lt;/p&gt;
&lt;p&gt;iOS 本身也有很多适合这类信息的入口。桌面小组件适合看概览，实时活动和灵动岛适合盯一个正在派送的包裹，Apple Watch 适合抬腕确认状态。取件码如果能从快捷指令写入，就不必临时翻短信。&lt;/p&gt;
&lt;p&gt;这些想法单独看都不复杂，放进一个工程后却会互相影响。主 App 保存的数据要同步给小组件和手表，物流更新要同时刷新通知与实时活动，点击锁屏卡片还要准确回到对应的包裹详情。ParcelBoard 后面的开发，主要就是在处理这些连接处。&lt;/p&gt;
&lt;h2 id=&quot;第一版先把最小闭环跑通&quot;&gt;&lt;a href=&quot;#%e7%ac%ac%e4%b8%80%e7%89%88%e5%85%88%e6%8a%8a%e6%9c%80%e5%b0%8f%e9%97%ad%e7%8e%af%e8%b7%91%e9%80%9a&quot; class=header-anchor&gt;&lt;/a&gt;第一版先把最小闭环跑通&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;1.0.0&lt;/code&gt; 只做了四件事：包裹列表、状态筛选、物流动态和设置。数据都保存在本地，添加、查看、删除能够正常工作，就算完成第一步。&lt;/p&gt;
&lt;p&gt;这个阶段看起来朴素，却很有必要。如果一开始就同时接接口、做地图、加组件和手表，很难判断一个问题究竟出在数据、界面还是跨进程同步上。先让本地模型稳定下来，后面的功能才有可以依靠的底座。&lt;/p&gt;
&lt;p&gt;到了 &lt;code&gt;2.1.0&lt;/code&gt;，我开始在真机上调整空列表、状态筛选和详情交互，同时给新版工具栏准备布局，并保留 iOS 18 的兼容路径。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/parcelboard/early-real-device.webp&quot; alt=&quot;ParcelBoard 2.1.0 的早期真机设置页&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在回看，早期版本和今天的外观差别没有想象中大。变化最大的不是颜色或圆角，而是数据从哪里来，以及同一份包裹状态要送到多少个系统入口。&lt;/p&gt;
&lt;h2 id=&quot;从演示数据走到真实物流&quot;&gt;&lt;a href=&quot;#%e4%bb%8e%e6%bc%94%e7%a4%ba%e6%95%b0%e6%8d%ae%e8%b5%b0%e5%88%b0%e7%9c%9f%e5%ae%9e%e7%89%a9%e6%b5%81&quot; class=header-anchor&gt;&lt;/a&gt;从演示数据走到真实物流&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;2.2.0&lt;/code&gt; 开始加入数据服务选择，&lt;code&gt;2.3.0&lt;/code&gt; 接入快递100真实查询。工程里目前保留四种模式：本地演示、快递100直连、自建 HTTPS 代理，以及受控测试使用的专用服务 Beta。&lt;/p&gt;
&lt;p&gt;演示模式一直没有删。它不仅方便截图，也能在不消耗接口次数、不暴露真实单号的情况下测试状态变化、异常包裹、跨城路线和通知。开发者选项还可以忽略本地限频、模拟网络延迟、显示数据来源和导出诊断信息。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/parcelboard/developer-options.webp&quot; alt=&quot;ParcelBoard 开发者选项中的演示模式与查询调试开关&quot;&gt;&lt;/p&gt;
&lt;p&gt;真实查询比发送一个运单号麻烦。不同快递公司需要不同的承运商编码，顺丰和中通等查询有时还需要手机号。返回的数据也不一定完整，状态、时间、地点和经纬度都有缺失的可能。App 需要把这些结果整理成统一模型，再决定该不该触发通知、更新实时活动或者重绘地图。&lt;/p&gt;
&lt;p&gt;为了避免无意中连续调用接口，我给同一运单加了 30 分钟的本地查询保护。手表端也不会直接查询快递服务，只接收 iPhone 已经保存的快照，因此不会因为抬腕或点同步而额外消耗 API 次数。&lt;/p&gt;
&lt;p&gt;这里还有一笔不能忽略的长期成本。快递100的&lt;a class=link href=&quot;https://api.kuaidi100.com/document/5f0ffb52bc8da837cbd8aefb.html&quot; target=_blank rel=noopener&gt;实时快递查询接口&lt;/a&gt;是按查询量使用的付费服务。现在个人测试的调用量还容易控制；如果以后用户变多，就需要购买更多查询额度或企业套餐，价格以官方后台当时显示的方案为准。到那一步，服务器代理、预算上限、缓存和防滥用就不再是“以后再做”的优化，而是能不能持续提供服务的前提。&lt;/p&gt;
&lt;p&gt;授权信息保存在设备钥匙串里，但这不等于可以把共享密钥直接放进公开版本。个人真机测试可以直连，真正公开分发时更合适的做法是把服务商凭据留在服务器，通过自己的 HTTPS 代理转发请求。&lt;/p&gt;
&lt;h2 id=&quot;添加包裹不能只靠手动输入&quot;&gt;&lt;a href=&quot;#%e6%b7%bb%e5%8a%a0%e5%8c%85%e8%a3%b9%e4%b8%8d%e8%83%bd%e5%8f%aa%e9%9d%a0%e6%89%8b%e5%8a%a8%e8%be%93%e5%85%a5&quot; class=header-anchor&gt;&lt;/a&gt;添加包裹不能只靠手动输入&lt;/h2&gt;
&lt;p&gt;如果每个运单都要逐字输入，这个 App 很快就会变成一个不想打开的工具。因此后面的版本逐步加入了几条入口：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;手动填写单号、快递公司和名称。&lt;/li&gt;
&lt;li&gt;用相机扫描条形码。&lt;/li&gt;
&lt;li&gt;从运单照片里同时识别条码和印刷文字。&lt;/li&gt;
&lt;li&gt;回到前台时检查剪贴板里的单号，确认后进入添加页。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里最容易误判的是权限。iOS 对相机、照片和剪贴板有各自的系统机制，App 不能假装已经获得权限，也不应该一启动就读取所有内容。ParcelBoard 把识别动作放在用户能看见的入口里，并在首次引导中解释为什么需要这些权限。&lt;/p&gt;
&lt;p&gt;照片识别也不是简单 OCR。运单上可能同时出现订单号、手机号、地址和多个条码。识别结果必须先筛选格式，再交给用户确认，不能看到一串数字就直接加入包裹列表。&lt;/p&gt;
&lt;h2 id=&quot;地图画的是物流节点不是快递车的位置&quot;&gt;&lt;a href=&quot;#%e5%9c%b0%e5%9b%be%e7%94%bb%e7%9a%84%e6%98%af%e7%89%a9%e6%b5%81%e8%8a%82%e7%82%b9%e4%b8%8d%e6%98%af%e5%bf%ab%e9%80%92%e8%bd%a6%e7%9a%84%e4%bd%8d%e7%bd%ae&quot; class=header-anchor&gt;&lt;/a&gt;地图画的是物流节点，不是快递车的位置&lt;/h2&gt;
&lt;p&gt;地图是这个项目里返工最多的部分之一。&lt;/p&gt;
&lt;p&gt;快递100在部分结果里会返回行政区中心坐标，自建服务也可以提供经纬度。旧数据只有地点文字时，App 会尝试用系统地理编码补出坐标，然后用 MapKit 把有效节点连起来。&lt;/p&gt;
&lt;p&gt;这条线只能表达“包裹经过了哪些物流节点”。它不是车辆 GPS，更不是严格沿道路行驶的路线。为了不把示意图做得像实时追踪，我在只有两个节点时只生成轻微弧度，多节点使用平滑样条减少尖锐折线，并在界面和说明里保留这个边界。&lt;/p&gt;
&lt;p&gt;到了 &lt;code&gt;3.1.5&lt;/code&gt;，详情页开始参考 Apple 健身 App 的层次：地图成为整页视觉底层，标题和物流卡片从渐变中自然进入；横屏则改成全屏地图加左侧半透明信息面板。这个方向确定以后，仍然连续改了七个小版本。&lt;/p&gt;
&lt;p&gt;有时是地图容器跟着滚动缩放，有时是内容穿出玻璃面板，有时是灵动岛安全区读成零，还有一次只是标题和卡片之间多出了一截很明显的空隙。&lt;code&gt;3.1.12&lt;/code&gt; 最后处理的是横屏返回按钮与面板触控区域重叠。这样的 Bug 在模拟器里不一定明显，换到真机横屏、下拉和旋转以后才会出现。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/parcelboard/map-landscape.webp&quot; alt=&quot;ParcelBoard 3.1.12 横屏地图详情，路线与包裹均为演示数据&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;实时活动不是缩小版详情页&quot;&gt;&lt;a href=&quot;#%e5%ae%9e%e6%97%b6%e6%b4%bb%e5%8a%a8%e4%b8%8d%e6%98%af%e7%bc%a9%e5%b0%8f%e7%89%88%e8%af%a6%e6%83%85%e9%a1%b5&quot; class=header-anchor&gt;&lt;/a&gt;实时活动不是缩小版详情页&lt;/h2&gt;
&lt;p&gt;我一开始也想把更多物流信息塞进灵动岛，结果很快遇到文字裁切、安全区和载荷大小问题。后来按照 Apple 的设计方式，把实时活动拆成锁屏、紧凑、最小和展开四种形态。&lt;/p&gt;
&lt;p&gt;紧凑状态只保留图标和配送进度，展开后才显示起点、运输、终点以及一条关键动态。点击活动会通过深层链接直接打开对应包裹，而不是只回到 App 首页。&lt;/p&gt;
&lt;p&gt;Apple 要求实时活动的静态数据和动态数据合计不能超过 4 KB，而且扩展本身不能联网或持续读取位置。ParcelBoard 因此只把必要状态交给 ActivityKit，迷你路线在本地根据物流节点绘制。布局结构发生变化时，还需要提高布局版本并重建旧活动，否则系统可能继续显示缓存中的旧版空白内容。&lt;/p&gt;
&lt;p&gt;这部分后来比预计多花了很多时间。锁屏卡片能显示，不代表紧凑灵动岛不会被圆角裁掉；新安装正常，也不代表从旧版本升级后不会留下旧活动。真正稳定的标准，是四种形态、深浅色、升级路径和点击跳转都能在真机上走通。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/parcelboard/live-activity-lock-screen.webp&quot; alt=&quot;ParcelBoard 在锁屏上显示的派送中实时活动，内容为演示数据&quot;&gt;&lt;/p&gt;
&lt;p&gt;Apple 的 &lt;a class=link href=&quot;https://developer.apple.com/design/human-interface-guidelines/live-activities&quot; target=_blank rel=noopener&gt;Live Activities 设计规范&lt;/a&gt; 强调“快速扫一眼就能理解”，&lt;a class=link href=&quot;https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities&quot; target=_blank rel=noopener&gt;ActivityKit 文档&lt;/a&gt; 也明确说明了 4 KB 限制和扩展不能联网。这两条最后直接改变了 ParcelBoard 的布局和数据结构。&lt;/p&gt;
&lt;h2 id=&quot;取件码为什么用了快捷指令&quot;&gt;&lt;a href=&quot;#%e5%8f%96%e4%bb%b6%e7%a0%81%e4%b8%ba%e4%bb%80%e4%b9%88%e7%94%a8%e4%ba%86%e5%bf%ab%e6%8d%b7%e6%8c%87%e4%bb%a4&quot; class=header-anchor&gt;&lt;/a&gt;取件码为什么用了快捷指令&lt;/h2&gt;
&lt;p&gt;取件码看起来像一条短信里的几个字符，但普通 iOS App 不能直接扫描系统短信数据库。与其做一个无法正常工作的“自动读取”，我最后选择了快捷指令。&lt;/p&gt;
&lt;p&gt;用户可以让快捷指令接收短信内容，提取取件码后写入 ParcelBoard。App 再把它同步到包裹详情、最近动态、实时活动、灵动岛、小组件和 Apple Watch。这样系统边界清楚，自动化过程也由用户主动安装和授权。&lt;/p&gt;
&lt;p&gt;我把目前使用的快捷指令放在这里：&lt;a class=link href=&quot;https://www.icloud.com/shortcuts/c6269f4a0e5d45f3a1307cb9feb0bf48&quot; target=_blank rel=noopener&gt;安装 ParcelBoard 取件码快捷指令&lt;/a&gt;。安装前仍然应该逐步检查动作，确认它只处理自己愿意交给 App 的内容。&lt;/p&gt;
&lt;h2 id=&quot;小组件与-apple-watch-共用一份快照&quot;&gt;&lt;a href=&quot;#%e5%b0%8f%e7%bb%84%e4%bb%b6%e4%b8%8e-apple-watch-%e5%85%b1%e7%94%a8%e4%b8%80%e4%bb%bd%e5%bf%ab%e7%85%a7&quot; class=header-anchor&gt;&lt;/a&gt;小组件与 Apple Watch 共用一份快照&lt;/h2&gt;
&lt;p&gt;ParcelBoard 的小组件支持不同尺寸，显示包裹概览或最近动态。主 App 会把经过整理的快照写入 App Group，Widget 扩展只负责读取和展示。这样小组件不需要复制整套数据库和网络层。&lt;/p&gt;
&lt;p&gt;Apple Watch 采用相似思路。iPhone 通过 WatchConnectivity 发送已保存的包裹快照，手表保存最近一次结果，因此手机暂时不在附近时仍能查看。手表首页只放在途、派送中、异常和最近包裹，点进详情再看位置、预计送达和最近几条物流动态。&lt;/p&gt;
&lt;p&gt;Apple 对 &lt;a class=link href=&quot;https://developer.apple.com/documentation/watchconnectivity&quot; target=_blank rel=noopener&gt;Watch Connectivity&lt;/a&gt; 的定位就是在配对的 iPhone 与 Apple Watch 之间传递少量数据或文件。对这个项目来说，同步快照比在手表端重新建立网络查询更简单，也更节制。&lt;/p&gt;
&lt;h2 id=&quot;一个列表点击问题连续出了两个紧急版本&quot;&gt;&lt;a href=&quot;#%e4%b8%80%e4%b8%aa%e5%88%97%e8%a1%a8%e7%82%b9%e5%87%bb%e9%97%ae%e9%a2%98%e8%bf%9e%e7%bb%ad%e5%87%ba%e4%ba%86%e4%b8%a4%e4%b8%aa%e7%b4%a7%e6%80%a5%e7%89%88%e6%9c%ac&quot; class=header-anchor&gt;&lt;/a&gt;一个列表点击问题，连续出了两个紧急版本&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;3.0.0&lt;/code&gt; 加入 Apple Watch、取件码和新版实时活动以后，我又把列表交互改回系统原生导航，并希望保留 iOS 的双指连续多选。&lt;/p&gt;
&lt;p&gt;问题出在 SwiftUI 的 &lt;code&gt;List(selection:)&lt;/code&gt;。选择绑定一直存在时，普通单击会被选择逻辑抢走，用户点包裹却进不了详情。&lt;code&gt;3.0.1&lt;/code&gt; 先修了一次，真机上仍然不彻底，于是 &lt;code&gt;3.0.2&lt;/code&gt; 直接在普通状态停用列表选择绑定，双指手势再单独开启多选。&lt;/p&gt;
&lt;p&gt;这件事很能代表 ParcelBoard 的开发过程。代码看起来符合系统组件的用法，预览里也没有报错，但真实手指、导航动画和多选状态叠在一起，行为才会变得不一样。后来我不再尝试用一套状态同时承担导航和选择，而是把两种交互明确分开。&lt;/p&gt;
&lt;h2 id=&quot;后台更新有系统边界&quot;&gt;&lt;a href=&quot;#%e5%90%8e%e5%8f%b0%e6%9b%b4%e6%96%b0%e6%9c%89%e7%b3%bb%e7%bb%9f%e8%be%b9%e7%95%8c&quot; class=header-anchor&gt;&lt;/a&gt;后台更新有系统边界&lt;/h2&gt;
&lt;p&gt;App 可以在回到前台时刷新，也可以注册后台刷新任务并发送本地通知，但这不代表 iOS 会在每条物流更新出现的那一秒唤醒它。后台任务何时运行由系统决定，用户设置、使用习惯、电量和网络状态都会影响调度。&lt;/p&gt;
&lt;p&gt;所以 ParcelBoard 当前的本地方案适合“系统认为合适时检查”，不能承诺即时推送。要做到服务端一有变化就更新，需要自己的服务器定期查询，再通过 APNs 或 ActivityKit 推送把状态送到设备。Apple 的 &lt;a class=link href=&quot;https://developer.apple.com/documentation/backgroundtasks&quot; target=_blank rel=noopener&gt;Background Tasks 文档&lt;/a&gt; 也把这类能力描述为由系统调度的后台处理，而不是常驻进程。&lt;/p&gt;
&lt;h2 id=&quot;真正卡住发布的不是代码&quot;&gt;&lt;a href=&quot;#%e7%9c%9f%e6%ad%a3%e5%8d%a1%e4%bd%8f%e5%8f%91%e5%b8%83%e7%9a%84%e4%b8%8d%e6%98%af%e4%bb%a3%e7%a0%81&quot; class=header-anchor&gt;&lt;/a&gt;真正卡住发布的，不是代码&lt;/h2&gt;
&lt;p&gt;工程能够在自己的设备上运行，不等于已经具备上架条件。我在注册 Apple Developer Program 时遇到提示：一台受信任设备已经和现有开发者账户关联，因此注册无法继续。没有完成开发者计划注册，我就无法走正式签名、TestFlight 和 App Store 发布流程。&lt;/p&gt;
&lt;p&gt;我已经联系 Apple Developer Support。支持人员说明，他们出于隐私原因无法告诉我这台设备关联的是哪个账户，只能请我登录 Apple 账户安全页面，检查受信任设备列表并移除不属于自己的设备。我照着步骤检查并继续沟通过，但截至写这篇文章时，问题仍然没有解决。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/parcelboard/developer-program-trusted-device.webp&quot; alt=&quot;Apple Developer Support 对受信任设备关联问题的说明，案例编号与个人信息已裁去&quot;&gt;&lt;/p&gt;
&lt;p&gt;所以现在没有 ParcelBoard 的 App Store 下载链接，也不应该把它写成已经发布的产品。这个问题我会留到后面继续处理。先把账户与设备关联弄清楚，再谈正式签名、测试分发和上架，会比绕过注册问题更稳妥。&lt;/p&gt;
&lt;h2 id=&quot;现在怎样在自己的设备上构建&quot;&gt;&lt;a href=&quot;#%e7%8e%b0%e5%9c%a8%e6%80%8e%e6%a0%b7%e5%9c%a8%e8%87%aa%e5%b7%b1%e7%9a%84%e8%ae%be%e5%a4%87%e4%b8%8a%e6%9e%84%e5%bb%ba&quot; class=header-anchor&gt;&lt;/a&gt;现在怎样在自己的设备上构建&lt;/h2&gt;
&lt;p&gt;项目当前最低支持 iOS 18，Apple Watch 目标最低支持 watchOS 11。构建前需要准备 Xcode 27 或更高版本，以及自己的 Apple Developer Team。&lt;/p&gt;
&lt;p&gt;基本步骤如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用 Xcode 打开 &lt;code&gt;ParcelBoard.xcodeproj&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;在主 App、小组件和 Apple Watch 三个 Target 的 Signing &amp;amp; Capabilities 中选择同一个 Team。&lt;/li&gt;
&lt;li&gt;为自己的构建修改 Bundle Identifier，并保持 Watch Identifier 以 iPhone App Identifier 为前缀。&lt;/li&gt;
&lt;li&gt;确认主 App 与 Widget 扩展启用了同名 App Group；如果改了组标识，代码和 entitlement 也要一起修改。&lt;/li&gt;
&lt;li&gt;连接 iPhone，在 Xcode 顶部选择真机，按 &lt;code&gt;Command + R&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;只想看界面时，可以先开启演示模式，不填任何快递服务账号。要查询真实物流，再到设置中选择快递100或自己的 HTTPS 代理。&lt;/p&gt;
&lt;h2 id=&quot;当前局限&quot;&gt;&lt;a href=&quot;#%e5%bd%93%e5%89%8d%e5%b1%80%e9%99%90&quot; class=header-anchor&gt;&lt;/a&gt;当前局限&lt;/h2&gt;
&lt;p&gt;ParcelBoard 已经能在我的测试环境中使用，但离正式产品仍有距离。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;工程仍是测试项目，签名、App Group、Widget 和 Watch Target 对第一次构建的人并不算轻松。&lt;/li&gt;
&lt;li&gt;Apple Developer Program 注册仍被受信任设备关联问题卡住，因此目前无法通过 TestFlight 或 App Store 分发。&lt;/li&gt;
&lt;li&gt;地图只是物流节点示意，不代表道路轨迹或车辆实时位置；缺少坐标时，地理编码也可能失败。&lt;/li&gt;
&lt;li&gt;本地后台刷新没有固定时刻，不能代替服务端推送。&lt;/li&gt;
&lt;li&gt;快递100直连适合个人测试，公开分发前必须把共享凭据移到服务端；用户量增加后还要为查询额度准备持续预算。&lt;/li&gt;
&lt;li&gt;实时活动受系统缓存、活动数量和载荷限制影响，系统升级后仍需要持续真机验证。&lt;/li&gt;
&lt;li&gt;扫描、剪贴板与取件码自动化都受 iOS 权限和隐私边界约束，不可能完全无感运行。&lt;/li&gt;
&lt;li&gt;README 里的旧版本说明还没有完全跟上 3.1.12，工程设置与应用内更新日志才是当前版本依据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此外，项目已经有 Kotlin、Compose 和 Material 3 的 Android 移植方向，也做了 Wear OS 与通知取件码的尝试。不过这篇只记录 iOS 主线，两边的系统能力和交互习惯不同，不适合简单照搬。&lt;/p&gt;
&lt;h2 id=&quot;这段开发最真实的感受&quot;&gt;&lt;a href=&quot;#%e8%bf%99%e6%ae%b5%e5%bc%80%e5%8f%91%e6%9c%80%e7%9c%9f%e5%ae%9e%e7%9a%84%e6%84%9f%e5%8f%97&quot; class=header-anchor&gt;&lt;/a&gt;这段开发最真实的感受&lt;/h2&gt;
&lt;p&gt;ParcelBoard 从 &lt;code&gt;1.0.0&lt;/code&gt; 到 &lt;code&gt;3.1.12&lt;/code&gt; 只跨了一个多月，版本号看起来走得很快，实际大部分时间并不是在堆新功能。&lt;/p&gt;
&lt;p&gt;我会把真机截图和现象交给 Codex，一起定位布局、状态和系统 API 的问题，再回到 Xcode 构建、安装、旋转屏幕、锁屏、点灵动岛、抬手看手表。很多修复第一次并不完整，列表点击连续发了两个紧急版本，地图详情也在同一套设计上改了许多次。&lt;/p&gt;
&lt;p&gt;这种过程有点慢，却比只在模拟器里把界面做漂亮更可靠。一个包裹 App 真正难的地方，不是画出一张列表，而是让同一份状态在主 App、地图、通知、锁屏、小组件和手表之间保持一致，同时不越过系统边界。&lt;/p&gt;
&lt;p&gt;接下来我还会继续开发 ParcelBoard。短期内先处理开发者账户与受信任设备的关联问题，整理当前工程和文档，继续修正真机细节，再把查询、推送和发布方式做得更适合长期使用。它现在还不是一个可以交付完就不再管的成品，但已经从最初那个本地列表，变成了我愿意每天打开的工具。&lt;/p&gt;
</description></item></channel></rss>