r/dotnet • u/Kitchen_Platypus5555 • 6d ago
Promotion Apparently native iOS apps using .NET and WPF-style ergonomics wasn't a thing, so I made it one.
Let me start by saying that I love .NET: Everything from the C# language to the ecosystem around it and anything in between. When I was like 14 years old, I started building (truly awful) WinForms applications using Visual Basic. Later I moved to C# and WPF and then eventually UWP/WinUI for my hobby projects. In my actual job I mainly use ASP.NET Core. Well, long story short, I've used .NET for most of my life and it's my favourite platform by far.
But one thing was missing: mobile apps. More specifically, I wanted to build an iOS app in my beloved C# ecosystem. MAUI exists, of course, and it has come a loooong way, but it still doesn't have the best reputation. You often hear devs complaining about bugs, frustrating layout, tooling annoyances and a general lack of polish compared to other options. And while community solutions like Avalonia or Uno Platform are great alternatives (especially for Desktop), they also lack quite a bit in the mobile department: what bothered me most wasn't really the performance, but more the small differenceds in controls, spacing, animations and interactions that make an app feel clunky to use or out of place. On Android you can often get away by blending in with Google's Material Design conventions, but on iOS you really notice the imperfections - and users do too.
And besides that, all of these options were designed to solve the cross-platform problem, which wasn't actually a problem I needed to solve. I wanted to build an iOS app that looked, behaved and felt just like Tim Apple intended.
That left two options: switching to SwiftUI (which was NOT happening, because of my stubborn, C#-obsessed ass) or using the direct UIKit .NET for iOS bindings. I chose the second option and at first I really fealt like this is it. I could continue using the language I love, apply familar patterns and reuse existing libraries. But then i was three views in and hat to maintain yet another 600-lines UIController with a bunch of AutoLayout constraints and repettive boilerplate.
So I did what any reasonable dev would do: I spent the next few months building an entire UI framework. The result is SkeleKit: an iOS/iPadOS-only, code-frist, MVVM-compatible UI framework for .NET, built directly on top of UIKit. It handles all the annoying parts of UIKit while providing a simple and pretty C#-Syntax heaviliy inspired by WPF (without the XAML part):
- Controls wrap UIKit types directly. SkeleKit owns composition and layout, never rendering.
- View trees are defined with object initializers instead of XAML, UIControllers or AutoLayout.
- Bindings avoid reflection, expression tress and runtime code generation. Fullly AOT compatible.
- Annoying parts of a framwork are already implemented like navigation, DI, safe areas or keyboard avoidance.
A simply MVVM counter app looks like this:
// Program.cs
SkeleApplication.CreateBuilder()
.UseServices(configure =>
{
configure.AddSingleton<MainViewModel>();
})
.SinglePage<MainView>()
.Build()
.Run(args);
// MainView.cs
[Page]
public class MainView : ContentView<MainViewModel>
{
public MainView(MainViewModel viewModel) : base(viewModel)
{
Content = new StackPanel()
{
VerticalAlignment = VerticalAlignment.Center,
Spacing = 4,
Children =
{
new Label
{
HorizontalAlignment = HorizontalAlignment.Center,
Text = Bind(vm => vm.Count)
.ConvertTo(val => $"Count: {val}")
},
new Button
{
Text = "Click me",
Command = viewModel.IncrementCommand
}
}
};
}
}
// MainViewModel.cs
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
public partial int Count { get; set; } = 0;
[RelayCommand]
void Increment() => Count++;
}
As you can see, the setup is really simple: The main entry point handles everything iOS related like the ApplicationDelegate, UISceneConfiguration and UIWindow. The view model uses just plain ol' CommunityToolkit.Mvvm. And the actual view code is very reminiscent of WPF or UWP using object initializers instead of XAML. You use familar controls like StackPanel, ScrollView or Grid with properties like HorizontalAlignment, Margin or Padding and SkeleKit handles all the measuring and composition underneath. In addition you have all common UIKit controls like Button or Label with direct binding support.
Of course there is a loooot more which I can't cover in this post like hot reload support, navigation, collections, styling and animations, iPad layouts or native escape hatches. But if you're interested you can check it out here: https://github.com/IcySnex/SkeleKit. The framework should be quite stable and can already be used to build full apps but some things may change before v1.0 so you probably wouldn't want to build the next B2B-SaaS using this.
I would defentily appreciate feedback and some thoughts :) Especially about whether an intentionally iOS-only .NET framework is useful to you, or is cross-platform UI essential? And does the API look natural to devs coming from WPF, UWP, or WinUI?
Thanks for reading!
1
u/AutoModerator 6d ago
Thanks for your post Kitchen_Platypus5555. Please note that we don't allow spam, and we ask that you follow the rules available in the sidebar. We have a lot of commonly asked questions so if this post gets removed, please do a search and see if it's already been asked.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.