【问题标题】:Subclass UIScrollView in Swift for touches Began & touches MovedSwift 中的子类 UIScrollView 用于触摸开始和触摸移动
【发布时间】:2015-06-30 05:26:46
【问题描述】:

我正在使用 Swift 1.2

我正在尝试使用此 UIScrollview touchesbegan,touchesmoved,touchesended actions 以及已接受答案的第二条评论中的链接。

我正在使用带有自动布局的情节提要,我在自定义类中为 UIScrollView 设置了我的自定义类。

我没有在包含我的自定义 UIScrollView 的 UIViewController 中接收到这些触摸事件

编辑:用@Victor Sigler 的回答更新了我如何使用它的代码。

自定义ScrollView代码:

import UIKit

protocol PassTouchesScrollViewDelegate {

func scrollTouchBegan(touches: Set<NSObject>, withEvent event: UIEvent)
func scrollTouchMoved(touches: Set<NSObject>, withEvent event: UIEvent)
}

class PassTouchesScrollView: UIScrollView {

var delegatePass : PassTouchesScrollViewDelegate?

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

    self.delegatePass?.scrollTouchBegan(touches, withEvent: event)


}

override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {

    self.delegatePass?.scrollTouchMoved(touches, withEvent: event)

}

}

我的视图控制器:

import UIKit

class ViewController: UIViewController, PassTouchesScrollViewDelegate {

@IBOutlet weak var scrollView: UIScrollView!

override func viewDidLoad() {
    super.viewDidLoad()

    scrollView.delegatePass = self
}

func scrollTouchBegan(touches: Set<NSObject>, withEvent event: UIEvent)    {

    println("began \(touches)")

}

func scrollTouchMoved(touches: Set<NSObject>, withEvent event: UIEvent)      {

    println("moved \(touches)")
}     

}

我试图让用户在 UIImage 上画一条线,我使用 PanGesture 识别器开始工作,但性能很差,尤其是在旧硬件上,我遵循了 Ray Wenderlich 教程,该教程使用了 touches Began 和性能要好得多,但它是在 UIView 而不是 ScrollView 上。我需要一个 UIScrollView,因为在用户绘制图像之前,他们可以放大和围绕它。

【问题讨论】:

    标签: swift uiscrollview touchesbegan


    【解决方案1】:

    touchesBegan 仅适用于 UIView 的子类。把它从你的 UIViewController 中取出来让它工作。

    UIResponder Apple Docs

    【讨论】:

    • 我对这个答案感到困惑,当我触摸 UIScrollView 之外的屏幕区域时会调用 touchesBegan 和 touchesMoved,你的意思是我应该将 UIScrollView 放在 UIView 内吗?
    • 我是说委托方法 touchesBegan 应该只在 UIView 子类内部触发。将它们放在 UIViewController 中不应触发这些方法。所以是的,如果你把这些方法放在 UIScrollView 中也可以。只是不在控制器中。
    • UIViewController 确实包含它自己的 UIView,这就是为什么当我触摸 UIScrollView 外部的屏幕时它会响应(它的框架是 600x200),并且在 UIScrollView 的自定义子类中我试图通过我使用 super.touchesBegan 和 super.touchesMoved 在 UIViewController 的视图中放置的触摸事件
    • UIViewController 确实包含它自己的 UIView,这就是为什么当我触摸 UIScrollView 之外的屏幕时它会做出响应(它的大小是 600x400),并且在 UIScrollView 的自定义子类中我试图通过我通过使用 super.touchesBegan 和 super.touchesMoved 将触摸事件放在该 UIViewController 的视图中。我在我的问题中添加了屏幕截图。当我触摸 UIScrollView 上方和下方的白色区域时,我会在 touchesBegan 和 touchesMoved 上获得 println 输出。
    【解决方案2】:

    你想错了。如果您想知道UIScrollView 何时移动,则无需对其进行子类化。 iOS 已经在UIScrollViewDelegate 中设置了你需要的所有方法。

    您必须实现UISCrollViewDelegate 才能收到有关UIScrollView 中的操作的通知,并通过Interface Builder 或在代码中设置delegate,这取决于您。

    请参阅以下示例以了解如何操作:

    class ViewController: UIViewController, UIScrollViewDelegate {
    
         @IBOutlet weak var scrollView: UIScrollView!
    
         override func viewDidLoad() {
           super.viewDidLoad()
           self.scrollView.delegate = self
         }
    }
    

    如果你想知道上面解释的方式是如何被触动的,你必须遵循以下步骤:

    1. 您必须像在 PassTouchesScrollView 中一样从 UIScrollView 类继承,并实现委托模式以通过以下方式收到有关 UIScrollView 的通知:

      import UIKit
      
      protocol PassTouchesScrollViewDelegate {
         func touchBegan()
         func touchMoved()
      }
      
      
      class PassTouchesScrollView: UIScrollView {
      
        var delegatePass : PassTouchesScrollViewDelegate?
      
        override init(frame: CGRect) {
          super.init(frame: frame)
        }
      
        required init(coder aDecoder: NSCoder) {
           super.init(coder: aDecoder)
        }
      
        override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
      
           // Notify it's delegate about touched
           self.delegatePass?.touchBegan()
      
          if self.dragging == true {
             self.nextResponder()?.touchesBegan(touches, withEvent: event)
          } else {
             super.touchesBegan(touches, withEvent: event)
          }
      
       }
      
        override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent)  {
      
           // Notify it's delegate about touched
           self.delegatePass?.touchMoved()
      
           if self.dragging == true {            
              self.nextResponder()?.touchesMoved(touches, withEvent: event)
           } else {            
             super.touchesMoved(touches, withEvent: event)
           }
        }   
      }
      
    2. 你的类ViewController必须以如下方式实现:

      class ViewController: UIViewController, UIScrollViewDelegate {
      
        @IBOutlet weak var scrollView: PassTouchesScrollView!
      
        override func viewDidLoad() {
          super.viewDidLoad()        
          scrollView.delegate = self  
          scrollView.delegatePass = self      
        }
      
        override func didReceiveMemoryWarning() {
          super.didReceiveMemoryWarning()
          // Dispose of any resources that can be recreated.
        }
      
        func touchMoved() {
           println("touch moved")
        }
      
        func touchBegan() {
           println("touch began")
        }
      
      }
      
    3. 您必须在 Interface Builder 中选择您的 UIScrollView 并将其类设置为您的类 PassTouchesScrollView,在类部分的 Identity Inspector 中。

    您应该在控制台中看到以下内容:

    touch began
    touch began
    touch began
    touch began
    touch began
    touch began
    touch moved
    touch move
    

    希望对你有所帮助。

    【讨论】:

    • 我不想知道它什么时候移动,我想知道它什么时候被触摸,遗憾的是委托方法没有提供,在用户触摸滚动的时间点查看它的 scrollEnabled 属性设置为 false(以确保正确缩放)。
    • 我不知道为什么,但这对我不起作用,这就是我所拥有的。
    • @thefredelement 你已经在Interface Builder 中为UIScrollView 设置了类??这很重要
    • 我将在 Github 上分享一个项目,上面已经解释过了。我要把链接发给你看看。
    • 经过几个小时的测试,我知道了解决方案:您忘记在 ViewController 中链接“PassTouchesScrollViewDelegate”。所以应该是:"class ViewController: UIViewController, UIScrollViewDelegate, PassTouchesScrollViewDelegate {"
    【解决方案3】:

    试试这个

      extension UIScrollView {
    
        override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            self.next?.touchesBegan(touches, with: event)
            print("touchesBegan")
        }
    
        override open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
            self.next?.touchesMoved(touches, with: event)
            print("touchesMoved")
        }
    
        override open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
            self.next?.touchesEnded(touches, with: event)
            print("touchesEnded")
        }
    
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多