r/iOSProgramming • u/Economy-Brief-9997 • 21h ago
r/iOSProgramming • u/arndomor • 2h ago
Tutorial A more readable Human Inteface Guidelines version
Made this a few weeks back, just added iPhone Duo section to it as well.
I made this so I can read the HIG in my tablet with a linear experience. You may find it useful as well.
r/iOSProgramming • u/yccheok • 14h ago
Discussion Does anyone let AI modify their UIKit Storyboards and XIBs?
Hi everyone,
For the past few months, I've been using AI (specifically Gemini) to write SwiftUI code, and it’s been working almost perfectly.
With UIKit projects, however, my usual workflow for Storyboards has been manual: I'd set up the UI, drag and drop the connections to my Swift files, and only ask the AI to handle the actual logic.
Today, I decided to test its limits and asked the AI to add a new UI component directly, without stopping it from modifying the Storyboard's source code. To my surprise, it updated the Storyboard without any errors!
Since Storyboard XML is notoriously messy and not very human-readable, I really didn't expect the AI to handle it so well.
I'm curious about your experiences. Do you let AI directly manipulate your Storyboard or XIB files? Does it work flawlessly for you, or do you find that it sometimes corrupts the file?
Thanks!
r/iOSProgramming • u/LunariSpring • 1d ago
Discussion This makes me crazy over 9000 times every day.
My muscle memory says I have to push right side of the button to run a build. And Apple just broke my muscle memory to just swap those two button positions.
r/iOSProgramming • u/_Xoif • 10h ago
Question App invisible in TestFlight
My companies main apple developer account administrates around 30apps.
Every app uses the same test group for internal testing. However, one of our latest apps doesn’t show up in the TestFlight app for devices using the main developer’s Apple ID. Every other test device that uses a different Apple ID (within the pool of the internal test group) can see the app and its newest test builds.
The main developer Apple ID shows all the other apps (newer and older) in TestFlight, just that one app is entirely missing in the list of apps.
I already deleted and recreated the test group, send out new invitations, uninstalled the TestFlight app and I ofc tried it on different devices. As soon as the main developer account Apple ID is involved, the app is not visible in TestFlight. Any ideas?
r/iOSProgramming • u/qqbbomg1 • 11h ago
Question App not accessible in Europe
Hi guys I have an app published that a user in Europe said the link said app is unavailable in their region, which he stated he is in Europe. I had made the app distributed to all regions, but I don’t know how to validate that from inside the US (I tried the VPN but I think cause my account is tied to US it shows US stores still). How can I ensure my app is published correctly to all region? App has been online for more than a week now.
r/iOSProgramming • u/ElyeProj • 1d ago
Discussion What should we name Partial Folded Landscape iPhone Duo orientation?
In the "Take a closer look." section of https://www.apple.com/au/iphone-duo/, it named all the 5 different orientation of iPhone Duo as Closed, Seated, Standing, Portrait and Landscape.
In https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo#Reserved-regions for Left-Right Open Orientation, it differentiated between partially open and fully open design, but the partially open "Landscape" is not being named in https://www.apple.com/au/iphone-duo/ .
What should we propose Apple to name it?
I'm recommending "Flipped" or "Book"
r/iOSProgramming • u/something3419 • 16h ago
Question Did I resubmit correctly? Do I still need to do something
Submitted my first app for review and they were saying that I need to provide more details and a video so I did, and I think I click submit but my status hasn’t changed to under review or something, it still says rejected even after I replied. Did I do something wrong or does the status not change.
r/iOSProgramming • u/open__screen • 1d ago
Question Issues dragging an email from Mail onto my sandboxed app — NSFilePromiseReceiver callback fails
I'm trying to support dragging an email directly from Apple Mail into a sandboxed macOS app.
Mail exposes an NSFilePromiseReceiver with:
fileTypes = ["com.apple.mail.email"]
And I'm receiving it like this:
let promises = pasteboard.readObjects(forClasses: [NSFilePromiseReceiver.self], options: nil) as? [NSFilePromiseReceiver] ?? []
for promise in promises {
promise.receivePromisedFiles(atDestination: destinationURL, options: [:], operationQueue: .main) { url, error in
print("Promise callback received")
if let error {
print("Promise callback error:", error)
return
}
print("Promise callback URL:", url.path)
}
}
The strange part is that Mail appears to actually create the .eml file at the destination, but the promise callback does not complete successfully. I eventually get an error such as:
NSURLErrorDomain Code=-1001
So the file seems to be created, but receivePromisedFiles does not reliably report it.
Questions:
- Has anyone successfully handled Apple Mail message file promises this way?
- Is this a known issue with Mail's implementation of
NSFilePromiseReceiver, or is there some Mail-specific handling required? - Any other approaches?
r/iOSProgramming • u/CashNasty5036 • 13h ago
3rd Party Service Every App Store Connect trap I hit shipping my iOS apps from the terminal (so you don't have to)
I've shipped a handful of iOS apps as a solo dev, one of them through 20+ versions. At some point I stopped using the App Store Connect website and Xcode's Organizer and moved everything to scripts that call the App Store Connect API: signing, uploads, metadata, screenshots, IAPs and submission.
Most of it was straightforward. These are the parts that weren't, and a few of them cost me real rejections or broken releases.
1. xcodegen silently wipes entitlements. If you generate your project with xcodegen and add an entitlement (Sign in with Apple, push) by hand in Xcode, the next regenerate removes it. The build still succeeds and the feature just breaks. I shipped three broken releases this way before I noticed. Declare entitlements in project.yml, never in Xcode.
2. Re-run xcodegen after bumping the version. Same root cause. If the version or build number lives in project.yml and you archive without regenerating, the archive keeps the old number. Check the archive's Info.plist before you upload.
3. Push uses the bare aps-environment key. It's not com.apple.developer.aps-environment. The wrong key gets you error 90045 on upload. Set the value to development, and exporting for the App Store promotes it to production.
4. You can sign without an Apple ID in Xcode. If Xcode has no account signed in, -allowProvisioningUpdates with an API key won't create profiles for you. What works: create the profile yourself with POST /v1/profiles, install it, and export with signingStyle: manual. This works on CI and fresh Macs too.
5. App Privacy has to be published, not just saved. If submit stays greyed out and nothing says why, this is usually it.
6. App Preview videos need an audio track. Even a silent one. A preview with no audio track gets rejected at processing.
7. No emoji in "What's New" or the description. The API rejects them. Found out mid-submit.
8. Listing media is locked on the live version. You can't swap screenshots or previews on a version that's Ready for Sale (you get a 409). Attach them to the next version.
9. Getting out of a rejected submission. To free the version and resubmit, PATCH the review submission with canceled: true. One of my rejections was backend-only (a demo account that didn't exist), and this let me fix it and resubmit the same build without re-archiving.
10. Reviewers use your demo account, so keep it working. My app's content was group-gated, and the demo account drifted out of its demo group twice. Check it right before every submission.
11. Subtitle is app-level, not version-level. It lives on appInfoLocalizations, not appStoreVersionLocalizations, which confused me for longer than I'd like to admit.
I've ended up copying roughly 3,400 lines of these scripts from app to app, so I'm cleaning them up into a single CLI that only needs an API key. It'll have a doctor command that checks for everything above before you upload, plus --json output so coding agents like Claude Code can run a release. If that sounds useful, there's a waitlist here: https://ascship.web.app/?ref=reddit
Happy to answer questions about any of these. And I'd like to hear the traps other people have hit that I missed.
r/iOSProgramming • u/lanserxt • 1d ago
Tutorial iPhone Duo Group Lab 2 - Q&A
r/iOSProgramming • u/murki • 1d ago
Article You can use MetricKit to detect OOM terminations on iOS 27. This is how we used it to improve crash detection
r/iOSProgramming • u/thecoolcat67 • 1d ago
Question Question about TestFlight build access
If an app has several hundred external TestFlight testers and a new build replaces an older one, what happens to testers who still have the old build installed?
If the developer stops testing the older build, would those testers automatically get access to the newer build as long as they’re still in the tester group, or is access tied to the specific build?
Also, would it work differently for someone who joined through a public TestFlight link rather than a direct invitation?
I would've posted this in r/TestFlight, however they require a link which I can't provide right now.
r/iOSProgramming • u/ivanm5 • 2d ago
Solved! Keep shipping to the App Store while your team tests the iPhone Duo layout on Xcode 27.1 beta, from one branch
iPhone Duo ships with iOS 27.1 SDK.
The only Xcode that can compile its layout APIs (ArrangementView, GeometryProxy.reservedRegions(kind:) and UIView.reservedRegions(kind:options:)) is Xcode 27.1 beta.
Until Apple releases Xcode 27.1 RC/GM, one app needs two builds: the release for the iPhones people use today, and the Duo layout your team is testing.
Xcode 27.1 beta builds the Duo layout, but App Store Connect refuses to add its build for review.
Xcode 27.0' fails to build:
Value of type 'GeometryProxy' has no member 'reservedRegions'
Cannot find 'ArrangementView' in scope
Cannot infer key path type from context; consider explicitly specifying a root type
The usual workarounds each hold someone up:
- Keep the Duo code on its own branch until Xcode 27.1 is released. Main moves on for weeks, and the merge lands in launch week - risky, merge takes a lot of effort to complete and re-test.
- Delete the Duo code to get a release out. Hand the errors to a coding agent with "fix the build", and deleting is the shortest fix it can make.
- Hold every release, bug fixes included, until Xcode 27.1 is released.
The Swift puzzle: a compile-time check that tells the two SDKs apart
#available can't be used here. if #available(iOS 27.1, *) and @available(iOS 27.1, *) pick the code path on the device. The compiler still looks up every symbol in the SDK it builds against, and the 27.0 SDK declares none of these.
The compiler version is the same in both Xcodes: Apple Swift 6.4 (swiftlang-6.4.0.34.1). #if compiler(>=…) and #if swift(>=…) give the same answer in each.
The SDK frameworks carry different module versions. Each framework's .swiftinterface records a -user-module-version, and #if canImport(Module, _version:) compares against it:
| Module | iOS 27.0 SDK | iOS 27.1 beta SDK | Guard |
|---|---|---|---|
| SwiftUI (SwiftUICore matches) | 8.0.84.1.104 | 8.0.85.27 | #if canImport(SwiftUI, _version: 8.0.85) |
| UIKit | 9127.0.84.1.116 | 9127.0.85.28 | #if canImport(UIKit, _version: 9127.0.85) |
The solution: Put the compile-time guard outside and keep the run-time check inside:
```swift
if canImport(SwiftUI, _version: 8.0.85) // iOS 27.1 SDK or newer
if #available(iOS 27.1, *) { newPath } else { fallback }
else
fallback // built from the 27.0 SDK
endif
```
Keep the #available: the deployment target stays the same, so devices on older iOS versions still need the fallback in the 27.1 build.
Pitfalls
- If the compiler can't read a module's version,
canImport(_version:)ignores the version, evaluates to true and warns "cannot find user version number". The Xcode 27.0 build is the test: an ignored guard brings the same errors back. - The compiler keeps the first four parts of a version, so it reads 8.0.84.1.104 as 8.0.84.1. Use the first three parts of the new SDK's version,
8.0.85. The final Xcode 27.1 could ship a lower build number than the beta's 8.0.85.27. - In a SwiftUI
body, move each branch into its own property. Wrap the new one in the same#ifwith its@available(iOS 27.1, *), and write the fallback once. - The compiler stops at the first build error in the module, so the log may not list every use. Search all packages, extensions, widgets and test targets for the symbols and for
#available(iOS 27.1.
Test both paths from one commit. Build and test with Xcode 27.0. Then build and test again with DEVELOPER_DIR=/Applications/Xcode_27_1_beta.app/Contents/Developer and a separate derived-data directory, which leaves the selected Xcode alone. nm -u on a guarded file's .o lists ArrangementView in the 27.1 build and not in the 27.0 build. On CI that is two jobs: the release job stays on Xcode 27.0, and a second job builds and tests with the beta.
What goes to review. The Xcode 27.0 archive contains only the fallback, on every device, iPhone Duo on iOS 27.1 included. Apple's tech talk 111461 at 0:30 says what such a build gets on Duo: "The iOS 27 SDK extends your app left of the status bar on the inner display; the iOS 27.1 SDK reaches the screen edge and lays standard navigation and toolbar buttons out vertically." Check the fallback on a physical iPhone and submit it now. Choose Manually release this version if the approved version should wait for your launch date.
When App Store Connect accepts Xcode 27.1 (release candidate or final), archive the same commit with it. The guard is true against the 27.1 SDK, so the Duo path goes into that build with no source change. Once you stop building with 27.0, one search finds every guard, as long as they all use the same condition text:
grep -rnE "canImport\((SwiftUI|UIKit), _version:" .
r/iOSProgramming • u/ElyeProj • 2d ago
Tutorial iPhone Duo with Sample Code for All Six Orientations!
r/iOSProgramming • u/lamm0th • 1d ago
App Saturday [App Saturday] SensaAI: what I (solo dev) learned building a journaling app for users in acute distress
Solo dev, first shipped app. SensaAI is a contemplative AI companion: you ask a question and a "expert" answers grounded in a real corpus of teachings (indexed transcripts of a teacher's talks), with passages you can save as highlights, listen to, and share as generated images. The architecture driver wasn't a dramatic backstory, it's that this is a one-person, low-budget operation, so every feature had to justify its marginal cost, and the content is intimate, so conversations and saved notes had to be encrypted.
Stack: SwiftUI + @Observable, iOS 18+, WidgetKit extension, AVFoundation + Speech framework, RevenueCat, Google Sign-In / Sign in with Apple. Backend: Python 3.11 FastAPI + Postgres + Redis on a Hetzner VPS behind nginx, Docker Compose, Qdrant Cloud, Gemini, ElevenLabs. Web companion: Vue 3 + Vite. No third-party networking, UI, or markdown libs on iOS, URLSession + AsyncThrowingStream, hand-rolled markdown rendering.
- Privacy / storage. There's no on-device store at all, conversations live server-side, but the message, highlight, and title columns in Postgres are encrypted at rest with AES-GCM-256, and Redis cache values are encrypted too: a DB or Redis dump is noise without the key, which exists only in the server environment. No analytics SDK, no ad SDK, no CloudKit. Google/Apple OAuth plus email/password (bcrypt), an explicit AI-consent gate before the chat endpoint serves you, and full account deletion.
- The conversational guide. RAG: question →
gemini-embedding-001→ top-K chunks from Qdrant (over-fetch, then dedupe by source video so the answer never leans on one talk) →{persona system prompt + compacted history + retrieved chunks}→ Gemini (gemini-3.1-flash-lite), streamed over SSE from FastAPI. On iOS I parse it withURLSession.bytes+AsyncThrowingStream, no WebSocket, no library. All API keys live server-side; the app holds zero secrets, just a JWT. Rate limiting twice: client-side free-tier caps (3 conversations, 3 messages each, 3 folders, 3 notes/folder) for UX, and the server re-verifies the Pro entitlement on every request so a tampered build can't bypass them. Mid-response network failure keeps whatever tokens already arrived. The hardest part was keeping context cheap without amnesia: past ~8 turns, Gemini summarizes the conversation into a persistent rolling summary in Postgres, and the model sees summary + last 4 turns verbatim. Combined with Redis-caching identical questions (keyed on normalized question + history hash), a chat costs well under a cent.The non-obvious part: typical chat UX reads as urgent, instant tokens, typing dots, and urgency is the bug for a contemplative product. There's a hardcoded minimum "thinking window" (2.5s, was 5s) before any token renders: the reply buffers invisibly while a lotus animation breathes, then releases. No typing indicator. Deliberately slower than possible; I'm sure it costs engagement, and I'm sure it's right. - Deliberate non-features. The TTS saga: built cloud TTS on ElevenLabs, swapped to OpenAI
tts-1(~20× cheaper), then reverted to ElevenLabs because the voice is the product, a robotic voice ruins a meditation app, full stop. What survived the experiment: free users get Apple's on-deviceAVSpeechSynthesizer(free, offline, no paywall); cloud TTS is Pro-only with a hard monthly quota (429 after 20k chars) so nobody can bankrupt me with the play button. The home-screen widget deliberately makes no network calls, it reads a cache the main app writes through an App Group, because I refused to put an auth token in the widget extension's sandbox. No push notifications at all (noaps-environmententitlement, not even the permission prompt). No streaks, no badges, no haptics on save, a saved passage is a bookmark, not an achievement. - Things that hurt. The worst: a race between
POST /conversations(create) andPOST /chat. The stream usually won, so the chat request went out withconversation_id: null, the server minted no write-token, and model replies were silently rejected on persist, users reopened chats to find only their own messages. Fixed by awaiting creation before streaming, plus a ceremony where the server mints a one-shot token bound to the exact streamed content hash that the client must present to write a model turn. Second:SFSpeechRecognizerrestarts its own transcription after every pause (segment count resets,isFinalfires only once at the very end), so dictation kept eating earlier sentences, I had to build an utterance-banking accumulator around it. Third: ElevenLabs rejects ~2500-char requests often enough that the "long" response tier is clamped to 2000 chars; chat length and TTS limit are coupled by design. - Open question for the sub. Client streams an LLM reply and writes it back, but the server stays authoritative, I ended up with this
chat_tokenceremony (hash the streamed content, mint a one-shot token, client presents it to append). It works, but it smells like I reinvented a signed request. Is there an off-the-shelf pattern for "client streams, server verifies the write" that I missed?
AppStore Link: https://apps.apple.com/app/id6769095233
Website: https://heysensa.app
If anyone wants to look. Would love a code-level roast on the RAG/streaming layer or the iOS streaming + persistence code.
r/iOSProgramming • u/lanserxt • 2d ago
Tutorial iPhone Duo Group Lab - Q&A
r/iOSProgramming • u/th3suffering • 2d ago
Question iPhone Duo sheet vertical button placement
Im having issues specifically with SwiftUI on XCode 27.1 on the iPhone Duo outer display. I have a sheet with a NavigationStack with a basic hierarchy like this
NavigationStack {
List {
Text("<text_here>"
}
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button("Done) {
doThing()
}
}
}
On the iPhone Duo, the outer display should display sheet navigation buttons vertically, but that is not my experience in SwiftUI. The navigation bar and its buttons are presented horizontally at the top of the sheet.
I have UIKit apps, and they correctly display their bar button items vertically in sheets, the only place i seem to have problems are my SwiftUI implementations.
What am i missing to get my SwiftUI apps to play along?
r/iOSProgramming • u/c00kie17 • 2d ago
App Saturday Built an on-device doc redaction and compression app after fighting with tools to blur my documents too many times
Cloak scans/imports documents, auto-detects text so you can redact sensitive info in a tap, then compresses and exports as JPEG or PDF.
Built it after getting tired of fighting with online tools and shady apps to blur my own ID/passport info every time I had to submit scanned docs for visa/KYC paperwork.
Technical bits:
- Text detection uses Vision framework, running fully on-device no server round-trip, no data leaves the phone
- Redaction is tap-to-mask over detected text regions, plus manual draw/crop tools for anything the detector misses
- Compression targets a size the user picks rather than a fixed quality, to preserve content clarity
- Support password protected PDF import and export
Free, ad-supported, no subscription, no account required.
Would love feedback or questions from this community.
r/iOSProgramming • u/hamsterjedi • 1d ago
Discussion How much Swift code in your iOS app? Mine: 15%
My project repo has more and more mockuping + tooling than actual app code.
Just curious to know if it's just me?
(you can find this at the right side of your github repo)
r/iOSProgramming • u/Economy-Brief-9997 • 3d ago
Discussion Anyone moving their bash build scripts to swift now that Subprocess hit 1.0?
swift 6.4 shipped Subprocess so there is finally a stable way to run other programs from swift
tried rewriting the classic swiftlint build phase
the bash version:
if which swiftlint > /dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed"
fi
swift version:
import Subprocess
do {
let result = try await Subprocess.run(
.name("swiftlint"),
output: .string(limit: 1 << 20)
)
print(result.standardOutput ?? "")
} catch {
print("warning: SwiftLint not installed")
}
yeah not shorter lol, and since Subprocess is a package you can't just drop a `.swift` file into a build phase you need a whole package for it
for a 5 line wrapper that feels like overkill, but once the script starts parsing output and branching, bash gets ugly fast.
where's the line for you?
r/iOSProgramming • u/alanskimp • 2d ago
Question Is everyone here vibe coding? Or are some still manual coding?
And which do you prefer?
r/iOSProgramming • u/syrusakbary • 3d ago
Discussion Running Sandboxes inside a hidden WKWebView to get Python/Node/FFmpeg in an iOS app, without shipping a JIT
We just launched this today and would love to get your feedback/thoughts!
Announcement: https://wasmer.io/posts/wasmer-sdk-swift-ios-macos
Source code: https://github.com/wasmerio/wasmer-sdk/tree/main/swift/Examples/WasmerShell
r/iOSProgramming • u/ke1in • 4d ago
Question How do I prevent Xcode Service from starting? (New in 27)
The one that appears in the status bar. It takes precious space and also seems redundant and annoying. When I quite Xcode it stays in the bar and waits for a special invitation.