为啥不能将“UIView”类型的值转换为其他视图?

Posted

技术标签:

【中文标题】为啥不能将“UIView”类型的值转换为其他视图?【英文标题】:Why could not cast value of type 'UIView' to other View?为什么不能将“UIView”类型的值转换为其他视图? 【发布时间】:2018-10-21 12:35:12 【问题描述】:

这个问题与我之前的问题处理相同的代码。 (上一题是Why is this View nil in awakeFromNib()?) 但完全不同的方法。 这不是重复的问题。 所以让我重新构造我的问题。

首先,让我总结一下我的项目。

感谢之前的回答,我现在可以重用 xib。 这是 CardContentView.xib

代码如下

@IBDesignable class CardContentView: UIView 

    @IBOutlet weak var backgroundView: UIView!

    @IBInspectable var nibName:String?
    var contentView: UIView?


    override func awakeFromNib() 
        super.awakeFromNib()
        xibSetup()
    

    override func prepareForInterfaceBuilder() 
        super.prepareForInterfaceBuilder()
        xibSetup()
        contentView?.prepareForInterfaceBuilder()
    


    func xibSetup()
        guard let view = loadViewFromNib() else  return 
        view.frame = self.bounds
        view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        addSubview(view)
        contentView = view
    


    func loadViewFromNib() -> UIView? 
        guard let nibName = nibName else  return nil 
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: nibName, bundle: bundle)
        return nib.instantiate(withOwner: self, options: nil).first as? UIView
    

这是 CardView.xib,属性跟在 'class CardContentView' 之后

代码如下

class CardView: UIView 

    @IBOutlet weak var cardContentView: CardContentView!

    override func awakeFromNib() 
        cardContentView.layer.cornerRadius = 16
    

这是 Main.storyboard。使用单个 UIView。

代码如下

class ViewController: UIViewController 

    @IBOutlet weak var cardView: UIView!

    override func viewDidLoad() 
        super.viewDidLoad()
    

但是,我想在 ViewController 中将类 'CardView' 重用为 'cardView' 属性。 我想将 'background' 属性设置为 'cardView' 属性(简单来说,我想将 CardContentView 中的黄色框更改为蓝色框!)。 我想制作带有过渡效果的“cardView”属性。 但是,我无法进行扩展,因为它不在 UIView 类中,而是在 ViewController 类中。 所以我需要制作另一个 UIView 类。 这就是我单独制作 CardView 类的原因。 (当然,我想通过制作另一个文件来整齐地组织代码。)

所以,我尝试了 2 种不同的方法。

    将属性“cardView”类设置为 CardView,并将其连接到 ViewController。

    class ViewController: UIViewController 
    
        @IBOutlet weak var cardView: CardView!
    
        override func viewDidLoad() 
            super.viewDidLoad()
        
    
    

    将“CardView”类转换为 ViewController 中的其他属性

    override func viewDidLoad() 
        super.viewDidLoad()
    
        let tappedView = self.cardView as! CardView
        self.view.addSubview(tappedView)    
    
    

但他们都犯了错误。 1. 当我制作'@IBOutlet weak var cardView: CardView!'时,它会抛出错误消息,'Unexpectedly found nil while unwrapping an Optional value, cardContentView = nil'。 2.当我让'let tappedView = self.cardView as! CardView',它会抛出错误消息,'Could not cast value of type 'UIView' (0x10a229ff8) to 'AwakeFromNibTutorial.CardView' (0x1060aa8d0).'

我该如何解决这个问题? 请帮帮我!

【问题讨论】:

【参考方案1】: 在 CardView 类的 awakeFromNib() 中,您没有调用 super.awakeFromNib()。 您必须使用与从其对应的 XIB 加载 CardContentView 相同的逻辑 (xibSetup()),以便也从其 XIB 加载 CardView . 在情节提要的 ViewController 中,您是否已将 UIView 的类分配给 CardView

【讨论】:

1. 'super.awakeFromNib()' 仍然会出现错误 2. 怎么样? 3.当然是我分配的。 2.我试过但仍然抛出 'cardContentView = nil' plus, 'contentView = nil' 对于 CardView,在 IB 中,您似乎已将类名分配给 UIView,而不是文件的所有者。尝试更新它。 更新什么?在 CardView.xib 中,没有文件的所有者,将默认视图的类设置为“CardView”,将 UIView 类设置为“CardContentView”。

以上是关于为啥不能将“UIView”类型的值转换为其他视图?的主要内容,如果未能解决你的问题,请参考以下文章

无法将类型“(MapViewController).Type”(又名“MapViewController.Type”)的值转换为预期的参数类型“UIView”

为啥转换后的 UIView 会与层次结构中较高的其他视图重叠?

为啥我不能将 UIView 分配给 self.view?

无法将“UIView”类型的值转换为“SKView”(已删除情节提要)

无法将类型“(SwipeableTabBarController).Type”的值转换为预期的参数类型“UIView”

为啥我们不能把 UIView 的子视图放在它的 CALayer 前面?