views:

292

answers:

3

iPHone: We use MonoTouch, but Obj-C answers are ok.

My singleton domain object takes a while to get all the data so it runs internally parts of the fetch in a thread.

I need to inform the UI that the domain is done. Currently I do this. Is there a better way? In WinForms I would call Application.DoEvents() instead of Thread Sleep.

PlanDomain domain = PlanDomain.Instance ();
while (domain.IsLoadingData)
{
    Thread.Sleep (100);  //this is the main UI thread
}

TableView.Hidden = false;
TableView.Source = new TableSource (this);
TableView.ReloadData ();
+1  A: 

I'd see if you can use performSelectorOnMainThread : move your Tableview code to its own method and call back to that when you are done with the loading data.

Delegates are also useful in this scenario - get your PlanDomain to callback to a delegate function when its done.

Simlarly, if you want something more detached, look at using NSNotification s. These are most useful when the code you write doesn't need to know or care what is going to happen when its finished - it just needs to announce to the world that its done its job. (Most useful where there is potentially more than one thing that may be interested in acting when its complete.

In any of these, you don't want sleeps - just let the runloop handle it.

Andiih
+2  A: 

Generally speaking you want to avoid DoEvents. The iPhone equivilant in objective-c looks something like this:

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
Lounges
+2  A: 

It would be better to have something derived from AlertView (a loading dialog), unless you want to perform background loading.

This then runs the task in a separate Thread which you Join and then close the dialog. There's an example here, but doesn't feature any threading however it's trivial to add:

public class LoadingView : UIAlertView
{
    private UIActivityIndicatorView _activityView;

    public void Show(string title)
    {
        Title = title;
        Show();

        // Spinner - add after Show() or we have no Bounds.
        _activityView = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.WhiteLarge);
        _activityView.Frame = new RectangleF((Bounds.Width / 2) - 15, Bounds.Height - 50, 30, 30);
        _activityView.StartAnimating();
        AddSubview(_activityView);

        // I haven't tested this, it should display the dialog still.
        Thread thread = new Thread(DoWork);
        thread.Start();
        thread.Join();

        Hide();
    }

    private void DoWork()
    {
        PlanDomain domain = PlanDomain.Instance ();
        while (domain.IsLoadingData)
        {
            // Maybe replace domain.IsLoadingData with an Event for when it finishes.
            // And then use a Mutex (WaitHandle) to communicate back
        }
    }

    public void Hide()
    {
        DismissWithClickedButtonIndex(0, true);
    }
}
Chris S