All skills
johnrogers avatar

/ios-26-platform

@d62eb71

Use when implementing iOS 26 features (Liquid Glass, new SwiftUI APIs, WebView, Chart3D), deploying iOS 26+ apps, or supporting backward compatibility with iOS 17/18.

Use this Skill: https://skilld.dev/gh/johnrogers/claude-swift-engineering/ios-26-platform

This session only. Nothing lands on disk.

referencesbackward-compat.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Backward Compatibility

iOS 17/18 + iOS 26

UIDesignRequiresCompatibility Key

Opt Out of Liquid Glass (Temporarily)

<!-- Info.plist -->
<key>UIDesignRequiresCompatibility</key>
<true/>

Effect:

  • App built with iOS 26 SDK
  • Appearance matches iOS 18 and earlier
  • Liquid Glass effects disabled
  • Previous blur/material styles used

Migration Strategy

  1. Ship with UIDesignRequiresCompatibility enabled
  2. Audit interface changes in separate build
  3. Update interface incrementally
  4. Remove key when ready for Liquid Glass

@available Patterns

Basic Check

if #available(iOS 26, *) {
    content
        .glassEffect()
} else {
    content
        .background(.ultraThinMaterial)
}

View Modifier Pattern

extension View {
    @ViewBuilder
    func adaptiveGlass() -> some View {
        if #available(iOS 26, *) {
            self.glassEffect()
        } else {
            self.background(.regularMaterial)
        }
    }
}

// Usage
Button("Action") { }
    .adaptiveGlass()

Toolbar Spacer Fallback

extension View {
    @ViewBuilder
    func adaptiveToolbar() -> some View {
        if #available(iOS 26, *) {
            self.toolbar {
                ToolbarItemGroup(placement: .topBarTrailing) {
                    Button("Up") { }
                    Button("Down") { }
                    Spacer(.fixed) // iOS 26 feature
                    Button("Settings") { }
                }
            }
        } else {
            self.toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Up") { }
                }
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Down") { }
                }
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Settings") { }
                }
            }
        }
    }
}

WebView Fallback

struct ArticleView: View {
    let url: URL

    var body: some View {
        if #available(iOS 26, *) {
            WebView(url: url)
        } else {
            WebViewRepresentable(url: url) // UIViewRepresentable wrapper
        }
    }
}

// iOS 17/18 fallback
struct WebViewRepresentable: UIViewRepresentable {
    let url: URL

    func makeUIView(context: Context) -> WKWebView {
        WKWebView()
    }

    func updateUIView(_ webView: WKWebView, context: Context) {
        webView.load(URLRequest(url: url))
    }
}

@Animatable Fallback

#if swift(>=6.0)
@Animatable
struct ModernShape: Shape {
    var progress: Double

    @AnimatableIgnored
    var style: ShapeStyle
}
#else
struct LegacyShape: Shape {
    var progress: Double

    var animatableData: Double {
        get { progress }
        set { progress = newValue }
    }
}
#endif

Search Tab Role Fallback

TabView {
    if #available(iOS 26, *) {
        SearchView()
            .tabItem { Label("Search", systemImage: "magnifyingglass") }
            .tabRole(.search)
    } else {
        SearchView()
            .tabItem { Label("Search", systemImage: "magnifyingglass") }
    }
}

AttributedString TextEditor

struct CommentEditor: View {
    @State private var richText = AttributedString("Comment")
    @State private var plainText = "Comment"

    var body: some View {
        if #available(iOS 26, *) {
            TextEditor(text: $richText) // Rich text support
        } else {
            TextEditor(text: $plainText) // Plain text only
        }
    }
}

Migration from Previous Materials

From UIBlurEffect

// Before (UIKit)
let blurEffect = UIBlurEffect(style: .systemMaterial)
let blurView = UIVisualEffectView(effect: blurEffect)

// After (SwiftUI with fallback)
extension View {
    @ViewBuilder
    func adaptiveMaterial() -> some View {
        if #available(iOS 26, *) {
            self.glassEffect()
        } else {
            self.background(.regularMaterial)
        }
    }
}

From Custom Materials

Keep custom materials when:

  • Backward compatibility with iOS < 26 required
  • Specific artistic effect not achievable with glass
  • Non-standard UI paradigm

Testing Checklist

iOS 26 Tests

  • Liquid Glass appearance correct
  • Scroll edge effects working
  • Toolbar grouping renders properly
  • Search placement is platform-appropriate
  • Accessibility settings respected

iOS 17/18 Tests

  • Fallback materials render correctly
  • No runtime crashes from @available checks
  • Functionality preserved without glass
  • Layout doesn't break

Deprecated APIs

iPadOS 26

<!-- Remove entirely — deprecated in iPadOS 26 -->
<key>UIRequiresFullscreen</key>

Apps must support resizable windows on iPad.

SwiftUI Updates

// Old (deprecated)
.onChange(of: value, perform: { newValue in })

// New (iOS 17+)
.onChange(of: value) { oldValue, newValue in }

Performance Considerations

When supporting multiple iOS versions:

  • Use @available checks at view level, not inside body
  • Prefer conditional view modifiers over entire view branches
  • Test performance on oldest supported version
  • Profile with Instruments on both old and new iOS

Source: SKILL.md on GitHub

1 warning16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The analyzed skill consists purely of markdown documentation and reference guides for implementing speculative iOS 26 platform features. No code execution, external downloads, prompt injections, or other security threats were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    6/6 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at d62eb71. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 9 months ago

README badge

README badge for johnrogers/claude-swift-engineering/ios-26-platform