我正试图弄清楚如何在控件的父视图上钩入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;
}
}
问题,正如在评论中所指出的,是我需要知道什么时候按钮的父视图被卸载,以便我可以处置订阅。我可以很容易地访问父视图,但是当父视图被卸载时,我找不到任何钩子来通知。
有人知道有什么方法可以做到这一点吗?
使用WillMoveToSuperView
代替MovedToSuperView
-它将被调用两次,一次当按钮被添加到视图(即=>订阅),一次当按钮即将被丢弃(其中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()
{
/* ... */
}
}