From 9d6f138e40a5322ee731f8096eaa3332c94a6532 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 18 May 2026 17:54:35 +0800
Subject: [PATCH] Speed up repeated app list opens
---
Apptag/DataLayer.swift | 53 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/Apptag/DataLayer.swift b/Apptag/DataLayer.swift
index 518258d..779beac 100644
--- a/Apptag/DataLayer.swift
+++ b/Apptag/DataLayer.swift
@@ -51,6 +51,10 @@
// MARK: - App Scanner
enum AppIndexer {
+ private static let scanCacheLock = NSLock()
+ private static var cachedScanApps: [AppInfo]? = nil
+ private static var cachedScanAt: Date? = nil
+ private static let scanCacheTTL: TimeInterval = 1800
static let searchPaths: [URL] = [
URL(fileURLWithPath: "/Applications"),
@@ -72,7 +76,42 @@
}
/// Scan all standard locations. Tags are annotated from TagDatabase by the caller.
- static func scan() -> [AppInfo] {
+ static func scan(useCache: Bool = true) -> [AppInfo] {
+ if useCache, let cached = cachedScanIfFresh() {
+ return cached
+ }
+
+ let apps = performScan()
+ updateScanCache(apps)
+ return apps
+ }
+
+ static func invalidateScanCache() {
+ scanCacheLock.lock()
+ cachedScanApps = nil
+ cachedScanAt = nil
+ scanCacheLock.unlock()
+ }
+
+ private static func cachedScanIfFresh() -> [AppInfo]? {
+ scanCacheLock.lock()
+ defer { scanCacheLock.unlock() }
+
+ guard let cachedScanApps,
+ let cachedScanAt,
+ Date().timeIntervalSince(cachedScanAt) < scanCacheTTL
+ else { return nil }
+ return cachedScanApps
+ }
+
+ private static func updateScanCache(_ apps: [AppInfo]) {
+ scanCacheLock.lock()
+ cachedScanApps = apps
+ cachedScanAt = Date()
+ scanCacheLock.unlock()
+ }
+
+ private static func performScan() -> [AppInfo] {
var seenResolvedPaths = Set<String>()
var apps: [AppInfo] = []
@@ -220,12 +259,18 @@
var seenAppIDsByGroup: [String: Set<URL>] = [:]
for app in apps {
+ if app.isAppleApp {
+ appendGroupedApp(app, to: macCategory, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup)
+ }
+
if app.tags.isEmpty {
- let bucket = app.isAppleApp ? macCategory : defaultGroupName
- appendGroupedApp(app, to: bucket, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup)
+ if !app.isAppleApp {
+ appendGroupedApp(app, to: defaultGroupName, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup)
+ }
} else {
for tag in uniqueOrdered(app.tags) {
let displayName = nameOverrides[tag] ?? tag
+ guard displayName != macCategory else { continue }
appendGroupedApp(app, to: displayName, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup)
}
}
@@ -1253,7 +1298,7 @@
}
var current = store.appTags[path] ?? []
- if !copy, !sourceTag.isEmpty {
+ if !copy, !sourceTag.isEmpty, sourceTag != "Mac自带", sourceTag != tr("group.appleBuiltIn") {
current.removeAll { $0 == sourceTag }
}
if !current.contains(targetTag) {
--
Gitblit v1.9.3