0

I'm trying to add some error handling (to cope with loses of network connectivity when initializing my view models as well as elsewhere) by having it publish a message that is picked up by my view models that will then do a ChangePresentation with a PresentationHint that causes my presenter (derived from MvxTouchViewPresenter) to do this:

this.MasterNavigationController.PopToRootViewController(false);

This occasionally works, but a lot of the time it doesn't, getting stuck on whatever view it was currently on and I see the message Unbalanced calls to begin/end appearance transitions for <MyView: 0x...>. I believe this is because sometimes the message is getting thrown before the view that was loading has had time to finish loading (the actual loading of data is asynchronous and fires up on another thread - hence the problem).

So my question is, is there a way to synchronize this so that instead of immediately popping to the root, it will finish what it's doing, then pop to the root? Or is there some better way to handle this?

4

1 回答 1

0

您的问题中没有足够的代码来弄清楚发生了什么。StackOverflow 上还有很多其他问题包含该错误消息 - 可能值得查看它们,看看是否有一个很好的解决方案来解决您的问题。eg UINavigationController popToRootViewController,然后立即push一个新视图


如果您确实想检测“完成加载”,那么这样做的方法是收听正在显示的 ViewControllers 中的 ViewDidAppear 消息。在 mvx 中,这很容易做到,因为所有 ViewController 都支持一个ViewDidAppearCalled事件,您可以轻松地将其连接到您的自定义演示器中:

    private readonly Queue<Action> _pendingActions = new Queue<Action>();
    private bool _isBusy;

    public override void Show(Cirrious.MvvmCross.Touch.Views.IMvxTouchView view)
    {
        if (_isBusy)
        {
            _pendingActions.Enqueue(() => Show(view));
            return;
        }

        _isBusy = true;
        var eventSource = view as IMvxEventSourceViewController;
        eventSource.ViewDidAppearCalled += OnViewAppeared;

        base.Show(view);
    }

    private void OnViewAppeared(object sender, MvxValueEventArgs<bool> mvxValueEventArgs)
    {
        _isBusy = false;
        var eventSource = sender as IMvxEventSourceViewController;
        eventSource.ViewDidAppearCalled -= OnViewAppeared;
        if (!_pendingActions.Any())
            return;

        var action = _pendingActions.Dequeue();
        action();
    }

    public override void ChangePresentation(Cirrious.MvvmCross.ViewModels.MvxPresentationHint hint)
    {
        if (_isBusy)
        {
            _pendingActions.Enqueue(() => ChangePresentation(hint));
            return;
        }

        base.ChangePresentation(hint);
    }

注意:此代码需要 3.0.13 或更高版本才能工作(ViewDidAppear在早期版本的某些视图控制器中存在错误)

如果您使用的是简单的 UINavigationController,实现类似效果的另一种方法是在该控制器上使用 Delegate - 请参阅https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationControllerDelegate_Protocol/Reference/Reference .html

于 2013-10-10T06:51:57.693 回答