Search code examples
iosswiftuipangesturerecognizer

Infinite Outlets


Hi i'm making an app where you can decorate a Christmas tree with baubles i have wrote code to be able to drag it around the view but i run out of baubles how do i make it so i can have lots of baubles to put on the christmas tree. I have tried duplicating one bauble lots of times but then added them all to the code and it doesn't work it drags them all at the same time. If you look in the picture it has the bauble in it but i want it to drag one but one to still be there to put on

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var red_bauble_1: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let gesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.wasDragged(_ :)))
        red_bauble_1.addGestureRecognizer(gesture)
        red_bauble_1.isUserInteractionEnabled = true
    }

    @objc func wasDragged (_ gesture: UIPanGestureRecognizer) {

        let translation = gesture.translation(in: self.view)
        let red_bauble_1 = gesture.view

        red_bauble_1?.center = CGPoint(x: red_bauble_1!.center.x + translation.x, y: (red_bauble_1?.center.y)! + translation.y)
        gesture.setTranslation(CGPoint.zero, in: self.view)

    }

}

Solution

  • If you are adding a variable number of ornaments as subviews and want to keep a reference to them, just have an array for them, e.g.

    var ornaments = [UIView]()  // or, if they're image views, `[UIImageView]()`
    

    then you can add your ornaments to that array as you add them to your tree and you have an array to keep track of all of them.


    For example:

    class ViewController: UIViewController {
    
        @IBOutlet weak var treeImageView: UIImageView!
        @IBOutlet weak var ornamentToolImageView: UIImageView!
    
        private var currentOrnament: UIView!
    
        private var ornaments = [UIView]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let pan = UIPanGestureRecognizer(target: self, action: #selector(dragOrnamentFromToolbar(_:)))
            ornamentToolImageView.addGestureRecognizer(pan)
        }
    
        /// Gesture for dragging ornament from toolbar on to the tree
        ///
        /// This creates new ornament and adds it to view hierarchy as well as to our array of `ornaments`
    
        @IBAction func dragOrnamentFromToolbar(_ gesture: UIPanGestureRecognizer) {
            let location = gesture.location(in: treeImageView)
    
            switch gesture.state {
            case .began:
                gesture.view?.isHidden = true                 // temporarily hide toolbar view so it feels like we're dragging it
                let image = UIImage(named: "ornament")!
                currentOrnament = UIImageView(image: image)
                ornaments.append(currentOrnament)
                treeImageView.addSubview(currentOrnament)
                fallthrough
    
            case .changed:
                currentOrnament.center = location
    
            case .ended, .cancelled:
                // when done, add new pan gesture for dragging around new ornament
    
                gesture.view?.isHidden = false                // restore toolbar view
                currentOrnament.isUserInteractionEnabled = true
                let pan = UIPanGestureRecognizer(target: self, action: #selector(dragExistingOrnament(_:)))
                currentOrnament.addGestureRecognizer(pan)
                currentOrnament = nil
    
            default:
                break
            }
        }
    
        /// Gesture for dragging existing ornament
        ///
        /// This grabs existing and allows you to drag it around
    
        @IBAction func dragExistingOrnament(_ gesture: UIPanGestureRecognizer) {
            let location = gesture.location(in: treeImageView)
    
            switch gesture.state {
            case .began:
                currentOrnament = gesture.view
                fallthrough
    
            case .changed:
                currentOrnament.center = location
    
            default:
                break
            }
        }
    
    }
    

    That yields:

    enter image description here