vovgou / loxodon-framework

An MVVM & Databinding framework that can use C# and Lua to develop games
MIT License
1.86k stars 363 forks source link

在FormattableTextMeshProUGUI & TemplateTextMeshProUGUI中Text.text会被自身的OnEnable设置为初始值 #38

Closed FirmianaMarsili closed 6 months ago

FirmianaMarsili commented 6 months ago

源代码:

        protected override void OnEnable()
        {
            base.OnEnable();
            Initialize();
        }

        public override void SetAllDirty()
        {
            base.SetAllDirty();
            Initialize();
        }

        protected virtual void Initialize()
        {
            SetText(BUFFER.Clear().Append(m_Template));//格式化为默认值
        }

重现步骤:

  1. 将任意Template or Formattable绑定数据模型
  2. 在Text激活状态下更新数据
  3. 将Text的状态关闭并再次激活
  4. 此时Text.text会被Initialize设置为Text.Format
vovgou commented 6 months ago

好的,我改一下

FirmianaMarsili commented 6 months ago
        GenericParameters<int, int,string> example;

        ViewModel = new FormattableViewModel();
        BindingSet<FormattableView, FormattableViewModel> bindingSet = this.CreateBindingSet(ViewModel);
        bindingSet.Bind(Example).For(v => v.Parameter1).To(vm => vm.Month);
        bindingSet.Bind(Example).For(v => v.Parameter2).To(vm => vm.Day);
        bindingSet.Bind(Example).For(v => v.Parameter3).To(vm => vm.Hour);

        protected internal override void OnParameterChanged()
        {
            try
            {
                if (m_Text == null || !m_Text.enabled)
                    return;

                m_Text.SetText(BUFFER.Clear().AppendFormat<P1, P2, P3>(m_Text.Format, parameter1, parameter2, Parameter3));
            }
            catch (Exception e)
            {
#if DEBUG
                if (Application.isEditor)
                    Debug.LogWarning(e);
#endif
                m_Text.SetText(BUFFER.Clear().Append(m_Text.Format));
            }
        }

另外在上述示例中,当GenericParameters存在引用类型时,在绑定Parameter1后更新视图会因为stringnull导致AppendFormat失败。在我两个版本的unity,2021.3.7f12022.3.14f1中测试一个表现为长时间卡顿,一个崩溃。需要避免混用,或者可以先绑定Parameter3

vovgou commented 6 months ago
        GenericParameters<int, int,string> example;

        ViewModel = new FormattableViewModel();
        BindingSet<FormattableView, FormattableViewModel> bindingSet = this.CreateBindingSet(ViewModel);
        bindingSet.Bind(Example).For(v => v.Parameter1).To(vm => vm.Month);
        bindingSet.Bind(Example).For(v => v.Parameter2).To(vm => vm.Day);
        bindingSet.Bind(Example).For(v => v.Parameter3).To(vm => vm.Hour);

        protected internal override void OnParameterChanged()
        {
            try
            {
                if (m_Text == null || !m_Text.enabled)
                    return;

                m_Text.SetText(BUFFER.Clear().AppendFormat<P1, P2, P3>(m_Text.Format, parameter1, parameter2, Parameter3));
            }
            catch (Exception e)
            {
#if DEBUG
                if (Application.isEditor)
                    Debug.LogWarning(e);
#endif
                m_Text.SetText(BUFFER.Clear().Append(m_Text.Format));
            }
        }

另外在上述示例中,当GenericParameters存在引用类型时,在绑定Parameter1后更新视图会因为stringnull导致AppendFormat失败。在我两个版本的unity,2021.3.7f12022.3.14f1中测试一个表现为长时间卡顿,一个崩溃。需要避免混用,或者可以先绑定Parameter3

真是一个奇怪的bug,下面的代码,第一次点击Unity的Play运行时,正确调用 Format(ReadOnlySpan format,object value, StringBuilder builder)这个函数,但是第二次点击Play,则调用的是 void Format(string format, object value, StringBuilder builder)函数,所以崩溃了。

IFormatter formatter = IFormatter.GetFormatter(); ReadOnlySpan format = new ReadOnlySpan(new char[] { 'a' }); formatter.Format(format, null, builder);

vovgou commented 6 months ago

使用这2个包吧,修复了

没别的办法,暂时将重载函数void Format(string format, object value, StringBuilder builder)注释掉了,避免调用紊乱

image