Skip to content

Commit d001677

Browse files
authored
refactor: replace GCD dispatch patterns with Swift structured concurrency (#538)
1 parent 8adf763 commit d001677

16 files changed

Lines changed: 59 additions & 59 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- Collapsible results panel (`Cmd+Opt+R`), multiple result tabs for multi-statement queries, result pinning
1818
- Inline error banner for query errors
1919

20+
### Changed
21+
22+
- Replace GCD dispatch patterns with Swift structured concurrency
23+
2024
### Fixed
2125

2226
- SQL Server: Unicode characters (Thai, CJK, etc.) in nvarchar/nchar/ntext columns displaying as question marks

TablePro/AppDelegate+WindowConfig.swift

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -326,34 +326,31 @@ extension AppDelegate {
326326

327327
isAutoReconnecting = true
328328

329-
DispatchQueue.main.async { [weak self] in
329+
Task { @MainActor [weak self] in
330330
guard let self else { return }
331331
WindowOpener.shared.pendingConnectionId = connection.id
332332
NotificationCenter.default.post(name: .openMainWindow, object: connection.id)
333333

334-
Task { @MainActor in
335-
defer { self.isAutoReconnecting = false }
336-
do {
337-
try await DatabaseManager.shared.connectToSession(connection)
338-
339-
for window in NSApp.windows where self.isWelcomeWindow(window) {
340-
window.close()
341-
}
342-
} catch is CancellationError {
343-
// User cancelled password prompt at startup — return to welcome
344-
for window in NSApp.windows where self.isMainWindow(window) {
345-
window.close()
346-
}
347-
self.openWelcomeWindow()
348-
} catch {
349-
windowLogger.error("Auto-reconnect failed for '\(connection.name)': \(error.localizedDescription)")
334+
defer { self.isAutoReconnecting = false }
335+
do {
336+
try await DatabaseManager.shared.connectToSession(connection)
350337

351-
for window in NSApp.windows where self.isMainWindow(window) {
352-
window.close()
353-
}
338+
for window in NSApp.windows where self.isWelcomeWindow(window) {
339+
window.close()
340+
}
341+
} catch is CancellationError {
342+
for window in NSApp.windows where self.isMainWindow(window) {
343+
window.close()
344+
}
345+
self.openWelcomeWindow()
346+
} catch {
347+
windowLogger.error("Auto-reconnect failed for '\(connection.name)': \(error.localizedDescription)")
354348

355-
self.openWelcomeWindow()
349+
for window in NSApp.windows where self.isMainWindow(window) {
350+
window.close()
356351
}
352+
353+
self.openWelcomeWindow()
357354
}
358355
}
359356
}

TablePro/Core/Services/Formatting/SQLFormatterService.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,7 @@ struct SQLFormatterService: SQLFormatterProtocol {
133133
}
134134

135135
private static func resolveDialectProvider(for dialect: DatabaseType) -> SQLDialectProvider {
136-
if Thread.isMainThread {
137-
return MainActor.assumeIsolated { SQLDialectFactory.createDialect(for: dialect) }
138-
}
139-
return DispatchQueue.main.sync {
140-
MainActor.assumeIsolated { SQLDialectFactory.createDialect(for: dialect) }
141-
}
136+
SQLDialectFactory.createDialect(for: dialect)
142137
}
143138

144139
// MARK: - Public API

TablePro/Core/Services/Query/SQLDialectProvider.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ private struct EmptyDialect: SQLDialectProvider {
3636
// MARK: - Dialect Factory
3737

3838
struct SQLDialectFactory {
39-
@MainActor
4039
static func createDialect(for databaseType: DatabaseType) -> SQLDialectProvider {
41-
if let descriptor = PluginManager.shared.sqlDialect(for: databaseType) {
40+
if let descriptor = PluginMetadataRegistry.shared.snapshot(
41+
forTypeId: databaseType.pluginTypeId
42+
)?.editor.sqlDialect {
4243
return PluginDialectAdapter(descriptor: descriptor)
4344
}
4445
return EmptyDialect()

TablePro/Views/AIChat/AIChatCodeBlockView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ struct AIChatCodeBlockView: View {
4343
Button {
4444
ClipboardService.shared.writeText(code)
4545
isCopied = true
46-
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
46+
Task { @MainActor in
47+
try? await Task.sleep(for: .seconds(1.5))
4748
isCopied = false
4849
}
4950
} label: {

TablePro/Views/Components/SQLReviewPopover.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ struct SQLReviewPopover: View {
200200
ClipboardService.shared.writeText(joined)
201201
copied = true
202202

203-
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
203+
Task { @MainActor in
204+
try? await Task.sleep(for: .seconds(1.5))
204205
copied = false
205206
}
206207
}

TablePro/Views/Components/SyncStatusIndicator.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ struct SyncStatusIndicator: View {
120120
showActivationSheet = true
121121
default:
122122
UserDefaults.standard.set(SettingsTab.sync.rawValue, forKey: "selectedSettingsTab")
123-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
123+
Task { @MainActor in
124+
try? await Task.sleep(for: .milliseconds(100))
124125
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
125126
}
126127
}

TablePro/Views/Connection/ConnectionExportOptionsSheet.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ struct ConnectionExportOptionsSheet: View {
9595
confirmPassphrase = ""
9696
dismiss()
9797

98-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
98+
Task { @MainActor in
99+
try? await Task.sleep(for: .milliseconds(200))
99100
let panel = NSSavePanel()
100101
panel.allowedContentTypes = [.tableproConnectionShare]
101102
let defaultName = capturedConnections.count == 1

TablePro/Views/Connection/WelcomeWindowView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ struct WelcomeWindowView: View {
7878
LicenseActivationSheet()
7979
case .importFile(let url):
8080
ConnectionImportSheet(fileURL: url) { count in
81-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
81+
Task { @MainActor in
82+
try? await Task.sleep(for: .milliseconds(300))
8283
vm.showImportResultAlert(count: count)
8384
}
8485
}

TablePro/Views/Editor/EditorEventRouter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal final class EditorEventRouter {
3939
if textView.window != nil {
4040
installWindowObserver(for: key)
4141
} else {
42-
DispatchQueue.main.async { [weak self] in
42+
Task { [weak self] in
4343
guard let self, self.editors[key]?.windowObserver == nil else { return }
4444
self.installWindowObserver(for: key)
4545
}

0 commit comments

Comments
 (0)