为什么 Swift 游乐场打印和循环两次?

Why is this Swift Playground Printing & Looping Twice?

我不明白为什么 for 循环和我打印的 所有内容 都在重复。

我可以发誓他们在我写for循环之前没有这样做,但我尝试重新启动Xcode;将代码复制到新的游乐场;注释掉最后几行;和谷歌搜索——无济于事。

prints 在显然被第二次执行之前都执行了一次这一事实让我觉得不知何故整个事情被调用了两次,也许这也可以解释循环,但我只是不看看会发生什么。

我是 运行 Xcode 8.3.3 (8E3004b)(不是开发版)。

这是代码,下面是我得到的截图

//: I don't see why it's printing everything twice, or why the for loop is looping twice

import UIKit
import PlaygroundSupport


class CustomView: UIView {

    let pathCG: [CGPoint] = [CGPoint(x:50, y:300), CGPoint(x:100, y:350), CGPoint(x:230, y:350), CGPoint(x:230, y:120)]

    override func draw(_ rect: CGRect) {

        print("what the hell")
        print(pathCG)
        print(pathCG.dropLast().count)

        for v in 0...pathCG.dropLast().count {
            let segAngle = vecDirCG(vec: [pathCG[v], pathCG[(v+1) % 4]]) * 180/CGFloat.pi
        }
    }

    // MARK: get direction given two points
    func vecDirCG(vec: [CGPoint]) -> CGFloat {
        return atan2(-vec[1].y + vec[0].y, vec[1].x - vec[0].x)
    }
}

let containerView = CustomView(frame: CGRect(x: 0, y: 0, width: 250, height: 600))
containerView.backgroundColor = UIColor.orange

PlaygroundPage.current.liveView = containerView

编辑:这是接受@MohammadSadiq 的回答后的更新。它摆脱了双重印刷,但双重循环似乎仍然存在。但是,更改 pathCGCGPoint 的值只会更改循环的 第一个 结果,而不是第二个。现在我注意到在原始操场 中注释掉 container.backgroundColor 行已经 修复了(明显的)重复执行(循环),所以我认为这是某种缓存问题。

关于override func draw(_ rect: CGRect)

This method is called when a view is first displayed or when an event occurs that invalidates a visible part of the view.

你的线路

containerView.backgroundColor = UIColor.orange

可能导致 draw 接到另一个电话。

正如 luk2302 已经评论过的,在实际的应用程序中,很难预测何时或多少次 draw(_:) 被调用。而且 Playground 不是探索 draw(_:).

行为的好地方

在操场上:

import UIKit
import PlaygroundSupport

class CustomView: UIView {

    let pathCG: [CGPoint] = [CGPoint(x:50, y:300), CGPoint(x:100, y:350), CGPoint(x:230, y:350), CGPoint(x:230, y:120)]

    override func draw(_ rect: CGRect) {

        print(pathCG)

        for v in pathCG.indices {
            let segAngle = vecDirCG(vec: [pathCG[v], pathCG[(v+1) % pathCG.count]]) * 180 / .pi
        }
    }

    // MARK: get direction given two points
    func vecDirCG(vec: [CGPoint]) -> CGFloat {
        return atan2(-vec[1].y + vec[0].y, vec[1].x - vec[0].x)
    }
}

let containerView = CustomView(frame: CGRect(x: 0, y: 0, width: 250, height: 600))
print("---------- CustomView created ----------")
containerView.backgroundColor = .orange
print("---------- backgroundColor set ----------")
PlaygroundPage.current.liveView = containerView
print("---------- liveView set ----------")

输出:

draw [(50.0, 300.0), (100.0, 350.0), (230.0, 350.0), (230.0, 120.0)]
---------- CustomView created ----------
draw [(50.0, 300.0), (100.0, 350.0), (230.0, 350.0), (230.0, 120.0)]
---------- backgroundColor set ----------
---------- liveView set ----------

似乎 draw(_:) 被调用了两次,

  • 创建视图的新实例时
  • 修改时 backgroundColor 属性

但你不应该认为这种行为与实际应用程序中的行为相同。


在单视图应用程序中:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let containerView = CustomView(frame: CGRect(x: 0, y: 0, width: 250, height: 600))
        print("---------- CustomView created ----------")
        containerView.backgroundColor = .orange
        print("---------- backgroundColor set ----------")
        self.view!.addSubview(containerView)
        print("---------- addSubview finished ----------")
    }

}

class CustomView: UIView {

    let pathCG: [CGPoint] = [CGPoint(x:50, y:300), CGPoint(x:100, y:350), CGPoint(x:230, y:350), CGPoint(x:230, y:120)]

    override func draw(_ rect: CGRect) {

        print(#function, pathCG)

        for v in pathCG.indices {
            let segAngle = vecDirCG(vec: [pathCG[v], pathCG[(v+1) % pathCG.count]]) * 180 / .pi
        }
    }

    // MARK: get direction given two points
    func vecDirCG(vec: [CGPoint]) -> CGFloat {
        return atan2(-vec[1].y + vec[0].y, vec[1].x - vec[0].x)
    }
}

输出:

---------- CustomView created ----------
---------- backgroundColor set ----------
---------- addSubview finished ----------
draw [(50.0, 300.0), (100.0, 350.0), (230.0, 350.0), (230.0, 120.0)]

draw(_:) 仅在 addSubview 完成后调用一次。 (实际上,在上面的代码中,它是在 viewDidLoad 完成后调用的。)


Playground 保留了一些中间结果。对于 UIViews,它保留绘制的结果。 (这导致 draw(_:) 被调用。)但是在实际应用中,不会保留这种中间结果,因此可能不会在相同位置调用 draw(_:)