.NET (Microsoft) logo

Skill

ios-slim-bindings

create iOS slim bindings for MAUI

Covers MAUI iOS .NET Swift Xcode

Description

Create iOS slim bindings for MAUI. USE FOR: slim iOS binding, Native Library Interop, Swift/Objective-C wrappers, XcodeGen project.yml, Podfile, CocoaPods static linking, BUILD_LIBRARY_FOR_DISTRIBUTION, XcodeProject MSBuild, `@objc`/`[Export]` selector crashes, async completion handlers. DO NOT USE FOR: Android bindings, general MAUI apps, or NuGet packaging.

SKILL.md

When to use this skill

Activate this skill when the user asks:

  • How do I create iOS bindings for a native library?
  • How do I wrap an iOS SDK for use in .NET MAUI?
  • How do I create slim bindings for iOS?
  • How do I use Native Library Interop for iOS?
  • How do I bind a Swift library to .NET?
  • How do I use Objective Sharpie for iOS bindings?
  • How do I integrate an xcframework into .NET MAUI?
  • How do I create a Swift wrapper for a native iOS library?
  • How do I update iOS bindings when the native SDK changes?
  • How do I fix iOS binding build errors?
  • How do I expose native iOS APIs to C#?
  • How do I handle CocoaPods dependencies in iOS bindings?
  • How do I handle Swift Package Manager dependencies?

Overview

This skill guides the creation of Native Library Interop (Slim Bindings) for iOS. This modern approach creates a thin native Swift/Objective-C wrapper exposing only the APIs you need from a native iOS library, making bindings easier to create and maintain.

When to Use Slim Bindings vs Traditional Bindings

ScenarioRecommended Approach
Need only a subset of library functionalitySlim Bindings
Easier maintenance when SDK updatesSlim Bindings
Prefer working in Swift/Objective-C for wrapperSlim Bindings
Better isolation from breaking changesSlim Bindings
Need entire library API surfaceTraditional Bindings
Creating bindings for third-party developersTraditional Bindings
Already maintaining traditional bindingsTraditional Bindings

Inputs

ParameterRequiredExampleNotes
libraryNameyesFirebaseMessaging, LottieName of the native iOS library to bind
bindingProjectNameyesMyBinding.MaciOSName for the C# binding project
dependencySourcenococoapods, spm, xcframeworkHow the native library is distributed
targetFrameworksnonet10.0-ios;net10.0-maccatalystTarget frameworks (default: latest .NET iOS + Mac Catalyst)
exposedApisnoList of specific APIsWhich native APIs to expose (helps scope the wrapper)

Project Structure

MyBinding/
 macios/
 native/   
 MyBinding/                    # Xcode project      
 MyBinding.xcodeproj/          
 project.pbxproj             
 MyBinding/          
 DotnetMyBinding.swift  # Swift wrapper implementation             
 Podfile                    # If using CocoaPods          
 Package.swift              # If using Swift Package Manager          
 MyBinding.MaciOS.Binding/   
 MyBinding.MaciOS.Binding.csproj       
 ApiDefinition.cs       
 sample/
 MauiSample/                        # Sample MAUI app   
 MauiSample.csproj       
 MainPage.xaml.cs       
 README.md

Step-by-step Process

For detailed code examples and full implementation walkthroughs, see references/ios-slim-bindings-implementation.md.

Step 1: Create Project Structure

Install XcodeGen (brew install xcodegen) and create the directory structure:

BINDING_NAME="MyBinding"
mkdir -p ${BINDING_NAME}/macios/native/${BINDING_NAME}/${BINDING_NAME}
mkdir -p ${BINDING_NAME}/macios/${BINDING_NAME}.MaciOS.Binding

Step 2: Create the Xcode Project

Create a project.yml for XcodeGen with framework target, then run xcodegen generate. Key build settings:

  • BUILD_LIBRARY_FOR_DISTRIBUTION: YES
  • MACH_O_TYPE: staticlib
  • DEFINES_MODULE: YES
  • SWIFT_VERSION: "5.0"

Step 3: Create the C# Binding Project

Create a .csproj with <IsBindingProject>true</IsBindingProject> and reference the Xcode project:

<XcodeProject Include="../native/MyBinding/MyBinding.xcodeproj">
  <SchemeName>MyBinding</SchemeName>
</XcodeProject>

Create an initial ApiDefinition.cs with [BaseType], [Static], and [Export] attributes.

Step 4: Build and Verify

dotnet build

This invokes XcodeBuild, creates the xcframework, and generates the C# binding assembly.

Step 5: Add Native Library Dependencies

Choose the appropriate method:

MethodWhen to Use
CocoaPodsLibrary distributed via CocoaPods. Use use_frameworks! :linkage => :static. After pod install, reference .xcworkspace instead of .xcodeproj.
Swift Package ManagerLibrary distributed via SPM. Add via Xcode UI or Package.swift.
Manual XCFrameworkPre-built xcframework. Drag into Xcode project, set "Do Not Embed" for static linking.

Step 6: Implement the Swift Wrapper

Create DotnetMyBinding.swift with these requirements:

  • All classes must inherit from NSObject and have @objc(ClassName) annotation
  • All methods must be public with @objc(selector:) annotation
  • Use only Objective-C compatible types (see Type Mapping table below)
  • Use completion handlers (Result?, NSError?) -> Void for async operations
  • Convert all errors to NSError for proper propagation to C#

Step 7: Generate ApiDefinition.cs

After building, find the generated Swift header and use Objective Sharpie:

sharpie bind --output=sharpie-output --namespace=MyBinding --sdk=iphoneos18.0 \
  --scope=Headers "path/to/MyBinding-Swift.h"

Clean up the generated output: add [Async] attributes, [NullAllowed] for nullable types, remove [Verify] attributes after review, and remove InitWithCoder constructors.

Step 8: Build the Final Binding

dotnet build -c Release

Step 9: Use in Your MAUI App

Add a conditional <ProjectReference>, initialize in MauiProgram.cs with #if IOS || MACCATALYST, and use [Async]-generated methods with await.

Updating Bindings When Native SDK Changes

  1. Update native dependency version (CocoaPods: pod update, SPM: update version, or replace xcframework)
  2. Update Swift wrapper if APIs changed
  3. Clean and rebuild: dotnet clean && dotnet build
  4. Regenerate Objective Sharpie output and diff with existing ApiDefinition.cs
  5. Merge changes: add new bindings, update signatures, preserve custom attributes.
  6. Test with sample app

For detailed update instructions, see references/ios-slim-bindings-implementation.md.

Troubleshooting

ErrorCauseSolution
"Framework not found"XCFramework path incorrect or missing architecturesVerify path in <XcodeProject>, check lipo -info
"Undefined symbols for architecture"Missing linked frameworks or symbol visibilityAdd system frameworks, verify public + @objc annotations
"No type or protocol named"Missing import or protocol mismatchAdd using directives, use interface types
"Duplicate symbol"Multiple framework referencesRemove duplicates, resolve version conflicts
"Native class hasn't been loaded" (runtime)Framework not embedded or missing @objcSet <ForceLoad>true</ForceLoad>, check annotations
"unrecognized selector" (runtime)Selector mismatch between C# and SwiftVerify [Export("...")] matches @objc(...) exactly
"Library not loaded: @rpath" (runtime)Swift runtime or embedding issueAdd linker flags, set "Embed & Sign" for dynamic frameworks
Callbacks not workingWrong thread, GC'd reference, or missing @escapingUse DispatchQueue.main.async, hold strong reference

For detailed troubleshooting with code examples, see references/ios-slim-bindings-implementation.md.

Quick Reference

Swift Wrapper Annotation Requirements

@objc(ClassName)
public class ClassName: NSObject {
    @objc(methodNameWithParam:anotherParam:)
    public func methodName(param: String, anotherParam: Int) -> Bool { ... }

    @objc(staticMethodWithValue:)
    public static func staticMethod(value: String) -> String { ... }
}

Type Mapping

Swift TypeObjective-C TypeC# Type
StringNSString *string
BoolBOOLbool
Int, Int32intint
Int64long longlong
Doubledoubledouble
Floatfloatfloat
DataNSData *NSData
[String: Any]NSDictionary *NSDictionary
[Any]NSArray *NSArray
UIViewUIView *UIView
UIImageUIImage *UIImage
URLNSURL *NSUrl
Custom ClassMust inherit NSObjectInterface with [BaseType]
(Result, Error?) -> VoidBlockAction<Result?, NSError?>

ApiDefinition Attributes

AttributePurpose
[BaseType(typeof(NSObject))]Specifies base class
[Static]Static method/property
[Export("selector:")]Objective-C selector
[Async]Generate async wrapper for completion handler methods
[NullAllowed]Nullable parameter/return
[Protocol]Objective-C protocol
[Model]Protocol implementation
[Abstract]Required protocol method
[Internal]Don't expose publicly
[Sealed]Prevent subclassing

XcodeProject MSBuild Properties

PropertyDescriptionDefault
SchemeNameXcode scheme to buildRequired
ConfigurationBuild configurationRelease
KindFramework or StaticAuto-detected
SmartLinkEnable smart linkingtrue
ForceLoadForce load all symbolsfalse

Resources

Official Documentation

Tools

  • XcodeGen — Generate Xcode projects from YAML specification

Templates and Examples

Reference Files

Output Format

When assisting with iOS slim bindings, provide:

  1. Project structure - File/folder layout for the binding
  2. Swift wrapper code - Complete DotnetMyBinding.swift implementation
  3. Xcode configuration - Build settings and dependency setup
  4. C# binding project - .csproj and ApiDefinition.cs files
  5. Usage examples - How to call the binding from MAUI/C#
  6. Troubleshooting guidance - Common issues and solutions for the specific library

Always verify:

  • Swift classes have @objc(ClassName) annotations
  • Methods have @objc(selector:) annotations matching Objective-C conventions
  • Types are marshallable between Swift and C#
  • Async operations use completion handlers with [Async] attribute
  • Error handling uses NSError for proper propagation

© 2026 YourAI.tools. Every skill from an identity-verified publisher.

Independent catalog. Not affiliated with, endorsed by, or sponsored by Anthropic or any listed publisher. All trademarks belong to their respective owners.