在更新底层模型时,定位、更新和/或添加或删除与该模型对应的SceneKit节点的最明智方法是什么?
我不知道如何最好地表达这个问题,所以可能更容易有一个最小的例子:
我有一些东西,比如说一组彩色物体,我可能想用Quartz二维表示为正方形,或者用SceneKit三维表示。由于这两种情况下的底层数据都是相同的,因此抽象掉模型并定义如下内容似乎更合适:
struct Foo {
var uid: String
var color: UIColor
var position: [Float] // array of 3 floats for x, y, z
}
然后我有:
var collectionOfFoo: [Foo]
然后我可以通过在我的CCD_ 1上循环并为每个CCD_
问题:用户可能会向collectionOfFoo
添加新的Foo
,或删除现有的Foo
,或更改现有Foo
的存储值之一,然后必须更新SceneKit场景以反映这一点。破坏场景并从头开始重建似乎很浪费,而且速度太慢了。这可能需要每秒调用数百次。
我目前的方法是:给与给定Foo
对应的SceneKit节点一个与Foo
的uid
匹配的名称,然后使用collectionOfFoo
0手动搜索节点层次结构。然而,这确实不能很好地扩展(低帧率),而且感觉"错误",好像有一种更容易/更习惯的方法可以做到这一点。我一直在研究像ReactiveCocoa
这样的东西,因为它似乎解决了这类问题,但我不确定这是否使事情过于复杂。
如果我使用Objective-C,我可能会尝试创建一个Foo
类,其中每个实例只包含一个指向相关SceneKit节点的指针;这不会很优雅,但至少会很有效,并会产生所需的结果。我只是在寻找一种更好的方法,一种在Swift中有效的方法。
建议非常受欢迎,也非常感谢——我仍在开发我的第一个应用程序,仍然认为自己是这方面的初学者。
我建议你看一看斯坦福大学的这门课程,并看一下MVC讲座:https://itunes.apple.com/gb/course/developing-ios-8-apps-swift/id961180099
他们建议使用NSNotification
提醒您的控制器(在您的情况下可能是您的SCNScene
)您的型号发生了变化。然后,控制器转到并更改其视图(在您的情况下为SCNNode
s)。这里有一个例子:
1.您的模型中发生了一些事情-创建了一个新的Foo
!因此,张贴NSNotification
:
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.postNotificationName("FooWasCreatedNotification",
object: nil,
userInfo: ["Foo": fooInstance])
(为了能够在这里传递Foo
的实例,Foo
需要是一个类,因为SCNBox
0 s不能添加到userInfo
)
2.在您的SCNScene
(或您正在使用的任何其他内容)中,接收NSNotification
并更新:
func didRevieveNewFooNotification(notification: NSNotification!) {
if let info = notification.userInfo as? Dictionary<String,AnyObject>,
let foo = info["Foo"] as? Foo {
// Create new node using foo's properties...
// And add it to the array:
collectionOfFoo.append(foo)
}
}
使用NSNotification
使您的模型非常便携,因为NSNotification
是盲通信。因此,您的控制器和节点可以是您想要的任何对象,而无需更改模型。
希望能有所帮助。
我对Swift了解不多,所以大部分内容可能都是错误的,但这里有一个疯狂的猜测:
为什么不切换到Class
而不是Struct
?您的代码不会有太大的变化,但它将帮助您存储SCNNode,以及任何其他图形表示以及您所拥有的数据。
如果这不可能,那用一本单独的词典怎么样?只需将SCNNode与已有的uid一起存储即可:
var nodes = [String: SCNNode]()
...
nodes[current.uid] = aNewNode
您也可以随时在场景中添加和删除节点,而无需"销毁和重建"。如果我们保留我之前的例子,你可以简单地做:
nodes[uidToDelete].removeFromParentNode()
顺便说一句,帧速率低可能与添加/删除节点的方式无关。试着在你的场景中启用统计数据,看看你在哪里浪费了时间。