Migrando de ZXing.Net.MAUI para IronBarcode
Este guia fornece um caminho de migração completo do ZXing .NET.MAUI para o IronBarcode para desenvolvedores .NET MAUI . O documento aborda os motivos pelos quais as equipes realizam essa migração, uma comparação de recursos para embasar a decisão, os passos práticos para substituir o pacote e atualizar os arquivos do projeto, exemplos de código antes e depois para cada padrão de uso principal, uma referência de tradução de API, uma seção de solução de problemas para questões que surgem durante a transição, uma lista de verificação da migração para acompanhar o progresso e um resumo dos resultados que a migração proporciona.
Por que migrar do ZXing .NET para o MAUI?
A decisão de migrar do ZXing .NET.MAUI geralmente é motivada por uma ou mais condições concretas do projeto. Não se tratam de preferências estilísticas — são casos em que a arquitetura ou o estado de conservação da biblioteca impedem que uma exigência seja atendida.
Windows MAUI não é suportado: ZXing .NET.MAUI não possui implementação de câmera para Windows e não há planos públicos para desenvolver uma. A biblioteca é construída em torno das APIs de câmera das plataformas iOS e Android. Se um projeto MAUI adicionar um alvo Windows após a compilação inicial — um padrão comum em equipes que começam com foco em dispositivos móveis — o ZXing .NET.MAUI não poderá atender a esse alvo. Não há solução alternativa, nem alternativa, nem solução falsa.
Problema de Auto-Foco do iPhone 15 Pro: O rastreador de problemas do GitHub para Redth/ZXing.Net.Maui documenta que dispositivos iPhone 15 Pro e Pro Max (iPhone16,1 e iPhone16,2) não conseguem atingir um foco confiável para detecção de códigos de barras ao usar CameraBarcodeReaderView. O código de barras está visível no enquadramento da câmera, mas o sistema de foco automático não trava com nitidez suficiente para que o decodificador extraia um resultado. A única mitigação documentada é instruir o usuário a ajustar manualmente a distância entre o dispositivo e o código de barras — uma instrução que exige uma interação visível com o usuário e paciência, e que não é um resultado aceitável em produção para um fluxo de trabalho principal.
Vazamento de Recursos da Câmera: CameraBarcodeReaderView não implementa IDisposable. Quando o usuário sai de uma página de digitalização, os recursos da câmera não são liberados por meio de um padrão de descarte padrão. A solução documentada é definir IsDetecting = false em OnDisappearing(), o que reduz o impacto mas não libera formalmente a câmera. Aplicativos que navegam frequentemente entre páginas de digitalização acumulam consumo de recursos, o que pode se manifestar como aumento do uso de memória, drenagem da bateria e falhas intermitentes na inicialização da câmera ao retornar à página de digitalização.
Especificação de Formato com Falha Silenciosa: O ZXing .NET.MAUI herda a exigência do ZXing.Net de declarar cada formato de código de barras a ser lido antes do início da leitura. Os formatos omitidos de BarcodeReaderOptions.Formats são silenciosamente ignorados, mesmo quando claramente visíveis no quadro da câmera. Um usuário que aponta o dispositivo para um formato de código de barras que o desenvolvedor não previu não vê nenhum erro — o aplicativo simplesmente não detecta nada. Em ambientes onde os formatos de código de barras são controlados por fornecedores externos, clientes ou sistemas de terceiros, essa falha silenciosa se torna um problema persistente de suporte.
Estabilidade Pré-1.0: ZXing.Net.MAUI é publicado na versão v0.7.4 — um lançamento estável no NuGet, mas ainda pré-1.0 sob versionamento semântico. Mudanças na API da versão menor ainda são possíveis antes de 1.0, o ritmo de correção de bugs depende da disponibilidade dos mantenedores da comunidade, e não há SLA de suporte comercial. Para aplicações empresariais sujeitas a auditorias de dependência ou análise de composição de software, uma biblioteca comunitária pré-1.0 sem suporte comercial pode não passar no processo de aprovação.
O problema fundamental
O problema estrutural é que CameraBarcodeReaderView bloqueia o desenvolvedor em um loop de eventos centrado na câmera com gerenciamento manual do ciclo de vida e uma lista de formatos fixos. Para qualquer coisa além do escaneamento básico de câmera no iOS e Android com formatos de código de barras conhecidos, a arquitetura atinge seu limite:
// ZXing.Net.MAUI: event loop, format list, lifecycle boilerplate on every scan page
public partial class ScannerPage : ContentPage
{
public BarcodeReaderOptions ReaderOptions { get; }
public ScannerPage()
{
InitializeComponent();
ReaderOptions = new BarcodeReaderOptions
{
Formats = BarcodeFormats.QRCode |
BarcodeFormats.Code128 |
BarcodeFormats.Ean13 |
BarcodeFormats.UpcA,
TryHarder = true,
AutoRotate = true
};
BindingContext = this;
}
private void OnBarcodesDetected(object sender, BarcodeDetectionEventArgs e)
{
MainThread.BeginInvokeOnMainThread(() =>
{
foreach (var barcode in e.Results)
ResultLabel.Text = $"{barcode.Format}: {barcode.Value}";
});
CameraView.IsDetecting = false;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
CameraView.IsDetecting = false; // Required — no Dispose() available
}
protected override void OnAppearing()
{
base.OnAppearing();
CameraView.IsDetecting = true;
}
}Imports ZXing.Net.MAUI
Public Partial Class ScannerPage
Inherits ContentPage
Public ReadOnly Property ReaderOptions As BarcodeReaderOptions
Public Sub New()
InitializeComponent()
ReaderOptions = New BarcodeReaderOptions With {
.Formats = BarcodeFormats.QRCode Or
BarcodeFormats.Code128 Or
BarcodeFormats.Ean13 Or
BarcodeFormats.UpcA,
.TryHarder = True,
.AutoRotate = True
}
BindingContext = Me
End Sub
Private Sub OnBarcodesDetected(sender As Object, e As BarcodeDetectionEventArgs)
MainThread.BeginInvokeOnMainThread(Sub()
For Each barcode In e.Results
ResultLabel.Text = $"{barcode.Format}: {barcode.Value}"
Next
End Sub)
CameraView.IsDetecting = False
End Sub
Protected Overrides Sub OnDisappearing()
MyBase.OnDisappearing()
CameraView.IsDetecting = False ' Required — no Dispose() available
End Sub
Protected Overrides Sub OnAppearing()
MyBase.OnAppearing()
CameraView.IsDetecting = True
End Sub
End ClassO IronBarcode substitui o loop de eventos por uma única chamada assíncrona ao tocar em um botão, remove completamente a configuração de formato e elimina o gerenciamento do ciclo de vida da página:
// NuGet: dotnet add package IronBarcode
// IronBarcode: stateless, all platforms, auto-detection, no lifecycle boilerplate
using IronBarCode;
public partial class ScannerPage : ContentPage
{
public ScannerPage() => InitializeComponent();
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
// Não OnAppearing / OnDisappearing needed
}
##IronBarcode vs ZXing .NET.MAUI: Comparação de Recursos
| Recurso | ZXing.Net.MAUI | IronBarcode |
|---|---|---|
| Status da versão | Estável, pré-1.0 (v0.7.4) | Lançamento comercial estável |
| iOS PRINCIPAL | Sim (foco do iPhone 15 Pro com defeito) | Sim |
| Android MAUI | Sim (Problemas de compilação da câmera 1.5.0) | Sim |
| Windows MAUI | Não suportado | Sim |
| macOS MAUI | Não suportado | Sim |
| Lado do servidor / ASP.NET Core | Não | Sim |
| Visor da câmera ao vivo | Sim | Não (interface do usuário do sistema MediaPicker) |
| Especificação de formato necessária | Sim | Não (detecção automática, mais de 50 formatos) |
| Gerenciamento do ciclo de vida da câmera | Manual (IsDetectando) | Não aplicável |
| Implementação de Dispose() | Não | Não aplicável — sem estado |
| Foco automático do iPhone 15 Pro | Quebrado (documentado) | Não aplicável |
| Extração de código de barras PDF | Não | Sim |
| Entrada do caminho do arquivo | Não (apenas câmera) | Sim |
| Recuperação de código de barras danificado | Tente com mais afinco, apenas | Sim (com tecnologia de aprendizado de máquina) |
| Geração de código de barras | Sim (via ZXing .NET) | Sim |
| Suporte comercial | None | Sim |
| Licença | MIT (grátis) | Comercial |
Início rápido
Passo 1: Remova ZXing .NET.Maui.Controls e limpe o arquivo MauiProgram.cs.
Remova o pacote NuGet ZXing .NET .MAUI:
dotnet remove package ZXing.Net.Maui.Controls
ZXing.Net.MAUI requer uma chamada de registro única em MauiProgram.cs. Remova esta linha se ela estiver presente:
// Remover this line from MauiProgram.cs
builder.UseBarcodeReader();
A importação using ZXing.Net.Maui; que suporta esta chamada também pode ser removida de MauiProgram.cs.
Passo 2: Instale o IronBarcode
dotnet add package IronBarcode
O tutorial de scanner de código de barras .NET MAUI cobre a configuração completa do projeto, incluindo entradas de permissão de câmera Info.plist para iOS e declarações de permissão AndroidManifest.xml para Android.
Etapa 3: Atualizar Namespaces e Inicializar Licença
Remova as importações do namespace .NET.MAUI do ZXing de todos os arquivos:
// Remover these from every .cs file that imported them
using ZXing.Net.Maui;
using ZXing.Net.Maui.Controls;
Adicione o namespace IronBarcode e inicialize a chave de licença na inicialização do aplicativo. O local apropriado é MauiProgram.cs ou App.xaml.cs, antes de qualquer operação de código de barras ser realizada:
using IronBarCode;
// In MauiProgram.cs CreateMauiApp() or App.xaml.cs constructor
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";Imports IronBarCode
' In MauiProgram.vb CreateMauiApp() or App.xaml.vb constructor
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"Exemplos de migração de código
Substituindo o controle de câmera XAML e o código subjacente
O controle XAML CameraBarcodeReaderView e seu código de suporte são o principal alvo de migração. A alteração remove a visualização da câmera do layout da página e substitui o padrão de varredura orientado a eventos por uma captura assíncrona acionada por botão.
Abordagem ZXing .NET.MAUI:
XAML:
<ContentPage xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI.Controls">
<StackLayout>
<zxing:CameraBarcodeReaderView
x:Name="CameraView"
Options="{Binding ReaderOptions}"
BarcodesDetected="OnBarcodesDetected"
VerticalOptions="FillAndExpand" />
<Label x:Name="ResultLabel" Text="Scanning..." />
</StackLayout>
</ContentPage>
Código subjacente:
using ZXing.Net.Maui;
using ZXing.Net.Maui.Controls;
public partial class ScannerPage : ContentPage
{
public BarcodeReaderOptions ReaderOptions { get; }
public ScannerPage()
{
InitializeComponent();
ReaderOptions = new BarcodeReaderOptions
{
Formats = BarcodeFormats.QRCode | BarcodeFormats.Code128 | BarcodeFormats.Ean13,
TryHarder = true,
AutoRotate = true
};
BindingContext = this;
}
private void OnBarcodesDetected(object sender, BarcodeDetectionEventArgs e)
{
MainThread.BeginInvokeOnMainThread(() =>
{
foreach (var barcode in e.Results)
ResultLabel.Text = $"{barcode.Format}: {barcode.Value}";
});
CameraView.IsDetecting = false;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
CameraView.IsDetecting = false;
}
protected override void OnAppearing()
{
base.OnAppearing();
CameraView.IsDetecting = true;
}
}Imports ZXing.Net.Maui
Imports ZXing.Net.Maui.Controls
Public Partial Class ScannerPage
Inherits ContentPage
Public ReadOnly Property ReaderOptions As BarcodeReaderOptions
Public Sub New()
InitializeComponent()
ReaderOptions = New BarcodeReaderOptions With {
.Formats = BarcodeFormats.QRCode Or BarcodeFormats.Code128 Or BarcodeFormats.Ean13,
.TryHarder = True,
.AutoRotate = True
}
BindingContext = Me
End Sub
Private Sub OnBarcodesDetected(sender As Object, e As BarcodeDetectionEventArgs)
MainThread.BeginInvokeOnMainThread(Sub()
For Each barcode In e.Results
ResultLabel.Text = $"{barcode.Format}: {barcode.Value}"
Next
End Sub)
CameraView.IsDetecting = False
End Sub
Protected Overrides Sub OnDisappearing()
MyBase.OnDisappearing()
CameraView.IsDetecting = False
End Sub
Protected Overrides Sub OnAppearing()
MyBase.OnAppearing()
CameraView.IsDetecting = True
End Sub
End ClassAbordagem do IronBarcode:
XAML:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
<StackLayout>
<Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
<Label x:Name="ResultLabel" Text="Tap to scan..." />
</StackLayout>
</ContentPage>
Código subjacente:
// NuGet: dotnet add package IronBarcode
using IronBarCode;
public partial class ScannerPage : ContentPage
{
public ScannerPage() => InitializeComponent();
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var first = results.FirstOrDefault();
ResultLabel.Text = first != null
? $"{first.Format}: {first.Value}"
: "No barcode found";
}
// Não OnAppearing or OnDisappearing required — no camera state exists between scans
}
O namespace XAML zxing:, a lista de formatos BarcodeReaderOptions, o invólucro MainThread.BeginInvokeOnMainThread() e ambas as substituições de ciclo de vida são eliminados inteiramente. A continuação do método async roda no contexto de chamada — que é a thread principal para um manipulador de eventos de IU — portanto, não é necessário um checkpoint explícito de marshalling de threads.
Removendo a especificação de formato
Qualquer bloco de configuração BarcodeReaderOptions disperso por várias páginas ou cenários de escaneamento na base de código é deletado. O IronBarcode realiza a detecção automática de formatos em todos os mais de 50 formatos suportados, sem necessidade de pré-configuração.
Abordagem ZXing .NET.MAUI:
// ZXing.Net.MAUI: every anticipated format must be listed explicitly
// Formats not listed here will silently fail to detect
var readerOptions = new BarcodeReaderOptions
{
Formats = BarcodeFormats.QRCode |
BarcodeFormats.DataMatrix |
BarcodeFormats.Aztec |
BarcodeFormats.Pdf417 |
BarcodeFormats.Code128 |
BarcodeFormats.Code39 |
BarcodeFormats.Ean13 |
BarcodeFormats.UpcA |
BarcodeFormats.Codabar,
TryHarder = true
};' ZXing.Net.MAUI: every anticipated format must be listed explicitly
' Formats not listed here will silently fail to detect
Dim readerOptions As New BarcodeReaderOptions With {
.Formats = BarcodeFormats.QRCode Or
BarcodeFormats.DataMatrix Or
BarcodeFormats.Aztec Or
BarcodeFormats.Pdf417 Or
BarcodeFormats.Code128 Or
BarcodeFormats.Code39 Or
BarcodeFormats.Ean13 Or
BarcodeFormats.UpcA Or
BarcodeFormats.Codabar,
.TryHarder = True
}Abordagem do IronBarcode:
// IronBarcode: no format configuration needed
// All formats are detected automatically on every read call
var results = BarcodeReader.Read(imageBytes);
// Optional: restrict to specific formats for performance tuning (not required for correctness)
var options = new BarcodeReaderOptions
{
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128
};
var tunedResults = BarcodeReader.Read(imageBytes, options);Imports IronBarcode
' IronBarcode: no format configuration needed
' All formats are detected automatically on every read call
Dim results = BarcodeReader.Read(imageBytes)
' Optional: restrict to specific formats for performance tuning (not required for correctness)
Dim options As New BarcodeReaderOptions With {
.ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128
}
Dim tunedResults = BarcodeReader.Read(imageBytes, options)O IronBarcode oferece dicas de formatação para cenários que exigem alto desempenho, mas são opcionais. Um código de barras em um formato não listado em um objeto de opções ainda será detectado e retornado.
Removendo o gerenciamento do ciclo de vida de detecção
Todos os OnAppearing e OnDisappearing substituem que existem para alternar CameraView.IsDetecting são removidos. Se essas substituições de método contiverem outra lógica de ciclo de vida de página, preserve essa lógica e remova apenas as linhas IsDetecting.
Abordagem ZXing .NET.MAUI:
// Required boilerplate on every page — omitting this causes camera resource leaks
protected override void OnDisappearing()
{
base.OnDisappearing();
if (CameraView != null)
CameraView.IsDetecting = false;
}
protected override void OnAppearing()
{
base.OnAppearing();
if (CameraView != null)
CameraView.IsDetecting = true;
}' Required boilerplate on every page — omitting this causes camera resource leaks
Protected Overrides Sub OnDisappearing()
MyBase.OnDisappearing()
If CameraView IsNot Nothing Then
CameraView.IsDetecting = False
End If
End Sub
Protected Overrides Sub OnAppearing()
MyBase.OnAppearing()
If CameraView IsNot Nothing Then
CameraView.IsDetecting = True
End If
End SubAbordagem do IronBarcode:
// Delete both methods if they contain only IsDetecting management.
// If they contain other logic, remove only the IsDetecting lines and keep the rest.
//IronBarcode is stateless — there is no camera view running between button taps.
Windows MAUI: O mesmo código, sem compilação condicional
Com o ZXing .NET.MAUI, adicionar um alvo Windows a um projeto resultava em falha de compilação ou exigia stubs específicos da plataforma, pois a implementação para Windows nunca havia sido escrita. Com o IronBarcode, o mesmo código que roda no iOS e no Android compila e roda no Windows sem modificações.
Abordagem ZXing .NET.MAUI:
// Windows MAUI: either fails to compile or requires a platform-specific stub
// There is no documented path to Windows support
#if ANDROID || IOS
// ZXing.Net.MAUI scanning — Windows has no implementation
#endifnetAbordagem do IronBarcode:
// NuGet: dotnet add package IronBarcode
// Não platform conditionals — same code runs on iOS, Android, Windows, and macOS
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
No Windows, MediaPicker.CapturePhotoAsync() mapeia para o seletor de arquivos do Windows, permitindo que o usuário selecione um arquivo de imagem — comportamento apropriado para um ambiente de desktop. O guia de código de barras para desktop do MAUI aborda detalhadamente a configuração do MAUI no Windows e no macOS.
Leitura de código de barras em PDF (Nova funcionalidade)
O ZXing .NET.MAUI não possui uma API para leitura de códigos de barras em documentos PDF. Se este for um novo requisito que a migração possibilita, o seguinte padrão se aplica:
Abordagem ZXing .NET.MAUI:
// ZXing.Net.MAUI: no API for PDF or file-based barcode reading
// Cannot fulfill this requirement — a separate library is required' ZXing.Net.MAUI: no API for PDF or file-based barcode reading
' Cannot fulfill this requirement — a separate library is requiredAbordagem do IronBarcode:
// NuGet: dotnet add package IronBarcode
using IronBarCode;
// Read all barcodes from all pages of a PDF
var pdfResults = BarcodeReader.Read("invoice.pdf");
foreach (var barcode in pdfResults)
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Format} — {barcode.Value}");
// Read from a user-selected file using MAUI FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
var file = await FilePicker.PickAsync(new PickOptions
{
PickerTitle = "Select image or PDF"
});
if (file == null) return;
var fileResults = BarcodeReader.Read(file.FullPath);
foreach (var result in fileResults)
ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}Imports IronBarCode
' Read all barcodes from all pages of a PDF
Dim pdfResults = BarcodeReader.Read("invoice.pdf")
For Each barcode In pdfResults
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Format} — {barcode.Value}")
Next
' Read from a user-selected file using MAUI FilePicker
Private Async Sub ReadFileButton_Clicked(sender As Object, e As EventArgs)
Dim file = Await FilePicker.PickAsync(New PickOptions With {
.PickerTitle = "Select image or PDF"
})
If file Is Nothing Then Return
Dim fileResults = BarcodeReader.Read(file.FullPath)
For Each result In fileResults
ResultLabel.Text &= $"\n{result.Format}: {result.Value}"
Next
End SubO fluxo de trabalho completo de leitura de códigos de barras em PDF — incluindo documentos com várias páginas, metadados de número de página e documentos com formatos mistos — está documentado no guia de leitura de códigos de barras em PDF .
Referência de mapeamento da API .NET.MAUI do ZXing para o IronBarcode
| ZXing.Net.MAUI | IronBarcode | Notas |
|---|---|---|
builder.UseBarcodeReader() | Não é necessário | Remova de MauiProgram.cs |
using ZXing.Net.Maui; | using IronBarCode; | Substituição de namespace |
using ZXing.Net.Maui.Controls; | Não é necessário | Remover |
xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;..." | Não é necessário | Remover do XAML |
<zxing:CameraBarcodeReaderView> | <Button> + MediaPicker.CapturePhotoAsync() | Substituição arquitetônica |
Options="{Binding ReaderOptions}" | Não é necessário | Remover a ligação |
BarcodesDetected="OnBarcodesDetected" | valor de retorno BarcodeReader.Read() | Evento → retorno assíncrono |
new BarcodeReaderOptions { Formats = BarcodeFormats.X | ... } | Não é necessário | A detecção automática substitui as listas de formatação. |
BarcodeDetectionEventArgs e | IEnumerable<BarcodeResult> | Entrega de resultados diferenciada |
e.Results | Valor de retorno de BarcodeReader.Read() | |
barcode.Value | result.Value | Mesmo nome de propriedade |
barcode.Format | result.Format | Mesmo nome de propriedade |
BarcodeFormats.QRCode | BarcodeEncoding.QRCode | Renomear Enum |
BarcodeFormats.Code128 | BarcodeEncoding.Code128 | Renomear Enum |
BarcodeFormats.Ean13 | BarcodeEncoding.EAN13 | Renomear Enum |
BarcodeFormats.UpcA | BarcodeEncoding.UPCA | Renomear Enum |
CameraView.IsDetecting = false | Não é necessário | Remova de OnDisappearing |
CameraView.IsDetecting = true | Não é necessário | Remova de OnAppearing |
| Sem API de entrada de arquivos | BarcodeReader.Read("path/to/image.png") | Nova capacidade |
| Sem API de entrada de PDF | BarcodeReader.Read("document.pdf") | Nova capacidade |
| Somente para iOS e Android | iOS, Android, Windows, macOS, servidor | Expansão da plataforma |
Problemas e soluções comuns em migrações
Problema 1: Não existe equivalente ao visor eletrônico
ZXing.Net.MAUI: O CameraBarcodeReaderView exibe um feed contínuo de câmera no layout da página, mostrando ao usuário uma pré-visualização ao vivo com feedback de escaneamento sobreposto.
Solução: O IronBarcode não oferece um controle de visualização em tempo real. O padrão de substituição usa MediaPicker.CapturePhotoAsync(), que abre a IU da câmera de sistema da plataforma. A câmera do sistema oferece sua própria pré-visualização ao vivo e indicador de foco. Depois que o usuário captura a imagem e confirma, o resultado é passado para BarcodeReader.Read(). Se um observador persistente no aplicativo for um elemento de UX necessário que não pode ser substituído pela IU da câmera do sistema, a camada de integração da câmera deve ser construída separadamente usando Microsoft.Maui.Media ou APIs de câmera da plataforma, com IronBarcode lidando com a etapa de decodificação.
Questão 2: Declarações de permissão para uso da câmera
ZXing .NET.MAUI: As permissões da câmera podem ter sido declaradas no projeto como parte das instruções de configuração do ZXing .NET.MAUI.
Solução: Permissões de câmera permanecem necessárias para a chamada MediaPicker.CapturePhotoAsync() que o padrão MAUI do IronBarcode usa. Verifique se NSCameraUsageDescription está presente em Info.plist para iOS e se <uses-permission android:name="android.permission.CAMERA" /> está presente em AndroidManifest.xml para Android. O próprio IronBarcode não acessa a câmera diretamente — ele processa imagens — mas a chamada MediaPicker que fornece imagens requer permissão da câmera. A configuração de permissões é abordada no tutorial do leitor de código de barras .NET MAUI .
Problema 3: A compilação para Windows agora é bem-sucedida onde antes falhava.
ZXing .NET.MAUI: Projetos que tentavam incluir um alvo Windows com ZXing .NET.MAUI normalmente encontravam erros de compilação ou exigiam que a biblioteca fosse excluída da compilação do Windows por meio de lógica condicional do MSBuild.
Solução: Após remover o ZXing .NET.MAUI e instalar o IronBarcode, a compilação do MAUI para Windows é bem-sucedida sem quaisquer condições de plataforma. Remova qualquer #if ANDROID || As proteções do iOS foram colocadas em torno das chamadas .NET.MAUI do ZXing para excluí-las da compilação do Windows. A chamada BarcodeReader.Read() do IronBarcode compila e roda em todas as estruturas alvo. Se MediaPicker.CapturePhotoAsync() foi excluído das construções do Windows, essa exclusão também pode ser removida — o método é suportado noWindows MAUIe mapeia para o seletor de arquivos. Verifique se a solução completa é compilada sem erros para todas as estruturas de destino após a remoção das condições.
Edição 4: Referências da enumeração BarcodeFormats
ZXing.Net.MAUI: O enum BarcodeFormats de ZXing.Net.Maui é extensivamente utilizado em configurações BarcodeReaderOptions. Após a remoção do pacote, quaisquer referências restantes geram erros de compilação.
Solução: Delete todos os blocos de inicialização BarcodeReaderOptions que foram usados para configurar listas de formatos. O IronBarcode não exige especificação de formato para funcionar corretamente. Se algum código restante faz referência aos valores BarcodeFormats para fins de log, exibição ou comparação, substitua-os por valores BarcodeEncoding do namespace IronBarCode. Execute grep -rn "BarcodeFormats\." --include="*.cs" . para encontrar todas as referências restantes após a remoção do pacote.
Lista de verificação para migração do ZXing .NET.MAUI
Tarefas pré-migração
Antes de fazer alterações, verifique toda a utilização do .NET.MAUI do ZXing no código-fonte:
grep -rn "ZXing.Net.Maui" --include="*.cs" --include="*.xaml" .
grep -rn "CameraBarcodeReaderView" --include="*.cs" --include="*.xaml" .
grep -rn "BarcodeDetectionEventArgs" --include="*.cs" .
grep -rn "BarcodeReaderOptions" --include="*.cs" .
grep -rn "BarcodeFormats\." --include="*.cs" .
grep -rn "IsDetecting" --include="*.cs" .
grep -rn "UseBarcodeReader" --include="*.cs" .
grep -rn "zxing:" --include="*.xaml" .
grep -rn "e\.Results" --include="*.cs" .
Documente todas as páginas digitalizadas identificadas pela auditoria. Note quais substituições OnAppearing e OnDisappearing contêm apenas gerenciamento IsDetecting (a serem deletadas) versus aquelas que contêm outras lógicas (a serem parcialmente modificadas). Note quaisquer instâncias de BarcodeReaderOptions que possam conter listas de formatos usadas de formas além da configuração de detecção.
Tarefas de atualização de código
- Remova o pacote NuGet
ZXing.Net.Maui.Controlsdo arquivo de projeto - Remova
builder.UseBarcodeReader()deMauiProgram.cs - Remova as importações de namespaces
using ZXing.Net.Maui;eusing ZXing.Net.Maui.Controls;de todos os arquivos - Instale o pacote NuGet
IronBarcode - Adicione
using IronBarCode;a todos os arquivos que irão utilizar leitura de código de barras - Adicione
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";no início do aplicativo - Remova a declaração do namespace
xmlns:zxingde todos os arquivos XAML - Remova todos os elementos
<zxing:CameraBarcodeReaderView>dos arquivos XAML - Substitua a visualização da câmera removida por um controle
<Button>em cada arquivo XAML - Adicione
Clicked="ScanButton_Clicked"a cada botão de escaneamento - Exclua os métodos do manipulador de eventos
OnBarcodesDetectedde todos os arquivos de código-behind - Adicione métodos
async void ScanButton_ClickedimplementandoMediaPicker.CapturePhotoAsync()+BarcodeReader.Read()a cada página - Apague todos os blocos de inicialização
BarcodeReaderOptions - Apague todas as substituições
OnDisappearingeOnAppearingque existem apenas para gerenciamentoIsDetecting - Remova as linhas
IsDetectingde qualquer substituiçãoOnDisappearingeOnAppearingque contenham outras lógicas - Remova qualquer
#if ANDROID|| Mecanismos de proteção de compilação condicional do iOS que isolavam a compilação do .NET.MAUI do ZX das compilações do Windows. - Substitua qualquer referência restante ao enum
BarcodeFormats.Xpor equivalentesBarcodeEncoding.X
Testes pós-migração
Após a migração ser compilada sem erros, verifique o seguinte:
- Android MAUI: o botão de leitura abre a câmera do sistema, captura uma foto e retorna o código de barras correto — confirme com o guia de leitura do Android.
- iOS MAUI: o mesmo fluxo funciona no iOS, inclusive no hardware do iPhone 15 Pro, onde o problema de foco automático ocorria anteriormente.
- Windows MAUI: a versão para Windows compila sem erros e o botão de digitalização abre o seletor de arquivos e retorna um resultado correto da imagem selecionada.
- Formatos: teste a leitura de códigos de barras em formatos que não foram incluídos na lista antiga
BarcodeFormatspara confirmar a autodetecção - Navegação entre páginas: navegue até a página de digitalização e retorne a ela várias vezes e verifique se não ocorrem falhas no crescimento da memória ou na inicialização da câmera.
- Leitura de PDF: se a migração adicionar a leitura de código de barras em PDF como uma nova funcionalidade, verifique se os PDFs com várias páginas retornam resultados com os metadados de número de página corretos.
Principais benefícios da migração para o IronBarcode
Cobertura de plataforma expandida: após a migração, o aplicativo oferece suporte a plataformas MAUI para Windows e macOS, além de iOS e Android — tudo a partir do mesmo pacote e do mesmo padrão de verificação. Projetos que anteriormente exigiam stubs específicos para cada plataforma ou excluíam o Windows da funcionalidade de código de barras agora possuem cobertura completa sem código adicional.
Confiabilidade de Hardware de Última Geração: A abordagem de captura de imagem por meio de MediaPicker e BarcodeReader.Read() não é afetada pelo modelo de autofoco CameraBarcodeReaderView que falha no hardware do iPhone 15 Pro e Pro Max. A câmera do sistema gerencia o foco de forma independente, e o IronBarcode processa a imagem capturada após o usuário confirmar a foto.
Eliminação do Gerenciamento de Recursos da Câmera: Remover CameraBarcodeReaderView elimina toda a categoria de bugs de vazamento de recursos da câmera. Não há estado IsDetecting a rastrear, nem boilerplate de OnAppearing e OnDisappearing a manter em cada página de escaneamento, e nem acumulação de recursos da câmera em ciclos de navegação. A API sem estado torna as páginas de varredura indistinguíveis de qualquer outra página em termos de ciclo de vida do recurso.
Cobertura de formatos sem configuração: qualquer formato de código de barras encontrado em campo é detectado automaticamente. Falhas de escaneamento causadas por entradas ausentes em uma lista BarcodeFormats são eliminadas. As solicitações de suporte de usuários cujos códigos de barras foram ignorados silenciosamente porque um fornecedor alterou o formato da etiqueta deixaram de ocorrer.
Processamento de Arquivos e Documentos: A migração possibilita a leitura de códigos de barras em documentos PDF, arquivos de imagem e fluxos de bytes sem a necessidade de bibliotecas adicionais. Fluxos de trabalho que antes estavam fora do escopo do ZXing.Net.MAUI — leitura de códigos de barras de faturas enviadas, processamento de ingressos digitais, escaneamento em lote de diretórios de imagens — se tornam disponíveis através da mesma chamada BarcodeReader.Read() usada para capturas de câmera.
Estabilidade de nível de produção: o IronBarcode é distribuído como uma versão comercial estável com um ritmo de desenvolvimento ativo, suporte comercial e atualizações regulares que acompanham os lançamentos da versão .NET . Auditorias de dependências, análises de composição de software e processos de aprovação Enterprise encontram uma biblioteca com suporte e um compromisso de manutenção documentado, em vez de um pacote de pré-lançamento da comunidade.

Curtis Chau é bacharel em Ciência da Computação (Universidade Carleton) e se especializa em desenvolvimento front-end, com experiência em Node.js, TypeScript, JavaScript e React. Apaixonado por criar interfaces de usuário intuitivas e esteticamente agradáveis, Curtis gosta de trabalhar com frameworks modernos e criar manuais bem estruturados e visualmente atraentes.