Exception handling
One way to report about exceptions on iOS
Go to Main.cs
file in iOS project and change existed code, like presented below:
static void Main(string[] args)
{
try
{
UIApplication.Main(args, null, "AppDelegate");
}
catch (Exception ex)
{
Debug.WriteLine("iOS Main Exception: {0}", ex);
var watson = new LittleWatson();
watson.SaveReport(ex);
}
}
ILittleWatson
interface, used in portable code, could look like this:
public interface ILittleWatson
{
Task<bool> SendReport();
void SaveReport(Exception ex);
}
Implementation for iOS project:
[assembly: Xamarin.Forms.Dependency(typeof(LittleWatson))]
namespace SomeNamespace
{
public class LittleWatson : ILittleWatson
{
private const string FileName = "Report.txt";
private readonly static string DocumentsFolder;
private readonly static string FilePath;
private TaskCompletionSource<bool> _sendingTask;
static LittleWatson()
{
DocumentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
FilePath = Path.Combine(DocumentsFolder, FileName);
}
public async Task<bool> SendReport()
{
_sendingTask = new TaskCompletionSource<bool>();
try
{
var text = File.ReadAllText(FilePath);
File.Delete(FilePath);
if (MFMailComposeViewController.CanSendMail)
{
var email = ""; // Put receiver email here.
var mailController = new MFMailComposeViewController();
mailController.SetToRecipients(new string[] { email });
mailController.SetSubject("iPhone error");
mailController.SetMessageBody(text, false);
mailController.Finished += (object s, MFComposeResultEventArgs args) =>
{
args.Controller.DismissViewController(true, null);
_sendingTask.TrySetResult(true);
};
ShowViewController(mailController);
}
}
catch (FileNotFoundException)
{
// No errors found.
_sendingTask.TrySetResult(false);
}
return await _sendingTask.Task;
}
public void SaveReport(Exception ex)
{
var exceptionInfo = $"{ex.Message} - {ex.StackTrace}";
File.WriteAllText(FilePath, exceptionInfo);
}
private static void ShowViewController(UIViewController controller)
{
var topController = UIApplication.SharedApplication.KeyWindow.RootViewController;
while (topController.PresentedViewController != null)
{
topController = topController.PresentedViewController;
}
topController.PresentViewController(controller, true, null);
}
}
}
And then, somewhere, where app starts, put:
var watson = DependencyService.Get<ILittleWatson>();
if (watson != null)
{
await watson.SendReport();
}