You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在UIView中绘制字符串时,NSString的draw(in: rect)方法自行修改rect参数

问题分析与解决办法

嘿,我来帮你搞定这个问题!先纠正代码里的关键错误,再解释你疑惑的draw(in:)方法的问题~

一、先改代码里的核心错误:不要手动调用draw(_:)方法

你在viewDidLoad里直接调用anotheR.draw(CGRect(...))是完全错误的!UIView的draw(_ rect: CGRect)方法是系统自动触发的——当视图第一次显示、调用setNeedsDisplay()标记需要重绘时,系统会自动创建合适的图形上下文,再调用这个方法。手动调用它不仅不会正确完成绘图,还可能导致上下文混乱,出现各种奇怪的问题。

正确的做法是:把绘图逻辑放到anotherView的draw(_:)方法里,系统会自动帮你调用。比如:

class anotherView: UIView {
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        // 在这里写你的绘图代码
        let textRect = CGRect(x: 100, y: 300, width: 50, height: 10)
        "要绘制的文本".draw(in: textRect, withAttributes: [
            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12)
        ])
    }
}

然后在ViewController里只需要把anotherView添加到父视图就好,不用手动调用draw:

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .yellow
    let anotherView = anotherView(frame: view.bounds)
    anotherView.backgroundColor = .lightGray
    view.addSubview(anotherView)
    // 如果之后需要更新绘图,调用这个方法,系统会自动触发draw(_:)
    // anotherView.setNeedsDisplay()
}

二、关于NSString.draw(in:)“修改rect”的疑惑

其实准确来说,这个方法不会修改你传入的原始rect参数——因为Swift里的结构体(比如CGRect)是值类型,方法参数默认是值传递,方法内部的修改不会影响外部的原始变量。你觉得rect被修改,大概率是这几种情况:

可能的原因

  1. 混淆了方法行为和参数修改:draw(in:)会在你指定的rect范围内绘制文本,但如果文本超出rect的大小,会被截断或者自动调整排版(比如换行),这看起来像是rect“变了”,但实际上只是文本在指定区域内的渲染逻辑,你的原始rect变量根本没被改动。
  2. 坐标系统的误解:UIKit的坐标原点在左上角,而Core Graphics默认原点在左下角。如果你混用了UIKit和Core Graphics的绘图方法,可能会导致绘制位置和预期不符,误以为是rect被修改了。不过NSString的draw(in:)是UIKit的方法,已经适配了UIKit的坐标,所以这个问题概率不大。
  3. 代码里复用了rect变量:如果你在调用draw(in:)前后,用同一个rect变量做了其他操作,可能是其他代码修改了它,而非draw(in:)的锅。

解决办法

  1. 独立使用绘图用的rect:在绘图时创建专门的rect变量,不要和其他逻辑复用,比如上面示例里的textRect,这样就能明确区分原始值和绘图用的值。
  2. 如果需要保留原始rect,创建副本:哪怕你担心意外修改,也可以直接复制一个rect来用,比如:
    let originalRect = CGRect(x: 100, y: 300, width: 50, height: 10)
    let drawingRect = originalRect // 创建副本
    "文本".draw(in: drawingRect)
    // 这里originalRect完全不受影响
    
  3. 检查绘图属性:如果文本显示位置不对,先检查字体大小、对齐方式这些属性,比如如果字体高度超过了rect的height,文本会被截断,看起来像是位置偏移,这时候调整rect的大小或者字体就好。

内容的提问来源于stack exchange,提问作者Ninja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:55:04