扩展 UIViewController - 自定义转换,@objc func 参数问题
Extension UIViewController - custom transition , problem with @objc func parametr
我想为 UIViewController 创建一个扩展,但我的 @objc 函数有一个问题。
下面这个参数怎么传?
#selector(handlePanGestExt(sender: **cardOriginY:** )))
fileprivate var cardOriginY : CGFloat!
extension UIViewController {
func panGestureRecognizerToHandleDragAndDissmisView(inCardView : UIView, cardOriginY : CGFloat) {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestExt(sender: cardOriginY: )))
inCardView.addGestureRecognizer(panGesture)
}
@objc func handlePanGestExt(sender: UIPanGestureRecognizer, cardOriginY : CGFloat) {
let fileView = sender.view!
switch sender.state {
case .began, .changed:
moveViewWithPan(view: fileView, sender: sender)
case .ended:
let dragVelocity = sender.velocity(in: view)
if dragVelocity.y >= 1300 {
dismiss(animated: false, completion: nil)
} else {
returnViewToOrigin(view: fileView, cardOriginY: cardOriginY)
}
default:
break
}
}
func moveViewWithPan(view: UIView, sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
guard translation.y >= 0 else { return }
view.center = CGPoint(x:view.center.x, y: view.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: view)
}
func returnViewToOrigin(view: UIView, cardOriginY : CGFloat) {
UIView.animate(withDuration: 0.3) {
view.frame.origin = CGPoint(x: 0.0 , y: cardOriginY)
}
}
我做错了什么?当我调用 func panGestureRecognizerToHandleDragAndDissmisView
时,我想传递这个参数 cardOriginY
UIPanGestureRecognizer
的选择器只能接受一个参数,它就是 UIPanGestureRecognizer
本身。基本上它应该是这样的
@objc func handlePanGestExt(_ sender: UIPanGestureRecognizer) {
// your code here
}
根据您的具体情况,您需要为您的计算再传递一个参数cardOriginY
。我可以建议你做下一件事:
- 添加
DismissableCardContainer
重用能力
- 添加
PanGestureActionHandler
以避免与 @objc 修饰符出现不必要的并发症
- 根据您的目的实施
DismissableCardContainer
协议
代码如下:
protocol DismissableCardContainer: AnyObject {
func addPanGestureRecognizerToHandleDragAndDissmis(
to cardView : UIView,
cardOriginY : CGFloat
)
}
extension DismissableCardContainer where Self: UIViewController {
func addPanGestureRecognizerToHandleDragAndDissmis(
to cardView : UIView,
cardOriginY : CGFloat
) {
let panGesture = PanGestureActionHandler(
action: { [weak self] gesture in
self?.handlePanGestExt(
gesture,
cardOriginY
)
}
)
cardView.addGestureRecognizer(panGesture)
}
private func handlePanGestExt(
_ sender: UIPanGestureRecognizer,
_ cardOriginY: CGFloat
) {
let fileView = sender.view!
switch sender.state {
case .began, .changed:
moveViewWithPan(view: fileView, sender: sender)
case .ended:
let dragVelocity = sender.velocity(in: view)
if dragVelocity.y >= 1300 {
dismiss(animated: false, completion: nil)
} else {
returnViewToOrigin(view: fileView, cardOriginY: cardOriginY)
}
default:
break
}
}
private func moveViewWithPan(view: UIView, sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
guard translation.y >= 0 else { return }
view.center = CGPoint(x:view.center.x, y: view.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: view)
}
private func returnViewToOrigin(view: UIView, cardOriginY : CGFloat) {
UIView.animate(withDuration: 0.3) {
view.frame.origin = CGPoint(x: 0.0 , y: cardOriginY)
}
}
}
final class PanGestureActionHandler: UIPanGestureRecognizer {
typealias Callback = ((PanGestureActionHandler) -> Void)
private let action: PanGestureActionHandler.Callback
init(
action: @escaping PanGestureActionHandler.Callback
) {
self.action = action
super.init(target: nil, action: nil)
addTarget(
self,
action: #selector(self.handleGestureAction)
)
}
@objc private func handleGestureAction(_ gr: UIPanGestureRecognizer) {
action(gr as! PanGestureActionHandler)
}
}
在那之后,只剩下在你需要的地方遵守 DismissableCardContainer
协议
final class YourViewController: UIViewController, DismissableCardContainer {
// Your code here
}
我想为 UIViewController 创建一个扩展,但我的 @objc 函数有一个问题。
下面这个参数怎么传?
#selector(handlePanGestExt(sender: **cardOriginY:** )))
fileprivate var cardOriginY : CGFloat!
extension UIViewController {
func panGestureRecognizerToHandleDragAndDissmisView(inCardView : UIView, cardOriginY : CGFloat) {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestExt(sender: cardOriginY: )))
inCardView.addGestureRecognizer(panGesture)
}
@objc func handlePanGestExt(sender: UIPanGestureRecognizer, cardOriginY : CGFloat) {
let fileView = sender.view!
switch sender.state {
case .began, .changed:
moveViewWithPan(view: fileView, sender: sender)
case .ended:
let dragVelocity = sender.velocity(in: view)
if dragVelocity.y >= 1300 {
dismiss(animated: false, completion: nil)
} else {
returnViewToOrigin(view: fileView, cardOriginY: cardOriginY)
}
default:
break
}
}
func moveViewWithPan(view: UIView, sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
guard translation.y >= 0 else { return }
view.center = CGPoint(x:view.center.x, y: view.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: view)
}
func returnViewToOrigin(view: UIView, cardOriginY : CGFloat) {
UIView.animate(withDuration: 0.3) {
view.frame.origin = CGPoint(x: 0.0 , y: cardOriginY)
}
}
我做错了什么?当我调用 func panGestureRecognizerToHandleDragAndDissmisView
时,我想传递这个参数 cardOriginY
UIPanGestureRecognizer
的选择器只能接受一个参数,它就是 UIPanGestureRecognizer
本身。基本上它应该是这样的
@objc func handlePanGestExt(_ sender: UIPanGestureRecognizer) {
// your code here
}
根据您的具体情况,您需要为您的计算再传递一个参数cardOriginY
。我可以建议你做下一件事:
- 添加
DismissableCardContainer
重用能力 - 添加
PanGestureActionHandler
以避免与 @objc 修饰符出现不必要的并发症 - 根据您的目的实施
DismissableCardContainer
协议
代码如下:
protocol DismissableCardContainer: AnyObject {
func addPanGestureRecognizerToHandleDragAndDissmis(
to cardView : UIView,
cardOriginY : CGFloat
)
}
extension DismissableCardContainer where Self: UIViewController {
func addPanGestureRecognizerToHandleDragAndDissmis(
to cardView : UIView,
cardOriginY : CGFloat
) {
let panGesture = PanGestureActionHandler(
action: { [weak self] gesture in
self?.handlePanGestExt(
gesture,
cardOriginY
)
}
)
cardView.addGestureRecognizer(panGesture)
}
private func handlePanGestExt(
_ sender: UIPanGestureRecognizer,
_ cardOriginY: CGFloat
) {
let fileView = sender.view!
switch sender.state {
case .began, .changed:
moveViewWithPan(view: fileView, sender: sender)
case .ended:
let dragVelocity = sender.velocity(in: view)
if dragVelocity.y >= 1300 {
dismiss(animated: false, completion: nil)
} else {
returnViewToOrigin(view: fileView, cardOriginY: cardOriginY)
}
default:
break
}
}
private func moveViewWithPan(view: UIView, sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
guard translation.y >= 0 else { return }
view.center = CGPoint(x:view.center.x, y: view.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: view)
}
private func returnViewToOrigin(view: UIView, cardOriginY : CGFloat) {
UIView.animate(withDuration: 0.3) {
view.frame.origin = CGPoint(x: 0.0 , y: cardOriginY)
}
}
}
final class PanGestureActionHandler: UIPanGestureRecognizer {
typealias Callback = ((PanGestureActionHandler) -> Void)
private let action: PanGestureActionHandler.Callback
init(
action: @escaping PanGestureActionHandler.Callback
) {
self.action = action
super.init(target: nil, action: nil)
addTarget(
self,
action: #selector(self.handleGestureAction)
)
}
@objc private func handleGestureAction(_ gr: UIPanGestureRecognizer) {
action(gr as! PanGestureActionHandler)
}
}
在那之后,只剩下在你需要的地方遵守 DismissableCardContainer
协议
final class YourViewController: UIViewController, DismissableCardContainer {
// Your code here
}