【问题标题】:Public properties are always null in ViewDidLoad in a custom TabBarController in MonoTouchMonoTouch 中自定义 TabBarController 中的 ViewDidLoad 中的公共属性始终为空
【发布时间】:2011-08-22 01:49:40
【问题描述】:

我一直在研究从 UITabBarController 派生的类。在最基本的层面上,我要做的是添加一个 BackgroundColor 属性和其他公共属性,我可以在构建 TabBarController 时在我的 AppDelegate 中实例化它们。

我遇到的问题是,当调用 ViewDidLoad 时,我可以让所有公共属性最终都为空,或者,我可以添加一个构造函数和一个 [Register] 属性,最终让属性不为空,但是 ViewControllers 属性(包含所有选项卡)变得莫名其妙地为空(即使您在 ViewDidLoad 中设置了它)。

显然,我需要这两件事都是真实的,但我缺少一些具体的东西。

即使我在 AppDelegate 中显式设置,以下代码版本始终会导致背景颜色为空:

public class TabBarController : UITabBarController
{
    public UIColor BackgroundColor { get; set; }

    public override ViewDidLoad()
    {
        base.ViewDidLoad();

        if(BackgroundColor != null) // Always null, even when set explicitly
        {
            var frame = new RectangleF(0.0f, 0.0f, this.View.Bounds.Size.Width, 46);
            UIView myTabView = new UIView(frame);
            myTabView.BackgroundColor = BackgroundColor;
            myTabView.Alpha = 0.5f;
            this.TabBar.InsertSubview(myTabView, 0);
        }

        // Add tabs here, which show up correctly (on default background color)
        ViewControllers = new UIViewController[] { one, two, three, etc };
    }
}

这里是显示正确背景颜色的编辑代码(属性不为空),但不允许 ViewControllers 属性为空,即使它只是在 ViewDidLoad 中设置:

[Register("TabBarController")]
public class TabBarController : UITabBarController
{
    public UIColor BackgroundColor { get; set; }

    // Added a binding constructor
    [Export("init")]
    public TabBarController() : base(NSObjectFlag.Empty)
    {

    }

    public override ViewDidLoad()
    {
        base.ViewDidLoad();

        if(BackgroundColor != null) // Hey, this works now!
        {
            var frame = new RectangleF(0.0f, 0.0f, this.View.Bounds.Size.Width, 46);
            UIView myTabView = new UIView(frame);
            myTabView.BackgroundColor = BackgroundColor;
            myTabView.Alpha = 0.5f;
            this.TabBar.InsertSubview(myTabView, 0);
        }

        // Tabs disappear, ViewControllers is always null
        ViewControllers = new UIViewController[] { one, two, three, etc };
        if(ViewControllers == null)
        {
            Console.WriteLine("Not bro");
        }
    }
}

如果我必须显式添加所有元素而无法在运行时访问公共属性,这显然会阻碍我编写一些自定义控件的能力。有谁知道我哪里出错了?

【问题讨论】:

  • “public override ViewDidLoad()”将无法编译。请提供足够完整的内容以对希望帮助您的人有用:-)

标签: c# controls xamarin.ios uitabbarcontroller viewdidload


【解决方案1】:

在调用 ViewDidLoad 之前必须发生一些事情。它们可以在构造函数中完成。但是以下 ctor 不好:

 public TabBarController() : base(NSObjectFlag.Empty)

因为它不允许 UITabController 默认 ctor 执行 - 它的工作是向 'init' 选择器发送消息。

我觉得你想要的有点像:

public class TabBarController : UITabBarController
{
    UIViewController one = new UIViewController ();
    UIViewController two = new UIViewController ();
    UIViewController three = new UIViewController ();

    private UIView myTabView;

    public UIColor BackgroundColor { 
        get { return myTabView.BackgroundColor; }
        set { myTabView.BackgroundColor = value; }
    }       

    public TabBarController()
    {
        var frame = new RectangleF(0.0f, 0.0f, this.View.Bounds.Size.Width, 46);
        myTabView = new UIView(frame);
        myTabView.Alpha = 0.5f;
        this.TabBar.InsertSubview(myTabView, 0);

        // Add tabs here, which show up correctly (on default background color)
        ViewControllers = new UIViewController[] { one, two, three };
    }
}

    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        TabBarController controller = new TabBarController ();
        // change background (to cyan) works before adding subview
        controller.BackgroundColor = UIColor.Cyan;
        window.AddSubview (controller.View);
        // change background (to blue) works after adding subview
        controller.BackgroundColor = UIColor.Blue;
... 

编辑: 删除了 .ctor 中的无操作背景设置。添加 FinishedLaunching 示例代码。

【讨论】:

  • 这有一些问题,即我想使用一个属性,而您在 ctor 中更改 BackgroundColor 的调用基本上是无操作的,但是使用基于 ctor 的方法并删除另一个ctors 具有在我的第一个示例中忽略 BackgroundColor 的效果,即使在保留 myTabView 时也是如此,但感谢您的努力。
  • 是的,它是无操作的(您可以删除它,它是我之前尝试的遗留物),但它确实允许您在控制器完成后选择背景颜色(此处不忽略)在不破坏初始化的情况下创建。我将编辑示例
  • 样本已编辑。无论如何,要点是有些事情只能在特定时间完成。添加一些 Console.WriteLine 行将在调用时向您显示(例如,当不调用“init”时,顺序会有所不同,这是您的两个示例之间的主要区别)。
  • 在查看了您编辑的样本后,我能够将这些点联系起来并让它发挥作用,谢谢!我仍然对这意味着如何组合感到困惑。例如,你能解释一下为什么简单地在 ctor 的前四行代码周围添加一个“if(BackgroundColor != null) { }”范围会导致 NullReferenceException 吗?当简单地访问属性时,似乎隐藏的支持字段正在引发异常......
  • IIRC 添加“if(BackgroundColor != null) { }”删除(未引起)NRE。问题是 ViewDidLoad 是从 .ctor 调用的(所以在设置属性之前)。尝试添加 Console.WriteLine(Environment.StackTrace);在几个地方。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多