I'm running a template right out-of-the-box on a Mac. To test yourself, you can simply go to Visual Studio:
- File
- New Solution
- Multiplatform: App
- Tabbed Forms App
When running this on an iPhone device or iPhone emulator, the spinner at the top of the list will not stop spinning. I suspect it is due to this code in the shared forms project:
public class ItemsViewModel : BaseViewModel { public ObservableCollection<Item> Items { get; set; } public Command LoadItemsCommand { get; set; } public ItemsViewModel() { Title = "Browse"; Items = new ObservableCollection<Item>(); LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand()); MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) => { var newItem = item as Item; Items.Add(newItem); await DataStore.AddItemAsync(newItem); }); } async Task ExecuteLoadItemsCommand() { if (IsBusy) return; IsBusy = true; try { Items.Clear(); var items = await DataStore.GetItemsAsync(true); foreach (var item in items) { Items.Add(item); } } catch (Exception ex) { Debug.WriteLine(ex); } finally { IsBusy = false; } } }
Specifically, the fact that LoadItemsCommand = new Command(async () => await ExecuteLoadItemCommand()),
which, along with the method signature, is treating this like an async Task.
I though invoking Tasks as void was a big no-no because, among other reasons, the CLR state machine can't do anything with the result(s) of the task? Additionally, anything that this task changes that is being watched by some delegate, notable IsBusy, will not be impacted?
From BaseViewModel.cs:
public class BaseViewModel : INotifyPropertyChanged { public IDataStore<Item> DataStore => DependencyService.Get<IDataStore<Item>>(); bool isBusy = false; public bool IsBusy { get { return isBusy; } set { SetProperty(ref isBusy, value); } } ... }
From the view, specifically the spinner control, ItemsPage.xaml:
IsRefreshing="{Binding IsBusy, Mode=OneWay}"