Alessandro Izzo Alessandro Izzo - 1 year ago 201
iOS Question

PCLStorage problems with Xamarin.iOS

I've written my application in Xamarin, tested first for Android and later for iOS. On Android all works fine, not in iOS. My problem is related to

PCLStorage
, that fails when read the content of file because
GetFileAsync
result is
null
, but not
CheckExistsAsync
result.

My code is:

public static async Task loadMyFile(Func<bool, Task> result) {
IFolder rootFolder = FileSystem.Current.LocalStorage;
await rootFolder.CheckExistsAsync("myfile.txt").ContinueWith(async (checkExistsTask) => {
if (checkExistsTask.Result == ExistenceCheckResult.FileExists) {
await rootFolder.GetFileAsync("myfile.txt").ContinueWith(async (getFileTask) => {
try
{
await getFileTask.Result.ReadAllTextAsync().ContinueWith(async (readTextTask) => {
try
{
if (!string.IsNullOrEmpty(readTextTask.Result))
{
doWork(readTextTask.Result);
await result(true);
return;
}
else
{
await result(false);
return;
}
}
catch (Exception e)
{
await result(false);
return;
}
});
}
catch (Exception e)
{
await result(false);
return;
}
});
} else {
await result(false);
return;
}
});
}


Any idea?
Thanks.

Answer Source

I have no idea why you are using ContinueWith here when you are awaiting your Tasks anyways.

I would probably write the code more like this:

public static async Task loadMyFile(Func<bool, Task> result) 
{
    IFolder rootFolder = FileSystem.Current.LocalStorage;
    var exists = await rootFolder.CheckExistsAsync("myfile.txt");
    if (exists == ExistenceCheckResult.FileExists) 
    {
        var file = await rootFolder.GetFileAsync("myfile.txt");
        try
        {
            var text = await file.ReadAllTextAsync();
            if (!string.IsNullOrEmpty(text))
            {
                doWork(text);
                await result(true);
                return;
            }
            else
            {
                await result(false);
                return;
            }
        }
        catch (Exception e)
        {
            await result(false);
            return;
        }
    } else {
        await result(false);
        return;                 
    }
}

This reads much more easily, and you get rid of an unnecessary try/catch.

You may want to add ConfigureAwait(false) to your Tasks, so you do not do so much context switching.

You could simplify your method a lot by getting rid of the callback and just return a bool as a result of your Task:

public static async Task<bool> loadMyFile() 
{
    IFolder rootFolder = FileSystem.Current.LocalStorage;
    var exists = await rootFolder.CheckExistsAsync("myfile.txt");
    if (exists == ExistenceCheckResult.FileExists) 
    {
        var file = await rootFolder.GetFileAsync("myfile.txt");
        try
        {
            var text = await file.ReadAllTextAsync();
            if (!string.IsNullOrEmpty(text))
            {
                doWork(text);
                return true;
            }
        }
        catch (Exception e)
        {
        }
    }

    return false;
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download