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



如果调用该函数,我下面的 swift 代码应该添加一个图像视图。然后当按下它时应该四处移动。现在第一次按下按钮时,图像视图不起作用,但如果调用该函数两次,则第一个图像视图会移动。如果调用 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({
$0.backgroundColor = UIColor.systemTeal
self.view.addSubview($0)
})
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中设置约束,但不能在帧中设置约束。

好的,你试试这个怎么样。这就是我更改的: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({
$0.backgroundColor = UIColor.systemTeal
self.view.addSubview($0)
})
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)    
}
}

最新更新