自定义 UILabel 视图未在 Interface Builder 中更新其框架

Posted

技术标签:

【中文标题】自定义 UILabel 视图未在 Interface Builder 中更新其框架【英文标题】:Custom UILabel View not updating it's frame in Interface Builder 【发布时间】:2019-10-14 22:13:39 【问题描述】:

我正在尝试为 Font Awesome 创建一个 UILabel,目前它似乎运行良好。我遇到的问题是,当我更改 prepareForInterfaceBuilder() 中标签的字体大小时,它不会反映在 Interface Builder 中。

这是我的代码:

import Foundation
import UIKit

@IBDesignable
class FALabel : UILabel 

    @IBInspectable
    private var icon: String = ""

    @IBInspectable
    private var weight: NSInteger = 0

    /**
     * The type for the Font Awesome Label
     */
    enum FAType 
        case Brands
        case Light
        case Regular
        case Solid
    

    override init(frame: CGRect) 
        super.init(frame: frame)
        setupView()
    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        setupView()
    

    /**
     * Prepare the view or the Interface Builder.
     */
    override func prepareForInterfaceBuilder() 
        super.prepareForInterfaceBuilder()
        setupView()
    

    /**
     * Set up the view.
     */
    func setupView() 
        let type: FAType =  
            switch self.weight 
            case 0:  return .Light
            case 2:  return .Solid
            case 3:  return .Brands
            default: return .Regular
            
        ()

        setFontAwesomeIcon(faType: type, size: self.font.pointSize, icon: FAIcons.iconNamed(name: self.icon))
        self.sizeToFit()
        self.frame = CGRect(x: self.frame.minX, y:self.frame.minY, width:self.frame.width, height:self.frame.height)
        self.invalidateIntrinsicContentSize()
    

    /**
     * Calculate the intrinsic content size.
     */
    override var intrinsicContentSize: CGSize 
        return CGSize(width: self.frame.width, height: self.frame.height)
    

    /**
     * Set the Font Awesome Icon for the label.
     *
     * - parameter fatype: The type to set.
     * - parameter size:   The size for the font.
     * - parameter icon:   The icon to use.
     */
    func setFontAwesomeIcon(faType: FAType, size: CGFloat, icon:String) 
        if faType == .Regular 
            self.font = UIFont(name: "FontAwesome5Pro-Regular", size: size)
         else if faType == .Solid 
            self.font = UIFont(name: "FontAwesome5Pro-Solid", size: size)
         else if faType == .Light 
            self.font = UIFont(name: "FontAwesome5Pro-Light", size: size)
         else if faType == .Brands 
            self.font = UIFont(name: "FontAwesome5Brands-Regular", size: size)
        
        self.text = icon
    


当我在 Interface Builder 中更改任何内容时,框架似乎保持相同的大小,但图标本身却像我想要的那样被绘制得更大。

我认为从prepareForInterfaceBuilder() 调用self.sizeToFit() 应该调整视图大小并更改那些15x18 尺寸,但似乎并非如此。

【问题讨论】:

【参考方案1】:

我认为任何尺寸相关的调整都应该放在layoutSubviews

override func layoutSubviews() 
   super.layoutSubviews()
   setupView()

您可能会使用prepareForInterfaceBuilder 来填充一些样本数据,例如在 IB 中进行预览,但您不应该回忆您在 init 方法中所做的设置(例如 setupView())。

您也可以省略我猜想的 init 方法并将所有内容简化为:

import Foundation
import UIKit

@IBDesignable
class FALabel : UILabel 

    @IBInspectable
    public var icon: String = ""  
        didSet  setupView()  
    

    @IBInspectable
    public var weight: NSInteger = 0  
        didSet  setupView()  
    

    override func layoutSubviews() 
        super.layoutSubviews()
        setupView()
    

    /**
     * The type for the Font Awesome Label
     */
    enum FAType 
        case Brands
        case Light
        case Regular
        case Solid
    

    /**
     * Set up the view.
     */
    func setupView() 
        let type: FAType =  
            switch self.weight 
            case 0:  return .Light
            case 2:  return .Solid
            case 3:  return .Brands
            default: return .Regular
            
        ()

        setFontAwesomeIcon(faType: type, size: self.font.pointSize, icon: FAIcons.iconNamed(name: self.icon))
        self.sizeToFit()
        self.frame = CGRect(x: self.frame.minX, y:self.frame.minY, width:self.frame.width, height:self.frame.height)
        self.invalidateIntrinsicContentSize()
    

    /**
     * Calculate the intrinsic content size.
     */
    override var intrinsicContentSize: CGSize 
        return CGSize(width: self.frame.width, height: self.frame.height)
    

    /**
     * Set the Font Awesome Icon for the label.
     *
     * - parameter fatype: The type to set.
     * - parameter size:   The size for the font.
     * - parameter icon:   The icon to use.
     */
    func setFontAwesomeIcon(faType: FAType, size: CGFloat, icon:String) 
        if faType == .Regular 
            self.font = UIFont(name: "FontAwesome5Pro-Regular", size: size)
         else if faType == .Solid 
            self.font = UIFont(name: "FontAwesome5Pro-Solid", size: size)
         else if faType == .Light 
            self.font = UIFont(name: "FontAwesome5Pro-Light", size: size)
         else if faType == .Brands 
            self.font = UIFont(name: "FontAwesome5Brands-Regular", size: size)
        
        self.text = icon
    

【讨论】:

以上是关于自定义 UILabel 视图未在 Interface Builder 中更新其框架的主要内容,如果未能解决你的问题,请参考以下文章

UILabel 未在 iOS8 中显示子视图

未在 UICollectionViewCell 中的 UILabel(或 UITextField)中设置文本

以编程方式创建的 UILabel 未在旋转时调整大小

存储在序列化视图中的子类 UILabel 不存储自定义变量

自定义 UICollectionViewCell 中的 UILabel 始终为空,无法更新文本

水平居中 UIToolbar 中的所有项目,包括使用 UILabel 的自定义视图