diff --git a/docs/core/deploying/media/native-aot-ios-like-platforms/xcode-add-framework-reference.png b/docs/core/deploying/media/native-aot-ios-like-platforms/xcode-add-framework-reference.png
new file mode 100644
index 0000000000000..30d921774e616
Binary files /dev/null and b/docs/core/deploying/media/native-aot-ios-like-platforms/xcode-add-framework-reference.png differ
diff --git a/docs/core/deploying/media/native-aot-ios-like-platforms/xcode-add-framework-search-path.png b/docs/core/deploying/media/native-aot-ios-like-platforms/xcode-add-framework-search-path.png
new file mode 100644
index 0000000000000..a4b97cef7d554
Binary files /dev/null and b/docs/core/deploying/media/native-aot-ios-like-platforms/xcode-add-framework-search-path.png differ
diff --git a/docs/core/deploying/native-aot/index.md b/docs/core/deploying/native-aot/index.md
index db1d86228e100..be77453107eb4 100644
--- a/docs/core/deploying/native-aot/index.md
+++ b/docs/core/deploying/native-aot/index.md
@@ -152,11 +152,11 @@ The following table shows supported compilation targets.
| Windows | x64, Arm64 | |
| Linux | x64, Arm64 | |
| macOS | x64, Arm64 | |
-| iOS | Arm64 | Experimental support |
-| iOSSimulator | x64, Arm64 | Experimental support |
-| tvOS | Arm64 | Experimental support |
-| tvOSSimulator | x64, Arm64 | Experimental support |
-| MacCatalyst | x64, Arm64 | Experimental support |
+| [iOS](./ios-like-platforms/index.md) | Arm64 | Experimental support |
+| [iOSSimulator](./ios-like-platforms/index.md) | x64, Arm64 | Experimental support |
+| [tvOS](./ios-like-platforms/index.md) | Arm64 | Experimental support |
+| [tvOSSimulator](./ios-like-platforms/index.md) | x64, Arm64 | Experimental support |
+| [MacCatalyst](./ios-like-platforms/index.md) | x64, Arm64 | Experimental support |
| Android | x64, Arm64 | Experimental, no built-in Java interop |
### [.NET 9+](#tab/net9plus)
@@ -166,11 +166,13 @@ The following table shows supported compilation targets.
| Windows | x64, Arm64, x86 | |
| Linux | x64, Arm64, Arm | |
| macOS | x64, Arm64 | |
-| iOS | Arm64 | |
-| iOSSimulator | x64, Arm64 | |
-| tvOS | Arm64 | |
-| tvOSSimulator | x64, Arm64 | |
-| MacCatalyst | x64, Arm64 | |
+| [iOS](./ios-like-platforms/index.md) | Arm64 | |
+| [iOSSimulator](./ios-like-platforms/index.md) | x64, Arm64 | |
+| [tvOS](./ios-like-platforms/index.md) | Arm64 | |
+| [tvOSSimulator](./ios-like-platforms/index.md) | x64, Arm64 | |
+| [MacCatalyst](./ios-like-platforms/index.md) | x64, Arm64 | |
| Android | x64, Arm64, Arm | Experimental, no built-in Java interop |
---
+
+For more information about how specific platform is supported with Native AOT, follow the link from the table.
diff --git a/docs/core/deploying/native-aot/ios-like-platforms/creating-and-consuming-custom-frameworks.md b/docs/core/deploying/native-aot/ios-like-platforms/creating-and-consuming-custom-frameworks.md
new file mode 100644
index 0000000000000..5d0325a74022f
--- /dev/null
+++ b/docs/core/deploying/native-aot/ios-like-platforms/creating-and-consuming-custom-frameworks.md
@@ -0,0 +1,245 @@
+---
+title: Create and consume custom frameworks for iOS-like platforms
+description: How to create and consume custom frameworks with Native AOT for iOS-like platforms
+author: ivanpovazan
+ms.author: ivanpovazan
+ms.date: 11/21/2024
+---
+
+# Create and consume custom frameworks for iOS-like platforms
+
+Starting from .NET 9, Native AOT supports publishing .NET class libraries that don't depend on iOS workloads for iOS-like platforms.
+This support enables you to create self-contained native libraries that can be consumed from iOS, Mac Catalyst, and tvOS applications.
+
+> [!IMPORTANT]
+> This approach does not come with the built-in Objective-C interoperability support and additional code adaptations might be required (such as marshalling reference type arguments) to achieve interoperability.
+
+## Build shared libraries
+
+This section describes steps to create a simple .NET Class Library project with NativeAOT support and produce a native library for iOS-like platforms from it.
+
+1. Download .NET 9 SDK
+2. Create a class library project
+
+ ```bash
+ dotnet new classlib -n "MyNativeAOTLibrary"
+ ```
+
+3. Add the following properties into the project file `MyNativeAOTLibrary.csproj`
+
+ ```xml
+ true
+ true
+ ```
+
+4. Edit the `MyNativeAOTLibrary/Class1.cs` source code to expose a managed method so that it can be referenced from the native code as `aotsample_add`. For example:
+
+ ```cs
+ using System.Runtime.InteropServices;
+ namespace NaotLib;
+
+ public class Class1
+ {
+ [UnmanagedCallersOnly(EntryPoint = "aotsample_add")]
+ public static int Add(int a, int b)
+ {
+ return a + b;
+ }
+ }
+ ```
+
+5. Publish the class library and target the desired iOS-like platform by specifying the appropriate runtime identifier (referenced below as ``):
+
+ ```bash
+ dotnet publish -r MyNativeAOTLibrary/MyNativeAOTLibrary.csproj
+ ```
+
+Successful completion of the previous step produces a pair of files: a shared library `MyNativeAOTLibrary.dylib` and its debug symbols `MyNativeAOTLibrary.dylib.dSYM`, which are located at: `MyNativeAOTLibrary/bin/Release/net9.0//publish/`.
+
+> [!NOTE]
+> For creating universal frameworks, it is required to publish the class library for both `Arm64` and `x64` architectures for a given platform.
+> This means that you need to repeat step 5 with a different runtime identifier.
+> For example, you'd publish the class library with both `maccatalyst-arm64` and `maccatalyst-x64` runtime identifiers as a prerequisite for [Packaging the shared library into a custom MacCatalyst universal framework](#package-the-shared-library-into-a-custom-maccatalyst-universal-framework).
+
+## Create and consume a custom framework
+
+Apple imposes a requirement that shared libraries (.dylibs) need to be packaged into frameworks in order to be consumed from applications.
+
+This section describes all required steps to achieve this and a simple scenario of a iOS/MacCatalyst application consuming a shared NativeAOT library/framework.
+
+> [!NOTE]
+> The described steps are just for demonstration purposes. The actual requirements might differ depending on the exact use case.
+
+### Package the shared library into custom iOS framework
+
+1. Create a framework folder:
+
+ ```bash
+ mkdir MyNativeAOTLibrary.framework
+ ```
+
+2. Adjust load commands:
+
+ - `LC_RPATH` load command
+
+ ```bash
+ install_name_tool -rpath @executable_path @executable_path/Frameworks MyNativeAOTLibrary/bin/Release/net9.0/ios-arm64/publish/MyNativeAOTLibrary.dylib
+ ```
+
+ - `LC_ID_DYLIB` load command
+
+ ```bash
+ install_name_tool -id @rpath/MyNativeAOTLibrary.framework/MyNativeAOTLibrary MyNativeAOTLibrary/bin/Release/net9.0/ios-arm64/publish/MyNativeAOTLibrary.dylib
+ ```
+
+3. Manually package the binary into a universal file:
+
+ ```bash
+ lipo -create MyNativeAOTLibrary/bin/Release/net9.0/ios-arm64/publish/MyNativeAOTLibrary.dylib -output MyNativeAOTLibrary.framework/MyNativeAOTLibrary
+ ```
+
+4. Add a property list file to your framework:
+
+ - Create a `Info.plist` file
+
+ ```bash
+ touch MyNativeAOTLibrary.framework/Info.plist
+ ```
+
+ - Add the contents from the [appendix](#appendix-infoplist-contents) into the created `Info.plist` file
+
+After the final step, the framework structure should look like this:
+
+```
+MyNativeAOTLibrary.framework
+ |_ MyNativeAOTLibrary
+ |_ Info.plist
+```
+
+### Package the shared library into a custom MacCatalyst universal framework
+
+Universal frameworks require binaries for both `Arm64` and `x64` architecture.
+For this reason, you must publish native libraries targeting both of the following RIDs beforehand: `maccatalyst-arm64` and `maccatalyst-x64`.
+
+1. Create a framework folder structure:
+
+ ```bash
+ mkdir -p MyNativeAOTLibrary.framework/Versions/A/Resources
+ ln -sfh Versions/Current/MyNativeAOTLibrary MyNativeAOTLibrary.framework/MyNativeAOTLibrary
+ ln -sfh Versions/Current/Resources MyNativeAOTLibrary.framework/Resources
+ ln -sfh A MyNativeAOTLibrary.framework/Versions/Current
+ ```
+
+2. Adjust load commands:
+
+ - `LC_RPATH` load command
+
+ ```bash
+ install_name_tool -rpath @executable_path @executable_path/../Frameworks MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-arm64/publish/MyNativeAOTLibrary.dylib
+ install_name_tool -rpath @executable_path @executable_path/../Frameworks MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-x64/publish/MyNativeAOTLibrary.dylib
+ ```
+
+ - `LC_ID_DYLIB` load command
+
+ ```bash
+ install_name_tool -id @rpath/MyNativeAOTLibrary.framework/Versions/A/MyNativeAOTLibrary MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-arm64/publish/MyNativeAOTLibrary.dylib
+ install_name_tool -id @rpath/MyNativeAOTLibrary.framework/Versions/A/MyNativeAOTLibrary MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-x64/publish/MyNativeAOTLibrary.dylib
+ ```
+
+3. Manually package the binary into a universal file:
+
+ ```bash
+ lipo -create MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-arm64/publish/MyNativeAOTLibrary.dylib MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-x64/publish/MyNativeAOTLibrary.dylib -output MyNativeAOTLibrary.framework/Versions/A/MyNativeAOTLibrary
+ ```
+
+4. Add a property list file to your framework:
+
+ - Create a `Info.plist` file
+
+ ```bash
+ touch MyNativeAOTLibrary.framework/Versions/A/Resources/Info.plist
+ ```
+
+ - Add the contents from the [appendix](#appendix-infoplist-contents) into the created `Info.plist` file
+
+After the final step, the framework structure should look like this:
+
+```
+MyNativeAOTLibrary.framework
+ |_ MyNativeAOTLibrary -> Versions/Current/MyNativeAOTLibrary
+ |_ Resources -> Versions/Current/Resources
+ |_ Versions
+ |_ A
+ | |_ Resources
+ | | |_ Info.plist
+ | |_ MyNativeAOTLibrary
+ |_ Current -> A
+```
+
+### Consume custom frameworks
+
+1. Open `Xcode` (in this example `Xcode 16.0` is used)
+2. Create a new `App` project
+3. Choose the name for your app (for example, `MyiOSApp`) and choose Objective-C as the source language
+4. Add a reference to the `MyNativeAOTLibrary` framework
+ - In the `MyiOSApp` targets **General** tab, under **Frameworks, Libraries and Embedded Content**, select **+** to add `MyNativeAOTLibrary` as the referenced framework
+ - In the dialog, choose **Add Other** -> **Add Files** and then browse to the location of `MyNativeAOTLibrary.framework` and select it
+ - Once selected, set `Embed and Sign` option for `MyNativeAOTLibrary` framework
+
+ ![Xcode add framework reference](../../media/native-aot-ios-like-platforms/xcode-add-framework-reference.png)
+
+5. Add `MyNativeAOTLibrary.framework` location to the list of **Framework Search Paths** in the **Build Settings** tab
+
+ ![Xcode add framework search path](../../media/native-aot-ios-like-platforms/xcode-add-framework-search-path.png)
+
+6. Edit `main.m` by calling the exposed managed method `aotsample_add` and printing the result
+
+ ```objc
+ extern int aotsample_add(int a, int b);
+ int main(int argc, char * argv[]) {
+ ...
+ NSLog(@"2 + 5 = %d", aotsample_add(2, 5));
+ ...
+ }
+ ```
+
+7. Select your physical iOS device and build/run the app
+8. Inspect the logs after the app has successfully launched. The app should print out: `2 + 5 = 7`
+
+> [!NOTE]
+> For MacCatalyst, use the same steps except for step 7, where the Run Destination needs to be set as: `Mac (Mac Catalyst)`.
+
+## Build static libraries with NativeAOT for iOS-like platforms
+
+As described in [building native libraries overview](../libraries.md#building-native-libraries), it's better to build shared libraries over static ones due to several limitations.
+
+However, if desired, you can build a static library by following the steps for building a shared one and including an additional property in the project file:
+
+```xml
+Static
+```
+
+After the project has been published, the static library `MyNativeAOTLibrary.a` can be found at: `MyNativeAOTLibrary/bin/Release/net9.0//publish`.
+
+This article doesn't cover how to consume the static library and configure the consumer project.
+
+## Appendix Info.plist contents
+
+```xml
+
+
+
+
+ CFBundleName
+ MyNativeAOTLibrary
+ CFBundleIdentifier
+ com.companyname.MyNativeAOTLibrary
+ CFBundleVersion
+ 1.0
+ CFBundleExecutable
+ MyNativeAOTLibrary
+ CFBundlePackageType
+ FMWK
+
+
+```
diff --git a/docs/core/deploying/native-aot/ios-like-platforms/index.md b/docs/core/deploying/native-aot/ios-like-platforms/index.md
new file mode 100644
index 0000000000000..247e4228a06c5
--- /dev/null
+++ b/docs/core/deploying/native-aot/ios-like-platforms/index.md
@@ -0,0 +1,48 @@
+---
+title: Native AOT support for iOS-like platforms overview
+description: Learn how Native AOT supports iOS-like platforms
+author: ivanpovazan
+ms.author: ivanpovazan
+ms.date: 11/21/2024
+---
+
+# Native AOT support for iOS-like platforms
+
+Starting from .NET 9, Native AOT supports targeting iOS-like platforms. The term *iOS-like platforms* refers to Apple platforms that use similar APIs such as: iOS, MacCatalyst and tvOS.
+
+Based on the use case, the support can be divided into:
+
+- support for applications and libraries referencing OS-specific APIs
+- support for applications and libraries without OS-specific API dependencies
+
+## Support for applications and libraries referencing OS-specific APIs
+
+This refers to .NET MAUI projects targeting OS-specific target frameworks (like: `net9.0-ios`).
+How Native AOT can be enabled for .NET MAUI apps, see [Native AOT deployment on iOS and Mac Catalyst](/dotnet/maui/deployment/nativeaot).
+
+## Support for applications and libraries without OS-specific API dependencies
+
+This refers to .NET projects targeting the general or non-OS-specific target framework (like: `net9.0`), for which Native AOT can be enabled in the following way:
+
+1. Include the following properties in your project file:
+
+ ```xml
+ true
+ true
+ ```
+
+2. Publish the project for the desired iOS-like target platform by specifying adequate runtime identifier (later referred to as ``):
+
+ - `ios-arm64`, for iOS physical devices
+ - `iossimulator-arm64` or `iossimulator-x64`, for iOS simulators
+ - `maccatalyst-arm64` or `maccatalyst-x64`, for Mac Catalyst
+ - `tvos-arm64`, for tvOS physical devices
+ - `tvossimulator-arm64` or `tvossimulator-x64`, for tvOS simulators
+
+ and execute the following command:
+
+ ```
+ dotnet publish -r
+ ```
+
+For specifics of building and consuming native libraries on iOS-like platforms, see [How to create and consume custom frameworks with Native AOT for iOS-like platforms](./creating-and-consuming-custom-frameworks.md).
diff --git a/docs/navigate/devops-testing/toc.yml b/docs/navigate/devops-testing/toc.yml
index a142a86181538..84d66c9764c81 100644
--- a/docs/navigate/devops-testing/toc.yml
+++ b/docs/navigate/devops-testing/toc.yml
@@ -527,6 +527,12 @@ items:
href: ../../core/deploying/native-aot/warnings/il3055.md
- name: IL3056
href: ../../core/deploying/native-aot/warnings/il3056.md
+ - name: iOS-like platforms
+ items:
+ - name: Overview
+ href: ../../core/deploying/native-aot/ios-like-platforms/index.md
+ - name: Create and consume custom frameworks
+ href: ../../core/deploying/native-aot/ios-like-platforms/creating-and-consuming-custom-frameworks.md
- name: Runtime package store
href: ../../core/deploying/runtime-store.md
- name: Runtime Identifier (RID) catalog