简体   繁体   English

如何在自定义 UIView 中正确使用 intrincSize。 在哪里/何时计算和更新大小?

[英]How to correctly use intrincSize in custom UIView. Where/when to calculate and to update the size?

I have been trying to understand and utilize intrinsicSize on a custom UIView for some days now.几天来,我一直在尝试在自定义UIView上理解和利用intrinsicSize So far with little success.迄今为止收效甚微。

The post is quite long, sorry for that:-) Problem is, that the topic is quite complex.这篇文章很长,很抱歉:-) 问题是,这个话题很复杂。 While I know that there might be other solutions, I simply want to understand how intrinsicSize can be used correctly.虽然我知道可能有其他解决方案,但我只是想了解如何正确使用intrinsicSize

So when someone knows a good source for a in depth explanation on how to use / implement intrinsicSize you can skip all my questions and just leave me link.因此,当有人知道关于如何使用/实现intrinsicSize的深入解释的良好来源时,您可以跳过我的所有问题并留下链接。

My goal:我的目标:

Create a custom UIView which uses intrinsicSize to let AutoLayout automatically adopt to different content.创建一个自定义UIView ,它使用intrinsicSize让 AutoLayout 自动采用不同的内容。 Just like a UILabel which automatically resizes depending on its text content, font, font size, etc.就像UILabel根据其文本内容、字体、字体大小等自动调整大小一样。

As an example assume a simple view RectsView which does nothing but drawing a given number of rects of a given size with given spacing.举个例子,假设一个简单的视图RectsView ,它除了绘制给定数量的给定尺寸和给定间距的矩形之外什么都不做。 If not all rects fit into a single row, the content is wrapped and drawing is continued in another row.如果不是所有的矩形都适合一行,则内容被包装并在另一行中继续绘制。 Thus the height of the view depends on the different properties (number of rects, rects size, spacing, etc.)因此,视图的高度取决于不同的属性(矩形数量、矩形大小、间距等)

This is very much like a UILabel but instead of words or letters simple rects are drawn.这与UILabel非常相似,但绘制的不是单词或字母,而是简单的矩形。 However, while UILabel works perfectly I was not able to achive the same for my RectsView .然而,虽然UILabel工作得很好,但我无法为我的RectsView实现同样的效果。

Why intrinsicSize为什么intrinsicSize

As @DonMag pointed out in his excellent answers to my previous question, I do not have to use intrinsicSize to achieve my goal.正如@DonMag 在他对我之前的问题的出色回答中指出的那样,我不必使用intrinsicSize来实现我的目标。 I could also use subviews and add constraints to create such a rect pattern.我还可以使用子视图并添加约束来创建这样的矩形模式。 Or I could use a UICollectionView , etc.或者我可以使用UICollectionView等。

While this might certainly work, I think it would add a lot of overhead.虽然这肯定会奏效,但我认为它会增加很多开销。 If the goal would be to recreate a UILabel class, one would not use AutoLayout or a CollectionView to arrange the letters to words, would one?如果目标是重新创建UILabel class,则不会使用 AutoLayout 或 CollectionView 将字母排列成单词,对吗? Instead one would certainly try to draw the letters manually... Especially when using the RectsView in a TableView or a CollectionView a plain view with direct drawing is certainly better than a complex solution compiled of tons of subviews arranged using AutoLayout.相反,人们肯定会尝试手动绘制字母......尤其是在 TableView 或 CollectionView 中使用RectsView时,直接绘制的普通视图肯定比使用 AutoLayout 排列的大量子视图编译的复杂解决方案要好。

Of course this is an extreme example.当然,这是一个极端的例子。 However, at the bottom line there are cases where using intrinsicSize is certainly the better option.然而,归根结底,在某些情况下使用intrinsicSize肯定是更好的选择。 Since UILabel and other build in views uses intrinsicSize perfectly, there has to be a way to get this working and I just want to know how:-)由于UILabel和其他内置视图完美地使用了intrinsicSize ,因此必须有一种方法可以使其正常工作,我只想知道如何:-)

My understanding of intrinsic Size我对内在尺寸的理解

@DonMag suspected, that "I do not really understanding what intrinsicContentSize does and does not do" . @DonMag 怀疑, “我并不真正了解 intrinsicContentSize 做什么和不做什么” He is most likely correct:-) However, the problem is that I found no source which really explains it... Thus I have spend several hours trying to understand how to correctly use intrinsicSize without little progress.他很可能是正确的:-) 然而,问题是我没有找到真正解释它的来源......因此我花了几个小时试图理解如何正确使用intrinsicSize而没有一点进展。

This is what I have learned from the docs :这是我从文档中学到的:

  • intrinsicSize is a feature used in AutoLayout . intrinsicSizeAutoLayout中使用的一项功能。 Views which offer an intrinsic height and/or width do not need to specify constraints for these values.提供固有高度和/或宽度的视图不需要为这些值指定约束。
  • There is no guarantee that the view will exactly get its intrinsicSize .不能保证视图会准确地得到它的intrinsicSize It is more like a way to tell autoLayout which size would be best for the view while autoLayout will calculate the actual size.它更像是告诉 autoLayout 哪种尺寸最适合视图,而 autoLayout 将计算实际尺寸。
  • The calculation is done using the intrinsicSize and the Compression Resistance + Content Hugging properties.计算是使用intrinsicSizeCompression Resistance + Content Hugging属性完成的。
  • The calculation of the intrinsicSize should only depend on the content, not of the views frame. intrinsicSize的计算应该只取决于内容,而不是视图框架。

What I do not understand:我不明白的是:

  • How can the calculation be independend from the views frame?计算如何独立于视图框架? Of course the UIImageView can use the size of its image but the height of a UILabel can obviously only be calculated depending on its content AND its width.当然UIImageView可以使用其图像的大小,但UILabel的高度显然只能根据其内容和宽度来计算。 So how could my RectsView calculate its height without considering the frames width?那么我的RectsView如何在不考虑框架宽度的情况下计算它的高度呢?
  • When should the calculation of the intrinsicSize happen?什么时候应该计算intrinsicSize In my example of the RectsView the size depends on rect size, spacing and number.在我的RectsView示例中,大小取决于矩形大小、间距和数量。 In a UILabel the size also depends on multiple properties like text, font, font size, etc. If the calculation is done when setting each property it will be performed multiple times which is quite inefficient.UILabel中,大小还取决于多个属性,如文本、字体、字体大小等。如果在设置每个属性时进行计算,则会执行多次,这是非常低效的。 So what is the right place to do it?那么什么是正确的地方呢?

Example implementation:示例实现:

Here is a simple implementation of my RectsView :这是我的RectsView的简单实现:

@IBDesignable class RectsView: UIView {
    
    // Properties which determin the intrinsic height
    @IBInspectable public var rectSize: CGFloat = 20 {
        didSet {
            calcContent()
            setNeedsLayout()
        }
    }
    
    @IBInspectable public var rectSpacing: CGFloat = 10 {
        didSet {
            calcContent()
            setNeedsLayout()
        }
    }
    
    @IBInspectable public var rowSpacing: CGFloat = 5 {
        didSet {
            calcContent()
            setNeedsLayout()
        }
    }
    
    @IBInspectable public var rectsCount: Int = 20 {
        didSet {
            calcContent()
            setNeedsLayout()
        }
    }
    
    
    // Calculte the content and its height
    private var rects = [CGRect]()
    func calcContent() {
        var x: CGFloat = 0
        var y: CGFloat = 0
        
        rects = []
        if rectsCount > 0 {
            for _ in 0..<rectsCount {
                let rect = CGRect(x: x, y: y, width: rectSize, height: rectSize)
                rects.append(rect)
                
                x += rectSize + rectSpacing
                if x + rectSize > frame.width {
                    x = 0
                    y += rectSize + rowSpacing
                }
            }
        }
        
        height = y + rectSize
        invalidateIntrinsicContentSize()
    }
    
    
    // Intrinc height
    @IBInspectable var height: CGFloat = 50
    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIView.noIntrinsicMetric, height: height)
    }
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        invalidateIntrinsicContentSize()
    }
    
    
    // Drawing
    override func draw(_ rect: CGRect) {
        super.draw(rect)
                
        let context = UIGraphicsGetCurrentContext()
        
        for rect in rects {
            context?.setFillColor(UIColor.red.cgColor)
            context?.fill(rect)
        }
        
        
        let attrs = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: UIFont.systemFontSize)]
        let text = "\(height)"
        
        text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attrs)
    }
}

class ViewController: UITableViewController {
    let CellId = "CellId"

    // Dummy content with different values per row
    var data: [(CGFloat, CGFloat, CGFloat, Int)] = [
        (10.0, 15.0, 13.0, 35),
        (20.0, 10.0, 16.0, 28),
        (30.0, 5.0, 19.0, 21)
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: "IntrinsicCell", bundle: nil), forCellReuseIdentifier: CellId)
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: CellId, for: indexPath) as? IntrinsicCell ?? IntrinsicCell()
        
        // Dummy content with different values per row
        cell.rectSize = data[indexPath.row].0     // CGFloat((indexPath.row+1) * 10)
        cell.rectSpacing = data[indexPath.row].1  // CGFloat(20 - (indexPath.row+1) * 5)
        cell.rowSpacing = data[indexPath.row].2   // CGFloat(10 + (indexPath.row+1) * 3)
        cell.rectsCount = data[indexPath.row].3   // (5 - indexPath.row) * 7
        
        return cell
    }

    // Add/remove content when tapping on a row
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        var rowData = data[indexPath.row]
        rowData.3 = (indexPath.row % 2 == 0 ? rowData.3 + 5 : rowData.3 - 5)
        data[indexPath.row] = rowData
        tableView.reloadRows(at: [indexPath], with: .automatic)
    }
}


// Simple cell holing an intrinsic rectsView
class IntrinsicCell: UITableViewCell {
    @IBOutlet private var rectsView: RectsView!
        
    var rectSize: CGFloat {
        get { return rectsView.rectSize }
        set { rectsView.rectSize = newValue }
    }
    
    var rectSpacing: CGFloat {
        get { return rectsView.rectSpacing }
        set { rectsView.rectSpacing = newValue }
    }
    
    var rowSpacing: CGFloat {
        get { return rectsView.rowSpacing }
        set { rectsView.rowSpacing = newValue }
    }
    
    var rectsCount: Int {
        get { return rectsView.rectsCount }
        set { rectsView.rectsCount = newValue }
    }
} 

Problems:问题:

Basicly the intrinsicSize works fine: When the TableView is rendered for the first time each row has a different height depending on its intrinsic content.基本上, intrinsicSize工作正常:第一次呈现 TableView 时,每行根据其内在内容具有不同的高度。 However, the size is not correctly, since the intrinsicSize is calculated before the TableView actually layouts its subviews.但是,大小不正确,因为intrinsicSize是在TableView 实际布局其子视图之前计算的。 Thus the RectsView s calculate their content size using the default width instead of there acutal, final width.因此RectsView使用默认宽度而不是实际的最终宽度来计算它们的内容大小。

So: When/Where to calculate the initial layout?那么:何时/何处计算初始布局?

Additionally updates to the properties (= tapping on the cells) are not handled correctly此外,对属性的更新(= 点击单元格)未正确处理

So: When/Where to calculate the updated layout?那么:何时/何处计算更新的布局?

在此处输入图像描述

Again: Sorry for the long post and thank you very much if you have managed to read until here.再次:抱歉,很长的帖子,如果您能读到这里,非常感谢。 I really appreciate that!我非常感谢!

I you know any good source / tutorial / howto which explains all this, I happy about any link you can provide!我您知道任何可以解释所有这些的好的来源/教程/方法,我很高兴您可以提供任何链接!

UPDATE: Some more observations更新:更多观察

I have added some debug output to my RectsView and to a UILabel subclass to see how intrinsicContentSize is used.我在我的RectsViewUILabel子类中添加了一些调试 output 以查看如何使用intrinsicContentSize

In RectsView intrinsicContentSize is called only once before the bounds are set to their final size.RectsView intrinsicContentSize仅在边界设置为其最终大小之前调用一次。 Since at this point I not not know the final size yet, I can only calculate the intrinsic size based on the old, outdated width which leads to a wrong result.由于此时我还不知道最终尺寸,我只能根据旧的、过时的宽度来计算内在尺寸,这会导致错误的结果。

In UIView however, intrinsicContentSize is called multiple times ( why? ) and in the last call, the result seems to be fitting the upcoming, final size.然而,在UIView中, intrinsicContentSize被多次调用(为什么? ),在最后一次调用中,结果似乎适合即将到来的最终大小。 How can this size be known at this point?在这一点上如何知道这个大小?

RectsView willSet frame: (-120.0, -11.5, 240.0, 23.0)
RectsView didSet frame: (40.0, 11.0, 240.0, 23.0)
RectsView didSet rectSize: 10.0
RectsView didSet rectSpacing: 15.0
RectsView didSet rowSpacing: 20
RectsView didSet rectsCount: 35
RectsView get intrinsicContentSize: 79.0
RectsView willSet bounds: (0.0, 0.0, 240.0, 23.0)
RectsView didSet bounds: (0.0, 0.0, 350.0, 79.33333333333333)
RectsView layoutSubviews
RectsView layoutSubviews

MyLabel willSet frame: (-116.5, -9.5, 233.0, 19.0)
MyLabel didSet frame: (53.0, 13.0, 233.0, 19.0)
MyLabel willSet text: (53.0, 13.0, 233.0, 19.0)
MyLabel didSet text: (53.0, 13.0, 233.0, 19.0)
MyLabel get intrinsicContentSize: (65536.0, 20.333333333333332)
MyLabel get intrinsicContentSize: (675.0, 20.333333333333332)
MyLabel get intrinsicContentSize: (65536.0, 20.333333333333332)
MyLabel get intrinsicContentSize: (338.0, 40.666666666666664)
MyLabel get intrinsicContentSize: (65536.0, 20.333333333333332)
MyLabel get intrinsicContentSize: (65536.0, 20.333333333333332)
MyLabel get intrinsicContentSize: (338.0, 40.666666666666664)
MyLabel get intrinsicContentSize: (65536.0, 20.333333333333332)
MyLabel get intrinsicContentSize: (338.0, 40.666666666666664)
MyLabel willSet bounds: (0.0, 0.0, 233.0, 19.0)
MyLabel didSet bounds: (0.0, 0.0, 350.0, 41.0)
MyLabel layoutSubviews
MyLabel layoutSubviews

When called for the first time UILabel returns a intrinsic width of 65536.0 is this some constant?当第一次调用UILabel返回一个65536.0的固有宽度时,这是一些常数吗? I am only aware of UIView.noIntrinsicMetric = -1 which specifies, that the view does not have a instrinsic size in the given dimension.我只知道UIView.noIntrinsicMetric = -1指定视图在给定维度中没有内在大小。

Why, is intrinsicContentSize called multiple times on UILabel ?为什么, intrinsicContentSizeUILabel上被多次调用? I tried to return the same size (65536.0, 20.333333333333332) in RectsView but this does not make any difference, intrinsicContentSize is still only called once.我试图在RectsView中返回相同的大小(65536.0, 20.333333333333332) ,但这没有任何区别, intrinsicContentSize仍然只调用一次。

In the last call to intrinsicContentSize of UILabel the value (338.0, 40.666666666666664) is returend.在最后一次调用UILabelintrinsicContentSize时,返回值(338.0, 40.666666666666664) It seems that UILabel know at this point, that it will be re-sized to a width of 350 , but how?似乎UILabel在这一点上知道,它将被重新调整为350的宽度,但是如何?

Another oberservation is, that on both views intrinsicContentSize is NOT called after bounds.didSet .另一个观察是,在这两个视图上, intrinsicContentSizebounds.didSet之后都没有被调用。 Thus there has to be a way to know the upcomming frame changes in intrinsicContentSize before bounds.didSet .因此,必须有一种方法可以在bounds.didSet之前知道intrinsicContentSize中即将到来的帧变化。 How?如何?

UPDATE 2:更新 2:

I have added debug output to following, other UILabel methods as well, but they are not called (thus seem not to influence the problem):我已将调试 output 添加到以下其他UILabel方法中,但未调用它们(因此似乎不会影响问题):

sizeToFit()
sizeThatFits(_ :)
contentCompressionResistancePriority(for :)
contentHuggingPriority(for :)
systemLayoutSizeFitting(_ :)
systemLayoutSizeFitting(_ :, withHorizontalFittingPriority :, verticalFittingPriority:)
preferredMaxLayoutWidth  get + set

As @DonMag suggested I used a Technical Support Incident to get a feedback directly from an Apple engineer.正如@DonMag 建议的那样,我使用技术支持事件直接从 Apple 工程师那里获得反馈。 It took some time to get an answer but eventually it arrived:花了一些时间才得到答案,但最终还是到了:

Long story short: Do not use intrinsic size长话短说:不要使用内在大小

It seems that intrinsic size is more a less an internal feature which is not intended to be used by custom views.似乎内在大小更像是一个不打算由自定义视图使用的内部功能。 Of course it is not a private API and can be uses.当然它不是私有的 API 并且可以使用。 However, without (many) being uses along side with other private iOS features it is pretty limited and can hardly be used.但是,如果没有(很多)与其他私有 iOS 功能一起使用,它非常有限,几乎无法使用。

Apple suggested to use AutoLayout and constraints instead. Apple 建议改用 AutoLayout 和约束。 Even for such a basic example as a custom UILabel clone.即使对于像自定义 UILabel 克隆这样的基本示例也是如此。

Came across this question: UITableViewCell with intrinsic height based on width which seems to be a similar issue.遇到了这个问题: UITableViewCell with intrinsic height based on width这似乎是一个类似的问题。

That solution was to override systemLayoutSizeFitting(...) in the cell class.该解决方案是覆盖单元格 class 中的systemLayoutSizeFitting(...) Seems to work for your case -- with a necessary change in RectsView to re-calculate when bounds changes.似乎适用于您的情况 - 在RectsView中进行必要的更改以在bounds更改时重新计算。

See how this behaves for you:看看这对你有什么影响:

@IBDesignable class RectsView: UIView {
    
    // calcContent needs to be called
    //  when any of these values are changed
    
    // Properties which determin the intrinsic height
    @IBInspectable public var rectSize: CGFloat = 20 {
        didSet {
            calcContent(bounds.width)
        }
    }
    
    @IBInspectable public var rectSpacing: CGFloat = 10 {
        didSet {
            calcContent(bounds.width)
        }
    }
    
    @IBInspectable public var rowSpacing: CGFloat = 5 {
        didSet {
            calcContent(bounds.width)
        }
    }
    
    @IBInspectable public var rectsCount: Int = 20 {
        didSet {
            calcContent(bounds.width)
        }
    }
    
    // Calculte the content and its height
    private var rects = [CGRect]()
    
    // using newWidth parameter allows us to
    //  pass the new bounds width when
    //  the bounds is set
    func calcContent(_ newWidth: CGFloat) {
        var x: CGFloat = 0
        var y: CGFloat = 0
        
        rects = []
        if rectsCount > 0 {
            for i in 0..<rectsCount {
                let rect = CGRect(x: x, y: y, width: rectSize, height: rectSize)
                rects.append(rect)
                
                x += rectSize + rectSpacing
                if x + rectSize > newWidth && i < rectsCount - 1 {
                    x = 0
                    y += rectSize + rowSpacing
                }
            }
        }
        
        height = y + rectSize
        
        // need to trigger draw()
        setNeedsDisplay()
    }
    
    // Intrinsic height
    @IBInspectable var height: CGFloat = 10 {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }
    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIView.noIntrinsicMetric, height: height)
    }
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        invalidateIntrinsicContentSize()
    }
    
    // Drawing
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        let context = UIGraphicsGetCurrentContext()
        
        for rect in rects {
            context?.setFillColor(UIColor.red.cgColor)
            context?.fill(rect)
        }
        
        let attrs = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: UIFont.systemFontSize)]
        let text = "\(height)"
        
        text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attrs)
    }
    
    override var bounds: CGRect {
        willSet {
            calcContent(newValue.width)
        }
    }
}

// Simple cell holing an intrinsic rectsView
class IntrinsicCell: UITableViewCell {
    @IBOutlet var rectsView: RectsView!
    
    var rectSize: CGFloat {
        get { return rectsView.rectSize }
        set { rectsView.rectSize = newValue }
    }
    
    var rectSpacing: CGFloat {
        get { return rectsView.rectSpacing }
        set { rectsView.rectSpacing = newValue }
    }
    
    var rowSpacing: CGFloat {
        get { return rectsView.rowSpacing }
        set { rectsView.rowSpacing = newValue }
    }
    
    var rectsCount: Int {
        get { return rectsView.rectsCount }
        set { rectsView.rectsCount = newValue }
    }
    
    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        //force layout of all subviews including RectsView, which
        //updates RectsView's intrinsic height, and thus height of a cell
        self.setNeedsLayout()
        self.layoutIfNeeded()
        
        //now intrinsic height is correct, so we can call super method
        return super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
    }
    
}

class ViewController: UITableViewController {
    let CellId = "CellId"
    
    // Dummy content with different values per row
    var data: [(CGFloat, CGFloat, CGFloat, Int)] = [
        (10.0, 15.0, 13.0, 35),
        (20.0, 10.0, 16.0, 28),
        (30.0, 5.0, 19.0, 21),
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //tableView.register(UINib(nibName: "IntrinsicCell", bundle: nil), forCellReuseIdentifier: CellId)
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: CellId, for: indexPath) as! IntrinsicCell
        
        // Dummy content with different values per row
        cell.rectSize = data[indexPath.row].0     // CGFloat((indexPath.row+1) * 10)
        cell.rectSpacing = data[indexPath.row].1  // CGFloat(20 - (indexPath.row+1) * 5)
        cell.rowSpacing = data[indexPath.row].2   // CGFloat(10 + (indexPath.row+1) * 3)
        cell.rectsCount = data[indexPath.row].3   // (5 - indexPath.row) * 7
        
        return cell
        
    }
    
    // Add/remove content when tapping on a row
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        var rowData = data[indexPath.row]
        rowData.3 = (indexPath.row % 2 == 0 ? rowData.3 + 5 : rowData.3 - 5)
        data[indexPath.row] = rowData
        tableView.reloadRows(at: [indexPath], with: .automatic)
    }
} 

Edit编辑

Yes, that would be a work-around... although, if it solves the issue, maybe not such a bad thing.是的,这将是一种解决方法......尽管,如果它解决了问题,也许不是一件坏事。

As you've noted, UILabel can re-calculate its intrinsicContentSize correctly based on the final width -- which doesn't seem to be available in time for the way this code is written.正如您所指出的, UILabel可以根据最终宽度正确地重新计算其intrinsicContentSize ——这似乎无法及时用于编写此代码的方式。

Take a look at UILabel.h (search for iOS runtime headers), and you'll see a lot of things "under-the-hood" that we're not privy to.查看UILabel.h (搜索 iOS 运行时标头),您会看到很多我们不知道的“幕后”内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM