索引数组中的最后一项不响应 UIPanGestureRecognizer

last item in index array not responsive to UIPanGestureRecognizer

我的 swift 下面的代码应该在调用该函数时添加图像视图。然后当按下它时应该四处移动。现在第一次按下按钮时,imageview 不起作用,但如果该函数被调用两次,第一个 imageview 移动。如果 func 被调用 3 次,则第一个和第二个图像视图移动,但第三个图像视图不移动。当图像视图放在屏幕上时,我希望它立即移动

import UIKit

class ViewController: UIViewController {

    var myArray = [UIImageView]()
    var bt = UIButton()
    var count : Int = 0
    var pgGesture = UIPanGestureRecognizer()
    var ht = -90

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(bt)
        bt.backgroundColor = UIColor.systemOrange
        bt.frame = CGRect(x: view.center.x - 80, y: view.center.y , width: 50, height: 50)
        bt.addTarget(self, action: #selector(add), for: .touchUpInside)
    }

    @objc func add() { 
        pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))

        for index in myArray.indices {
            myArray[index].isUserInteractionEnabled = true
            myArray[index].addGestureRecognizer(pgGesture)
            myArray[index].tag = index
        }

        myArray.insert(UIImageView(), at: count)

        myArray[count].frame = CGRect(x: view.center.x - 0, y: view.center.y + CGFloat(ht), width: 50, height: 30)
        myArray.forEach({
            [=10=].backgroundColor = UIColor.systemTeal
            self.view.addSubview([=10=])
        })

        count += 1
        ht += 50  
    }

    @objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
        self.view.bringSubviewToFront(sender.view!)
        let tranistioon = sender.translation(in: self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
        sender.setTranslation(CGPoint.zero,in: self.view)    
    }
}

好的,你试试这个怎么样。这是我改变的:pgGesture 的声明现在是一个可选的(不需要两次初始化它,这是你在代码中所做的),将 pgGesture 的初始化移动到 ViewDidLoad 而不是它在 addFunction 内部(它只需要被初始化一次,而不是每次调用 add() 函数时都被初始化),最后(这就是你所看到的问题的原因),我在插入图像之前将 pgGesture 添加到图像中(之前你没有分配panGesture 到正在插入的图像,而不是数组的所有其他条目)。

import UIKit

class ViewController: UIViewController {

    var myArray = [UIImageView]()
    var bt = UIButton()
    var count : Int = 0
    var pgGesture: UIPanGestureRecognizer?
    var ht = -90

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(bt)
        bt.backgroundColor = UIColor.systemOrange
        bt.frame = CGRect(x: view.center.x - 80, y: view.center.y , width: 50, height: 50)
        bt.addTarget(self, action: #selector(add), for: .touchUpInside)
        pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))

    }

    @objc func add() { 

        for index in myArray.indices {
            myArray[index].isUserInteractionEnabled = true
            myArray[index].tag = index
        }

        let imageToInsert = UIImageView()
        imageToInsert.addGestureRecognizer(pgGesture)
        myArray.insert(UIImageView(), at: count)

        myArray[count].frame = CGRect(x: view.center.x - 0, y: view.center.y + CGFloat(ht), width: 50, height: 30)
        myArray.forEach({
            [=10=].backgroundColor = UIColor.systemTeal
            self.view.addSubview([=10=])
        })

        count += 1
        ht += 50  
    }

    @objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
        self.view.bringSubviewToFront(sender.view!)
        let tranistioon = sender.translation(in: self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
        sender.setTranslation(CGPoint.zero,in: self.view)    
    }
}

这里有几个问题:

  1. 您的手势识别器处理程序正在更新手势视图的 center。显然,目的是将此手势添加到您要拖动的视图中。

    所以这里的主要问题是您将手势识别器添加到错误的视图中。您应该将其添加到青色可拖动视图中,但您将其添加到主视图中。

  2. 这无关紧要,但是 add 方法做了很多不必要的事情。假设您要添加第 100 个新的蓝绿色子视图。你为什么还要重新更新之前的99个子视图?

    只需配置要添加的视图并摆脱那些不必要的 for/forEach 循环。

  3. 同样,无关,但我建议在使用 center 时要小心。这是相关视图在其父视图中的位置。因此,当向视图控制器的 view 添加按钮和蓝绿色子视图时,您应该引用 view.bounds.midX.midY,而不是 view.center。因为视图占据了整个屏幕,所以你不会真正看到差异,但是如果视图控制器是另一个视图的子视图控制器,那么就会有天壤之别。

因此:

class ViewController: UIViewController {
    // var mySubviews = [UIImageView]()
    var addButton = UIButton()
    var count: Int = 0
    var ht = -90

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(addButton)
        addButton.backgroundColor = .systemOrange
        addButton.addTarget(self, action: #selector(didTapAdd(_:)), for: .touchUpInside)
    }


    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        addButton.frame = CGRect(x: view.bounds.midX - 80, y: view.bounds.midY, width: 50, height: 50)
    }

    @objc func didTapAdd(_ sender: UIButton) {
        let subview = UIImageView()
        subview.isUserInteractionEnabled = true
        view.addSubview(subview)
        subview.frame = CGRect(x: view.bounds.midX - 0, y: view.bounds.midY + CGFloat(ht), width: 50, height: 30)
        subview.backgroundColor = .systemTeal
        subview.tag = count

        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        subview.addGestureRecognizer(pan)

        count += 1
        ht += 50
        // mySubviews.append(subview)
    }

    @objc func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
        let draggedView = gesture.view!
        view.bringSubviewToFront(draggedView)
        let translation = gesture.translation(in: view)
        draggedView.center = CGPoint(x: draggedView.center.x + translation.x, y: draggedView.center.y + translation.y)
        gesture.setTranslation(.zero, in: view)
    }
}

一些最后的观察:

  1. 我不鼓励使用 tag。用于诊断目的没问题,但仅此而已。

  2. 在我的代码片段中,我还注释掉了声明并​​附加到子视图数组,因为它完全没有必要。

  3. 请见谅,我已经重命名了方法和变量。

  4. 我不确定你为什么要使用 UIImageView。我个人会使用 UIView 除非你真的打算在以后最终添加图像。

  5. 如果您要对按钮的 frame 进行硬编码,则不能在 viewDidLoad 中执行此操作(因为视图尚未布局)。如果您要设置 frame,则需要在 viewDidLayoutSubviews 中进行设置。您可以在 viewDidLoad 中设置约束,但不能在框架中设置约束。