Xamarin iOS: Nem reagál az alkalmazás az értintésekre

Konzolban a hibaüzenet található, de az alkalmazás hiba nélkül kifordul, de az iOS 13.4.1-es verziót futtató eszközökön az érintések nem működnek.

Hiba a konzolban:

2020-04-12 15:25:09.177 PROJNAME.iOS[521:71276] <_UISystemGestureGateGestureRecognizer: 0x283c60b00>: Touch: Failed to receive system gesture state notification before next touch
2020-04-12 15:25:09.177 PROJNAME.iOS[521:71276] <_UISystemGestureGateGestureRecognizer: 0x283c60900>: Gesture: Failed to receive system gesture state notification before next touch

Megoldás: Visual Studio for Mac 8.5.1-es verzióról (vagy ennél kisebb verzióról) fel kell frissíteni a MacVS-t, a Windowsos verzójában a hiba a 16.5.2-től lett orvosolva.

https://github.com/xamarin/Xamarin.Forms/issues/10162

Xamarin Forms / iOS: Backspace detektálás Entryben

Androidtól eltérően, iOS-en az EntryRenderer nem rendelkezik overrideolható DispatchKeyEventtel. Viszont magának a UITextFieldnek van egy DeleteBackward metódusa, ami a visszatörlés esetén hívódik meg. Ahhoz, hogy ezt felüldefiniáljuk, örököltetnünk kell egy UITextField-et.

public class UITextFieldWithExtendedFuncionallity : UITextField
{
    public delegate void DeleteBackwardEventHandler(object sender, EventArgs e);

    public event DeleteBackwardEventHandler OnDeleteBackward;


    public void OnDeleteBackwardPressed()
    {
        if (OnDeleteBackward != null)
        {
            OnDeleteBackward(this, new EventArgs());
        }
    }

    public UITextFieldWithExtendedFuncionallity()
    {

    }

    public override void DeleteBackward()
    {
        base.DeleteBackward();
        OnDeleteBackwardPressed();
    }
}

Mivel ez egy natív Custom UserControl, ahelyett, ahogy StackOverFlow-n, és egyéb helyeken ajánlják, nem az EntryRenderer-ben fogjuk beállítani natív kontrolként. StackOverflow-on, és Xamarin Fórumon CTRL+C, CTRL-V kód működik jól, de nem tekinthető szép megoldásnak. Ezeken a helyeken azt ajánlják, hogy az EntryRenderer OnElementChanged metódusában hozzunk létre egy új példányt az általunk örököltetett natív usercontrolból, majd állítsuk be azt natív kontrolként. Ilyenkor létrejön feleslegesen egy UITextField, és mi is létrehozunk egy UITextField gyereket, és az előzőleg létrejött field feleslegesen került a memóriában lefoglalásra, feleslegesen fordított a készülék erőforrásokat a konstruktorok és egyéb inicializáló függvények és procedúrák megfuttatására.

Emiatt, létre kell hoznunk a natív egyedi usercontrolunkhoz egy Renderert a következőképp:

[assembly: ExportRenderer (typeof(Entry), typeof(UITextFieldWithExtendedFuncionallityRenderer))]  
namespace DemoApp.iOS.CustomControlRenderers
{
    public class UITextFieldWithExtendedFuncionallityRenderer : ViewRenderer<Entry, UITextFieldWithExtendedFuncionallity>
    {
        private UITextFieldWithExtendedFuncionallity nativeControl;

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            var model = e.NewElement;

            if (model == null)
            {
                return;
            }

            nativeControl = new UITextFieldWithExtendedFuncionallity();

            SetNativeControl(nativeControl);
        }
    }
}

Majd a Xamarin Forms Custom UserControl rendererjének ősét át kell állítani EntryRendererről az imént létrehozott rendererre.

public class NakedEntryRenderer : UITextFieldWithExtendedFuncionallityRenderer

Az Forms U.C. Elementchangedjében már elérhetőek a fent definiált delegatek.

protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                if(Control is UITextFieldWithExtendedFuncionallity nativeControl)
                {
                    nativeControl.OnDeleteBackward += NativeControl_OnDeleteBackward;
                }
            }
        }

        private void NativeControl_OnDeleteBackward(object sender, EventArgs e)
        {
            if(Element is CustomEntry formsEntry)
            {
                formsEntry.OnBackspacePressed();
            }
        }

A Forms-os UserControl-ban található BackspacePressed event az Androidos mintára épül.

public class CustomEntry: Entry
{
    public delegate void BackspaceEventHandler(object sender, EventArgs e);
 
    public event BackspaceEventHandler OnBackspace;
 
    public CustomEntry() { }
 
    public void OnBackspacePressed() 
    {
        if (OnBackspace != null)
        {
            OnBackspace(null, null);
        }
    }
}

KeyboardFlags.CapitalizeWord nem működik iOS-en

Ha úgy vesszük észre, hoyg a Keyboard.Create nem működik CapitalizeWord enumértékkel iOS-en, de Androidon igen, akkor gyanakodjunk a következőre:

FullNameEntry.Keyboard = Keyboard.Create(KeyboardFlags.CapitalizeWord);

A készülék beállításai között, az Általános / Billentyűzet menüpont alatt, ha nincs bekapcsolva az Auto-Capitalization, azaz az Automata nagybetűk funkció, az iOS figyelmenkívűl hagyja az általunk kódbol beállított értéket.

AppStore publish error: ITMS-90809 (Deprecated API Usage WebView-re [Xamarin])

Alkalmazás publikálásánál az AppStore-ban a következőt jelzi vissza az Apple:

ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of apps that use UIWebView APIs . See https://developer.apple.com/documentation/uikit/uiwebview for more information.

Ez azért van, mert a Xamarin Forms WebView implementációja a Xamarin Forms 4.4-es verziójánál kisebb verziókban a UIWebView-t használja platformspecifikus implementációként. (Forrás: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/webview?tabs=windows#performance)

"Therefore, since Xamarin.Forms 4.4, the Xamarin.Forms WebView is implemented on iOS by the WkWebView class, which supports faster browsing."

Főverzió frissítése után nem szabad dobnia a hibát a publikálásnál. Az alkalmazás publikálása ettől függetlenül végbemegy, amennyiben csak ez a hiba