ui 套件中的错误一致性错误

问题描述 投票:0回答:3

我在访问视图控制器 .cs 文件中的文本框时遇到问题

 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);
        }

正是在这个函数中,它抱怨无法访问 aynsc 方法上的文本框

    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");
        });
    }

出现错误的是这一行:

txtPassword.Text 

错误如下:

UIKit.UIKitThreadAccessException:UIKit一致性错误:你是 调用只能从 UI 线程调用的 UIKit 方法。

即使密码正确,我的密码正确也不会显示。 我必须在单独的线程上运行 UI 警报吗?

c# xamarin xamarin.ios
3个回答
29
投票

任何 UIKit 方法都必须从 UI 线程(或主线程、主队列等)调用。这确保了 UI 的一致性。 Xamarin 在调试模式下添加了对所有 UIKit 方法的检查,如果您尝试使用后台线程更改 UI,则会抛出该异常。

解决方案很简单:只从UI线程修改UI。这本质上意味着,如果您使用前面带有“UI”的类,您可能应该从 UI 线程执行此操作。 (这是一条经验法则,还有其他时间需要在 UI 线程上)。

如何在这个神秘的 UI 线程上获取我的代码?我很高兴你问了。在 iOS 中,您有几个选择:

  • 当在 NSObject 的子类中时,
    InvokeOnMainThread
    就可以了。
  • 无论在任何地方,
    CoreFoundation.DispatchQueue.MainQueue.DispatchAsync
    始终有效。

这两个方法都只接受

Action
,它可以是 lambda 或方法。

所以在你的代码中,如果我们添加一个

InvokeOnMainThread
(因为我认为这是在你的
UIViewController
子类中)...

 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");
    });
}

3
投票

也许这对某人有帮助。所以我会添加解决我的问题的内容,这与流氓相同。 在 iOS 中使用时遵循避免 xamarin 表单一致性错误的代码

 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);  

0
投票

不幸的是,最高分的答案并没有解决我的问题,但我最终通过忽略该问题来运行我的应用程序。不推荐,但确实有效。

我刚刚将行

UIApplication.CheckForIllegalCrossThreadCalls = false;
添加到我的
FinishedLaunching
覆盖

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     // code here
     UIApplication.CheckForIllegalCrossThreadCalls = false;    
     return base.FinishedLaunching(app, options);
}

代码在这里找到

© www.soinside.com 2019 - 2024. All rights reserved.