In this episode we use UIKit Dynamics to create something fun: Rope! By attaching many segments together with attachments, we can simulate the physics of a rope. We also discover the best way to move an object on the screen in conjunction with existing attachments.
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() }