iPhone equivalent of Application.DoEvents();

2019-05-22 08:21发布

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 ();

4条回答
老娘就宠你
2楼-- · 2019-05-22 08:46

Just to follow-up on Lounges answer, here is a C# code example:

NSRunLoop.Current.RunUntil(DateTime.Now.AddMilliseconds(2000));

This will pause 2000 milliseconds, but ensure that the UI updates. I just used this in some test code.

查看更多
放荡不羁爱自由
3楼-- · 2019-05-22 08:50

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);
    }
}
查看更多
够拽才男人
4楼-- · 2019-05-22 08:56

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.

查看更多
Fickle 薄情
5楼-- · 2019-05-22 08:57

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

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
查看更多
登录 后发表回答