11 min read

Issue #91: Your screenshot upload script is deprecated, Trust Insights for scam calls, and Xcode's translation skills outside Xcode

Apple deprecated the App Store Connect API endpoints most screenshot upload scripts use. Plus iOS 27’s Trust Insights for spotting scam coaching, Xcode 27’s translation skills in your own agent, three Swift Evolution decisions, and iPhone Duo size classes.
Issue #91: Your screenshot upload script is deprecated, Trust Insights for scam calls, and Xcode's translation skills outside Xcode

Apple didn't ship a new beta last week, but it did deprecate the App Store Connect API endpoints most screenshot upload scripts are built on. This issue covers that migration, a new iOS 27 framework for spotting users who are being coached through a scam, how to run Xcode 27's translation skills from your own agent, three Swift Evolution decisions, and a handful of layout details for iOS 27 and the iPhone Duo, which ships in 10 days. 🛠️📸

App Store Connect API 4.5.1: Screenshot Sets Are Deprecated (API 4.5.1)

If your release pipeline uploads screenshots through the App Store Connect API, read this one first. Version 4.5.1 (October 6) deprecates the App Screenshot Sets, App Screenshots, App Preview Sets, and App Previews resources, plus the screenshot and video clip resources for in-app events. Their replacement is the App Asset Library, the same library that showed up in App Store Connect last week.

The new model is upload once, then place. You create a library image or video, then create a placement that attaches it to an App Store version localization, a custom product page, an in-app event, or a product page experiment treatment. A separate request sets the order of placements. So one screenshot can now show up on your main page and three custom product pages without four uploads.

Two more additions are worth knowing. List app asset library ref data returns the supported placement types, dimensions, and limits, so your script can stop hard-coding screenshot sizes. And the new IPHONE_DUO display class is how you target Duo screenshots, which become mandatory in April.

The old endpoints still work today. If you maintain your own upload tooling, or depend on a third-party tool that wraps these endpoints, this is the time to check its plans. Apple published a migration guide alongside the release notes.

App Store Connect API 4.5.1 release notes | Apple Developer Documentation
Update your server-side code to use new features, and test your code against API changes.
App Store Connect API 4.5.1 release notes Manage your app's marketing and product media from one place with the App Asset Library. Apple Developer Documentation
Migrating to the App Asset Library Move an existing screenshot and app preview integration to library images, videos, and placements. Apple Developer Documentation

Trust Insights: Is Your User Being Coached? (iOS 27)

A common scam goes like this: someone on the phone talks the user through sending money or changing an account setting, one screen at a time. iOS 27's Trust Insights framework gives your app a signal for that situation. Anton Gubarenko walked through the first insight it offers, IsLikelyBeingCoachedInsight, which returns .unknown, .medium, or .high.

You build a request, describe the kind of operation the user is about to do, and ask for an evaluation:

let request = IsLikelyBeingCoachedInsight.request(
    schema: .version1,
    modelVersion: .current
)

var context = InsightEvaluator.InsightContext(
    operationCategory: .communication,
    requestedEvaluations: request
)

let evaluation = try await evaluator.requestEvaluation(
    context: context
)
let insight = evaluation.insight

Setup has some sharp edges. You need the Trust Insights capability, and the com.apple.developer.trustinsights.base entitlement has to be an array containing InsightSuiteStandard, or the app crashes. The user has to authorize access first. And evaluations can take several seconds because part of the work happens on Apple's servers, so request one as the user enters the flow, well before they reach the confirm button.

Anton is clear about what the result means: "Trust Insights doesn't tell us whether a person is definitely being scammed." Treat .high as a reason to add friction, like a cooling-off delay or an extra confirmation, and keep your own risk checks in place.

iOS 27: Trust Insights Framework
Analyze transactions for signs of coercive activity while protecting people’s privacy
iOS 27: Trust Insights Framework "Trust Insights should complement, not replace, your existing risk engine." Anton's Substack · Anton Gubarenko

Xcode 27: Run the Translation Skills From Your Own Agent (Xcode 27)

Xcode 27 can translate String Catalogs for you, but only inside Xcode with the models it supports. The guidance behind that feature lives in Apple's localization skills: how to gather context for a string, check project terminology, handle plural variations, and 56 per-language style guides. Max Seelemann found the catch when using them from another agent. The Xcode MCP server's StringCatalogRead tool expects the translation skill to be loaded, but the MCP server doesn't serve that skill. In his words, "You're stuck: the tool won't run, and the skill can't be found."

His fix is a command that Xcode 27 already ships. It prints the path to Apple's agent plugin, skills included, in the format your agent expects:

# Load Apple's skills and the Xcode MCP server as a Claude Code plugin
claude --plugin-dir $(xcrun agent plugin path --plugin-format claude)

xcrun agent plugin path supports Claude, Codex, and Gemini formats. If you'd rather not load everything, point your agent's instructions file at translation/SKILL.md for specific keys, or translation-coordinator/SKILL.md for whole-language jobs, inside that plugin's skills/ folder. Even if you translate by hand, the reference files in skills/translation/references are plain Markdown on pluralization, tone, and inclusive language, and they're worth reading.

Using Xcode 27’s localization skills over MCP
Xcode 27 ships with a new localization feature: automatic translation at the press of a button. Open any String Catalog, click “Generate Translations”, and watch your agent take it away… That is, if you have one of the supported agents installed. And even then, it only works inside Xcode. That
Using Xcode 27's localization skills over MCP How to load Apple's translation skills in your own agent so the String Catalog MCP tools work. macguru.dev · Max Seelemann

Swift Evolution: Three Decisions on October 8 (accepted, not yet shipped)

Three proposals came back accepted on the same day.

SE-0553: Task Identity. Tasks get a stable identity you can compare, through Task.currentID and an id on a Task handle. The main use is logging and tracing: tag every log line with the task that wrote it, so you can follow one request through concurrent code. It also covers per-task state in lock-free structures and custom executors, where using a task's memory address is unsafe because the runtime can reuse it. Task won't conform to Identifiable, on purpose, to discourage using tasks as dictionary keys.

SE-0545: SwiftPM build performance debugging. SwiftPM will be able to write per-task build traces, so you can see which tasks in a build cost the most and where your package graph is blocking parallelism.

SE-0547: SwiftPM compilation caching. Accepted with one change: the remote caching options were removed after review feedback, leaving local caching.

Not part of that batch, but the September Swift digest also lists SE-0540 as accepted with modifications. It adds defaultSwiftSettings to Package, so you stop copying the same upcoming-feature flags into every target:

let package = Package(
    // ...
    targets: [
        .target(name: "MyPackage"),
        .testTarget(
            name: "MyPackageTests",
            dependencies: ["MyPackage"]
        ),
    ],
    defaultSwiftSettings: [
        .enableUpcomingFeature("ApproachableConcurrency"),
    ]
)

A target that declares its own swiftSettings opts out of the defaults unless it includes .inherited() in its list.

SE-0553: Task Identity
Hi everyone. The review of SE-0553: Task Identity begins now and runs through October 7th, 2026. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager by DM. When contacting the review manager directly, please put "SE-0553" in the subject line. What goes into a review? The goal of the review process is to improve the proposal under review t…
SE-0553: Task Identity A stable identity for tasks, for logging, tracing, and per-task state. Swift Forums

SwiftUI: Concentric Corners You Can Do Math With (iOS 27)

ConcentricRectangle draws a shape whose corners match its container or the screen. iOS 27 adds concentricCornerRadii on GeometryProxy, which gives you the radii themselves so you can build your own shape. Sarun Wongpatcharapakorn explains it:

GeometryReader { proxy in
    let radii = proxy.concentricCornerRadii ?? RectangleCornerRadii()

    UnevenRoundedRectangle(cornerRadii: radii)
        .fill(.pink)
}
.frame(width: 220, height: 160)

The value is optional, so fall back to zero radii and the shape stays square. A corner near a screen corner gets the screen's radius minus the gap, and corners far from any screen corner get 0. To match a custom container instead of the screen, set containerShape(_:) on it, and use concentricCornerRadii(in:) when you need radii for a rectangle other than the proxy's own. On iOS 26, stick with ConcentricRectangle.

Get concentric corner radii from GeometryReader in iOS 27 | Sarunw
iOS 27 adds concentricCornerRadii to GeometryProxy. It tells you the corner radii a view needs to match the corners of its container or the screen.
Get concentric corner radii from GeometryReader in iOS 27 "It tells you the corner radii a view needs to match the corners of its container or the screen." Sarunw · Sarun Wongpatcharapakorn

SwiftUI: Which Toolbar Buttons Share a Glass Capsule (iOS 26+)

If two of your toolbar buttons merged into one Liquid Glass capsule and you didn't ask for it, here's the rule from Sarun: "items that are next to each other on the same edge share one glass capsule." That's true whether they're separate ToolbarItems or a group, and whether they're icons, text, or custom views. Prominent buttons (.buttonStyle(.glassProminent) or role: .confirm) always get their own capsule. Note that .confirmationAction placement alone isn't enough.

To split a group, drop a ToolbarSpacer between the items:

.toolbar {
    ToolbarItem(placement: .topBarTrailing) {
        Button("Share", systemImage: "square.and.arrow.up") { }
    }
    ToolbarItem(placement: .topBarTrailing) {
        Button("Favorite", systemImage: "heart") { }
    }

    ToolbarSpacer(.fixed, placement: .topBarTrailing)

    ToolbarItem(placement: .topBarTrailing) {
        Button("More", systemImage: "ellipsis") { }
    }
}

.fixed adds a small gap. .flexible pushes items apart in the bottom bar, but in the navigation bar it looks the same as .fixed. To take one item out of the glass entirely, use .sharedBackgroundVisibility(.hidden) on it.

When toolbar items share a glass background in iOS 26 | Sarunw
In iOS 26, toolbar items next to each other merge into one Liquid Glass capsule. Learn which items merge, which ones stand alone, and how to split them with ToolbarSpacer.
When toolbar items share a glass background in iOS 26 Which adjacent toolbar items merge into one Liquid Glass capsule, and how to separate them. Sarunw · Sarun Wongpatcharapakorn

iPhone Duo: Size Classes Won't Tell You About the Fold (iOS 27.1)

Sarun measured the size classes and point sizes for every Duo pose:

Folded, portrait     compact x regular    466 x 678
Folded, landscape    compact x compact    678 x 466
Half-open, portrait  regular x regular    669 x 951
Half-open, landscape regular x regular    951 x 669
Open, portrait       regular x regular    669 x 951
Open, landscape      regular x regular    951 x 669

Half-open and open are identical, so as he puts it, "If you need to know about the fold, size classes won't tell you." Use the hinge and reserved region APIs for that. And inside an ArrangementView, each pane gets its own size classes, so a pane can read compact in both directions while the screen around it is regular.

If you use ArrangementView, his follow-up covers splitArrangementLayoutRatio, which sets each view's share of the split. The default is half and half:

ArrangementView {
    FirstView()
        .splitArrangementLayoutRatio(idealHorizontal: 1 / 3)
} secondary: {
    SecondaryView()
}

idealHorizontal applies when the views sit side by side and idealVertical when they're stacked. On a half-open Duo the split sits on the hinge and the ratio is ignored, and content that needs more room than its share spills out, because "the view doesn't grow to fit."

Size classes on iPhone Duo | Sarunw
The horizontal and vertical size classes, and the display size in points, for every iPhone Duo pose and orientation.
Size classes on iPhone Duo Horizontal and vertical size classes and point sizes for each iPhone Duo pose and orientation. Sarunw · Sarun Wongpatcharapakorn
Set the split size of ArrangementView with splitArrangementLayoutRatio Control each view's share of the screen in ArrangementView on iOS 27.1. Sarunw · Sarun Wongpatcharapakorn

Accessibility: Switch Layouts at Large Text Sizes Without Losing State (iOS 16+)

A row with a title on the left and a date on the right looks fine until someone uses an accessibility text size and the title wraps to one word per line. Natascha Fadeeva switches to a vertical stack at those sizes, wrapped in AnyLayout so the child views keep their identity and state when the layout changes:

@Environment(\.dynamicTypeSize) private var dynamicTypeSize

private var taskLayout: AnyLayout {
    if dynamicTypeSize.isAccessibilitySize {
        AnyLayout(VStackLayout(alignment: .leading, spacing: 8))
    } else {
        AnyLayout(HStackLayout(alignment: .firstTextBaseline, spacing: 12))
    }
}

Then use taskLayout { ... } in place of an HStack. If the decision really depends on available width rather than text size, reach for ViewThatFits instead. And add a preview with .environment(\.dynamicTypeSize, .accessibility3) so you see the big-text version every time you open the file.

Adapting SwiftUI layouts for large Dynamic Type sizes
Learn how to adapt SwiftUI layouts for larger Dynamic Type sizes using the dynamic type environment and AnyLayout.
Adapting SwiftUI layouts for large Dynamic Type sizes "Supporting Dynamic Type doesn't end when text grows with the user's preferred size." tanaschita.com · Natascha Fadeeva

Quick Hits

Matt Massicotte revisits split isolation, where only some methods of a type are @MainActor, and concludes it's usually a design to avoid: "Isolation is about protecting data, not controlling where things execute." Point-Free started a series on advanced techniques in Swift macros, showing how a macro can surface type errors on the right line instead of inside generated code. Xu Yang asks whether UIKit is easier for agents than SwiftUI in AI-Friendly Frameworks, and argues SwiftUI needs verification tools at its own level of abstraction. And his Swift Weekly #157 worries that cheap AI cloning will push indie developers to stop building in public.


What to Do This Week

Find every place your pipeline calls the screenshot or app preview endpoints, and read Apple's migration guide to the App Asset Library. If your app handles payments, transfers, or account changes, try IsLikelyBeingCoachedInsight on one sensitive flow and request it early. If you localize with an agent, run xcrun agent plugin path and load Apple's translation skills. Search for places you branch on size class to guess the Duo's pose, and switch them to the hinge APIs. Add an accessibility-size preview to your busiest list row. And with the Duo out on the 23rd, make sure your update has already cleared review.

✌️ Alright, that's it for today! Let's spread the good code vibes ✨🧘☀️