| name | xcode-27-maui-upgrade |
|---|---|
| description | Upgrade .NET MAUI iOS and Mac Catalyst apps for Xcode 27 and Apple's scene-based lifecycle. Use when migrating Apple-platform builds, investigating NoSceneLifecycleAdoption launch crashes, or aligning .NET workloads with Xcode. |
| license | MIT |
Use this skill to migrate existing .NET MAUI apps to Apple's scene-based UIKit lifecycle and verify their Xcode/.NET build configuration. If the user asks for an explanation only, diagnose and explain without editing; otherwise, implement the migration.
- Read the repository's applicable instructions and inspect the app's Apple target frameworks, MAUI package/workload versions,
AppDelegate, entry point,Info.plistfiles, and CI workflows. - Inspect the crash log before changing lifecycle code. A launch trap in
___UIApplicationEvaluateRuntimeIssueForNoSceneLifecycleAdoption_block_invokeor aNoSceneLifecycleAdoptionmessage indicates that the app has not adopted scene lifecycle. Do not apply this migration to unrelated crashes. - Check whether each iOS and Mac Catalyst app head already has both a registered
SceneDelegateand aUIApplicationSceneManifest. A manifest without its delegate, or a delegate whose registered name differs from the manifest, is incomplete.
- Check
dotnet --info,dotnet workload --version,dotnet workload list, andxcodebuild -version. Usedotnet workload --versionto identify the workload set selected by the installed SDK;dotnet workload listshows the installed workloads. - When evaluating an upgrade, run
dotnet workload search version --format json --take 1to discover the latest released workload-set candidate for the SDK feature band. This reports candidates, not the active workload set. To inspect a specific candidate's manifest versions, rundotnet workload search version <workload-version>. For the active set and each candidate, inspectdata/microsoft.net.workloads.workloadset.jsonand find the iOS and Mac Catalyst manifest versions. Read each manifest'sdata/WorkloadDependencies.jsonand checkxcode.versionandxcode.recommendedVersion. The manifests are available in the installed SDK manifest directory or as NuGet packages underhttps://api.nuget.org/v3-flatcontainer/. - Do not infer compatibility from the .NET SDK major version alone or hardcode a version from old guidance. If the installed and candidate workload sets differ, use the set that CI will restore and report the exact Xcode range it requires.
- Keep the .NET SDK, workload set, and Xcode version compatible. If pinning for reproducibility, pin the complete pair and ensure CI restores the same workload set; do not pin only Xcode or only the SDK.
- Do not treat downgrading Xcode as the lifecycle fix. A downgrade does not add scene configuration and is not a durable way to support newer Apple operating systems.
For every Apple app head that builds with the affected SDK, add a platform-specific SceneDelegate.cs under both Platforms/iOS and Platforms/MacCatalyst as applicable. Use the app's existing namespace:
using Foundation;
namespace MyApp;
[Register("SceneDelegate")]
public class SceneDelegate : MauiUISceneDelegate
{
}
Add this scene manifest inside the root <dict> in each corresponding Info.plist:
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>__MAUI_DEFAULT_SCENE_CONFIGURATION__</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
Keep __MAUI_DEFAULT_SCENE_CONFIGURATION__ unchanged; it must match MAUI's framework configuration. Keep the SceneDelegate registration name and manifest class name identical. Leave multiple-scene support disabled unless the app intentionally supports multiple windows.
Keep the existing AppDelegate and entry point unless the app has a separately justified lifecycle refactor. MAUI's MauiUISceneDelegate creates the MAUI window and forwards scene lifecycle events; do not add duplicate window creation or manual lifecycle forwarding. If MauiUISceneDelegate is unavailable, update to a MAUI version that supports it rather than replacing it with a bare UIKit delegate.
The scene migration does not require network entitlements. Do not add com.apple.security.network.server; handle any entitlement review as a separate capability audit.
Keep workflow runner images and Xcode selectors consistent with the supported workload range. Run dotnet workload restore after selecting the SDK, then build each affected target using the repository's existing release and signing settings. Example target builds:
dotnet build path/to/App.csproj -c Debug -f net10.0-ios \
-p:RuntimeIdentifier=iossimulator-arm64
dotnet build path/to/App.csproj -c Debug -f net10.0-maccatalyst \
-p:RuntimeIdentifier=maccatalyst-arm64
Validate the source plists with plutil -lint. Inspect the generated app bundle's Info.plist to confirm the manifest, configuration name, and delegate class are present in the packaged app. Preserve the app's existing linker, AOT, and signing settings when validating Release builds.
When a simulator or device running the affected Apple OS is available, launch the built app and confirm it reaches its first MAUI window. A successful build alone does not verify startup. If that OS is unavailable, state that runtime launch remains unverified rather than claiming the crash is resolved.