首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从xib文件加载视图时获取System.InvalidCastException

从xib文件加载视图时获取System.InvalidCastException
EN

Stack Overflow用户
提问于 2018-02-20 13:45:12
回答 2查看 120关注 0票数 1

我有一个xib文件- LoaderView.xib和相关的类LoaderView.cs,它包含一个用于显示加载文本的视图。当我尝试将它加载到主ViewController中时-

代码语言:javascript
复制
public override void ViewDidAppear()
{
   base.ViewDidAppear();

   NSBundle.MainBundle.LoadNibNamed("LoaderView", this, out NSArray arr);
   var view = Runtime.GetNSObject<LoaderView>(arr.ValueAt(0));
   view.Frame = View.Frame;
   View.AddSubview(view);
}

我把System.InvalidCastException放在这条线上-

代码语言:javascript
复制
var view = Runtime.GetNSObject<LoaderView>(arr.ValueAt(0));

奇怪的是,我并不是每次都会得到异常。当它工作时,我看到加载的文本与默认视图重叠-与ViewController关联。

谁能指出什么是显示加载、错误和空状态的最佳方式?我应该为它们单独设置ViewControllers吗?或者我可以有单独的xib文件,我可以从主视图控制器加载/卸载这些文件?如何从xib文件加载视图?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-03-07 19:04:38

问题出在arr内部。

在上图中,可以看到LoadNibNamed方法并不是每次都以相同的顺序返回arr中的顶级对象。这就是为什么代码-

代码语言:javascript
复制
var view = Runtime.GetNSObject<LoaderView>(arr.ValueAt(0));

不能每次都将arr的第0项强制转换为LoaderView类型。

解决方案是遍历数组,找到您的LoaderView类型的项。对于我的例子-我写了一个静态类,它有一个泛型方法LoadViewFromNib,它返回一个从NSView继承的T类型的视图。

代码语言:javascript
复制
public static class LoadNib
{
    static NSArray xibItems;
    static nuint index;


    public static T LoadViewFromNib<T>(string filename, NSObject owner) where T : NSView
    {
        NSBundle.MainBundle.LoadNibNamed(filename, owner, out xibItems);

        for (nuint i = 0; i < xibItems.Count; i++)
        {
            NSObject item = xibItems.GetItem<NSObject>(i);
            if (item is T)
            {
                index = i;
                break;
            }
        }

        return Runtime.GetNSObject<T>(xibItems.ValueAt(index));
    }
}

至于重叠问题,我发现一个子视图是透明的,除非它的背景被明确设置。

票数 1
EN

Stack Overflow用户

发布于 2018-06-23 07:06:53

这是Xamarin的文档问题。他们的文档说使用第0个索引,但实际情况是,数组顺序并不是确定性的。

Anagh给出的答案在技术上是最优的,但您可以使用Linq使其更简洁,而且它也非常适合作为扩展方法:

代码语言:javascript
复制
public static class NibLoadingExtension
{
    public static T LoadViewFromNib<T>(this T @null) where T : NSView
    {
        NSBundle.MainBundle.LoadNibNamed(typeof(T).Name, null, out var array);
        return NSArray.FromArray<NSObject>(array).OfType<T>().FirstOrDefault();
    }
}

不幸的是,因为你不能在没有实例的情况下调用C#中的扩展方法,所以你必须这样使用它:

代码语言:javascript
复制
var loaderView = default(LoaderView).LoadViewFromNib();

还有一个论点支持向每个单独的视图类添加一个静态Create()方法或其他方法,因为这样您就可以调用私有初始化器,如下所示:

代码语言:javascript
复制
public static LoaderView Create(ExampleDependency dependency)
{
    var model = dependency ?? throw new ArgumentNullException(nameof(dependency));
    NSBundle.MainBundle.LoadNibNamed(nameof(LoaderView), null, out var array);
    var view = NSArray.FromArray<NSObject>(array).OfType<LoaderView>().FirstOrDefault();
    view.Initialize(model);
    return view;
}

private void Initialize(ExampleDependency dependency)
{
    _privateField1 = dependency.Value1;
    _privateField2 = dependency.Value2;
    _privateField3 = dependency.Value3;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48878626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档