I am working on a Xamarin.iOS project, and have a MVVMCross value converter that takes a file extension string and returns the corresponding file icon as an UIImage
.
This converter is used in a file list. I found that when I'm scrolling the list, as soon as the MvxTableViewCell
is recycled, the UI converter is often invoked in the background thread for the recycled cell, making my code to throw an error complaining calling a UIKit method from a background thread.
It looks like in the latest version of MVVMCross, the old IMvxMainThreadDispatcher.RequestMainThreadAction
method is obsolete. The documentation recommends to use IMvxMainThreadAsyncDispatcher.ExecuteOnMainThreadAsync
method.
However, this method returns a Task
with no generic type. This obviously can't work with the Convert
method of the value converter which expects the UIImage
.
Is there a way to configure MVVMCross to always invoke the converter on UI thread?
Update:
Take the following code example:
public class FileIconConverter : MvxValueConverter<string, UIImage>
{
protected override UIImage Convert(string fileExtension, Type targetType, object parameter, CultureInfo culture)
{
// When this is called, it could be in a background thread.
// Since UIDocumentInteractionController.FromUrl requires to be called
// on the UI thread, it would throw the UIKitThreadAccessException.
return UIDocumentInteractionController.FromUrl(NSUrl.FromFilename("/tmp/generic" + fileExtension)).Icons[0];
}
}
Since you have not added any code here all I can do is give you a bit of speculative advice.
What you can do is use the InvokeOnMainThread
method of Xamarin.iOS
When you check the Xamarin.iOS documentation on Working with the UI Thread in Xamarin.iOS
You can see that you use this method to make the changes that are supposed to be made on the UI
InvokeOnMainThread ( () => {
// manipulate UI controls
});
First of all, if you check the code for IMvxMainThreadDispatcher.RequestMainThreadAction
at the MvvmCross's Git it is internally calling the same API!
So what you can do to your existing code is something like
public class FileIconConverter : MvxValueConverter<string, UIImage>
{
protected override UIImage Convert(string fileExtension, Type targetType, object parameter, CultureInfo culture)
{
UIImage image;
IMvxMainThreadAsyncDispatcher.ExecuteOnMainThreadAsync(()=>{
image=UIDocumentInteractionController.FromUrl
(NSUrl.FromFilename("/tmp/generic" + fileExtension)).Icons[0];
});
return image;
}
}