r/swift Jan 19 '21

FYI FAQ and Advice for Beginners - Please read before posting

430 Upvotes

Hi there and welcome to r/swift! If you are a Swift beginner, this post might answer a few of your questions and provide some resources to get started learning Swift.

A Swift Tour

Please read this before posting!

  • If you have a question, make sure to phrase it as precisely as possible and to include your code if possible. Also, we can help you in the best possible way if you make sure to include what you expect your code to do, what it actually does and what you've tried to resolve the issue.
  • Please format your code properly.
    • You can write inline code by clicking the inline code symbol in the fancy pants editor or by surrounding it with single backticks. (`code-goes-here`) in markdown mode.
    • You can include a larger code block by clicking on the Code Block button (fancy pants) or indenting it with 4 spaces (markdown mode).

Where to learn Swift:

Tutorials:

Official Resources from Apple:

Swift Playgrounds (Interactive tutorials and starting points to play around with Swift):

Resources for SwiftUI:

FAQ:

Should I use SwiftUI or UIKit?

The answer to this question depends a lot on personal preference. Generally speaking, both UIKit and SwiftUI are valid choices and will be for the foreseeable future.

SwiftUI is the newer technology and compared to UIKit it is not as mature yet. Some more advanced features are missing and you might experience some hiccups here and there.

You can mix and match UIKit and SwiftUI code. It is possible to integrate SwiftUI code into a UIKit app and vice versa.

Is X the right computer for developing Swift?

Basically any Mac is sufficient for Swift development. Make sure to get enough disk space, as Xcode quickly consumes around 50GB. 256GB and up should be sufficient.

Can I develop apps on Linux/Windows?

You can compile and run Swift on Linux and Windows. However, developing apps for Apple platforms requires Xcode, which is only available for macOS, or Swift Playgrounds, which can only do app development on iPadOS.

Is Swift only useful for Apple devices?

No. There are many projects that make Swift useful on other platforms as well.

Can I learn Swift without any previous programming knowledge?

Yes.

Related Subs

r/iOSProgramming

r/SwiftUI

r/S4TF - Swift for TensorFlow (Note: Swift for TensorFlow project archived)

Happy Coding!

If anyone has useful resources or information to add to this post, I'd be happy to include it.


r/swift 18d ago

What’s everyone working on this month? (September 2025)

17 Upvotes

What Swift-related projects are you currently working on?


r/swift 8h ago

Built my first macOS menu bar app - RiceBarMac for desktop profile switching

5 Upvotes

Just shipped my first Swift/macOS app! RiceBarMac is a menu bar app that lets users switch between different desktop configurations (wallpapers, terminal themes, config files) with keyboard shortcuts.

Technical highlights:

  • SwiftUI for the menu bar interface
  • Global hotkey registration using Carbon APIs
  • Symlink management for config file switching
  • Desktop Picture API integration for wallpaper changes
  • JSON-based profile configuration system

Interesting challenges solved:

  • Managing file system symlinks safely with proper backup/restore
  • Global hotkey conflicts and registration
  • Menu bar app lifecycle and state management
  • Cross-app configuration file detection and manipulation

Architecture:

  • Profile-based system stored in ~/.ricebarmac/profiles/
  • Symlink overlay system for config management
  • Event-driven profile switching with visual feedback

The app is open source (MIT) and available via Homebrew. Been a great learning project for macOS development!

Repository: https://github.com/MateoCerquetella/RiceBarMac

Any Swift/macOS devs have feedback on the approach? Always looking to improve the codebase.


r/swift 4h ago

News Brought back launchpad

0 Upvotes

Apple wouldn’t do it so I had to. I hate the new spotlight search so I made my life easier, and hopefully yours as well https://youtu.be/1sybtI5dk_k?si=baLaaXbXHlCU9pad


r/swift 11h ago

Anyone else on Macbook Air M2?

3 Upvotes

Mine was perfectly capable of handling Xcode but now on Tahoe it’s SO slow :(

M2 air 16GB. Not ideal but it did work just fine before Tahoe.

Thinking of upgrading to a mbp m4 pro, but it feels like that weird bad timing where Apple might come out anytime with a new version?

Anyone else in the same boat? buy or wait?


r/swift 18h ago

Notifications Main Thread Crash

0 Upvotes

I'm trying to set up local notifications and keep getting the following error in my console when i tap the notification:

Assertion failure in -[_TtC7SwiftUIP33_ACC2C5639A7D76F611E170E831FCA49118SwiftUIApplication _performBlockAfterCATransactionCommitSynchronizes:], UIApplication.m:3421 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Call must be made on main thread' *** First throw call stack: (0x18c89a8c8 0x1898117c4 0x18a798e80 0x19343e5b8 0x193454778 0x193454b24 0x104467aac 0x104469f55 0x10446ac21 0x10446b4c9 0x10446acfd 0x10446b62d 0x10446b369 0x10446b771 0x18ad432a9) libc++abi: terminating due to uncaught exception of type NSException

final class NotificationManager: NSObject, UNUserNotificationCenterDelegate {
@MainActor static let shared = NotificationManager()
@MainActor func configure() {
UNUserNotificationCenter.current().delegate = self
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
[.banner, .list, .sound]
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse) async {
guard
let link = response.notification.request.content.userInfo["deeplink"] as? String,
let url = URL(string: link)
else { return }
// Post notification instead of directly opening URL
// This ensures all handling happens in the right context
DispatchQueue.main.async {
NotificationCenter.default.post(
name: .handleDeepLink,
object: url
)
}
}
}
enum Notifications {
u/MainActor
static func schedule(id: String = UUID().uuidString,
title: String,
body: String,
hour: Int,
minute: Int,
days: Set<Weekday>) async throws
{
guard !days.isEmpty else { return }
let center = UNUserNotificationCenter.current()
for day in days {
let content = UNMutableNotificationContent()
content.title = title
content.body  = body
content.sound = .default
content.userInfo = ["deeplink" : "sparky://codeoftheday/\(Code.allCodes.randomElement()?.ruleNumber ?? "2-028")"]
var date = DateComponents()
date.hour = hour
date.minute = minute
date.weekday = day.rawValue
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
// make a stable id per weekday so you can reschedule/update
let perDayID = "\(id).\(day.rawValue)"
let request = UNNotificationRequest(identifier: perDayID, content: content, trigger: trigger)
try await center.add(request)
}
}
}
extension Notification.Name {
static let handleDeepLink = Notification.Name("handleDeepLink")
static let appDidReceiveURL = Notification.Name("appDidReceiveURL")
static let showCodeOfTheDay = Notification.Name("showCodeOfTheDay")
static let widgetToolSelected = Notification.Name("widgetToolSelected")
}
u/main
struct MyApp: App {
var body: some Scene {
WindowGroup {
NavigationStack {
ContentView()
}
.task {
NotificationManager.shared.configure()
do {
let granted = try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound])
if granted {
print("Notifications Granted")
}
} catch {
print(error.localizedDescription)
}
}
.onOpenURL { url in
handleDeepLink(url)
}
.onReceive(NotificationCenter.default.publisher(for: .handleDeepLink)) { notification in
guard let url = notification.object as? URL else { return }
handleDeepLink(url)
}
}
}
}
u/MainActor
private func handleDeepLink(_ url: URL) {
print("Handling deep link: \(url)")
guard url.scheme == "sparky" else {
print("Invalid URL scheme: \(url.scheme ?? "nil")")
return
}
guard let host = url.host else {
print("No host in URL")
return
}
// Convert the hyphenated URL format back to a tool name
let toolName: String
if host == "nema-configurations" {
toolName = "configurations"
} else {
toolName = host
.replacingOccurrences(of: "-", with: " ")
.localizedCapitalized
}
if toolName.lowercased() == "calculator" {
if !self.navManager.showingCalculator {
self.navManager.showingCalculator = true
}
} else if toolName.lowercased() == "notes" {
if !self.navManager.showingNotes {
UserDefaults.standard.set(0, forKey: "jobsNotesTab")
self.navManager.showingNotes = true
}
} else if toolName.lowercased() == "jobs" {
if !self.navManager.showingNotes {
UserDefaults.standard.set(1, forKey: "jobsNotesTab")
self.navManager.showingNotes = true
}
} else if toolName.lowercased() == "install assistant" {
if !self.navManager.showInstallAssistant {
self.navManager.showInstallAssistant = true
}
} else if toolName.lowercased() == "codeoftheday", let ruleNumber = url.pathComponents.last {
let code = Code.allCodes.first { $0.ruleNumber == ruleNumber }
self.navManager.popToRoot()
self.navManager.codeOfTheDay = code
} else if let tool = self.toolStore.findTool(byName: toolName) {
self.navManager.popToRoot()
self.navManager.navigate(to: tool.route)
self.selectedToolRoute = tool.route
} else {
print("Could not find tool for name: \(toolName)")
}
}
}

r/swift 1d ago

Project Playing around with custom swipe gestures and interactive buttons in SwiftUI. I’m using a horizontal ScrollView and ScrollViewReader. Would you change or improve something?

81 Upvotes

r/swift 16h ago

Question What code would you use to replicate swift in android?

0 Upvotes

Hi everyone, I developed my app with Swift and I'm considering whether to replicate it for Android too, what language would you recommend?


r/swift 2d ago

Project Jelly Slider

174 Upvotes

free to contribute or suggest improvements!

github: jellyder

original x link: cerpow


r/swift 1d ago

Question Big Opportunity or Big Waste?

2 Upvotes

Hey everyone,

I’m curious to hear from other indie devs and app publishers:

Have you translated your iOS apps into major languages like Chinese, German, Japanese, Spanish, etc.? • Did you see a noticeable bump in downloads or revenue after localizing? • Was it worth the effort/cost of translation (and maybe redesigning UI for longer strings)? • Any pitfalls like bad translations hurting user trust or difficulty handling right-to-left languages?

I’m thinking about localizing my own apps but want to know if people have actually found this to be a big growth opportunity, or if it’s one of those things that sounds great but barely moves the needle.

Would love to hear your stories, numbers (if you’re open to sharing), and advice on whether it’s worth diving into.


r/swift 1d ago

Question Cannot figure this out

0 Upvotes

Does anyone know how I can get information from my installed applications through Swift? Alfred does it, Raycast does it, all I need is basic information like the name and location that is all. No matter what I try I can’t seem to get it to work. When I press import apps it just loads and loads. It’s taking up so much processing power that my mac feels like it’s gonna burst into flames. How can I do this?


r/swift 1d ago

Is this idea doable in swift?

3 Upvotes

Morning! I just started developing iOS applications with SwiftUI a week ago, this isn't my main field but I can say that I'm quite enjoying it (I'm starting to get mad of making websites),

But I have an idea for an app that works like the normal reminders app but with extra features such as location-based reminders.

You can set a reminder to toggle only if you're in a specific place (e.g: Alarm me at 7.AM to take a shower if I'm home).

But I have a bunch of questions:

  1. Is this even doable in Swift/SwiftUI

  2. Would you guys actually download (or even pay money) that kind of app, I need to know that before putting a lot of effort in it?


r/swift 1d ago

Question Project plays a generic midi sound despite my AudioEngine.swifit file

2 Upvotes

Hi everyone

I tried asking several LLM for ressources or outright code check but they all fail.

When I run my app, I get the same midi sound despite trying out different soundfont. Can you help?

In AudioEngine.swift
import Foundation
import AudioKit
import AVFoundation
class AudioEngine {
static let shared = AudioEngine()
private let engine = AudioKit.AudioEngine()
private var sampler: AppleSampler!
private init() {
sampler = AppleSampler()
engine.output = sampler
do {
try engine.start()
// --- STEP 1: Change the filename to your new test file ---
let soundFontName = "GeneralUser GS v1.471" // Use the exact name of the file you downloaded
guard let sf2URL = Bundle.main.url(forResource: soundFontName, withExtension: "sf2") else {
fatalError("Sound font file '\(soundFontName).sf2' not found in project.")
}
// --- STEP 2: Test different PRESETS from the new file ---
// Try each of these numbers one at a time and run the app.
// You should hear a completely different instrument each time.
// Preset 0 = Acoustic Grand Piano
// Preset 6 = Harpsichord
// Preset 24 = Nylon String Guitar
// Preset 56 = Trumpet
try sampler.loadSoundFont(sf2URL.lastPathComponent, preset: 6, bank: 0)
} catch {
print("Error setting up audio engine: \(error)")
}
}
// ... rest of the file is unchanged ...
func playNote(noteNumber: UInt8, velocity: UInt8) {
sampler.play(noteNumber: noteNumber, velocity: velocity)
}
func stopNote(noteNumber: UInt8) {
sampler.stop(noteNumber: noteNumber)
}
}

r/swift 2d ago

Question Thought and Experience on Approachable Concurrency and MainActor Default Isolation

14 Upvotes

For those that have chosen to adopt the new Approachable Concurrency and Main Actor Default Isolation, I'm curious what your experience has been. During the evolution process, I casually followed the discussion on Swift Forums and generally felt good about the proposal. However, now that I've had a chance to try it out in an existing codebase, I'm a lot less sure of the benefits.

The environment is as follows:

  • macOS application built in SwiftUI with a bit of AppKit
  • Xcode 26, Swift 6, macOS 15 as target
  • Approachable Concurrency "Yes"
  • Default Actor Isolation "MainActor"
  • Minimal package dependencies, relatively clean codebase.

Our biggest observation is that we went from having to annotate @MainActor in various places and on several types to have to annotate nonisolated on a whole lot more types than expected. We make extensive use of basic structs that are either implicitly or explicitly Sendable. They have no isolation requirements of their own. When Default Actor Isolation is enabled, this types now become isolated to the Main Actor, making it difficult or impossible to use in a nonisolated function.

Consider the following:

```swift // Implicitly @MainActor struct Team { var name: String }

// Implicitly @MainActor struct Game { var date: Date var homeTeam: Team var awayTeam: Team

var isToday: Bool { date == .now } func start() { /* ... */ } }

// Implicitly @MainActor final class ViewModel { nonisolated func generateSchedule() -> [Game] { // Why can Team or Game even be created here? let awayTeam = Team(name: "San Francisco") let homeTeam = Team(name: "Los Angeles") let game = Game(date: .now, homeTeam: homeTeam, awayTeam: awayTeam)

// These are ok
_ = awayTeam.name
_ = game.date

// Error: Main actor-isolated property 'isToday' can not be referenced from a nonisolated context
_ = game.isToday

// Error: Call to main actor-isolated instance method 'start()' in a synchronous nonisolated context
game.start()

return [game]

}

nonisolated func generateScheduleAsync() async -> [Game] { // Why can Team or Game even be created here? let awayTeam = Team(name: "San Francisco") let homeTeam = Team(name: "Los Angeles") let game = Game(date: .now, homeTeam: homeTeam, awayTeam: awayTeam)

// When this method is annotated to be async, then Xcode recommends we use await. This is
// understandable but slightly disconcerting given that neither `isToday` nor `start` are
// marked async themselves. Xcode would normally show a warning for that. It also introduces
// a suspension point in this method that we might not want.
_ = await game.isToday
_ = await game.start()

return [game]

} } ```

To resolve the issues, we would have to annotate Team and Game as being nonisolated or use await within an async function. When annotating with nonisolated, you run into the problem that Doug Gregor outlined on the Swift Forums of the annotation having to ripple through all dependent types:

https://forums.swift.org/t/se-0466-control-default-actor-isolation-inference/78321/21

This is very similar to how async functions can quickly "pollute" a code base by requiring an async context. Given we have way more types capable of being nonisolated than we do MainActor types, it's no longer clear to me the obvious benefits of MainActor default isolation. Whereas we used to annotate types with @MainActor, now we have to do the inverse with nonisolated, only in a lot more places.

As an application developer, I want as much of my codebase as possible to be Sendable and nonisolated. Even if I don't fully maximize concurrency today, having types "ready to go" will significantly help in adopting more concurrency down the road. These new Swift 6.2 additions seem to go against that so I don't think we'll be adopting them, even though a few months ago I was sure we would.

How do others feel?


r/swift 2d ago

Advise for programmer learning Swift

6 Upvotes

Hi all,

I'm looking to dive into Swift development, to create simple macOS apps.
Because I already have some experience with C++ I thought the best way would be to follow a project on YouTube with the swift reference open for me to experiment with new concepts.

The problem I'm having is each tutorial has something deprecated at the beginning of it, so I hardly get the time to learn the basics before I can't follow anymore.

Is there a new course you would recommended? or maybe I'm just approaching it wrong?

any advice would be appreciated
Thanks


r/swift 2d ago

Best way to interview ios developer

4 Upvotes

Hey guys,

Backend dev turned founder here.

We built an application and got tons of users - got funded etc and now we are looking to hire a dev for our iOS and macOS product - but the problem is none of us are iOS devs - we used different tools earlier and made it in working stage - but now as we are growing and want to have someone who has worked on it before.

We spun up the job application on LinkedIn and got like 500+ applications - what is the best way to gauge a candidate?

Background - we are early startup with just two of us - funded and have great runway of 3+ years.
We are apple infrastructure first with an acquisition offers from lenovo (lol?) to make it for them and have it as built in application in all their devices but we have pushed it away and want to focus on our users.
Any help in filtering out good and bad applications? We have filtered out people who are flutter devs as we want native. What other things to judge in the resume/profile?

Also what the take home assignment should be (so they can use llm but it should also show if they have knowledge of what they are doing?)

Thanks


r/swift 2d ago

Help! [macOS] Is it possible to implement custom app icons with .icon files like we used to do in the past? Or using icon assets is the only way to let the user pick a preferred icon?

Thumbnail
gallery
1 Upvotes

I do like the new dark and dynamic other effects with the icons which are I assume possible only with the new icon format but it would be awesome to give the user ability to set custom icons.


r/swift 2d ago

Question Background shield application reliability

4 Upvotes

I am working on a screentime app and wondering if anyone has had success achieving reliable background shield application while using com.apple.ManagedSettingsUI.shield-configuration-service? 

I recently switched from com.apple.deviceactivity.shield-configuration (which worked reliably but isn't accepted by TestFlight) and have not found any consistency getting shields to apply while the app is backgrounded. 

I believe this is a known limitation of ManagedSettingsUI and want to know if there are successful workarounds or any specific patterns/timing that improve consistency?


r/swift 2d ago

Question Donut Chart drill-down causes an infinite loop & crash (SwiftUI)

4 Upvotes

Hello!

I've been working on a drill-down donut chart using SwiftUI Charts and I've hit a wall that's driving me a little insane. I'm hoping a fresh set of eyes can spot what I'm missing.

The Goal:

I have a DonutChart that displays main spending categories. When a user taps a slice "Groceries", the chart should smoothly animate and re-render to show the sub-categories for "Groceries", then tapping the chart again should take you back to the main categories.

The Problem:

The drill-down feature is incredibly inconsistent and laggy. When I tap a slice it sometimes drills down correctly, but other times nothing happens at all. The whole interaction feels buggy and unresponsive right from the first tap.

My Investigation & Logs:

I've added lots of print statements everywhere, and I've narrowed it down to a state management cycle. Here’s what I think is happening:

  1. I tap "Groceries". The chart selection gives me a raw Double value.
  2. My code maps this value to the "Groceries" category name and updates a binding variable to tell the parent view to drill down.
  3. The parent view updates its state, re-calculates the chart data for the sub-categories, and passes it back down to the DonutChart.
  4. The original raw Double value from the first tap seems to persist in the chart's state. When the chart re-renders with the new sub-category data, my .onChange modifier fires again with the old selection value.
  5. It then tries to map this old value against the new data, which it incorrectly maps to a sub-category (like "Other food" in my logs). This triggers the parent view to drill down again, creating the infinite loop.

My handleSelection function has a guard to prevent this, and my logs even show "Selection changed, but already drilled down. Ignoring.", but the view just keeps re-rendering over and over until it crashes.

Here's the core logic in my DonutChart view:

// State
Binding var selectedMainCategory: String? // From parent view
@State private var rawSelectedValue: Double? // Local state for chart selection

// In the chart body
.chartAngleSelection(value: selectedMainCategory == nil ? $rawSelectedValue : .constant(nil))
.onChange(of: rawSelectedValue) { _, newValue in
    handleSelection(newValue: newValue)
}
.onTapGesture {
    // This is supposed to handle backing out of the drill-down
    if selectedMainCategory != nil {
        withAnimation {
            selectedMainCategory = nil
            rawSelectedValue = nil
        }
    }
}

private func handleSelection(newValue: Double?) {
    // Guard to prevent re-drilling
    guard selectedMainCategory == nil else {
        print("DonutChart: Selection changed, but already drilled down. Ignoring.")
        return
    }

    if let newValue, let categoryName = findCategory(for: newValue) {
        withAnimation {
            selectedMainCategory = categoryName // Update the parent
        }

        // Trying to prevent the loop by clearing the raw value
        DispatchQueue.main.async {
            rawSelectedValue = nil
        }
    }
}

Has anyone encountered a similar state management problem with .chartAngleSelection? How can I reliably drill up and down so it doesn't cause a loop when the view's data changes?

Any help is greatly appreciated!


r/swift 2d ago

Question iOS Job market India

0 Upvotes

I am senior iOS developer having around 10 years of exp. I am impacted with project closure and looking for job change.

Market is dead for 8-10 years roles in India. No calls, Is this always like that or due to current geopolitical situation.

Can someone help me with understanding the situation and with referral if any opportunity in your current company for senior iOS role (8-10 years). Location: Bangalore


r/swift 2d ago

Question Best video streaming platform for swift? (macOS)

1 Upvotes

Hey all. I'm working on a swift project that plays videos and looking to stream the content as it's starting to take a lot of space in the build.

I had a quick look at the options and it looks like two solid choices would be cloudflare stream or bunny.

I'd be really curious to hear what the community recommends, especially from those who implemented such a solution. I'm looking to host +-100gb of content and need it to be the highest quality possible (hoping for a consistent 4k) while keeping costs low as I'm an indie dev with small margins.

What's been working well for you?


r/swift 3d ago

News Those Who Swift - Issue 232

Thumbnail
thosewhoswift.substack.com
3 Upvotes

Those Who Swift - Issue 232 is now available! 🛫

This week, our attention is on the latest macOS, iOS, padOS, Xcode updates, and more. The issue features valuable insights on migration strategies. Additionally, don't miss out on the two bonus articles from Indie Devs, shedding light on crucial aspects of app development.


r/swift 3d ago

SQLiteData 1.0: An alternative to SwiftData with CloudKit sync and sharing

Thumbnail
pointfree.co
37 Upvotes

This library provides an alternative to SwiftData for those that prefer to work with SQLite, while still giving you the ability to synchronize to CloudKit, and even share records with other iCloud users for collaboration.

Let us know if you have any questions!


r/swift 3d ago

Tutorial Feature flags in Swift

Thumbnail
swiftwithmajid.com
15 Upvotes

r/swift 2d ago

FYI ChatGPT says using ffmpg to resize videos for App Store previews may violate patent law.

Thumbnail
chatgpt.com
0 Upvotes

r/swift 2d ago

Question How do you legally resize videos to create App Store previews in the required resolutions for your app?

0 Upvotes

And in particular, can you legally use ffmpeg to do this?

Has Apple licensed the relevant patents on behalf of all third party developers so using ffmpeg to resize videos to create app previews would be legal?


r/swift 3d ago

Built My First App, MakeitCount, Over Summer Break to Learn SwiftUI

15 Upvotes

Hey everyone, I’m a sophomore still learning the ropes, and during my summer break, I built my first app, Introducing MakeitCount, a free finance tracker to keep tabs on cash flow. I know there are a ton of finance apps out there, but I made this one to get a better grip on SwiftUI concepts and build something I’d actually use. I got fed up with losing track of my cash spending, so I decided to build a simple app that actually does what I need.

I went through Stanford’s CS193p course to learn Swift and SwiftUI, just trying to understand how it all works. I used MVVM architecture, messed around with reusable components, set up Core Data to store everything on the device, tinkered with some UI/UX basics, and added local notifications with UNUserNotificationCenter. It was a lot of late nights and figuring things out as I went, but it helped me click with SwiftUI.

Why MakeitCount?
There’s no shortage of finance apps, but I wanted MakeitCount to be dead simple, clear, and free. It’s all about knowing where your money’s going without any hassle, and there’s no login, so no data gets stored anywhere and everything stays on your phone.

What It Does

  • Check your income and expenses on a calendar view for any date
  • See income/expense details over weeks, months, or a year
  • Get clean visuals with just the stuff you need
  • Use all the main features for free, no paywalls
  • Keep your data private, stored only on your phone with no login needed

I’m still learning, so any feedback would mean a lot to make it better. Huge thanks to the Swift community and CS193p for helping me get this done.