在 Swift 中的父类里面使用 IBInspectable 属性


作者:Jameson Quave 原文链接

  一个非常有用的功能就是在代码里面添加 IBInspectable 属性的背景图片。在一个娱乐类的应用里面,我写了一个可设计的 Cell,代码如下:

@IBDesignable
class TrailerCollectionViewCell: MediaCollectionViewCell {
    @IBOutlet weak var lengthLabel: UILabel!
    @IBInspectable weak var bgImage: UIImage! {
        didSet {
            imgView.frame = self.bounds
            self.addSubview(imgView)
            imgView.image = bgImage
            imgView.contentMode  = UIViewContentMode.Center
            self.sendSubviewToBack(imgView)
        }
    }
}

  这个代码的好处就是我可以很容易的在 Storyboard 里面去设置背景图片。因为背景图片的属性直接显示在 Storyboard 里,所以就很容易去设置 “播放” 的图形。

image

  注意: Storyboard 的 inspector 里面添加了 “Bg Image”。当你修改背景图片的时候 bgImage 代码里面的 didSet 代码块就会触发并在 Xcode 里面更新背景图片相关的视图。

  还有个麻烦的问题是我有另外两个 CollectionViewCell 的子类也需要这样的功能。这样,我用三个 Class 都继承自一个父类来实现:

import Foundation
import UIKit

class MediaCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var titleLabel: UILabel!
    var imgView = UIImageView()
    @IBInspectable weak var bgImage: UIImage! {
        didSet {
            imgView.frame = self.bounds
            self.addSubview(imgView)
            imgView.image = bgImage
            imgView.contentMode  = UIViewContentMode.Center
            self.sendSubviewToBack(imgView)
        }
    }
}

class TrailerCollectionViewCell: MediaCollectionViewCell {
    @IBOutlet weak var lengthLabel: UILabel!
}

class ReviewCollectionViewCell: MediaCollectionViewCell {
    @IBOutlet weak var ratingLabel: UILabel!
}

class PlaythroughCollectionViewCell: MediaCollectionViewCell {
    @IBOutlet weak var lengthLabel: UILabel!
    @IBOutlet weak var ratingLabel: UILabel!
}

但是,这样却不行Zephan

这样的问题是:这个 Bg image 字段在 Storyboard 里面不显示了!

我花了些时间来排查这个问题,解决方法就是在子类里面重写 bgImage 变量,但是不需要去重新实现 didSet 里面的代码。

修复技巧是加上这一行:

@IBInspectable override var bgImage: UIImage! { didSet {} }

完成之后代码会是这个样子:

import Foundation
import UIKit

class MediaCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var titleLabel: UILabel!
    var imgView = UIImageView()
    @IBInspectable weak var bgImage: UIImage! {
        didSet {
            imgView.frame = self.bounds
            self.addSubview(imgView)
            imgView.image = bgImage
            imgView.contentMode  = UIViewContentMode.Center
            self.sendSubviewToBack(imgView)
        }
    }
}

class TrailerCollectionViewCell: MediaCollectionViewCell {
    @IBOutlet weak var lengthLabel: UILabel!
    @IBInspectable override var bgImage: UIImage! { didSet {} }
}

class ReviewCollectionViewCell: MediaCollectionViewCell {
    @IBOutlet weak var ratingLabel: UILabel!
    @IBInspectable override var bgImage: UIImage! { didSet {} }
}

class PlaythroughCollectionViewCell: MediaCollectionViewCell {
    @IBOutlet weak var lengthLabel: UILabel!
    @IBOutlet weak var ratingLabel: UILabel!
    @IBInspectable override var bgImage: UIImage! { didSet {} }
}

Zephan:我自己通过 Xcode 7.2,子类继承自父类中的 IBInspectable 属性会在 Xcode 中显示(可能作者当时遇到的 Bug ),所以后面这段代码可以不需要,我是为了翻译,请大家注意了!