From ba8c94beb5889d8285dc800519c49bdc513cf1dd Mon Sep 17 00:00:00 2001 From: stanchiang Date: Sun, 6 Mar 2016 11:45:28 -0800 Subject: [PATCH 1/5] set up view with objects and reset button; ready to start implementing gestures --- DragAndDrop.xcodeproj/project.pbxproj | 18 ++---- DragAndDrop/AppDelegate.swift | 3 + .../Base.lproj/LaunchScreen.storyboard | 6 +- DragAndDrop/Base.lproj/Main.storyboard | 25 -------- DragAndDrop/Info.plist | 2 - DragAndDrop/View.swift | 60 +++++++++++++++++++ DragAndDrop/ViewController.swift | 7 ++- 7 files changed, 77 insertions(+), 44 deletions(-) delete mode 100644 DragAndDrop/Base.lproj/Main.storyboard create mode 100644 DragAndDrop/View.swift diff --git a/DragAndDrop.xcodeproj/project.pbxproj b/DragAndDrop.xcodeproj/project.pbxproj index 4bafdca..a645711 100644 --- a/DragAndDrop.xcodeproj/project.pbxproj +++ b/DragAndDrop.xcodeproj/project.pbxproj @@ -9,10 +9,10 @@ /* Begin PBXBuildFile section */ 52C3B2371C7CD0BA00F3151C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C3B2361C7CD0BA00F3151C /* AppDelegate.swift */; }; 52C3B2391C7CD0BA00F3151C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C3B2381C7CD0BA00F3151C /* ViewController.swift */; }; - 52C3B23C1C7CD0BA00F3151C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23A1C7CD0BA00F3151C /* Main.storyboard */; }; 52C3B23E1C7CD0BA00F3151C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */; }; 52C3B2411C7CD0BA00F3151C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */; }; 52C3B24C1C7CD0BA00F3151C /* DragAndDropTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C3B24B1C7CD0BA00F3151C /* DragAndDropTests.swift */; }; + F6DCCAED1C8CBAE0005A8A4E /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6DCCAEC1C8CBAE0005A8A4E /* View.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -29,13 +29,13 @@ 52C3B2331C7CD0BA00F3151C /* DragAndDrop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DragAndDrop.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52C3B2361C7CD0BA00F3151C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 52C3B2381C7CD0BA00F3151C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 52C3B23B1C7CD0BA00F3151C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 52C3B2401C7CD0BA00F3151C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52C3B2421C7CD0BA00F3151C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52C3B2471C7CD0BA00F3151C /* DragAndDropTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DragAndDropTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52C3B24B1C7CD0BA00F3151C /* DragAndDropTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DragAndDropTests.swift; sourceTree = ""; }; 52C3B24D1C7CD0BA00F3151C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F6DCCAEC1C8CBAE0005A8A4E /* View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -79,7 +79,7 @@ children = ( 52C3B2361C7CD0BA00F3151C /* AppDelegate.swift */, 52C3B2381C7CD0BA00F3151C /* ViewController.swift */, - 52C3B23A1C7CD0BA00F3151C /* Main.storyboard */, + F6DCCAEC1C8CBAE0005A8A4E /* View.swift */, 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */, 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */, 52C3B2421C7CD0BA00F3151C /* Info.plist */, @@ -179,7 +179,6 @@ files = ( 52C3B2411C7CD0BA00F3151C /* LaunchScreen.storyboard in Resources */, 52C3B23E1C7CD0BA00F3151C /* Assets.xcassets in Resources */, - 52C3B23C1C7CD0BA00F3151C /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -199,6 +198,7 @@ files = ( 52C3B2391C7CD0BA00F3151C /* ViewController.swift in Sources */, 52C3B2371C7CD0BA00F3151C /* AppDelegate.swift in Sources */, + F6DCCAED1C8CBAE0005A8A4E /* View.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -221,14 +221,6 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 52C3B23A1C7CD0BA00F3151C /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 52C3B23B1C7CD0BA00F3151C /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -388,6 +380,7 @@ 52C3B2521C7CD0BA00F3151C /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 52C3B2531C7CD0BA00F3151C /* Build configuration list for PBXNativeTarget "DragAndDropTests" */ = { isa = XCConfigurationList; @@ -396,6 +389,7 @@ 52C3B2551C7CD0BA00F3151C /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/DragAndDrop/AppDelegate.swift b/DragAndDrop/AppDelegate.swift index 4357155..a52c550 100644 --- a/DragAndDrop/AppDelegate.swift +++ b/DragAndDrop/AppDelegate.swift @@ -16,6 +16,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. + window = UIWindow(frame: UIScreen.mainScreen().bounds) + window?.rootViewController = ViewController() + window?.makeKeyAndVisible() return true } diff --git a/DragAndDrop/Base.lproj/LaunchScreen.storyboard b/DragAndDrop/Base.lproj/LaunchScreen.storyboard index 2e721e1..716eb56 100644 --- a/DragAndDrop/Base.lproj/LaunchScreen.storyboard +++ b/DragAndDrop/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,8 @@ - + - + + @@ -15,7 +16,6 @@ - diff --git a/DragAndDrop/Base.lproj/Main.storyboard b/DragAndDrop/Base.lproj/Main.storyboard deleted file mode 100644 index 3a2a49b..0000000 --- a/DragAndDrop/Base.lproj/Main.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/DragAndDrop/Info.plist b/DragAndDrop/Info.plist index 40c6215..eabb3ae 100644 --- a/DragAndDrop/Info.plist +++ b/DragAndDrop/Info.plist @@ -24,8 +24,6 @@ UILaunchStoryboardName LaunchScreen - UIMainStoryboardFile - Main UIRequiredDeviceCapabilities armv7 diff --git a/DragAndDrop/View.swift b/DragAndDrop/View.swift new file mode 100644 index 0000000..313adaf --- /dev/null +++ b/DragAndDrop/View.swift @@ -0,0 +1,60 @@ +// +// View.swift +// DragAndDrop +// +// Created by Stanley Chiang on 3/6/16. +// Copyright © 2016 SantaClaraiOSConnect. All rights reserved. +// + +import UIKit + +class View: UIView { + + var draggableView:UIView! + var trashArea:UIView! + var resetButton:UIButton! + + override init(frame: CGRect) { + super.init(frame: frame) + + draggableView = initDraggableView() + addSubview(draggableView) + + trashArea = initTrashArea() + addSubview(trashArea) + + resetButton = initResetButton() + addSubview(resetButton) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func initDraggableView() -> UIView { + let view = UIView(frame: CGRectMake(100,100,100,100)) + view.backgroundColor = UIColor.orangeColor() + return view + } + + func initTrashArea() -> UIView { + let view = UIView(frame: CGRectMake(0, frame.height * 2 / 3,frame.width,frame.height / 3 - 50)) + view.backgroundColor = UIColor.lightGrayColor() + return view + } + + func initResetButton() -> UIButton { + let button = UIButton(frame: CGRectMake(0,frame.height - 50,frame.width, 50)) + button.setTitle("Reset", forState: UIControlState.Normal) + button.setTitleColor(UIColor.lightTextColor(), forState: UIControlState.Normal) + button.backgroundColor = UIColor.darkGrayColor() + +// TODO: learn more about what it means to pass target as self all the time + button.addTarget(self, action: "resetAction:", forControlEvents: UIControlEvents.TouchUpInside) + return button + } + + func resetAction(sender: UIButton){ + print("reset") + } +} diff --git a/DragAndDrop/ViewController.swift b/DragAndDrop/ViewController.swift index 824f5f5..6bac3fe 100644 --- a/DragAndDrop/ViewController.swift +++ b/DragAndDrop/ViewController.swift @@ -10,9 +10,13 @@ import UIKit class ViewController: UIViewController { + var mainView:View! + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. + self.view.backgroundColor = UIColor.whiteColor() + mainView = View(frame: self.view.frame) + self.view.addSubview(mainView) } override func didReceiveMemoryWarning() { @@ -20,6 +24,5 @@ class ViewController: UIViewController { // Dispose of any resources that can be recreated. } - } From c5f4c4c41d64ac4e4f514ba45d0ddac962c5bef7 Mon Sep 17 00:00:00 2001 From: stanchiang Date: Sun, 6 Mar 2016 13:01:00 -0800 Subject: [PATCH 2/5] instead of a handler class i'll subclass uiview and add draggability to it. --- DragAndDrop.xcodeproj/project.pbxproj | 4 ++++ DragAndDrop/DraggableView.swift | 21 +++++++++++++++++++++ DragAndDrop/View.swift | 14 ++++++++++---- DragAndDrop/ViewController.swift | 6 +++++- 4 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 DragAndDrop/DraggableView.swift diff --git a/DragAndDrop.xcodeproj/project.pbxproj b/DragAndDrop.xcodeproj/project.pbxproj index a645711..f66709a 100644 --- a/DragAndDrop.xcodeproj/project.pbxproj +++ b/DragAndDrop.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 52C3B23E1C7CD0BA00F3151C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */; }; 52C3B2411C7CD0BA00F3151C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */; }; 52C3B24C1C7CD0BA00F3151C /* DragAndDropTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C3B24B1C7CD0BA00F3151C /* DragAndDropTests.swift */; }; + F6BAF15C1C8CC49200B6BD66 /* DraggableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6BAF15B1C8CC49200B6BD66 /* DraggableView.swift */; }; F6DCCAED1C8CBAE0005A8A4E /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6DCCAEC1C8CBAE0005A8A4E /* View.swift */; }; /* End PBXBuildFile section */ @@ -35,6 +36,7 @@ 52C3B2471C7CD0BA00F3151C /* DragAndDropTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DragAndDropTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52C3B24B1C7CD0BA00F3151C /* DragAndDropTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DragAndDropTests.swift; sourceTree = ""; }; 52C3B24D1C7CD0BA00F3151C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F6BAF15B1C8CC49200B6BD66 /* DraggableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DraggableView.swift; sourceTree = ""; }; F6DCCAEC1C8CBAE0005A8A4E /* View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -79,6 +81,7 @@ children = ( 52C3B2361C7CD0BA00F3151C /* AppDelegate.swift */, 52C3B2381C7CD0BA00F3151C /* ViewController.swift */, + F6BAF15B1C8CC49200B6BD66 /* DraggableView.swift */, F6DCCAEC1C8CBAE0005A8A4E /* View.swift */, 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */, 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */, @@ -199,6 +202,7 @@ 52C3B2391C7CD0BA00F3151C /* ViewController.swift in Sources */, 52C3B2371C7CD0BA00F3151C /* AppDelegate.swift in Sources */, F6DCCAED1C8CBAE0005A8A4E /* View.swift in Sources */, + F6BAF15C1C8CC49200B6BD66 /* DraggableView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/DragAndDrop/DraggableView.swift b/DragAndDrop/DraggableView.swift new file mode 100644 index 0000000..56a7a50 --- /dev/null +++ b/DragAndDrop/DraggableView.swift @@ -0,0 +1,21 @@ +// +// Drag.swift +// DragAndDrop +// +// Created by Stanley Chiang on 3/6/16. +// Copyright © 2016 SantaClaraiOSConnect. All rights reserved. +// + +import UIKit + +class DraggableView: UIView { + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} \ No newline at end of file diff --git a/DragAndDrop/View.swift b/DragAndDrop/View.swift index 313adaf..5d36b25 100644 --- a/DragAndDrop/View.swift +++ b/DragAndDrop/View.swift @@ -8,12 +8,18 @@ import UIKit +protocol ViewDelegate { + func reset() +} + class View: UIView { - var draggableView:UIView! + var draggableView:DraggableView! var trashArea:UIView! var resetButton:UIButton! + var delegate:ViewDelegate! + override init(frame: CGRect) { super.init(frame: frame) @@ -31,8 +37,8 @@ class View: UIView { fatalError("init(coder:) has not been implemented") } - func initDraggableView() -> UIView { - let view = UIView(frame: CGRectMake(100,100,100,100)) + func initDraggableView() -> DraggableView { + let view = DraggableView(frame: CGRectMake(100,100,100,100)) view.backgroundColor = UIColor.orangeColor() return view } @@ -55,6 +61,6 @@ class View: UIView { } func resetAction(sender: UIButton){ - print("reset") + delegate.reset() } } diff --git a/DragAndDrop/ViewController.swift b/DragAndDrop/ViewController.swift index 6bac3fe..ee16532 100644 --- a/DragAndDrop/ViewController.swift +++ b/DragAndDrop/ViewController.swift @@ -8,7 +8,7 @@ import UIKit -class ViewController: UIViewController { +class ViewController: UIViewController, ViewDelegate { var mainView:View! @@ -16,6 +16,7 @@ class ViewController: UIViewController { super.viewDidLoad() self.view.backgroundColor = UIColor.whiteColor() mainView = View(frame: self.view.frame) + mainView.delegate = self self.view.addSubview(mainView) } @@ -24,5 +25,8 @@ class ViewController: UIViewController { // Dispose of any resources that can be recreated. } + func reset() { + print("reset") + } } From cca7b5446d00a2d674b8fe49980bf9232501f935 Mon Sep 17 00:00:00 2001 From: stanchiang Date: Sun, 6 Mar 2016 14:02:49 -0800 Subject: [PATCH 3/5] finished: dragging to trash, snapping back to origin when not dragged to trash, full reset; should add a snap back animation --- DragAndDrop/DraggableView.swift | 36 ++++++++++++++++++++++++++++++++ DragAndDrop/View.swift | 14 +++++++++---- DragAndDrop/ViewController.swift | 7 ++++++- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/DragAndDrop/DraggableView.swift b/DragAndDrop/DraggableView.swift index 56a7a50..3aff39f 100644 --- a/DragAndDrop/DraggableView.swift +++ b/DragAndDrop/DraggableView.swift @@ -8,14 +8,50 @@ import UIKit +protocol draggableViewDelegate { + func didDragToTrash() -> Bool +} + class DraggableView: UIView { + var panGestureRecognizer:UIPanGestureRecognizer! + var initialPosition:CGPoint! + + var delegate:draggableViewDelegate! + override init(frame: CGRect) { super.init(frame: frame) + initialPosition = frame.origin + panGestureRecognizer = UIPanGestureRecognizer() + panGestureRecognizer.addTarget(self, action: "updatePosition:") + addGestureRecognizer(panGestureRecognizer) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + func updatePosition(sender: UIPanGestureRecognizer) { + let translation = sender.translationInView(self) + + frame.origin.x = initialPosition.x + translation.x + frame.origin.y = initialPosition.y + translation.y + + let willTrash: Bool = delegate.didDragToTrash() + + if willTrash { + layer.borderColor = UIColor.redColor().CGColor + layer.borderWidth = 3 + } else { + layer.borderWidth = 0 + } + + if panGestureRecognizer.state == UIGestureRecognizerState.Ended { + if !willTrash { + frame.origin = initialPosition + } else { + removeFromSuperview() + } + } + } } \ No newline at end of file diff --git a/DragAndDrop/View.swift b/DragAndDrop/View.swift index 5d36b25..3a6f8b5 100644 --- a/DragAndDrop/View.swift +++ b/DragAndDrop/View.swift @@ -12,7 +12,7 @@ protocol ViewDelegate { func reset() } -class View: UIView { +class View: UIView, draggableViewDelegate { var draggableView:DraggableView! var trashArea:UIView! @@ -23,14 +23,15 @@ class View: UIView { override init(frame: CGRect) { super.init(frame: frame) - draggableView = initDraggableView() - addSubview(draggableView) - trashArea = initTrashArea() addSubview(trashArea) resetButton = initResetButton() addSubview(resetButton) + + draggableView = initDraggableView() + addSubview(draggableView) + } required init?(coder aDecoder: NSCoder) { @@ -39,6 +40,7 @@ class View: UIView { func initDraggableView() -> DraggableView { let view = DraggableView(frame: CGRectMake(100,100,100,100)) + view.delegate = self view.backgroundColor = UIColor.orangeColor() return view } @@ -63,4 +65,8 @@ class View: UIView { func resetAction(sender: UIButton){ delegate.reset() } + + func didDragToTrash() -> Bool { + return draggableView.frame.intersects(trashArea.frame) + } } diff --git a/DragAndDrop/ViewController.swift b/DragAndDrop/ViewController.swift index ee16532..e9f9913 100644 --- a/DragAndDrop/ViewController.swift +++ b/DragAndDrop/ViewController.swift @@ -26,7 +26,12 @@ class ViewController: UIViewController, ViewDelegate { } func reset() { - print("reset") + mainView.removeFromSuperview() + + mainView = View(frame: self.view.frame) + mainView.delegate = self + self.view.addSubview(mainView) } + } From 8ff2d9c49ce42ff130a9ce2861e9cb1629b8df85 Mon Sep 17 00:00:00 2001 From: stanchiang Date: Sun, 6 Mar 2016 14:06:40 -0800 Subject: [PATCH 4/5] added snap back to origin animation --- DragAndDrop/DraggableView.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/DragAndDrop/DraggableView.swift b/DragAndDrop/DraggableView.swift index 3aff39f..540c856 100644 --- a/DragAndDrop/DraggableView.swift +++ b/DragAndDrop/DraggableView.swift @@ -48,10 +48,16 @@ class DraggableView: UIView { if panGestureRecognizer.state == UIGestureRecognizerState.Ended { if !willTrash { - frame.origin = initialPosition + snapToOriginAnimation() } else { removeFromSuperview() } } } + + func snapToOriginAnimation(){ + UIView.animateWithDuration(0.2) { () -> Void in + self.frame.origin = self.initialPosition + } + } } \ No newline at end of file From 02e0f90e671fda94bae69a4fbf6f356a985b435b Mon Sep 17 00:00:00 2001 From: stanchiang Date: Sun, 6 Mar 2016 14:15:46 -0800 Subject: [PATCH 5/5] added trash alpha fade out animation --- DragAndDrop/DraggableView.swift | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/DragAndDrop/DraggableView.swift b/DragAndDrop/DraggableView.swift index 540c856..99bbcb4 100644 --- a/DragAndDrop/DraggableView.swift +++ b/DragAndDrop/DraggableView.swift @@ -50,14 +50,24 @@ class DraggableView: UIView { if !willTrash { snapToOriginAnimation() } else { - removeFromSuperview() + trashActionAnimation() } } } - func snapToOriginAnimation(){ + func snapToOriginAnimation() { UIView.animateWithDuration(0.2) { () -> Void in self.frame.origin = self.initialPosition } } + + func trashActionAnimation() { + UIView.animateWithDuration(0.1, animations: { () -> Void in + self.alpha = 0 + }) { (complete) -> Void in + if complete { + self.removeFromSuperview() + } + } + } } \ No newline at end of file