
This video is only available to subscribers. Start a subscription today to get access to this and 376 other videos.
Simulating Rope with UIKit Dynamics
Episode Links
- Source Code
- Creating a Rope with UI Dynamics - The inspiration for this screencast.
Initial Rope Class
class Rope : UIView {
var numSegments: Int = 1
var links: [UIView] = []
var originalFrame = CGRectZero
var segmentWidth: CGFloat {
get {
return originalFrame.size.width
}
}
var segmentLength: CGFloat {
get {
return originalFrame.size.height / CGFloat(numSegments)
}
}
required init(coder: NSCoder) {
super.init(coder: coder)
}
init(frame: CGRect, numSegments: Int, referenceView: UIView) {
self.numSegments = numSegments
self.originalFrame = frame
super.init(frame: referenceView.frame)
clipsToBounds = false
backgroundColor = UIColor.clearColor()
addLinks()
}
func addLinks() {
for var i = 0; i < numSegments; i++ {
let linkFrame = CGRectMake(
originalFrame.origin.x + 0,
originalFrame.origin.y + CGFloat(i) * segmentLength,
segmentWidth,
segmentLength
)
var link = UIView(frame: linkFrame)
link.backgroundColor = UIColor.clearColor()
addSubview(link)
links.append(link)
}
}
}
Here we just add the segments based on our current frame, adding them as subviews.
Adding Attachments Between the Segments
func addToAnimator(animator: UIDynamicAnimator) {
for (index, link) in enumerate(links) {
var attachment: UIAttachmentBehavior!
if index == 0 {
attachment = UIAttachmentBehavior(item: link,
offsetFromCenter: UIOffsetMake(0, -segmentLength/2.0),
attachedToAnchor: originalFrame.origin)
} else {
let previousLink = links[index-1]
attachment = UIAttachmentBehavior(item: link,
offsetFromCenter: UIOffsetMake(0, -segmentLength/2.0),
attachedToItem: previousLink,
offsetFromCenter: UIOffsetMake(0, segmentLength/2.0))
}
attachment.length = 1
attachment.damping = 1
attachment.frequency = 10
attachment.action = {
self.setNeedsDisplay()
}
animator.addBehavior(attachment)
}
}
We won't own an animator. Instead, a view controller will pass one to this class and we can add our attachments there. Here we add an attachment between each segment, and another one as an anchor for the first attachment.
Drawing the Rope
Right now our rope doesn't look much like rope, it looks like rectangular views held together by attachments. We can make something more realistic by drawing a path between each of the segments.
override func drawRect(rect: CGRect) {
var path = UIBezierPath()
path.lineCapStyle = kCGLineCapRound
path.lineJoinStyle = kCGLineJoinRound
path.lineWidth = segmentWidth
var start = links.first!.center
start.y -= segmentLength / 2.0
path.moveToPoint(start)
for link in links {
if link == links.first! {
continue
}
path.addLineToPoint(link.center)
}
UIColor.blueColor().setStroke()
path.stroke()
}