问题
I have an iOS Xamarin project were I am getting the following error:
UIKit Consistency error: you are calling a UIKit method that
can only be invoked from the UI thread.
This error occurs with the following code:
In my Welcome view page I have a button called SyncButton
that gets clicked. This click of the button is supposed to sync data with a server using REST.
In my WelcomeController I have:
....
SyncButton.TouchUpInside += async (object sender, EventArgs e) => {
SyncButton.Enabled = false;
await welcomeDelegate.syncButtonCore (cred, iOSErrorAlert);
SyncButton.Enabled = true;
};
....
public void iOSErrorAlert(string LoginErrorTitle, string LoginErrorMessage){
var Alert = UIAlertController.Create (LoginErrorTitle, LoginErrorMessage, UIAlertControllerStyle.Alert);
Alert.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Cancel, null));
PresentViewController (Alert, animated: true, completionHandler: null);
}
Alerts should happen when there is a timeout or some other error really.
The SyncButtonCore()
is contained in a delegate class that looks like this:
public async Task syncButtonCore(UserCredentials cred, RequestWithAlertDelegate.ErrorAlert NativeAlert){
await Task.Run (async ()=>{
RequestWithAlertDelegate requestWithAlert = new RequestWithAlertDelegate();
string URL = URLs.BASE_URL + URLs.CASELOAD + "/" + cred.PID;
await requestWithAlert.RequestWithRetry(URL, cred.UserID, cred.Password, NativeAlert, null, async delegate (string Response1){...}, 1);
Where my RequestWithAlert
class is:
public async Task RequestWithRetry (string URL, string UserID, string Password, ErrorAlert NativeAlert, SyncAction Action, AsyncAction Action2, int times)
{
...make sure legit credentials...
if (LoginError) {
NativeAlert (LoginErrorTitle, LoginErrorMessage);
}
Where I am getting my error at the NativeAlert() function in that last bit of code. Which ultimately throws the UIKit error mentioned at the beginning in my code at
var Alert = UIAlertController.Create (LoginErrorTitle, LoginErrorMessage, UIAlertControllerStyle.Alert);
I'm not sure what I am doing wrong here and why I am not allowed to create this alert because I define it in my WelcomeController
which is where my UIThread should be correct?
回答1:
Problem was in my iOSErrorAlert()
function. I needed to surround it with the InvokeOnMainThread()
because UI actions should be performed in the main thread (which I was not doing because I was passing it around to other classes/threads). Thank you @Paulw11 for the comment.
Had to replace this:
public void iOSErrorAlert(string LoginErrorTitle, string LoginErrorMessage){
var Alert = UIAlertController.Create (LoginErrorTitle, LoginErrorMessage, UIAlertControllerStyle.Alert);
Alert.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Cancel, null));
PresentViewController (Alert, animated: true, completionHandler: null);
}
With this:
public void iOSErrorAlert(string LoginErrorTitle, string LoginErrorMessage){
InvokeOnMainThread (() => {
var Alert = UIAlertController.Create (LoginErrorTitle, LoginErrorMessage, UIAlertControllerStyle.Alert);
Alert.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Cancel, null));
PresentViewController (Alert, animated: true, completionHandler: null);
});
}
来源:https://stackoverflow.com/questions/37172290/ui-consistency-error-when-calling-ios-alert