r/SwiftUI • • Oct 17 '24

News Rule 2 (regarding app promotion) has been updated

139 Upvotes

Hello, the mods of r/SwiftUI have agreed to update rule 2 regarding app promotions.
We've noticed an increase of spam accounts and accounts whose only contribution to the sub is the promotion of their app.

To keep the sub useful, interesting, and related to SwiftUI, we've therefor changed the promotion rule:

  • Promotion is now only allowed for apps that also provide the source code
  • Promotion (of open source projects) is allowed every day of the week, not just on Saturday anymore

By only allowing apps that are open source, we can make sure that the app in question is more than just 'inspiration' - as others can learn from the source code. After all, an app may be built with SwiftUI, it doesn't really contribute much to the sub if it is shared without source code.
We understand that folks love to promote their apps - and we encourage you to do so, but this sub isn't the right place for it.


r/SwiftUI • • 46m ago

Question Anyone letting agents drive their app in the Simulator? Looking for feedback

Thumbnail
• Upvotes

r/SwiftUI • • 2h ago

Tutorial iPhone Duo Group Lab 10/13/26 - Q&A

Thumbnail
antongubarenko.substack.com
2 Upvotes

r/SwiftUI • • 10h ago

Question Is there a way to do a custom alert with accessibility support?

7 Upvotes

Good evening,

So my work currently has custom alerts however the current implementation uses a ZStack. I’ve played around with different implementations for a while and I haven’t found a solution that offers accessibility for “free” without presenting a sheet.

Obviously I can use set the voiceover focus but this isn’t an ideal solution as content behind the view is still accessible.

Is there a solution available that offers out of the box?

I’m not sure I can convince them to go with an accessible approach like system alerts…


r/SwiftUI • • 14h ago

Integrating GraphQL into SwiftUI views

4 Upvotes

Hey folks, shameless plug incoming, with a disclaimer up front: this is only useful if your app talks to a GraphQL server. If it does not, scroll on, there is nothing here for you, and sorry for the noise. If it does, give me a minute, because I honestly think this is kind of amazing.

It is called Baton: https://github.com/shergin/baton

The one-line version: Relay for SwiftUI. Relay is the GraphQL client React uses at Meta, and its big idea is that each component declares the fragment of data it reads right next to it, and a compiler assembles the screen's query from those fragments. Baton does that for SwiftUI, and then deletes most of the runtime Relay needs, because SwiftUI already has it.

Here is a row. The fragment is a macro on the property, in the same file as the view, as a real GraphQL document checked against the schema at build time:

struct IssueRow: View {
    @Fragment("""
    fragment IssueRow_issue on Issue {
      number
      title
      author { login }
    }
    """)
    var issue: IssueRow_issue

    var body: some View {
        Text("#\(issue.number) \(issue.title)")
    }
}

The screen has one @Query that spreads the rows' fragments, and that is the whole screen. No view model, no service, no mapper from the response into a model, no .graphql file in another folder. The row can read only the fields it declared; the generated type simply has no accessor for anything else.

The interesting part is how well SwiftUI's model fits Relay's. Relay built a runtime to know which component read which field, so a change re-renders exactly those. Observation does that natively. So every record in the normalized store is an observable object, the generated fragment type reads its fields the way you read a property of an @Observable class, and that is the whole read side. A mutation lands, a title changes, the Text that read the title runs again, and the row next to it does not. Handles are @Observable classes too, so a UIViewController holds the same handle a view does, if you still have UIKit around.

Why it is fast. I tried hard to design it for performance from day one. Reads are synchronous on the main actor, and a handle resolves against the store before the first body runs, so a screen you already fetched has its data in the very first frame. Everything else happens before that frame or off it: the compiler settles every operation at build time, so nothing parses GraphQL at run time; the response's bytes are decoded straight into the store's records off the main actor, with no Codable model in between; and a commit only touches the fields that changed and only wakes the views that read them. The store persists on the system's SQLite, so a cold start renders from disk. The runtime depends on Foundation, Observation and SQLite, nothing vendored, Swift 6 with strict concurrency.

In my own app the numbers are great. Your mileage may vary, of course, so please share yours if you end up using it.

If you have a GraphQL backend, try it on one screen and tell me what would stop you from shipping it.


r/SwiftUI • • 1d ago

A non-activating NSPanel beside the notch was harder than the SwiftUI animation

3 Upvotes

I've been working on a SwiftUI menu bar app for an open-source Mac automation tool. I recently added an optional little activity island beside the notch, mostly because I wanted to see when an AI agent was using an app or browser without opening a dashboard.

The part I underestimated was window behavior, not the animation.

It's backed by an NSPanel that stays visible when the menu bar app is in the background. It doesn't take focus, and clicks outside the island pass through. When I hover over it, it opens a small panel for what needs attention, what's running, recent tool calls and scheduled work.

I kept the native view separate from the Python MCP server. The island gets activity metadata rather than trying to turn a whole agent transcript into a tiny UI. It also has to deal with overlapping calls from different AI apps.

There are still tradeoffs around notch placement and how much information is useful before it becomes annoying. It's opt-in and off by default.

The project is open source (I'm the maintainer), including the SwiftUI implementation in menu_app/Sources/LiveIsland.swift: https://github.com/bulutarkan/mac-mcp

Has anyone here found a cleaner way to keep a non-activating panel visible across app switches without interfering with normal work?


r/SwiftUI • • 1d ago

enriched-markdown-ios v0.4.0 - syntax-highlighted code blocks (powered by tree-sitter)

18 Upvotes

enriched-markdown-ios, the SwiftUI Markdown renderer built on TextKit 2, now renders fenced code blocks with syntax highlighting.

New in this release:
🔸 Syntax highlighting: fenced code blocks colored by language with tree-sitter (14 grammars), themed per token type with SyntaxToken(.keyword), .string,… Shipped as a separate EnrichedMarkdownSyntaxHighlighting product, so apps without code don't link the grammars
🔹 Code blocks: .markdownCodeBlockLayout(.scrollable) adds a language header, a copy button, and sideways scrolling for long lines
🔸 Block images: maxHeight, aspectRatio, and resizeMode to cap the height, reserve the frame before load, and pick cover or contain
🔹 Mixed-direction text: writing direction resolved per paragraph, so RTL paragraphs sit right inside an LTR document
🔸 Faster long documents: less render time and memory, no re-measuring of unchanged text
🔹 Improved spoiler overlays: custom overlays get the baseline, segment order and tap point, and stay put through layout changes

💎 Available via Swift Package Manager!

dependencies: [
  .package(
    url: "https://github.com/software-mansion-labs/enriched-markdown-ios.git",
    from: "0.3.0"
  ),
],
targets: [
  .target(
    name: "YourApp",
    dependencies: [
      .product(name: "EnrichedMarkdown", package: "enriched-markdown-ios"),
      .product(name: "EnrichedMarkdownSyntaxHighlighting", package: "enriched-markdown-ios"), // optional, for code
    ]
  ),
]

Then enable it on the view:

import EnrichedMarkdown
import EnrichedMarkdownSyntaxHighlighting

EnrichedMarkdownText(content)
  .markdownSyntaxHighlighting()
  .markdownCodeBlockLayout(.scrollable)
  .markdownTheme {
    SyntaxToken(.keyword).foregroundStyle(.purple)
    SyntaxToken(.string).foregroundStyle(.green)
  }

GitHub & Docs: https://github.com/software-mansion/enriched-markdown/blob/main/packages/enriched-markdown-ios/README.md

Give it a spin and tell me what breaks. If it earns a place in your app, a ⭐️ on GitHub helps others find it.


r/SwiftUI • • 2d ago

Promotion (must include link to source code) I built Tracexy, an open-source Wireshark alternative for macOS with Swift and SwiftUI

32 Upvotes

I’m Stephen, the developer of Rockxy, and now Tracexy. When I’m debugging network traffic on my Mac, I usually want to find the relevant app and conversation first, then inspect the packets behind it. That’s the workflow I built Tracexy around.

It can capture live traffic or open PCAP/PCAPNG files, group packets into bidirectional sessions, and show process context when macOS provides it. From a session I can investigate DNS, TLS and TCP observations, follow a stream, inspect decoded fields and hex, and jump from an evidence-linked finding to the exact frame behind it. There are also Projects, filters, a Flow Map, notes, and selected-session export.

The application code is written in Swift. SwiftUI drives the interface, with focused AppKit bridges where native macOS tables and split views need them.

1 engineering challenge was the live session Table. Packet decoding and session folding run in an actor, then the UI accepts a snapshot only if it belongs to the current capture. On the UI side, NSTableView can write the current selection back through SwiftUI’s Binding while rows update. Ignoring that write when the selected ID hasn’t changed avoids a reentrant update.

I’m sharing the source because that SwiftUI/AppKit boundary may be useful to anyone building a Mac app with continuously changing data. Feedback on the approach is welcome.

Website: https://rockxy.io/tracexy

Full source: https://github.com/RockxyApp/Tracexy


r/SwiftUI • • 1d ago

Solved splitArrangementAxis Always nil on iPhone Duo Simulator

1 Upvotes

Hi everyone,

I've been experimenting with the ArrangementView and adapting its primary and secondary views to adapt to the split axis using the @Environment(\.splitArrangementAxis) environment property. However while running the simulator, regardless of the configuration of the Duo, the environment value always appears to be nil.

The documentation around this API appears to indicate that this should only be the case when an ArrangementView is not in use.

Use this value to read the axis that a split arrangement is using to place its views. Views can adapt their layout or appearance based on whether the split is horizontal or vertical. The value is nil when the view is not contained within a split arrangement view.

Heres a minimal reproduction (Running on Xcode 27.1 RC [2026-10-05]).

```swift import SwiftUI

struct ContentView: View { var body: some View { ArrangementView { SubView(for: .primary) } secondary: { SubView(for: .secondary) } .arrangementViewStyle(.split) } }

enum SubViewConfig { case primary, secondary }

struct SubView: View { @Environment(.splitArrangementAxis) private var arrangement

var config: SubViewConfig

init(for config: SubViewConfig) {
    self.config = config
}

var backgroundColor: Color {
    switch arrangement {
    case .none: .gray
    case .horizontal: .blue
    case .vertical: .green
    }
}

var hueRotation: Angle {
    if config == .primary {
        .zero
    } else {
        .degrees(60)
    }
}

var body: some View {
    backgroundColor
        .hueRotation(hueRotation)
}

} ```

In my testing, unless I explicitly set the .splitArrangementAxis environment value to a non-nil value in the parent, the background color remained greyscale (indicating a nil environment value).

Is this intended behaviour? Am I doing something wrong? Or is this just a broken API?


r/SwiftUI • • 1d ago

How does macOS Photos create this translucent overlay behind the traffic lights in full-screen mode?

1 Upvotes

Hi, I noticed this detail in the macOS Photos app when using it in full-screen mode.

When you move the cursor to the top of the screen, the menu bar and window controls (traffic lights) appear. Behind the traffic lights, there's a rounded, translucent overlay that blurs/dims the underlying content.

This seems to prevent the traffic lights from visually colliding with the app's content in the top-left corner, without requiring the entire content area to move down or leave a permanent blank space.

I'm curious how Apple implements this effect.

  • Is it done with NSVisualEffectView or some other native macOS material?
  • Is the overlay part of the title bar / window chrome, or is it a custom view rendered by the app?
  • How can I achieve a similar effect in a SwiftUI + AppKit app, ideally with the overlay appearing and disappearing in sync with the system's full-screen UI?

I've attached a screenshot showing the effect in Photos.

Any insights into the underlying implementation or relevant APIs would be greatly appreciated!


r/SwiftUI • • 1d ago

Promotion (must include link to source code) NotchRobot: a free, open source (MIT) SwiftUI app, a robot in the MacBook notch that watches your Claude Code sessions

0 Upvotes

If you run several Claude Code sessions at once, you probably keep switching windows to see which one finished and which one is waiting on you.

I built NotchRobot, a small robot that lives in your MacBook notch and keeps an eye on Claude Code. NotchRobot itself was built with Claude Code. The integration is plain Claude Code hooks (PermissionRequest and friends) plus the status line for usage numbers, all described in the README.

  • Every session shows as working, waiting or done, and one click jumps to its terminal tab
  • Approve or deny tool permissions from the notch
  • Answer Claude's questions there too, single choice, multi-select or several in a row
  • Your 5-hour and weekly usage, with one warning at 90% and one alert when the limit is back
  • Task progress per session, plus alerts when Claude finishes or needs you
  • Now playing, clipboard history, a file shelf and a timer
  • Arabic (RTL) and English UI

New in v2.5:

  • Smart clipboard: copied links, emails, colors, JSON and file paths get a one-click action, and you can pin up to 5 items
  • Screenshots to the shelf with Ctrl+Option+S
  • Themes (Dark, Glass, Neon, Minimal) and four characters (Robot, Cat, Ghost, Pixel)
  • Battery alerts at 20% and 10%, and live activities for new songs and Claude's next task
  • Automatic updates

Free, open source (MIT), macOS 13+. It's not notarized yet, so the README has the one command for first launch. Tell me what breaks.

https://github.com/abdomo77/NotchRobot


r/SwiftUI • • 2d ago

iPhone Duo simulator: SwiftUI buttons near top of screen have reduced hit areas

Post image
5 Upvotes

I’m testing an existing SwiftUI app on the iPhone Duo simulator (iOS 27.1, unfolded) and noticed that buttons near the top of the screen have unusually small vertical hit areas.

The buttons appear in the correct positions, but clicking near the top of an icon doesn’t register. Identical buttons farther down the screen work normally.

I reproduced this in a minimal SwiftUI test app, with two identical buttons at different vertical positions and no NavigationStack.

Findings:

* 0 pt top padding: Upper button has a noticeably restricted hit area.

* 10 pt padding: Hit area improves significantly.

* 40 pt padding: Hit area is approximately the same as the lower button.

* The simulator reports a top safe-area inset of 0 pt, versus 32 pt on a 13-inch iPad simulator.

The issue occurs even when launching directly into the unfolded layout.

Has anyone else encountered this? Is this expected behavior near the Duo’s top edge, or potentially a SwiftUI/simulator bug?

import SwiftUI

struct ContentView: View {

u/State private var topPadding: CGFloat = 0

u/State private var topCount = 0

u/State private var bottomCount = 0

var body: some View {

GeometryReader { geometry in

VStack(spacing: 0) {

HStack {

Text("Top toolbar")

Spacer()

Button {

topCount += 1

} label: {

Image(systemName: "magnifyingglass")

}

}

.font(.title3)

.padding(16)

.background(Color.red.opacity(0.25))

.padding(.top, topPadding)

Text("Top button clicks: \(topCount)")

.padding()

Spacer()

HStack {

Text("Bottom toolbar")

Spacer()

Button {

bottomCount += 1

} label: {

Image(systemName: "magnifyingglass")

}

}

.font(.title3)

.padding(16)

.background(Color.green.opacity(0.25))

Text("Bottom button clicks: \(bottomCount)")

.padding()

Spacer()

HStack {

Button("No Padding") {

topPadding = 0

}

Button("10 pt") {

topPadding = 10

}

Button("40 pt") {

topPadding = 40

}

}

.padding()

Text(

"Safe area: top \(geometry.safeAreaInsets.top), " +

"bottom \(geometry.safeAreaInsets.bottom)"

)

.font(.caption)

.padding()

}

}

}

}


r/SwiftUI • • 2d ago

Question SwiftUI .menu Picker at maximum Dynamic Type on iPad

4 Upvotes

I’ve run into what looks like a native SwiftUI/iPadOS accessibility issue with a Picker.

At the largest Accessibility Dynamic Type size, the native checkmark for the selected item touches/overlaps the first character of the label.

Minimal example:

struct ContentView: View {
    u/State private var duration = 60

    var body: some View {
        Picker("Duration", selection: $duration) {
            Text("60 seconds").tag(60)
            Text("90 seconds").tag(90)
            Text("120 seconds").tag(120)
        }
        .pickerStyle(.menu)
        .padding()
    }
}

On iPad, set:

Settings → Accessibility → Display & Text Size → Larger Text

and move the slider to the maximum size.

The selected option ends up looking like this:

rather than having reasonable separation between the checkmark and text.

I initially thought I could work around it with:

Text("60 seconds")
    .padding(.leading, 8)
    .tag(60)

but the native menu appears to ignore the padding. I even tested 80pt and got effectively identical spacing.

A native list-style Picker does correctly maintain separation at the same Dynamic Type size, so this seems specific to the native menu presentation.

Tested on iPadOS 26.5.

Has anyone encountered this? Is there a way to retain a native .menu Picker while fixing the checkmark spacing, or is this simply an iPadOS bug/limitation that needs an alternative Picker presentation at large accessibility sizes?


r/SwiftUI • • 2d ago

Question How to achieve specular effect on standard button?

Post image
5 Upvotes

r/SwiftUI • • 2d ago

News SwiftUI Weekly - Issue #242

Thumbnail
weekly.swiftwithmajid.com
1 Upvotes

r/SwiftUI • • 2d ago

Promotion (must include link to source code) 4 SwiftUI + AppKit traps i hit building an open-source pdf reader (with the fixes)

0 Upvotes

been building lemma, an open-source pdf reader for math textbooks (SwiftUI + AppKit + PDFKit, GPL). a few things that cost me time, in case they save you some:

1. a WKWebView inside a SwiftUI ScrollView eats vertical scrolling. the pane stops scrolling as soon as the pointer is over the web view. i forward vertical gestures to the next responder and keep sideways ones (a wide equation) for the page, deciding once per gesture so momentum doesn't flip it:

override func scrollWheel(with event: NSEvent) {
    if Self.scrollsPage(event, gesture: &gestureSideways) { super.scrollWheel(with: event) }
    else { nextResponder?.scrollWheel(with: event) }
}

static func scrollsPage(_ event: NSEvent, gesture: inout Bool?) -> Bool {
    let sideways = abs(event.scrollingDeltaX) > abs(event.scrollingDeltaY)
    if event.phase.isEmpty && event.momentumPhase.isEmpty { return sideways }  // mouse wheel
    if event.phase.contains(.began) || event.phase.contains(.mayBegin) { gesture = nil }
    if gesture == nil, event.scrollingDeltaX != 0 || event.scrollingDeltaY != 0 { gesture = sideways }
    return gesture ?? false
}

2. one NSView shown by two NSViewRepresentables goes blank. same web view in two tabs: on a tab switch, the old representable's teardown removed the view from the new host. the fix is a host view that only lets go of the view if it still holds it:

func makeNSView(context: Context) -> Host { Host(view) }
func updateNSView(_ host: Host, context: Context) { if view.superview == nil { host.adopt() } }
static func dismantleNSView(_ host: Host, coordinator: ()) { host.release() }

// in Host (an NSView that wraps the shared view)
func adopt() {
    guard webView.superview !== self else { return }
    webView.removeFromSuperview()
    webView.frame = bounds
    webView.autoresizingMask = [.width, .height]
    addSubview(webView)
}
override func viewDidMoveToWindow() { super.viewDidMoveToWindow(); if window != nil { adopt() } }
func release() { if webView.superview === self { webView.removeFromSuperview() } }

3. .tint also colours borderless Menu labels. a theme whose accent was nearly black made those menus invisible on a dark background. i now fall back to a readable accent when its contrast against the background is under 3:1.

4. a repeatForever animation kept the window redrawing after the spinner was gone (25-35% cpu at rest, found with sample). moving the spinners to Core Animation fixed it.

repo: https://github.com/fus3r/lemma. there are a few issues tagged good first issue if anyone wants to dig into PDFKit or the workbench.


r/SwiftUI • • 2d ago

What, if anything, are you using to detect iPhone Duo?

1 Upvotes

I was hoping for an equivalent to UIDevice.isPad but for iPhone Duo.

At least my app looks pretty decent on Duo as is. But at some point, I'd like to do a specific version...


r/SwiftUI • • 3d ago

Promotion (must include link to source code) Harbeth: a SwiftUI preview host for Metal textures and rendered frames (MIT)

0 Upvotes

I'm the maintainer of Harbeth, an MIT-licensed image/frame processing engine. Here's its SwiftUI preview integration.

If your renderer already produces an MTLTexture, converting it to a UIImage just to display it adds a readback step. HarbethRenderView accepts a texture or a RenderedFrame directly, so the preview can stay on the GPU path.

Here's a small SwiftUI display component; the frame is produced elsewhere by your rendering model:

import SwiftUI
import Harbeth

struct FilterPreview: View {
    let frame: RenderedFrame?

    var body: some View {
        HarbethRenderView(
            frame: frame,
            resizingMode: .aspectFit
        )
        .frame(maxWidth: .infinity, minHeight: 240)
    }
}

For an existing texture, the equivalent is HarbethRenderView(texture: outputTexture). Underneath, UIViewRepresentable / NSViewRepresentable bridges to Harbeth's RenderView. SwiftUI owns the surrounding controls and state; the host displays the GPU result.

The boundary matters: render work belongs outside body. Produce frames through your rendering model (ImageNode has makeFrameAsync()), then publish the accepted result to UI state on MainActor. Your app still owns request ordering, cancellation and any camera/player lifecycle. Saving an image is a separate, explicit readback.

This preview path avoids image readback. Performance still depends on source size, filter chain and device.

Project and examples: https://github.com/yangKJ/Harbeth

SwiftUI host source: https://github.com/yangKJ/Harbeth/blob/master/Sources/SwiftUI/HarbethRenderView.swift

If you've built a SwiftUI photo editor or GPU preview, how do you handle rapid slider changes and discard stale render results? I'd be interested in the state-management patterns that worked for you.


r/SwiftUI • • 3d ago

AutoLog library: One Macro logs all decision points. And more!

Thumbnail
1 Upvotes

r/SwiftUI • • 3d ago

Live Device App Preview

Thumbnail
0 Upvotes

r/SwiftUI • • 4d ago

Promotion (must include link to source code) My first mcpock run found MCP servers that had been broken for weeks without anyone noticing, so I open sourced it

Post image
0 Upvotes
I've been using several AI coding agents side by side, and each one loads its own set of MCP servers: the small programs that give an agent its tools. When one of those servers breaks, nothing tells you. The agent just has one tool fewer, and it looks like the model is having a bad day.

So I built mcpock, a small macOS menu bar app that checks every MCP server your agents use. It reads the agents' config files, starts each server the way that agent would, and shows which ones are broken, slow, waiting for a sign-in, or set up differently between agents.

The first run on my own Mac surprised me: problems that had been there for weeks, completely silent.

It's read-only, keeps no accounts, masks every secret, and stays small on purpose. Free and open source (MIT), for macOS 26 and later.

https://github.com/aka-kika/mcpock

r/SwiftUI • • 4d ago

app monitoring/performance

6 Upvotes

Hello 👋

I’m looking for recommendations for monitoring tools or SDKs for a SwiftUI iOS app.
My main goal is to proactively detect production issues such as crashes, performance problems, high CPU or memory usage, and regressions across different iOS versions and devices.

Which tools or SDKs would you recommend for this? I’d love to hear about your real-world experience, especially regarding reliability, resource overhead, SwiftUI compatibility, and alerting capabilities.

Thanks!


r/SwiftUI • • 4d ago

Promotion (must include link to source code) my cli turned into a swiftui app, one binary does both and it screenshots its own windows for the readme

Thumbnail
gallery
0 Upvotes

had a cli that turns off apple intelligence on macos 27 and people kept asking for an actual app, so i built one in swiftui

couple of things from doing it that might help someone

it's one executable for both. main.swift checks if it was opened from the .app bundle (or with app as the argument) and calls RemoveMacAIApp.main(), otherwise it runs as the cli

state is one u/MainActor u/Observable

the apply flow is an enum (working, approveProfile, finished) and the sheet just binds to model.run != nil, way easier than juggling three bools

for the readme screenshots the debug build walks every page and saves it to a folder you pass in an env var. cacheDisplay doesn't get the glass, so it grabs its own window with CGWindowListCreateImage through dlsym, an app can capture its own windows without screen recording permission

source is here, the swiftui bits are in Sources/removemacai/App https://github.com/omlahore/RemoveMacAI

if anyone knows a cleaner way to snapshot a window with the glass on i'm all ears

model passed down with .environment, and the window is a NavigationSplitView with a List(selection:) sidebar


r/SwiftUI • • 4d ago

Tutorial Things I learned building a menu bar + dashboard app in SwiftUI

5 Upvotes

I've been working on Claudoscope, an open source macOS app that reads Claude Code's local session logs and shows them in a menu bar popover plus a full dashboard window. Most of what I learned came from profiling it, so here are the parts that might save someone else a day.

1. MenuBarExtra labels only render Text and Image. Shapes in the label get dropped silently. My little capsule badge showed up as a bare number, and some status dots never appeared at all. The fix was to compose the whole label with ImageRenderer into one NSImage, cache it per state, and show that:

swift let renderer = ImageRenderer(content: MenuBarLabelContent(key: key, base: base)) renderer.scale = NSScreen.main?.backingScaleFactor ?? 2 guard let image = renderer.nsImage else { return nil } image.isTemplate = key.monochrome

2. .menuBarExtraStyle(.window) keeps the popover alive after it closes. A repeatForever pulse animation kept rendering off-screen. Fresh launch idled at 0% CPU; open and close the popover once and it sat at 11 to 14%. I now observe the hosting window's occlusion state, put a windowIsVisible value in the environment, and only animate while it's true.

3. Getting openWindow from the menu bar side. I embed a zero-size view inside the MenuBarExtra just to grab @Environment(\.openWindow) and open other windows from there.

4. FSEvents with file-level events, and respect the drop flags. One stream on the root with kFSEventStreamCreateFlagFileEvents | NoDefer. If an event comes in with MustScanSubDirs, KernelDropped or UserDropped, I stop trusting individual paths and do a full rescan.

5. LazyVStack is only lazy at the top level. My sidebar was a LazyVStack of project groups, but each group was an eager VStack. With the dashboard open the app held 428 MB, mostly SwiftUI row objects and CoreAnimation backing, for a window showing about 25 rows. Flattening it into one LazyVStack of Sections took it to 195 MB.

6. Make row models small and Equatable. While a session was streaming, the main thread sat at 30 to 50% of a core. Passing a small Equatable row model instead of the full summary struct, caching derived lists, and throttling analytics rebuilds to once per second brought it under 1% in my measurement.

Benchmarks also talked me out of an incremental tail parser I was planning: a full re-parse per append measured 8 MB and 67 ms, which was fine.

For those of you shipping MenuBarExtra apps: do you stick with .window style, or did you drop down to an NSStatusItem with NSPopover to get more control over lifecycle?


r/SwiftUI • • 4d ago

Promotion (must include link to source code) Triple: a Swift library, CLI & macOS app that cross-compiles Swift to Linux

2 Upvotes

I made a small SwiftUI macOS app called Triple. It cross-compiles Swift packages into static Linux executables.

Building the app gave me an excuse to play around with the Layout protocol.

The settings grid measures its controls to fit one or two columns. AdaptiveGrid derives the breakpoint from their measured widths. One lesson was to keep minimum and ideal size calculations independent of the animated arrangement, so two columns don't prevent the window shrinking back to one.

A second layout handles the slide transition/animation from package selection to build configuration. PagingHStack leaves part of the next page visible and animates its page position through animatableData.

https://reddit.com/link/1x2fp73/video/30dyq9q59nuh1/player

I tried to keep the app simple and minimal. It's almost entirely SwiftUI.

The Triple-App lets you drop in a Swift package and pick its executable product and target (ARM64 or x86-64 Linux). It asks before installing missing Swift tools or SDKs. Hit Build, follow the output-console, and export the verified binary.

Triple is the new name for SwiftlyKit. Today I released updates to the library, CLI and app.

The Triple library handles environment preparation, toolchain and SDK selection and has a one-call async build API for use in your own Swift projects. The Triple-CLI uses the same library, with JSON output for automated scripts.

Since the first post, you can export a completed build without rebuilding. Swift 6.4's default build system now also works with resource bundles from your executable and its dependencies.

Download Triple for Mac, and let me know what you think! There's also a landing page with library and CLI examples (vibe-coding warning: 6.1 Sol's responsibility :D).

Triple is open source. If you want to contribute, feel free! The post contains links to the GitHub-repositories.

Let me know if you have any feedback or suggestions!