Installation
Add the FeedbackKit Swift SDK to your project using Swift Package Manager.
Xcode
- 1 Open your project in Xcode
- 2 Go to File → Add Package Dependencies
-
3
Enter the repository URL:
https://github.com/Swiftly-Developed/SwiftlyFeedbackKit-Swift-SDK.git - 4 Set the version to 1.0.1 or "Up to Next Major"
- 5 Select the FeedbackKit library for your target
Package.swift
dependencies: [
.package(
url: "https://github.com/Swiftly-Developed/SwiftlyFeedbackKit-Swift-SDK.git",
from: "1.0.1"
)
],
targets: [
.target(
name: "YourApp",
dependencies: [
.product(name: "SwiftlyFeedbackKit", package: "SwiftlyFeedbackKit")
]
)
]
Quick Start
Initialize the SDK with your project API key in your app's entry point and start using the pre-built SwiftUI views.
import SwiftUI
import SwiftlyFeedbackKit
@main
struct MyApp: App {
init() {
// Configure SDK per build environment
#if DEBUG
SwiftlyFeedback.configure(
environment: .development,
key: "your-dev-api-key"
)
#elseif TESTFLIGHT
SwiftlyFeedback.configure(
environment: .testflight,
key: "your-staging-api-key"
)
#else
SwiftlyFeedback.configure(
environment: .production,
key: "your-prod-api-key"
)
#endif
}
var body: some Scene {
WindowGroup {
FeedbackListView()
}
}
}
Auto-Detection Configuration
Alternatively, use configureAuto to automatically detect the build environment and select the appropriate API key.
import SwiftlyFeedbackKit
@main
struct MyApp: App {
init() {
// Auto-detect environment and use appropriate key
SwiftlyFeedback.configureAuto(keys: EnvironmentAPIKeys(
debug: "your-dev-key", // Optional: localhost
testflight: "your-staging-key", // Staging server
production: "your-prod-key" // App Store
))
}
var body: some Scene {
WindowGroup {
FeedbackListView()
}
}
}
Configuration
Customize the SDK behavior with various configuration options.
| Option | Type | Default | Description |
|---|---|---|---|
| loggingEnabled | Bool | false | Enable debug logging |
| userEmail | String? | — | Default user email for submissions |
| showVoteEmailField | Bool | true | Show email field when voting |
| voteNotificationDefaultOptIn | Bool | false | Default value for notification opt-in |
| allowFeedbackSubmission | Bool | true | Allow users to submit feedback |
| feedbackSubmissionDisabledMessage | String | Default message | Message shown when submission disabled |
| enableAutomaticViewTracking | Bool | true | Automatically track view events |
Configuration Example
// Get shared instance after configuration
let feedback = SwiftlyFeedback.shared
// Enable debug logging
feedback.loggingEnabled = true
// Set default user email
feedback.userEmail = "user@example.com"
// Disable feedback submission
feedback.allowFeedbackSubmission = false
feedback.feedbackSubmissionDisabledMessage = "Coming soon!"
// Customize voting behavior
feedback.showVoteEmailField = false
feedback.voteNotificationDefaultOptIn = true
Views
The SDK provides pre-built SwiftUI views that can be easily integrated into your app.
FeedbackListView
Displays a list of all feedback items with voting, filtering, and sorting capabilities.
import SwiftUI
import SwiftlyFeedbackKit
struct ContentView: View {
var body: some View {
// Use default instance
FeedbackListView()
// Or pass a custom instance
FeedbackListView(swiftlyFeedback: SwiftlyFeedback.shared)
}
}
SubmitFeedbackView
Form for submitting new feedback with title, description, and category selection.
import SwiftUI
import SwiftlyFeedbackKit
struct ContentView: View {
@State private var showingSubmitForm = false
var body: some View {
Button("Submit Feedback") {
showingSubmitForm = true
}
.sheet(isPresented: $showingSubmitForm) {
SubmitFeedbackView {
showingSubmitForm = false
}
}
}
}
FeedbackDetailView
Detailed view showing feedback information, voting, and comments.
import SwiftUI
import SwiftlyFeedbackKit
struct FeedbackRow: View {
let feedback: Feedback
var body: some View {
NavigationLink {
FeedbackDetailView(feedback: feedback)
} label: {
Text(feedback.title)
}
}
}
API Reference
The SwiftlyFeedback class provides methods for interacting with the FeedbackKit API.
| Method | Description |
|---|---|
| getFeedback() async throws -> [Feedback] | Fetch all feedback items |
| submitFeedback(...) async throws -> Feedback | Submit new feedback |
| vote(for:email:notifyStatusChange:) async throws -> VoteResult | Vote for feedback |
| removeVote(for:) async throws -> VoteResult | Remove vote |
| getComments(for:) async throws -> [Comment] | Get feedback comments |
| addComment(to:content:) async throws -> Comment | Add a comment |
| view(_:properties:) | Track analytics event |
import SwiftlyFeedbackKit
// Get all feedback
let feedbacks = try await SwiftlyFeedback.shared.getFeedback()
// Submit feedback
let feedback = try await SwiftlyFeedback.shared.submitFeedback(
title: "Add dark mode",
description: "Please add dark mode support",
category: .featureRequest,
email: "user@example.com"
)
// Vote for feedback
let result = try await SwiftlyFeedback.shared.vote(
for: feedback.id,
email: "user@example.com",
notifyStatusChange: true
)
// Remove vote
try await SwiftlyFeedback.shared.removeVote(for: feedback.id)
// Get comments
let comments = try await SwiftlyFeedback.shared.getComments(for: feedback.id)
// Add comment
let comment = try await SwiftlyFeedback.shared.addComment(
to: feedback.id,
content: "Great idea!"
)
// Track analytics event
SwiftlyFeedback.shared.view("onboarding_completed", properties: [
"steps": 5,
"duration": 120
])
Models
Feedback
| Property | Type | Description |
|---|---|---|
| id | UUID | Unique identifier |
| title | String | Feedback title |
| description | String | Detailed description |
| status | FeedbackStatus | Current status |
| category | FeedbackCategory | Feedback category |
| voteCount | Int | Total vote count |
| hasVoted | Bool | User voted status |
| commentCount | Int | Total comment count |
| createdAt | Date | Creation timestamp |
| updatedAt | Date | Last update timestamp |
Enums
FeedbackStatus
| Case | Raw Value |
|---|---|
| pending | "pending" |
| approved | "approved" |
| inProgress | "in_progress" |
| testflight | "testflight" |
| completed | "completed" |
| rejected | "rejected" |
FeedbackCategory
| Case | Raw Value |
|---|---|
| featureRequest | "feature_request" |
| bugReport | "bug_report" |
| improvement | "improvement" |
| other | "other" |
Comment
| Property | Type | Description |
|---|---|---|
| id | UUID | Unique identifier |
| content | String | Comment text |
| userId | String | User identifier |
| isAdmin | Bool | Admin comment flag |
| createdAt | Date | Creation timestamp |
VoteResult
| Property | Type | Description |
|---|---|---|
| feedbackId | UUID | Feedback identifier |
| voteCount | Int | Updated vote count |
| hasVoted | Bool | Current vote status |
Theming
Customize the appearance of FeedbackKit views with the SwiftlyFeedbackTheme class.
ThemeColor
| Case | Description |
|---|---|
| .default | Use system default color |
| .color(Color) | Use specific SwiftUI Color |
| .adaptive(light: Color, dark: Color) | Different colors for light/dark mode |
Theme Customization
import SwiftUI
import SwiftlyFeedbackKit
// Access shared theme
let theme = SwiftlyFeedbackTheme.shared
// Customize accent color
theme.accentColor = .color(.purple)
// Use adaptive colors
theme.accentColor = .adaptive(
light: .blue,
dark: .cyan
)
// Customize status colors
theme.statusColors.pending = .color(.gray)
theme.statusColors.approved = .color(.blue)
theme.statusColors.inProgress = .color(.orange)
theme.statusColors.completed = .color(.green)
// Customize category colors
theme.categoryColors.featureRequest = .color(.blue)
theme.categoryColors.bugReport = .color(.red)
theme.categoryColors.improvement = .color(.purple)
theme.categoryColors.other = .color(.gray)
Error Handling
The SDK uses the SwiftlyFeedbackError enum for error handling.
| Error | Description |
|---|---|
| invalidResponse | Invalid server response |
| badRequest | Invalid request parameters |
| unauthorized | Authentication failed |
| invalidApiKey | Invalid or missing API key |
| notFound | Resource not found |
| conflict | Conflicting operation (e.g., duplicate vote) |
| serverError | Internal server error |
| networkError | Network connectivity error |
| decodingError | Failed to decode response |
| feedbackLimitReached | Feedback limit exceeded (upgrade required) |
Error Handling Example
import SwiftlyFeedbackKit
do {
let feedbacks = try await SwiftlyFeedback.shared.getFeedback()
// Process feedbacks
} catch SwiftlyFeedbackError.invalidApiKey {
print("Invalid API key")
} catch SwiftlyFeedbackError.networkError {
print("Check your internet connection")
} catch SwiftlyFeedbackError.feedbackLimitReached {
print("Please upgrade your plan")
} catch SwiftlyFeedbackError.notFound {
print("Feedback item not found")
} catch SwiftlyFeedbackError.conflict {
print("You've already voted")
} catch {
print("An error occurred: \(error.localizedDescription)")
}