如何创建一个显示带有可移动节点的图形的UIView?

时间:2018-04-12 20:30:54

标签: ios swift uiview drawing

请注意单词" graph"这里的意思是图论图,而不是统计图。

我正在尝试创建一个包含节点的图表,您可以在屏幕上移动它们。我决定使用自定义UIView子类 - NodeView来表示节点。为了使它可移动,我使用了CocoaPod SEDraggable

我决定整个图表将由另一个名为UIView的自定义GraphView绘制。此类具有graph属性,在设置时,它将首先从上一个图形中移除子视图(如果有)然后添加新的NodeView来绘制整个图形。然后我会拨打setNeedsDisplay,然后拨打draw(_:)

在重写的draw方法中,我将在节点之间绘制线条(边缘,用图表理论术语)。

现在我需要检测一个节点是否已被移动。当它们被移动时,我需要调用setNeedsDisplay来重绘线条。我环顾四周,明白这可以用KVO完成。但是,我的图表视图需要能够显示具有任意数量节点的图形。这意味着我将把我的节点放入一个数组中。根据这个post,KVOing数组是不可能的。

然后我尝试使用NSNotificationCenter但我很快发现没有关于何时从post移动视图的通知。

然后我发现了这个post,但OP使用KVO,由于上述原因,我不能使用KVO。此外,该帖子在Objective-C中,我无法理解。

如何创建这样的图形?我正朝着正确的方向前进吗?或者是否有一个我可以使用的技巧,不涉及在移动节点时重绘所有内容?我觉得重新绘制整个图表的每一帧都会很慢。

1 个答案:

答案 0 :(得分:0)

我发现我可以使用CADisplayLink执行此操作。 <{1}}移动时,我不是重新绘制线条,而是每帧重绘一次。

NodeView

// displayLink is a property of the GraphView class displayLink = CADisplayLink(target: self, selector: #selector(updateNodePositions)) displayLink.add(to: .main, forMode: .defaultRunLoopMode) // ... @objc func updateNodePositions() { // nodeViewsToNodes is a dictionary storing all the NodeViews as keys // and the corresponding Node (my model object) as values. So here // I am basically updating the model based on the view's positions for kvp in nodeViewsToNodes { kvp.value.x = kvp.key.frame.midX kvp.value.y = kvp.key.frame.midY } setNeedsDisplay() } 方法将根据模型绘制线条。