From efb60c8a302da8128ae625d4ca28d2870ac4940f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rutkowski?= Date: Mon, 3 Nov 2025 19:51:49 +0100 Subject: [PATCH 1/3] Combined implementation for all systems with default action --- Sources/LongPressButton/LongPressButton.swift | 63 +++++-------------- 1 file changed, 14 insertions(+), 49 deletions(-) diff --git a/Sources/LongPressButton/LongPressButton.swift b/Sources/LongPressButton/LongPressButton.swift index fa839a5..486341e 100644 --- a/Sources/LongPressButton/LongPressButton.swift +++ b/Sources/LongPressButton/LongPressButton.swift @@ -9,78 +9,43 @@ public struct LongPressButton: View { private let label: Label private let longPressActionName: Text? - @available(iOS, obsoleted: 26.0) @State private var didLongPress = false - @available(iOS, obsoleted: 26.0) - @State private var longPressTask: Task? public var body: some View { - button - .accessibilityAction { - action() - } - .accessibilityAction(named: longPressActionName ?? Text("Alternative Action")) { - longPressAction() - } - } - - @ViewBuilder - private var button: some View { - if #available(iOS 26.0, *) { - Button(action: {}) { - label - } - .simultaneousGesture(longPress.exclusively(before: tap)) - } else { - Button(action: performActionIfNeeded) { - label - } - .onLongPressGesture( - maximumDistance: maximumDistance, - perform: {}, - onPressingChanged: handleLongPress(isPressing:) - ) + Button(action: performActionIfNeeded) { + label + } + .simultaneousGesture(longPress.simultaneously(with: detectRelease)) + .accessibilityAction(named: longPressActionName ?? Text("Alternative Action")) { + longPressAction() } } private var longPress: some Gesture { LongPressGesture(minimumDuration: minimumDuration, maximumDistance: maximumDistance) .onEnded { _ in + didLongPress = true longPressAction() } } - private var tap: some Gesture { - TapGesture().onEnded { - action() + private var detectRelease: some Gesture { + DragGesture(minimumDistance: 0).onEnded { _ in + DispatchQueue.main.async { + // Mark long press as ended in next run loop to be sure that button action + // won't trigger together with it. + didLongPress = false + } } } - @available(iOS, obsoleted: 26.0) private func performActionIfNeeded() { - longPressTask?.cancel() if didLongPress { didLongPress = false } else { action() } } - - @available(iOS, obsoleted: 26.0) - private func handleLongPress(isPressing: Bool) { - longPressTask?.cancel() - guard isPressing else { return } - didLongPress = false - longPressTask = Task { - do { - try await Task.sleep(nanoseconds: UInt64(minimumDuration * 1_000_000_000)) - } catch { - return - } - didLongPress = true - longPressAction() - } - } } // MARK: - Initialization From e48ace947cb4b84f68a57b5907914ea93f647dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rutkowski?= Date: Mon, 3 Nov 2025 19:51:56 +0100 Subject: [PATCH 2/3] Document List limitation --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1ef19aa..6a67195 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ LongPressButton(minimumDuration: 0.5, maximumDistance: 10) { } ``` +## Known limitations + +This package doesn't work with default buttons that are used inside of Lists. If you want to use this inside of a List apply a different style to the button. For example `plain` or `bordered`. + ## Installation ### Swift Package Manager From 906a4f372df249747d0864c37cfc35a69fab75d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rutkowski?= Date: Tue, 4 Nov 2025 14:55:47 +0000 Subject: [PATCH 3/3] Update iOS 26 simulator --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 341ac46..82e07a5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,7 @@ jobs: device: 'iPhone 15' - version: '18.6' device: 'iPhone 16' - - version: '26.0' + - version: '26.0.1' device: 'iPhone 17' steps: