从子控件中检测ViewDidUnload

时间:2014-05-17 14:18:21

标签: c# ios .net xamarin system.reactive

我试图找出如何在控件的超级视图中加入ViewDidUnload。为了说明我需要这个的原因,请考虑我的ControlFactory类,它产生UIButton s(以及其他控件):

internal static class ControlFactory
{
        private static readonly IObservable<Unit> sharedDynamicTypeChanged = TinyIoCContainer.Current
            .Resolve<ISystemNotificationsService>()
            .DynamicTypeChanged
            .Publish()
            .RefCount();

        public static UIButton CreateButton()
        {
            return new DynamicTypeAwareButton(sharedDynamicTypeChanged, UIFont.PreferredHeadline);
        }
}

这里的想法是工厂生产的每个UIButton都会根据用户的动态类型设置自动缩放其字体。我的DynamicTypeAwareButton是一个内部类,如下所示:

private sealed class DynamicTypeAwareButton : UIButton
{
    private readonly IObservable<Unit> dynamicTypeChanged;
    private readonly UIFont font;
    private IDisposable subscription;

    public DynamicTypeAwareButton(IObservable<Unit> dynamicTypeChanged, UIFont font)
    {
        this.dynamicTypeChanged = dynamicTypeChanged;
        this.font = font;
    }

    public override void MovedToSuperview()
    {
        base.MovedToSuperview();

        // TODO: figure out when to subscribe/unsubscribe
        this.subscription = this.dynamicTypeChanged
            .StartWith(Unit.Default)
            .Subscribe(_ => this.UpdateFont());
    }

    private void UpdateFont()
    {
        this.Font = this.font;
    }
}

问题,如评论中所述,我需要知道按钮的超级视图何时被卸载,以便我可以处理订阅。我可以很容易地访问超级视图,但是当卸载超级视图时,我找不到任何要通知的挂钩。

有谁知道实现这一目标的任何方法?

1 个答案:

答案 0 :(得分:1)

而不是MovedToSuperView使用WillMoveToSuperView - 它将被调用两次,一次将Button添加到View(即=&gt;订阅)时,以及一次当Button即将被删除时(其中newSuperview将为null)。

此外,您可以使用SerialDisposable

更优雅地写出来
private sealed class DynamicTypeAwareButton : UIButton
{
    private readonly IObservable<Unit> dynamicTypeChanged;
    private readonly UIFont font;
    private SerialDisposable subscription = new SerialDisposable();

    public override void WillMoveToSuperView(UIView newView)
    {
        base.WillMoveToSuperView();

        // Whenever SerialDisposable.Disposable is assigned, it throws
        // away the previous one. That means, even if the Button gets
        // moved to a new non-null View, we're still not leaking a 
        // subscription
        if (newView != null) 
        {
            this.subscription.Disposable = this.dynamicTypeChanged
                .StartWith(Unit.Default)
                .Subscribe(_ => this.UpdateFont());
        } 
        else 
        {
            this.subscription.Disposable = Disposable.Empty;
        }
    }

    public void UpdateFont()
    {
        /* ... */
    }
}