我用 UIBezierPath 和 CAShapeLayer 制作的箭头如何指向 UILabel 的确切中心?

How can an arrow that I make with UIBezierPath and CAShapeLayer point to exact center of a UILabel?

我使用 UIBezierPath 和 CAShapeLayer 绘制了一个矩形视图,箭头指向视图上方的标签。 我希望箭头指向“P”标签的确切中心,并且 iPhone11 模拟器显示我想要的结果。但是,当我在 iPhone8 模拟器上 运行 时,箭头没有指向标签的中心。

为什么箭头指向 iPhone8 模拟器上的标签右侧有点偏?

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel! //horizontally and vertically aligned

@IBOutlet weak var pointingView: UIView! // leading & trailing constraints: 0, height:200

override func viewDidLoad() {
    super.viewDidLoad()
    drawPointingView()
}

private func drawPointingView() {
    let path = UIBezierPath()
    path.move(to: CGPoint(x: 0, y: 0))
    path.addLine(to: CGPoint(x: 0, y: pointingView.frame.height))
    path.addLine(to: CGPoint(x: pointingView.frame.width, y: pointingView.frame.height))
    path.addLine(to: CGPoint(x: pointingView.frame.width, y: 0))
    //draw an arrow pointing out to the center cordinate of the label. 
    path.addLine(to: CGPoint(x: label.center.x + 15, y: 0))
    path.addLine(to: CGPoint(x: label.center.x, y: -18))
    path.addLine(to: CGPoint(x: label.center.x - 15, y: 0))
    path.close()
    
    let shape = CAShapeLayer()
    shape.fillColor = UIColor.blue.cgColor
    shape.path = path.cgPath
    shape.strokeColor = UIColor.lightGray.cgColor
    shape.lineWidth = 1
    pointingView.layer.addSublayer(shape)
 }
}

iPhone11模拟器

iPhone8模拟器

因为你在viewDidLoad画画,viewDidLoad太早了。您所依赖的所有这些值,例如 pointingView.frame.width尚不为人所知。你必须等到 after 他们才知道。否则你只会在错误的地方画画(事实上你就是这样)。

类似的东西是布局的结果,所以你必须等到 viewDidLayoutSubviews 第一次被调用之后。