标签 SwiftUI 下的文章

之前在社区分享过 mytesla TeslaMate 的 Web 版看板,收到了不少车友的反馈。虽然 Web 版可以完美替换 grafana ,但手机浏览器的交互体验确实差点意思。

元旦开工以来,Vibe Coding 了一番,尝试把从 Next.js 转成 SwiftUI 。本想只是手痒重构,结果越写越上头,最后干脆完成了这个 iOS 原生版的 TeslaMate 客户端,并加了不少功能 —— Mytess (全部代码均为 Vibe Coding )

目前 App 已经跑通了核心功能并进入 TestFlight 阶段,想招募一批硬核车友参与内测,帮我一起找找 Bug 或者提提需求。

App 功能截图




核心功能

图文可以看官网 功能介绍

  • 基础监控:车辆实时状态、历史数据、电池健康度、各项统计报表。
  • 深度洞察:行程数据、周期数据洞察胶囊,用车环境、习惯、场景洞察。
  • 电费管理:地理围栏计费 + 历史电费批量更新。
  • 实时通知与灵动岛:商场停车时长、充电、导航信息直接上岛。
  • 交互式地图:在手机上平滑地回溯每一段行驶轨迹和细节。

参与方式(需要自建 TeslaMate )

为了适配 iOS 端,需要你在现有的 TeslaMate docker-compose.yml 中添加一个 API 容器。App 中配置改 API 服务地址和 Token 获取数据。可以自行打动或反向代理。

1. 修改 Docker 配置:
请务必使用 testflight 这个 tag:

teslamateapi:
    image: mytesla/teslamateapi:testflight
    restart: unless-stopped
    environment:
      - DATABASE_USER=${TM_DB_USER}
      - DATABASE_PASS=${TM_DB_PASS}
      - DATABASE_NAME=${TM_DB_NAME}
      - DATABASE_HOST=database
      - ENCRYPTION_KEY=${TM_ENCRYPTION_KEY}
      - MQTT_HOST=mosquitto
      - API_TOKEN=这里填你自定义的 Token
    ports:
      - 3030:8080

2. 加入 TestFlight:
https://testflight.apple.com/join/nreudJgB

问题反馈与交流

内测阶段难免有 Bug ,反馈参考如下:

  • 微信群交流:可以添加微信 mytesla-kefu 入群反馈问题。
  • 直截了当:在 TestFlight 中直接截图发送反馈。
  • 硬核 Debug:在 App 设置页最底部连点版本号 5 次,复制生成的日志发送至 [email protected],并附上简单描述。

一点心意:所有参与内测并积极反馈的用户,在正式版上线后都会提供专属折扣,并受邀参加后续的专属活动。

官网:https://cn.mytess.net/

最近因为要在 Mac 和 Android 手机之间传文件,发现目前可以用的工具要么是开源且丑的 whoozle/android-file-transfer-linux ,要么是好久没更新的 Google 开发的 Android File Transfer 。

为什么写这个?

  • Android File Transfer 不支持最新的 ARM 版本,且仍然使用 Intel 转译,体验很差
  • whoozle/android-file-transfer-linux 虽然开源,但界面简陋,而且需要自行编译 ARM 版本,对普通用户很不友好

于是决定自己撸一个开源工具——SwiftMTP 。折腾不到一个月终于能用了 🎉

关于我(先坦白)

我完全不会 Swift 和 GO 的开发,所以目前代码都是 AI 辅助生成的。正因为如此,可能存在 UI 样式异常或其他 bug 。如果你在使用过程中遇到任何问题,请务必及时反馈,我会尽力修复!

主要功能

  • 自动检测连接的 Android 设备( MTP 模式)
  • 文件浏览,支持文件夹导航
  • 文件下载/上传,支持拖放
  • 支持大文件传输(>4GB )
  • 批量选择和下载
  • 多语言支持(简中、英语、日语、韩语、俄语、法语、德语)
  • 显示设备存储空间

技术栈

  • 前端:SwiftUI ( MVVM 架构)
  • 后端:Go 1.22 + go-mtpx + libusb-1.0
  • 桥接:CGO ( Swift ↔ C ↔ Go )

目前已知限制

  • 仅支持 ARM 版本( Apple 芯片)
  • 要求系统版本在 macOS 26 或更高
  • 仅支持单个设备
  • 暂不支持文件夹上传(单文件上传)
  • 传输速度受 MTP 协议限制
  • UI 可能存在样式异常(因为我不会 Swift 😅)

下载方式

GitHub: https://github.com/wang93wei/SwiftMTP

可以从源码构建,或者直接下载安装包。

注意: 因为没有苹果开发者签名,所以可能需要其他方式方可使用:

如果看到 "SwiftMTP can't be opened because it is from an unidentified developer",尝试以下方法:

  1. 右键点击应用 → 选择「打开」
  2. 系统设置 → 隐私与安全性 → 允许 SwiftMTP
  3. 或在终端运行:xattr -cr /Applications/SwiftMTP.app

求反馈

  • 你的设备能否正常检测?
  • 传输速度如何?
  • UI 有没有样式问题?
  • 有没有遇到什么 bug ?
  • 有什么功能建议?

项目刚起步,代码写得可能不够优雅,欢迎提 issue 或 PR !

效果图

前言

在做图片相关功能时,有一个需求几乎绕不开:
用户拖动参数,图片实时变化。

比如:

  • 调整模糊强度
  • 改变对比度、饱和度
  • 预览滤镜效果,再决定是否应用

在 UIKit 时代,我们可能会用 UIImageView + CoreImage + GCD 硬撸。
但到了 SwiftUI,很多人第一反应是:

SwiftUI + CoreImage + 实时预览,这事靠谱吗?

答案是:靠谱,但得用对方式。

这篇文章就从一个最小可用 Demo开始,一步一步把实时滤镜预览这件事讲清楚。

先说结论:实时预览的关键点是什么?

在 SwiftUI 里做 CoreImage 实时预览,核心其实只有三点:

  1. 图片渲染要尽量轻
  2. 滤镜计算不能阻塞主线程
  3. UI 状态变化要最小化

如果你一上来就把所有滤镜计算都丢进 body
那基本等于在和 SwiftUI 的刷新机制正面硬刚。

一个最基础的目标效果

我们先定一个目标:

  • 显示一张原图
  • 拖动 Slider
  • 实时调整高斯模糊强度
  • 图片随着 Slider 连续变化

这是绝大多数滤镜编辑页的基础形态。

Step 1:准备 CoreImage 的基础组件

先把 CoreImage 的几个核心对象准备好:

import SwiftUI
import CoreImage
import CoreImage.CIFilterBuiltins

let context = CIContext()
let filter = CIFilter.gaussianBlur()

这里有两个细节值得注意:

  • CIContext 应该尽量复用
  • 不要在 body 里反复 new CIContext

CIContext 本身是重量级对象,频繁创建会直接拖垮性能。

Step 2:一个最简单的 SwiftUI 结构

我们先搭一个最基础的页面结构:

struct ContentView: View {
    @State private var intensity: Double = 0.5
    let image = UIImage(named: "example")!

    var body: some View {
        VStack {
            Image(uiImage: image)
                .resizable()
                .scaledToFit()

            Slider(value: $intensity)
                .padding()
        }
    }
}

到这一步,UI 是没问题的,但还没有任何滤镜逻辑

Step 3:把 CoreImage 滤镜接进来

关键思路是:
不要直接操作 UIImage,而是用 CIImage 作为中间态。

我们先写一个专门负责“生成滤镜图片”的方法:

func applyProcessing() -> UIImage {
    let beginImage = CIImage(image: image)
    filter.inputImage = beginImage
    filter.radius = Float(intensity * 20)

    guard let outputImage = filter.outputImage else {
        return image
    }

    if let cgimg = context.createCGImage(outputImage, from: beginImage!.extent) {
        return UIImage(cgImage: cgimg)
    }

    return image
}

这段代码做了几件事:

  1. UIImage 转成 CIImage
  2. 设置滤镜参数
  3. 通过 CIContext 渲染成 CGImage
  4. 再转回 UIImage

Step 4:把实时预览“接”到 SwiftUI 状态上

接下来是最关键的一步:
让 SwiftUI 在 Slider 变化时刷新图片,但不炸性能。

先引入一个新的状态:

@State private var processedImage: UIImage?

然后改造 body

var body: some View {
    VStack {
        Image(uiImage: processedImage ?? image)
            .resizable()
            .scaledToFit()

        Slider(value: $intensity)
            .padding()
            .onChange(of: intensity) { _ in
                processedImage = applyProcessing()
            }
    }
}

此时你已经可以看到:

  • Slider 一动
  • 图片跟着变
  • 滤镜是实时的

但——
这还不是一个“能上线”的写法。

性能问题从哪开始暴露?

当你快速拖动 Slider 时,会发现:

  • UI 有轻微卡顿
  • 真机上比模拟器更明显
  • 图片越大,问题越严重

原因也很直接:

滤镜计算跑在主线程。

Slider 的 onChange 本身就在主线程,
CoreImage 渲染又是 CPU / GPU 混合操作,
自然会影响 UI 响应。

Step 5:把滤镜计算移出主线程

一个简单、有效的方式是:
Task + MainActor 控制线程切换。

改造 onChange

.onChange(of: intensity) { _ in
    Task.detached {
        let output = applyProcessing()
        await MainActor.run {
            processedImage = output
        }
    }
}

这样做之后:

  • 滤镜计算在后台执行
  • UI 只负责展示结果
  • 拖动 Slider 明显顺滑很多

这一步,是“能不能实时预览”的分水岭。

再往前一步:为什么 SwiftUI 特别适合做这件事?

如果你用 UIKit 做过类似功能,会发现:

  • 手动管理线程
  • 手动刷新 ImageView
  • 状态和 UI 同步很痛苦

而 SwiftUI 的优势在于:

  • 状态驱动 UI
  • 图片只是状态的一个映射
  • 滤镜逻辑和 UI 逻辑可以完全解耦

你只需要保证一件事:

状态更新是轻的,计算是异步的。

一点真实项目里的经验总结

在真实项目中,我一般会遵守这几个原则:

  1. Slider 变化频繁时,必要时做节流
  2. 滤镜链尽量复用,不要每次 new
  3. 大图先 downscale 再做预览
  4. 最终导出时再跑一次“高质量渲染”

实时预览追求的是“看起来对”
而不是“每一帧都是最终质量”

总结

SwiftUI 并不是不适合做图像处理,
而是不能用同步思维去写异步计算

一旦你把:

  • CoreImage 的计算
  • SwiftUI 的状态刷新
  • 主线程和后台线程的职责

这三件事理顺了,
实时滤镜预览这件事,其实比 UIKit 时代要轻松得多。

自己做了一个 macOS 上的完整版任务管理器

为什么

macOS 上的官方任务管理器,也就是 “活动监视器 (Activity Monitor)”,是

只能监视,不能管理

也就是:只能查看进程,不能结束进程,更不能看进程文件位置

基本上没用

但我又是一个对这方面有大量需求的开发者,刚好我会 iOS 开发,于是我不能自己造一个呢?

怎么做

架构选型

最开始,我的目标很明确:做一个 macOS 版的 Windows 任务管理器 。

为了保证 “原生” 和 “极速”,我果断放弃了 Electron 这种网页套壳方案,选了 SwiftUI 。

但是,监控软件有个特点:数据更新非常快。如果让每个界面自己去拉数据,CPU 肯定受不了,界面也会卡。

所以,我确立了 MVVM + 单向数据流 的架构:

  1. 心脏 (SystemMonitorService.swift) :这是一个单例(Singleton)。它像心脏一样,每隔 2 秒跳动一次(Timer),负责把所有数据采集回来。
  2. 大脑 (AppViewModel.swift) :这是为了解决 “刷新页面数据重置” Bug 引入的。它把数据存住,不管界面怎么切,数据都在那儿。
  3. 脸面 (Views) :界面只负责展示,不负责逻辑。

数据获得

这是项目最难的部分。macOS 的上层 API(像 ProcessInfo )给的数据太浅了,根本不够用。我不得不 “下潜” 到内核层。

  1. CPU 计算
    我们不能直接问系统 “CPU 占用多少”,系统只会告诉你 “这一瞬间” 的状态。
    我们用的是 C 语言的 host_statistics 接口。
  • 逻辑 :现在看一眼 CPU,记录下 User/System/Idle 的时间滴答数(Ticks);过 2 秒再看一眼。
  • 计算 : (第二次的总数 - 第一次的总数) 就是这段时间的总工作量。然后算出百分比。这部分逻辑都在 SystemMonitorService.swift 的 getSystemCpuUsage 方法里。 内存压力
    普通的 “已用内存” 其实没意义。macOS 有个 “内存压缩” 技术。
    我们用了 host_statistics64 ,专门去读 VM_WIRE_COUNT (内核占的)、 VM_ACTIVE_COUNT (App 正在用的)和 VM_COMPRESSOR_PAGES (被压缩的)。
  • 磁盘读写(最硬核的部分)
    这个是很多同类软件做不到的。我没有监控文件系统(那样太慢了),而是直接找 驱动 。
    我们用了 IOKit 框架,去遍历硬件注册表,找到所有类型为 IOBlockStorageDriver 的硬件,直接问它们:“你们一共读写了多少字节?”。这招非常底层,但效率极高。
  • 网络测速
    这个相对标准,我们用了 BSD Socket 的 getifaddrs 。
    难点在于 去重 。电脑里有很多虚拟网卡(比如 lo0 本地回环),如果不剔除,速度会翻倍。我们写了个过滤器,只把真实网卡(WiFi、以太网)的流量加起来。

进程列表

做完监控,接下来就是那个密密麻麻的进程列表了 (ProcessListView.swift)。

这里有个大坑: 权限 。

  • 如果你是普通用户运行,macOS 的 SIP(系统完整性保护)不让你看别人的进程内存。
  • 所以我做了一套 Fallback(回退)机制 :
    • 先试着用高级 API (task_for_pid),如果系统报错说 “没权限”;
    • 我们立马切换到 libproc 库的 proc_pidinfo 。虽然拿不到极度精确的内存细节,但至少能把 CPU、内存占用显示出来,保证不白屏。

还有一个痛点优化: “打开文件位置” 。
以前点击这个,会跳转到 App 里面的二进制文件(比如 Safari.app/Contents/MacOS/Safari )。用户会一脸懵。
我们写了个正则逻辑:如果路径里包含 .app ,就自动截断路径,直接选中那个 App 图标。这就很符合直觉了。

画图

数据有了,得画出来。
在 PerformanceView.swift 里,我们用 SwiftUI 的 Path 画贝塞尔曲线。
为了让波形图平滑,我维护了一个长度为 60 的数组(代表最近 60 次采样),每次新数据进来,就把最老的数据挤出去(FIFO 队列),然后重绘线条。

能做什么

系统级性能监测

CPU

提供基于内核 Ticks 差值计算的实时负载分析,可以显示 CPU 利用率,实时绘制波形图

内存

实现内存压力 (Memory Pressure) 实时评估,精确展示、内存分页状态,内存使用率

磁盘 I/O

基于 IOKit 驱动层的数据采集,提供全系统块设备 的实时读写吞吐量监控。

网络流量

支持多网卡流量聚合 (Interface Aggregation) 及回环过滤,提供精确的上下行速率统计。

高级进程管理

进程结束

进程查看文件位置

总之,Windows 上的主要功能都有(不想写了)

硬件信息

可以查看当前设备的基本硬件信息

彩蛋

连续点击几下设备名称,就会可以进入一个

(自己去看)

的功能

「合法使用」!

如何安装?

只支持 macOS14 + 系统,M2 + 芯片(M1CPUData 算不出来,也不知道为什么)

App 文件:

XH Task Manager.zip

关于开源

这个项目目前还很不成熟,并且设计暴露系统 API,所以目前暂时不开放原代码。


📌 转载信息
转载时间:
2026/1/18 08:42:25

背景

  • Alfred 的翻译工作流不会自己配,只能用一个服务提供商,不满足
  • 没入正 Alfred(穷),用盗版心里过意不去
  • 原生聚焦搜索的操作逻辑不太符合我的习惯,喜欢 Alfred 的操作逻辑
  • 其他 app 要么免费不够用,要么够用不免费,要么外观不喜欢

核心功能(只整合自己最常用的)

  1. app 模糊搜索
  2. 支持多个服务的快捷翻译
  3. 代码片段
  4. 剪贴板历史

特性

  • 借鉴聚焦搜索和 Alfred 的操作逻辑,从激活到离开双手无需离开键盘
  • 支持最新的液态玻璃外观

项目地址: FocusLite

大家好,我是 Bin ,LoopCare 的独立开发者。

为什么做这个 App ?

作为一个轻度强迫症患者,市面上大多数 To-Do 应用让我感到焦虑。生活中的琐事(如猫咪驱虫、更换电动牙刷头、植物浇水)并不需要精确到“某年某月某日几点”。一旦我因为忙碌错过了打卡,看见满屏红色的“已过期”,反而会让我产生挫败感,最终选择放弃记录。

所以我开发了 LoopCare

它的核心理念是 “弹性周期”“上次是何时”
比如设置“每 14 天换床单”,如果你晚了 3 天才换,没关系,下一个周期会自动从你实际完成的那天开始顺延。生活不是考试,不应该有扣分。

技术与设计 (Talk is cheap, show the code)

  • 纯原生 SwiftUI 开发:为了追求极致的丝滑离手动画和响应速度。
  • CloudKit 同步:数据在 iPhone 和 iPad 间无感漫游。
  • Core Data 离线优先:在这个连备忘录都要联网的时代,我坚持所有数据通过 Core Data 本地优先存储。
  • 隐私至上:App 不收集任何用户数据。

Loop_Care.png

关于收费

App 免费下载,可体验核心功能(限制 5 个任务)。
一次性内购解锁 Pro (无限制任务 + iCloud 同步 + 图标库),无订阅制,一杯咖啡钱终身买断。

V 友福利

为了感谢 V 站大家的支持,这里提供 10 个 Pro 兑换码。

67M97A4HK94E
K3LH3EW69JYP
H6M4X7WFAT4L
HAH4P9KYR94X
MT9HE6HTEPRM
PANTFMXNX6AF
WM6REN9NTNY7
XYKHXP69YAL4
M7FF6JKKX4TR
PJKNRKFFF7EW

App Store 传送门: https://apps.apple.com/cn/app/loopcare-%E5%BC%B9%E6%80%A7%E5%91%A8%E6%9C%9F%E4%B9%A0%E6%83%AF%E4%B8%8E%E7%94%9F%E6%B4%BB%E8%AE%B0%E5%BD%95/id6757657981

(如果您觉得 App 不错,希望能去 App Store 给个好评,这对我这种冷启动的 App 真的太重要了 🙏)

[开源发布] VeloxClip —— 一款更聪明的 macOS 剪贴板管理器

我做了一款面向开发者与效率爱好者的剪贴板工具 VeloxClip ,主打 AI 增强与专业截图编辑,帮助你把“复制过的所有东西”都管理好、搜得到、用得快。

为什么值得试试:

  • 语义搜索与自动打标签:不止关键字,按“意思”找内容;自动识别 json 、表格、URL 、代码、Markdown 、长文本等类型并打标签,收藏项支持自定义彩色标签。
  • AI 能力即插即用:OCR 图片文字识别、长文总结、翻译(中/英/日/韩/西/法/德)、代码解释、文本润色;默认接入 OpenRouter (含可用的免费 DeepSeek Chat )。
  • 专业截图与编辑:支持区域截图(默认 F1 )与悬浮贴图( F3 ),内置标注工具(箭头/矩形/高亮/文字/马赛克/橡皮擦),编辑后可一键复制或保存。
  • 面向开发者的预览:JSON 高亮与校验、表格智能分隔符识别、URL 校验与快速操作、代码多语言高亮、颜色 HEX/RGB/HSL 转换、图片元数据查看等。
  • 隐私与性能:不做云同步,数据只在你的 Mac ;语义向量与搜索结果本地缓存;收藏项不受历史数量限制且永久保留。

核心体验:

  • Cmd+Shift+V 快速打开历史,并一键回粘到之前的应用。
  • 收藏与标签即组织,输入即检索,结果即使用。
  • 让复制变成“知识库”,而不是一次性的过路信息。

技术栈与要求:

  • Swift 6 + SwiftUI
  • macOS 14.0+
  • AI 需在偏好设置中粘贴 OpenRouter API Key (可选,启用 AI 功能)

开源仓库与下载:

欢迎关注与试用,期待你在实际工作流中的使用感受与改进建议。

主页: https://ilikebug.github.io/VeloxClip/

——————事情又双叒是这样的——————
由于我本人想在 Mac 上爽看小说,但是苦于各大平台广告贼多,像类似于 Android 的开源阅读【Legado】在 Mac 端找不到相关的资源。于是,趁着手头上还有一些闲下来的时间,用 Swift 和 SwiftUI 自己写了一个在 Mac 端上运行的阅读 App【Legado for Mac】,基于原版 Andorid 的开源阅读。

最重要的书源、订阅,都可以平滑地从安卓中迁移过来,在【导入书源】后【解析】,基本实现了【在线找书】-> 【阅读】 → 【换源】 和 【订阅】 → 【解析】超方便的一体化工具链。并且在阅读逻辑上,基本保持了人类的阅读习惯。

下载地址:Release Legado for Mac v1.0.0 · Kequans/legado-for-mac-pub · GitHub

书架页面:

书架 1

书架 2:

阅读页面:


书籍搜索页面:
书源管理页面:
订阅管理页面:
关于页面:

后续代码会陆续开源。

(有 BUG,可以积极回帖反馈呀,虽然可能改不动 wuwuwu​)

开源地址:
(因为目前一些拓展功能还在开发,所以暂时先把部分核心代码开源了,还有一些拓展功能后续再做…… 不知道有没有时间)

下载地址:Release Legado for Mac v1.0.0 · Kequans/legado-for-mac-pub · GitHub

觉得本项目不错的话,可以用 LDC 赞助一下帮帮我,Vibe coding 的额度要上天了,让我回回血呜呜呜 ~~~~

||
——————————

——————————

-------------------- 附赞助链接:(LDC 打赏,最低 0.01,都是支持!)-----------------------


📌 转载信息
原作者:
Kequan
转载时间:
2025/12/30 10:03:25