Alert and sheet tools for macOS and iOS
PromptManager is a versatile library designed to simplify the creation and management of alerts and sheets on macOS and iOS platforms. It provides a robust set of tools to handle various dialog types with ease, ensuring a consistent and user-friendly interface across different Apple devices.
- Cross-Platform Support: Works seamlessly on both macOS (v14 and above) and iOS (v17 and above).
- SwiftUI Ready: Fully compatible with SwiftUI, offering a modern way to manage UI components.
- Extensible: Easily extendable to include more complex alert types or custom interactions.
This example demonstrates how to present a simple alert with primary and secondary actions on both iOS and macOS platforms.
promptAlert(
title: "Save Changes?",
msg: "Do you want to save the changes you made?",
primaryText: "Save",
secondaryText: "Cancel",
primaryHandler: { print("Changes saved") },
secondaryHandler: { print("Cancelled") }
)
This example shows how to present an alert that includes text input fields, suitable for scenarios like login forms.
showTextInputAlert(
title: "Login",
message: "Please enter your username and password",
primaryTextPlaceholder: "Username",
secondaryTextPlaceholder: "Password",
primaryButtonText: "Login",
secondaryButtonText: "Cancel",
isSecure: true,
onComplete: { credentials in
if let username = credentials?.primary, let password = credentials?.secondary {
print("Username: \(username), Password: \(password)")
} else {
print("User cancelled login")
}
}
)
You can present an input alert within a SwiftUI view using the configInputAlert
function:
struct ContentView: View {
@State private var presentAlert = false
@State private var alertText: String = ""
var body: some View {
Button("Show Input Alert") {
presentAlert = true
}
.configInputAlert(
text: $alertText,
title: "Enter Text",
message: "Please enter some text below",
isPresented: $presentAlert
) { input in
print("User input: \(input)")
}
}
}
This example demonstrates how to present an alert with attributed text, which allows for more stylized text presentations.
let attrTitle = NSAttributedString(string: "Important Update", attributes: [.foregroundColor: UIColor.red])
let attrMSG = NSAttributedString(string: "Please read the terms and conditions carefully.", attributes: [.foregroundColor: UIColor.blue])
UIAlertController.promptAlert(
attrTitle: attrTitle,
attrMSG: attrMSG,
ok: { print("Accepted") },
cancel: { print("Declined") },
okTitle: "Accept",
cancelTitle: "Decline"
)
Using promptAlert
, you can display alerts with custom primary and secondary actions:
promptAlert(
title: "Delete File?",
msg: "Are you sure you want to delete this file?",
primaryText: "Delete",
secondaryText: "Cancel",
primaryHandler: {
print("File deleted")
},
secondaryHandler: {
print("Deletion cancelled")
}
)
Leverage SheetState
to manage sheet presentations in a SwiftUI view:
class AlertPrompt: SheetState<AlertCategory> {
enum AlertCategory: String {
case save, delete, cancel
}
}
struct ContentView: View {
@StateObject var alert = AlertPrompt()
var body: some View {
VStack {
Button("Save") { alert.state = .save }
Button("Delete") { alert.state = .delete }
}
.alert(
alert.state?.rawValue ?? "",
isPresented: $alert.isShowing
) {
Button("OK", action: { /* Handle OK */ })
} message: {
Text("Perform the \(alert.state?.rawValue ?? "") action?")
}
}
}
### Presenting an Alert with Text Input on macOS
```swift
showAlertWithTextFields(
title: "Login",
message: "Enter your credentials",
primaryTextPlaceholder: "Username",
secondaryTextPlaceholder: "Password",
isSecure: true
) { credentials in
if let username = credentials?.primary, let password = credentials?.secondary {
print("Username: \(username), Password: \(password)")
} else {
print("User cancelled login")
}
}
Here's how you can present a custom alert using PromptManager
:
import PromptManager
import SwiftUI
struct ContentView: View {
var body: some View {
Button("Show Alert") {
promptAlert(
title: "Hello World",
msg: "This is a custom alert message.",
primaryText: "OK",
secondaryText: "Cancel",
primaryHandler: {
print("OK tapped")
},
secondaryHandler: {
print("Cancel tapped")
}
)
}
}
}
.package(url: "https://github.com/sentryco/PromptManager", branch: "main")
- Generate Online Documentation Add Support for SPM DocC Documentation
- Use Modern Swift Features: Refactor the codebase to leverage the latest Swift language enhancements, such as
@MainActor
for UI updates. - Add Asynchronous Support: Implement
async/await
for asynchronous operations. - Improve macOS Previews: Enhance SwiftUI previews for macOS components.
- Refine Error Handling: Standardize error handling across the library.
@MainActor
class AlertManager {
// UI-related code guaranteed to run on the main thread
}
- Adopt Modern Swift Concurrency Use async/await: Refactor asynchronous code to leverage Swift's modern concurrency model. This makes your code more readable and efficient.
@MainActor
public func showAsyncAlert(title: String, message: String) async -> Bool {
await withCheckedContinuation { continuation in
promptAlert(
title: title,
msg: message,
primaryText: "OK",
secondaryText: "Cancel",
primaryHandler: {
continuation.resume(returning: true)
},
secondaryHandler: {
continuation.resume(returning: false)
}
)
}
}
- Define Custom Error Types: Create specific error types conforming to Error for more granular error handling.
enum AlertError: Error {
case invalidInput
case presentationFailed
}
- Use Result Types: Update function signatures to use Result where appropriate.
func showAlert(
title: String,
message: String,
completion: @escaping (Result<Void, AlertError>) -> Void
) {
// Implementation
}
- Simplify Function Signatures: Use structs to pass configurations, making your API cleaner and more maintainable.
struct AlertConfiguration {
let title: String
let message: String
let primaryButtonTitle: String
let secondaryButtonTitle: String?
let isSecureTextEntry: Bool
}
func presentAlert(configuration: AlertConfiguration, completion: @escaping (Result<Void, AlertError>) -> Void) {
// Implementation
}
-
Create Custom View Modifiers for SwiftUI
-
Streamline Alert Presentation: Develop view modifiers to make presenting alerts more Swifty and convenient.
-
Example:
extension View {
func promptAlert(
isPresented: Binding<Bool>,
title: String,
message: String,
primaryButtonTitle: String = "OK",
secondaryButtonTitle: String? = nil,
onPrimaryAction: @escaping () -> Void,
onSecondaryAction: (() -> Void)? = nil
) -> some View {
self.alert(
title,
isPresented: isPresented,
presenting: nil,
actions: {
Button(primaryButtonTitle, action: onPrimaryAction)
if let secondaryTitle = secondaryButtonTitle {
Button(secondaryTitle, role: .cancel, action: onSecondaryAction ?? {})
}
},
message: {
Text(message)
}
)
}
}
-
Add Support for Combine or Async Publishers
-
Reactive Programming: If applicable, provide support for Combine publishers to handle alert actions reactively.
-
Example:
import Combine
class AlertViewModel: ObservableObject {
@Published var isAlertPresented = false
private var cancellables = Set<AnyCancellable>()
func showAlert() {
isAlertPresented = true
}
func bindAlertActions() {
// Implementation
}
}
-
Implement Theming Support
-
Customize Appearance: Allow users to customize the appearance of alerts to match their app's theme.
-
Example:
struct AlertStyle { let titleFont: Font let messageFont: Font let titleColor: Color let messageColor: Color } func promptAlert( title: String, msg: String, style: AlertStyle, primaryHandler: @escaping () -> Void ) { // Implementation using the style parameters }