Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error in ui kit Consistency error

I am having a issue accesing a text box in a view controller .cs file

 async partial void loginUser(UIButton sender)

{

    // Show the progressBar as the MainActivity is being loade


    Console.WriteLine("Entered email : " + txtEmail.Text);


        // Create user object from entered email
        mCurrentUser = mJsonHandler.DeserialiseUser(txtEmail.Text);
        try
        {

            Console.WriteLine("Starting network check");
            // Calls email check to see if a registered email address has been entered
            if (EmailCheck(txtEmail.Text) == true)
            {
                await  CheckPassword();
            }
            else
            {
                UIAlertView alert = new UIAlertView()
                {
                    Title = "Login Alert",
                    Message = "Incorrect email or password entered"
                };
                alert.AddButton("OK");
                alert.Show();

            }


        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("An error has occured: '{0}'", ex);
        }

It is within this funciton that it complains it cannot access a text box which is on a aynsc method

    public Task CheckPassword()
    {

   return Task.Run(() =>
    {
            // Creates instance of password hash to compare plain text and encrypted passwords.
            PasswordHash hash = new PasswordHash();
            // Checks password with registered user password to confirm access to account.
            if (hash.ValidatePassword(txtPassword.Text ,mCurrentUser.password)==true)
            {
                Console.WriteLine("Password correct");


                UIAlertView alert = new UIAlertView()
                {
                    Title = "Login Alert",
                    Message = "Password Correct Loggin In"
                };
                alert.AddButton("OK");
                alert.Show();
                //insert intent call to successful login here.

            }
            else
            {
                UIAlertView alert = new UIAlertView()
                {
                    Title = "Login Alert",
                    Message = "Incorrect email or password entered"
                };
                alert.AddButton("OK");
                alert.Show();

            }
            Console.WriteLine("Finished check password");
        });
    }

Its this line the error occurs:

txtPassword.Text 

The error is as follows:

UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.

Also my Password Correct does not show even though if it is a correct password. Do i have to run the UI Alerts on a seperate thread?

like image 479
c-sharp-and-swiftui-devni Avatar asked Aug 24 '16 10:08

c-sharp-and-swiftui-devni


2 Answers

Any UIKit methods must be called from the UI thread (or Main thread, Main queue, etc.). This ensures consistency in the UI. Xamarin adds a check to all UIKit methods in debug mode and throws that exception if you try to use a background thread to change the UI.

The solution is simple: only modify the UI from the UI thread. That essentially means if you're using a class with "UI" in front it, you should probably do it from the UI thread. (That's a rule of thumb and there are other times to be on the UI thread).

How do I get my code on this mythical UI thread? I'm glad you asked. In iOS, you have a few options:

  • When in a subclass of NSObject, InvokeOnMainThread will do the trick.
  • From anywhere, CoreFoundation.DispatchQueue.MainQueue.DispatchAsync will always work.

Both of those methods just accept an Action, which can be a lambda or a method.

So in your code, if we add an InvokeOnMainThread (because I think this is in your UIViewController subclass)...

 public Task CheckPassword()
 {

     return Task.Run(() =>
     {
        // Creates instance of password hash to compare plain text and encrypted passwords.
        PasswordHash hash = new PasswordHash();
        // Checks password with registered user password to confirm access to account.
        InvokeOnMainThread(() => {
            if (hash.ValidatePassword(txtPassword.Text ,mCurrentUser.password)==true)
            {
                Console.WriteLine("Password correct");


                UIAlertView alert = new UIAlertView()
                {
                    Title = "Login Alert",
                    Message = "Password Correct Loggin In"
                };
                alert.AddButton("OK");
                alert.Show();
                //insert intent call to successful login here.

            }
            else
            {
                UIAlertView alert = new UIAlertView()
                {
                    Title = "Login Alert",
                    Message = "Incorrect email or password entered"
                };
                alert.AddButton("OK");
                alert.Show();

            }
        });
        Console.WriteLine("Finished check password");
    });
}
like image 200
dylansturg Avatar answered Nov 06 '22 08:11

dylansturg


Maybe this helps someone. So I will add what solve my issue, that was the same of rogue. Follow the code that avoid this error of consistency in xamarin forms when used in iOS

 await Task.Run(async () =>
            {
                await Device.InvokeOnMainThreadAsync(async () =>
                {
                    await MaterialDialog.Instance.SnackbarAsync(message: "Bla bla bla",
                                           msDuration: MaterialSnackbar.DurationShort).ConfigureAwait(false);

                }).ConfigureAwait(false);

            }).ConfigureAwait(false);  
like image 3
Douglas Flores Avatar answered Nov 06 '22 09:11

Douglas Flores