Xamarin.Forms na .NET MAUI 10: Kompletni migracijski vodič s checklistom (2026)

Kompletni migracijski vodič s .NET Upgrade Assistantom, Custom Renderers na Handlers portom, DependencyService zamjenom i CI/CD promjenama za tim koji seli s Xamarin.Forms na .NET MAUI 10 u 2026.

Xamarin na .NET MAUI 10: Vodič 2026

Ažurirano: 16. kolovoza 2026.

Migracija Xamarin.Forms aplikacije na .NET MAUI 10 je proces u kojem .NET Upgrade Assistant konvertira postojeći Xamarin.Forms 5.0 solution u SDK-style projekte s net10.0-android i net10.0-ios ciljanim frameworkovima, a razvojni tim ručno preporođuje Custom Renderere u Handlere, DependencyService u ugrađeni DI kontejner i Xamarin.Essentials u Microsoft.Maui.Essentials. Xamarin je službeno End of Life od 1. svibnja 2024., a Apple i Google više ne prihvaćaju build-ove nastale starim Xamarin toolchainom bez zaobilaznih rješenja, pa je migracija na .NET MAUI 10 obavezna, ne opcionalna. Ovaj vodič donosi kompletan checklist, redoslijed koraka i gotovo cijelu listu grešaka koje pravimo kad radimo migracije za klijente.

  • Xamarin je EOL od 1. svibnja 2024. App Store i Google Play zahtijevaju novije SDK-ove nego što Xamarin toolchain podržava.
  • Prije bilo kakve migracije nadogradite Xamarin.Forms na 5.0 i uklonite deprecirane pakete. To reducira površinu API razlika za 60–70%.
  • .NET Upgrade Assistant automatski konvertira project files, namespace i osnovnu strukturu, ali ne migrira Custom Renderere niti platform-specific kod.
  • Custom Renderers → Handlers je najkompleksniji dio migracije i troši 40–60% ukupnog vremena, pogotovo kod aplikacija s vlastitim UI komponentama.
  • Realistična procjena za srednje kompleksnu aplikaciju (30–60 ekrana, 10–20 renderera) je 4–8 tjedana s AI-asistiranim razvojem.
  • CI/CD pipeline treba mijenjati odmah. Stari mono agenti neće buildati net10.0-ios projekte, potreban je macOS runner s Xcode 16+.

Zašto morate migrirati s Xamarina na .NET MAUI 10

Xamarin je službeno End of Life od 1. svibnja 2024. Microsoft je zatvorio support pipeline za sve Xamarin SDK-ove uključujući Xamarin.Forms, Xamarin.iOS i Xamarin.Android. To znači da nema više security patcheva, kompatibilnosti s novim iOS/Android verzijama, niti podrške kroz službene kanale. Vaša aplikacija još uvijek radi i još uvijek se može uploadati u store, za sada.

Problem je što se store zahtjevi svake godine podižu, a Xamarin toolchain ne. Od ljeta 2025. Apple zahtijeva build sa Xcode 16 (iOS 18 SDK), a od travnja 2026. Google Play zahtijeva targetSdkVersion 35 (Android 15). Xamarin.iOS ne zna ciljati iOS 18 SDK bez hackova, a Xamarin.Android ima probleme s Android 15 privacy manifestom i foregroundServiceType validacijom. Iskreno, većina timova otkriva ovaj problem tek kad im Apple odbije upload sa greškom ITMS-90725, a onda je već kasno za planiran release.

.NET MAUI 10, službeno objavljen u studenom 2025., je Microsoftov intended successor. Dijeli isti jezik (C#) i UI jezik (XAML) s Xamarin.Forms, ali radi na .NET 10 runtime-u, koristi single-project strukturu i ima kompletno prerađen rendering pipeline s Handlerima umjesto Renderera. Performanse su vidljivo bolje, startup vrijeme je 30–40% brže na hladnom startu kod većine referentnih aplikacija, memory footprint manji za oko 20%.

Najvažnije, .NET MAUI je jedini put naprijed unutar Microsoft mobile ekosustava. Alternative postoje (Uno Platform, Avalonia, native rewriteovi u SwiftUI/Compose), ali sve traže veći rework i mijenjaju cijeli tim skill-set. Za tim koji je već u C#/XAML-u, MAUI je najkraća staza od EOL Xamarina do supported stanja.

Kako migrirati Xamarin.Forms na .NET MAUI: pregled procesa

Migracija je linearan proces sa sedam faza, i svaka faza mora biti dovršena prije sljedeće. Preskakanje ubija timeline u trećem tjednu kad se sve razmontira odjednom. Redoslijed koji koristimo na klijentima izgleda ovako:

  1. Baseline stabilizacija. Podignite postojeći Xamarin.Forms projekt na verziju 5.0 i najnovije Xamarin.iOS/Android verzije, riješite sve postojeće warninge, provjerite da build radi na CI-u.
  2. Dependency audit. Za svaku NuGet ovisnost provjerite postoji li .NET MAUI kompatibilna verzija. Ako ne postoji, planirajte zamjenu ili vlastitu implementaciju prije pokretanja Upgrade Assistanta.
  3. Upgrade Assistant pass. Pokrenite upgrade-assistant upgrade na solutionu. Alat mijenja project files, namespace i osnovnu strukturu.
  4. Renderer → Handler port. Za svaki Custom Renderer napišete novi Handler s PropertyMapper i platform-specific partial klasama. Ovo je najveći komad posla.
  5. Servisni sloj. DependencyService se zamjenjuje ugrađenim Microsoft.Extensions.DependencyInjection, MessagingCenter se zamjenjuje WeakReferenceMessenger-om iz CommunityToolkit.Mvvm.
  6. Essentials i platform APIs. Xamarin.Essentials namespace se zamjenjuje Microsoft.Maui.Devices, Microsoft.Maui.Storage i Microsoft.Maui.ApplicationModel.
  7. CI/CD i QA. Ažurirajte pipeline agente na .NET 10 SDK, macOS runner s Xcode 16+, i napravite kompletan regresijski prolaz na device farmu.

Migracijski checklist prije nego dodirnete kod

Većina timova preskoči ovo, i onda se u trećem tjednu vraća na početak jer nemaju rollback plan. Prije bilo kakvog upgrade-assistant upgrade poziva, prođite kroz cijeli checklist:

  • Git branch strategija. Napravite migration/net-maui-10 long-lived branch iz main. Ne radite migraciju direktno u main. Sve promjene idu kroz PR-ove u ovaj branch.
  • Backup i tag. Napravite git tag pre-maui-migration na trenutačnom Xamarin commitu. To je vaš rollback point.
  • Kompletan inventar Custom Renderera. Pokrenite grep -r "ExportRenderer" src/ i zapišite svaki jedan; ovo je vaš work item list za Fazu 4.
  • Kompletan inventar Effectsa. grep -r "ExportEffect" src/. Effectsi se ne migriraju automatski.
  • Kompletan inventar DependencyService poziva. grep -rn "DependencyService.Get" src/. Svaki će se mijenjati.
  • Third-party paketi. Napravite tablicu PackageId | TrenutačnaVerzija | MAUI-kompatibilna verzija | Zamjena. Ako je zamjena "custom", to je zaseban work item.
  • Platform-specific bind projekti. Xamarin Binding Library projekti se ne migriraju Upgrade Assistantom. Treba ih rewriteati kao .NET binding projects ili zamijeniti .NET wrapper paketima.
  • CI/CD trenutačno stanje. Screenshotajte trenutačnu pipeline konfiguraciju, capacitor plan i secrets. Novi pipeline se piše od nule.
  • Testni uređaji. Osigurajte da imate barem jedan iOS i jedan Android uređaj s najnovijim OS-om za device testing. Simulator nije dovoljan za renderer QA.
  • Provisioning profili i certifikati. .NET MAUI 10 koristi drugačiji Apple developer workflow, pa provjerite da imate valid distribution certificate i provisioning profil za novi bundle ID ako se mijenja.

Preskočene točke se otkrivaju kao skriveni radni pakete pola projekta unutra i redovito produžuju timeline za 30–50%.

Korak 1: Priprema Xamarin.Forms 5.0 baseline

.NET Upgrade Assistant službeno podržava projekte od Xamarin.Forms 4.8, ali preporučuje 5.0 s razlogom. Verzija 4.8 → MAUI ima toliko API razlika u navigation stacku i shell komponentama da alat samo baci hrpu TODO komentara i ostavi vas da ručno rješavate. Podignite se na 5.0 prvo.

# U starom Xamarin.Forms projektu, ažurirajte packages.config ili PackageReference
# na najnoviju 5.0.x verziju
dotnet add package Xamarin.Forms --version 5.0.0.2622
dotnet add package Xamarin.Essentials --version 1.8.1

# Build mora proći bez errora prije nastavka
msbuild MyApp.sln /t:Restore
msbuild MyApp.sln /p:Configuration=Release

Nakon build-a, deployjte na fizički iOS i Android uređaj i prođite kroz glavne user flow-e. Ako aplikacija na Xamarin.Forms 5.0 baseline-u ima bugove, ti bugovi neće nestati migracijom, samo će biti teže dijagnosticirati jer nećete znati je li novi bug ili prenesen iz baseline-a.

Također ovdje očistite deprecated API pozive u Xamarin.Forms 5.0. Kompajler generira warninge za sve što je označeno kao obsolete, pa nulirajte warning list prije migracije. Ovo je i prilika da uklonite Xamarin.Forms features koje ne koristite, na primjer stare MessagingCenter pozive koji su nasljeđe iz ranih verzija projekta. Naš checkpoint za baseline: aplikacija se deploya, radi glavne flow-e, msbuild vraća 0 errora i 0 warninga.

Korak 2: .NET Upgrade Assistant, instalacija i pokretanje

.NET Upgrade Assistant je Microsoftov službeni migracijski alat, dostupan kao Visual Studio 2022 extension (17.6+) i kao cross-platform CLI. Za CI-friendly workflow uvijek koristim CLI verziju, jer je reproducibilna, može se skriptati i ne zaključava se u IDE.

# Instalacija globalnog toola (macOS/Linux/Windows)
dotnet tool install -g upgrade-assistant

# Provjera verzije, trebala bi biti 0.5.x ili novija za MAUI 10 podršku
upgrade-assistant --version

# Pokretanje migracije na solutionu
cd /path/to/MyApp
upgrade-assistant upgrade MyApp.sln --non-interactive --target-tfm-support Current

Alat radi u nekoliko faza. Prvo konvertira project files iz starog <Project ToolsVersion="4.0"> formata u SDK-style <Project Sdk="Microsoft.NET.Sdk">. Zatim mijenja Target Framework Moniker u net10.0-android i net10.0-ios, dodaje <UseMaui>true</UseMaui> i uklanja properties koje MAUI ne treba (AndroidResgenClass, iOS specifične bind properties itd.).

Zatim prolazi kroz source i mijenja using Xamarin.Forms; na using Microsoft.Maui.Controls;, using Xamarin.Essentials; na odgovarajuće Microsoft.Maui.* namespaceove, uklanja ExportRenderer atribute (ali ne generira Handler kod, samo ostavi TODO). Ako imate NuGet feed s privatnim paketima koji failaju, dodajte --ignore-failed-sources zastavicu.

Prvi msbuild nakon Upgrade Assistanta gotovo sigurno neće proći. To je normalno. Pogledajte Task List u VS-u ili grep TODO u source-u. Alat je ostavio TODO komentare svugdje gdje je bilo nesigurno kako migrirati kod. Radite kroz njih jedan po jedan.

Korak 3: Migracija namespacea i strukture projekta

Namespace mapiranje je mehaničko ali ima nekoliko zamki. Upgrade Assistant pokriva 80% slučajeva, ostatak radite ručno:

Xamarin.Forms.NET MAUI 10Napomena
Xamarin.FormsMicrosoft.Maui.ControlsUI komponente, ViewCells, ItemsSource
Xamarin.Forms.XamlMicrosoft.Maui.Controls.XamlXAML kompajler atributi
Xamarin.EssentialsMicrosoft.Maui.Devices, Storage, ApplicationModel, Media, Networking, AuthenticationPodijeljeno u više namespaceova
Xamarin.Forms.PlatformConfiguration.iOSSpecificMicrosoft.Maui.Controls.PlatformConfiguration.iOSSpecificOstaje ista struktura
Xamarin.Forms.ShapesMicrosoft.Maui.Controls.ShapesPath, Rectangle, Ellipse

Struktura projekta se mijenja radikalno. Xamarin.Forms solution je imao tri odvojena projekta: shared class library, MyApp.iOS i MyApp.Android. .NET MAUI koristi single-project strukturu, jedan .csproj ciljajući više platformi, s platform-specific kodom u Platforms/Android/, Platforms/iOS/, Platforms/MacCatalyst/, Platforms/Windows/. Upgrade Assistant to ne radi automatski: konvertira postojeće tri projekte u SDK-style ali ih ne mergea u jedan.

Postoje dva pristupa. Ostati na multi-project strukturi (radi u MAUI 10, ali dobivate manje benefita), ili ručno migrirati na single-project. Za greenfield migracije klijentima uvijek preporučujem single-project, jer donosi bolji tooling support, jednostavniji CI, brži build. Za brownfield s ograničenim vremenom, multi-project je pragmatičan izbor u prvoj iteraciji. Za deep-dive u single-project setup i MauiProgram.cs bootstrap, pogledajte naš CommunityToolkit.Mvvm vodič za MVVM u .NET MAUI. Pokriva strukturu MauiAppBuildera do razine dependency registracije.

Korak 4: Custom Renderers na .NET MAUI Handlers

Ovo je najveći komad posla i najveći izvor grešaka. Custom Renderers u Xamarin.Forms su radili preko ViewRenderer<TView, TNativeView> s OnElementChanged i OnElementPropertyChanged metodama. .NET MAUI ih zamjenjuje ViewHandler<TVirtualView, TPlatformView> klasom i PropertyMapper dictionaryjem gdje svaka property change ide u svoju statičku metodu.

U zadnjem projektu koji sam vodio, prepisivanje 14 renderera na Handlere trajalo je nešto više od dva tjedna, pa računajte s tim tempom. Kompletni before/after za jednostavni custom Entry renderer izgleda ovako:

// PRIJE: Xamarin.Forms Custom Renderer
[assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessEntryRenderer))]
namespace MyApp.iOS.Renderers
{
    public class BorderlessEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                Control.BorderStyle = UITextBorderStyle.None;
                Control.Layer.BorderWidth = 0;
            }
        }
    }
}
// POSLIJE: .NET MAUI Handler pattern

// 1. Cross-platform kontrola (u shared kodu)
namespace MyApp.Controls
{
    public class BorderlessEntry : Entry { }
}

// 2. Partial handler klasa (u shared kodu)
namespace MyApp.Handlers
{
    public partial class BorderlessEntryHandler : EntryHandler
    {
        public static IPropertyMapper<BorderlessEntry, BorderlessEntryHandler> Mapper =
            new PropertyMapper<BorderlessEntry, BorderlessEntryHandler>(EntryHandler.Mapper)
            {
                // dodatna property mapiranja idu ovdje
            };

        public BorderlessEntryHandler() : base(Mapper) { }
    }
}

// 3. Platform-specific partial (u Platforms/iOS/Handlers/)
namespace MyApp.Handlers
{
    public partial class BorderlessEntryHandler
    {
        protected override UITextField CreatePlatformView()
        {
            var field = base.CreatePlatformView();
            field.BorderStyle = UITextBorderStyle.None;
            field.Layer.BorderWidth = 0;
            return field;
        }
    }
}

// 4. Registracija u MauiProgram.cs
public static MauiApp CreateMauiApp() =>
    MauiApp.CreateBuilder()
        .UseMauiApp<App>()
        .ConfigureMauiHandlers(handlers =>
        {
            handlers.AddHandler<BorderlessEntry, BorderlessEntryHandler>();
        })
        .Build();

Više koda, ali kompletno decoupled. Handler radi bez wrapper ViewGroup-a na Androidu, što reducira visual tree i poboljšava performanse. Za dublji pregled Handler API-ja, PropertyMapper-a i CommandMapper-a, imamo detaljan vodič za .NET MAUI Custom Handlere s primjerima.

Za detaljan mapping OnElementChanged na CreatePlatformView / ConnectHandler / DisconnectHandler životnog ciklusa, konzultirajte službenu Microsoft dokumentaciju za renderer-to-handler migraciju. Postoji i compat layer koji dopušta da originalni Xamarin renderer nastavi raditi u MAUI kroz Microsoft.Maui.Controls.Compatibility namespace. Koristan je kao privremeni most, ali nemojte to smatrati konačnim rješenjem. Compat layer nije garantiran u budućim MAUI verzijama i već je označen kao deprecated za sljedeći major.

Korak 5: DependencyService i MessagingCenter na moderne alternative

DependencyService.Get<T>() je bio Xamarin.Forms mehanizam za dependency injection, i, iskreno, bio je service locator anti-pattern. .NET MAUI koristi standardni Microsoft.Extensions.DependencyInjection kontejner, isti onaj koji koristi ASP.NET Core.

// PRIJE
DependencyService.Register<IDeviceInfoService, DeviceInfoService>();
var deviceInfo = DependencyService.Get<IDeviceInfoService>();

// POSLIJE, u MauiProgram.cs
public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder.UseMauiApp<App>();

    // Registracija servisa
    builder.Services.AddSingleton<IDeviceInfoService, DeviceInfoService>();
    builder.Services.AddTransient<MainViewModel>();
    builder.Services.AddTransient<MainPage>();

    return builder.Build();
}

// Konzumacija, constructor injection preferred
public partial class MainPage : ContentPage
{
    public MainPage(MainViewModel vm)
    {
        InitializeComponent();
        BindingContext = vm;
    }
}

Za slučajeve gdje ne možete koristiti constructor injection (recimo, unutar statične metode ili u XAML value converteru), postoji Microsoft.Maui.Controls.Application.Current?.Handler?.MauiContext?.Services pattern. To je code smell, koristite ga samo kao zadnju rezervu.

MessagingCenter je označen kao obsolete u .NET MAUI 8 i naprijed. Zamjena je WeakReferenceMessenger iz CommunityToolkit.Mvvm paketa. WeakReferenceMessenger drži samo weak reference na subscribere, što eliminira klasu memory leakova koje smo redovito nalazili na Xamarin projektima gdje netko zaboravi Unsubscribe. Sâm sam takav leak lovio dva dana prije nego što mi je sinulo gdje je izvor.

// PRIJE
MessagingCenter.Subscribe<MainViewModel, string>(this, "UserLoggedIn", (sender, userName) =>
{
    // handler
});
MessagingCenter.Send(this, "UserLoggedIn", "sofia");

// POSLIJE
public sealed class UserLoggedInMessage : ValueChangedMessage<string>
{
    public UserLoggedInMessage(string userName) : base(userName) { }
}

WeakReferenceMessenger.Default.Register<UserLoggedInMessage>(this, (r, m) =>
{
    // handler, m.Value je userName
});
WeakReferenceMessenger.Default.Send(new UserLoggedInMessage("sofia"));

Korak 6: Xamarin.Essentials na Microsoft.Maui.Essentials

Xamarin.Essentials je konsolidiran u više namespaceova unutar Microsoft.Maui.* hijerarhije. Nema više jednog using Xamarin.Essentials;, treba znati u koji namespace ide koja klasa. Upgrade Assistant pokriva većinu ali ne sve. Bitne migracije:

  • Xamarin.Essentials.PreferencesMicrosoft.Maui.Storage.Preferences
  • Xamarin.Essentials.SecureStorageMicrosoft.Maui.Storage.SecureStorage (isti API, drugi namespace)
  • Xamarin.Essentials.ConnectivityMicrosoft.Maui.Networking.Connectivity
  • Xamarin.Essentials.GeolocationMicrosoft.Maui.Devices.Sensors.Geolocation
  • Xamarin.Essentials.WebAuthenticatorMicrosoft.Maui.Authentication.WebAuthenticator
  • Xamarin.Essentials.DeviceInfoMicrosoft.Maui.Devices.DeviceInfo
  • Xamarin.Essentials.LauncherMicrosoft.Maui.ApplicationModel.Launcher

Većina API metoda ima identičnu signaturu, tako da je migracija čisto namespace rename. Iznimke: DisplayInfo i DeviceDisplay imaju blago drugačiji API, a MainThread.BeginInvokeOnMainThread i dalje postoji, ali je preporučeni obrazac Dispatcher.Dispatch(...) unutar MAUI kontrola. Ako radite s tokenima i credentialima kroz SecureStorage, preporučujem detaljno testiranje na svježim instalacijama. Vidjeli smo edge case gdje se old Xamarin.Essentials SecureStorage entryji ne čitaju iz novog Microsoft.Maui.Storage.SecureStorage-a jer je storage key prefix drugačiji na iOS Keychainu. Ako korisnici moraju ostati logirani preko migracije, potrebna je jednokratna migration routine koja čita iz starog storage prefix-a i piše u novi. Za deep-dive na SecureStorage sigurnosne prakse, vidite naš vodič za sigurnost .NET MAUI aplikacija.

Korak 7: CI/CD pipeline i regresijsko testiranje

CI/CD je gdje se najčešće razbije migracija u produkciji. Ljudi rade migraciju lokalno, sve prolazi u Visual Studiju, i onda pipeline umre jer agent nema pravi SDK. Sređivanje pipeline-a mora ići paralelno s kodom, ne poslije.

Ključne izmjene za GitHub Actions workflow:

name: MAUI Build

on:
  push:
    branches: [ migration/net-maui-10 ]

jobs:
  build-android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '10.0.x'
      - name: Install MAUI workload
        run: dotnet workload install maui-android
      - name: Build Android
        run: dotnet build src/MyApp/MyApp.csproj -f net10.0-android -c Release

  build-ios:
    runs-on: macos-15  # Xcode 16+ potreban za iOS 18 SDK
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '10.0.x'
      - name: Install MAUI workload
        run: dotnet workload install maui-ios
      - name: Select Xcode
        run: sudo xcode-select -s /Applications/Xcode_16.2.app
      - name: Build iOS
        run: dotnet build src/MyApp/MyApp.csproj -f net10.0-ios -c Release

Nema više msbuild, sve ide kroz dotnet build jer je projekt SDK-style. Nema više Mono agenata. Windows agent ne može buildati iOS bilo kako. Naš detaljan CI/CD vodič za .NET MAUI pokriva kompletni release pipeline s code signingom i store uploadom.

Za testni prolaz nakon migracije, nikad se ne oslanjajte samo na simulator/emulator. Radi se full regression na fizičkim uređajima. Naš minimum device matrix: iPhone SE (small screen, stariji SoC), iPhone 15 Pro (najnoviji), Android low-end (Pixel 4a ili Samsung A serija), Android flagship (Pixel 9 ili Samsung S24). Fokus na scroll performance, keyboard behavior kod custom entrieva i navigation transitions. To su tri područja gdje se Handler ponaša drugačije od Renderera i gdje ćete najlakše primijetiti regresije.

Koliko dugo traje migracija s Xamarina na MAUI

Realne procjene bazirane na projektima koje smo isporučili u 2025. i 2026.:

  • Mala aplikacija (do 20 ekrana, 0–5 custom renderera, minimalna platform-specific logika): 2–3 tjedna, jedan senior developer.
  • Srednja aplikacija (30–60 ekrana, 10–20 custom renderera, jedna component library): 4–8 tjedana s AI-asistiranim razvojem, dva developera. Bez AI asistencije 8–12 tjedana.
  • Velika aplikacija (100+ ekrana, 30+ renderera, više platform-specific bind projekata, third-party SDK integracije): 3–6 mjeseci, dedicated tim od 3–5 developera.

Distribucija napora na tipičnoj srednjoj migraciji: baseline stabilizacija 15%, Upgrade Assistant + namespace 10%, Renderers → Handlers 40%, servisni sloj i Essentials 10%, CI/CD 10%, testiranje i bug fixing 15%. Renderer migracija dominira jer je jedini dio koji nema pomoć od tooling-a.

Budgeting savjet: dodajte 25% contingency na estimate. Uvijek se pojavi neki third-party SDK bez MAUI verzije, ili neki custom XAML renderer koji koristi Cell/ListView legacy API koji Handler pattern ne pokriva. Bez contingency-ja pipeline slip-a najkasnije u petom tjednu. Meni se to dogodilo doslovno u petom tjednu, tako da vjerujem u ovaj broj.

Uobičajene greške koje viđam na svakoj migraciji

Deset stvari koje smo naučili kroz bol na klijentskim projektima:

  1. Migracija na main branchu. Uvijek u migration/*. Merge tek kad je sve zeleno na CI-u i QA-u.
  2. Preskakanje Xamarin.Forms 5.0 baseline-a. "Već smo na 4.8, samo ćemo napraviti veliki skok" nikad ne završi dobro.
  3. Držanje Compat layer-a kao trajnog rješenja. Microsoft.Maui.Controls.Compatibility je most, ne destinacija. Već je označen deprecated za sljedeći MAUI major.
  4. Ne migriranje Effectsa. Ljudi zapamte Renderere, ali zaborave Effects. ExportEffect ne radi u MAUI, pretvorite u PlatformBehavior<T>.
  5. Ignoriranje resource bundle-a. Xamarin.Forms je koristio .resx u shared projektu; MAUI single-project traži da resource fajlovi budu na specifičnim lokacijama (Resources/Fonts, Resources/Images, Resources/Raw) da bi ih SDK ispravno bundlao.
  6. Zaboravljanje na maui-android workload na CI-u. Lokalno je instaliran, na freshly provisioned agentu nije. dotnet workload install maui-android maui-ios mora biti eksplicitno u pipelineu.
  7. Neupdated Info.plist i AndroidManifest.xml. Novi iOS 18 privacy manifests i Android 15 foregroundServiceType deklaracije često se izostave jer je Upgrade Assistant ostavio stare vrijednosti.
  8. Provjere permissions runtime-a na Androidu. Xamarin je bio permisivan; MAUI striktno prati Android 13+ granular media permissions. Kod za camera/photo picker često treba kompletan rewrite.
  9. Šumljenje statistike aplikacije. App Center je EOL, Firebase Crashlytics je novi standard. Konfigurirajte prije prvog TestFlight uploada, inače nemate crash reports za novu build stack.
  10. Direktan push u store. Prva MAUI verzija ide u internal testing track (Google Play Console) i TestFlight beta grupu, ne u production. Uvijek. Bez izuzetka.

Za širi kontekst na store deployment za novu MAUI build stack, konzultirajte službenu Microsoft dokumentaciju za Xamarin → .NET MAUI migraciju i .NET MAUI GitHub wiki s napomenama za trenutačni preview toolinga.

Često postavljana pitanja

Je li .NET MAUI zamjena za Xamarin?

Da, .NET MAUI je Microsoftov službeni successor Xamarin.Forms-u i cijelom Xamarin ekosustavu. Dijeli isti jezik (C#), UI markup (XAML) i konceptualne obrasce, ali radi na .NET 10 runtime-u umjesto Mono runtime-a, koristi Handler arhitekturu umjesto Renderera i podržava macOS i Windows kao ciljane platforme uz iOS i Android.

Što se dogodilo s Xamarinom?

Xamarin je službeno End of Life od 1. svibnja 2024. Microsoft je prestao izdavati security patcheve, kompatibilnosne update-ove i podršku kroz službene kanale. Aplikacije mogu i dalje raditi, ali novi iOS/Android release-i store zahtjeva postaju neispunjivi bez migracije na .NET MAUI ili prelaska na drugi framework.

Koje su ključne razlike između Xamarin.Forms i .NET MAUI?

Glavne razlike su: single-project struktura umjesto multi-project solutiona, Handlers umjesto Renderera za native kontrole, ugrađeni Microsoft.Extensions.DependencyInjection umjesto DependencyService-a, WeakReferenceMessenger umjesto MessagingCenter-a, MauiProgram.cs bootstrap umjesto App.xaml partial klase, i podrška za macOS i Windows platforme uz iOS i Android.

Mogu li zadržati Custom Renderere u .NET MAUI?

Da, kroz Microsoft.Maui.Controls.Compatibility namespace koji omogućuje da originalni Xamarin Custom Renderers rade u MAUI kao privremeno rješenje. Nije preporučeno dugoročno jer je compat layer označen deprecated za sljedeći MAUI major release i ne dobiva performance benefite Handler arhitekture. Za produkcijski kod porta u Handlers unutar 12 mjeseci od migracije.

Radi li .NET Upgrade Assistant kompletnu migraciju?

Ne. Upgrade Assistant automatizira project file konverziju, namespace mapiranje i osnovnu strukturu, što pokriva 30–40% posla ovisno o kompleksnosti projekta. Custom Renderers, platform-specific bind projekti, Effects i third-party SDK integracije zahtijevaju ručnu migraciju. Alat ostavlja TODO komentare gdje je nesigurno kako migrirati kod.

Trebam li novi Apple developer certificate za .NET MAUI aplikaciju?

Ne, postojeći Apple Developer certificate i provisioning profil za bundle ID mogu se ponovno upotrijebiti pod pretpostavkom da zadržavate isti bundle ID. Ako mijenjate bundle ID (zbog rebrandinga ili strukture), potreban je novi provisioning profil. Novi build stack traži Xcode 16+ na macOS runner-u za iOS 18 SDK compliance.

Sofia Rodriguez
O Autoru Sofia Rodriguez

Mobile DevOps engineer focused on the unglamorous stuff: build pipelines, signing, store releases, and the tooling that keeps teams shipping.