我目前正在研究用Swift 3编写的SpriteKit游戏。
当我尝试使用SKShapeNodes初始化程序从存储在多维数组中的点生成init(splinePoints: UnsafeMutablePointer, count: Int)时,我发现我无法使用Swift的implicit bridging功能,即添加“&”在有问题的var前面,将它作为UnsafeMutablePointer传递给函数。
这是Xcode Playgrounds中错误再现的图像,包括错误:
错误读取
无法将'[CGPoint]'类型的值转换为预期的参数类型'CGPoint'
,尽管初始化引用明确指出它需要一个指向CGPoint数组的指针。即使在Apple provided example部分
也是如此从点创建形状节点,完全按照这种方式完成:
var points = [CGPoint(x: 0, y: 0),
CGPoint(x: 100, y: 100),
CGPoint(x: 200, y: -50),
CGPoint(x: 300, y: 30),
CGPoint(x: 400, y: 20)]
let linearShapeNode = SKShapeNode(points: &points,
count: points.count)
let splineShapeNode = SKShapeNode(splinePoints: &points,
count: points.count)
所以我的问题是为什么它不起作用,是否是编译器错误, 如果没有,我该如何解决它。
但请注意,在函数内部创建数组的副本,如...
func createPressurePointShape(arm: Int, finger: Int) {
var tempPoints = pointsArray[arm][finger]
let shapeNode = SKShapeNode.init(splinePoints: &tempPoints, count: pointsArray[arm][finger].count)
}
...对我来说不是一个解决方案,因为在我的实际应用程序中,变量只存在1帧,然后消失或者之后产生内存泄漏。事实上这可以让错误消失,虽然暗示了Swift或Xcode中的错误,而不是我的应用程序,但我不确定它。
提前感谢您的帮助。这是代码示例,如果有人想玩它:
//: Playground - noun: a place where people can play
import UIKit
import SpriteKit
let armCount = 4
let fingersPerArm = 4
let pressurePointsPerFinger = 3
private var pointsArray = [[[CGPoint]]](repeating: [], count: Int(armCount))
for armIndex in 0...Int(armCount - 1) {
for fingerIndex in 0...(fingersPerArm - 1) {
pointsArray[armIndex].append([])
for innerIndex in 0..<pressurePointsPerFinger {
pointsArray[armIndex][fingerIndex].append(CGPoint(x: 0.5, y: 0.5))
}
}
}
let exampleArm = 1
let exampleFinger = 1
func createPressurePointShape(arm: Int, finger: Int) {
let shapeNode = SKShapeNode.init(splinePoints: &pointsArray[arm][finger], count: pointsArray[arm][finger].count)
}
createPressurePointShape(arm: exampleArm, finger: exampleFinger)
答案 0 :(得分:2)
你说得对,这确实看起来像个错误。我有filed a report here。一个更简单的例子是:
func foo(_ ptr: UnsafeMutablePointer<Int>) {}
var arr = Array(repeating: Array(0 ..< 5), count: 5)
let i = 0
foo(&arr[i]) // Cannot convert value of type '[Int]' to expected argument type 'Int'
但我会对将&pointsArray[arm][finger][0]
传递给SKShapeNode
初始化者的建议保持警惕 - 发生工作,因为编译器只是传递地址数组中的第一个元素,但我不相信这是有保证的。编译器将第一个元素复制到临时元素,传递该临时元素的地址,然后写回数组同样有效。这将在初始化器中调用未定义的行为。
相反,我只是在SKShapeNode
上创建一个便利初始化程序,以便首先支持错误并使用更好的API:
extension SKShapeNode {
convenience init(splinePoints: inout [CGPoint]) {
self.init(splinePoints: &splinePoints, count: splinePoints.count)
}
}
func createPressurePointShape(arm: Int, finger: Int) {
let shapeNode = SKShapeNode(splinePoints: &pointsArray[arm][finger])
}
{p> inout
仍然不是完全令人满意的,因为我不相信传递的记忆会发生变异(真的是SKShapeNode
&#39; s API)。但是,如果inout
被取走并且临时可变变量被传递给init(splinePoints:count:)
,则数组的缓冲区将始终首先被复制(因为它需要被唯一引用),这可能是不可取。
答案 1 :(得分:1)
尝试像这样指向数组的第一个元素。
var finger = [CGPoint(x: 0.5, y: 0.5), CGPoint(x: 0.5, y: 0.5), CGPoint(x: 0.5, y: 0.5)]
var arm = [finger, finger, finger, finger]
var pointsArray = [arm, arm, arm, arm]
let exampleArm = 1
let exampleFinger = 1
func createPressurePointShape(arm: Int, finger: Int) {
let shapeNode = SKShapeNode.init(splinePoints: &pointsArray[arm][finger][0], count: pointsArray[arm][finger].count)
}
createPressurePointShape(arm: exampleArm, finger: exampleFinger)
答案 2 :(得分:0)
你可能错过了一个压力计数(每个手指),这是一个伪代码:
let examplePressuePointsPerFinger = 1
func createPressurePointShape(arm: Int, finger: Int, pressurePoint: Int) {
let shapeNode = SKShapeNode.init(splinePoints: &pointsArray[arm][finger][pressurePoint], count: pointsArray[arm][finger].count)
}
createPressurePointShape(arm: exampleArm, finger: exampleFinger, pressurePoint: examplePressuePointsPerFinger)