2026-06-11 12:57:14
在 SwiftUI 中,可通过 Method Swizzling 修改系统默认对象的底层行为,为其插入自定义协议方法以实现拖放操作等功能的扩展。 以下是具体实现思路与关键步骤:
1. 理解 SwiftUI 与 UIKit 的底层关系获取目标类的 Method 类型指针(通过 class_getInstanceMethod)。
使用 method_exchangeImplementations 交换方法实现。
确保在运行时(如 +load 方法或 DispatchQueue.once)执行 Swizzling,避免重复操作。
创建协议与扩展:
protocol DragDropDelegate: AnyObject { func didCancelDrag()}extension UIView { private struct AssociatedKeys { static var delegateKey = "dragDropDelegateKey" } weak var dragDropDelegate: DragDropDelegate? { get { return objc_getAssociatedObject(self, &AssociatedKeys.delegateKey) as? DragDropDelegate } set { objc_setAssociatedObject(self, &AssociatedKeys.delegateKey, newValue, .OBJC_ASSOCIATION_ASSIGN) } }}通过关联对象(Associated Objects)为 UIView 添加自定义属性 dragDropDelegate,避免修改系统类。
Swizzling 拖放相关方法:
extension UIView { static func swizzleDragDropMethods() { let originalSelector = #selector(UIView.endTracking(_:with:)) let swizzledSelector = #selector(UIView.swizzledEndTracking(_:with:)) guard let originalMethod = class_getInstanceMethod(UIView.self, originalSelector), let swizzledMethod = class_getInstanceMethod(UIView.self, swizzledSelector) else { return } method_exchangeImplementations(originalMethod, swizzledMethod) } @objc func swizzledEndTracking(_ touch: UITouch?, with event: UIEvent?) { swizzledEndTracking(touch, with: event) // 调用原方法 if let delegate = dragDropDelegate { delegate.didCancelDrag() // 插入自定义逻辑 } }}交换 endTracking(_:with:) 方法(触摸结束时调用),在原有逻辑后触发 didCancelDrag 回调。
通过 @objc 标记方法以确保动态性。
调用 Swizzling:
// 在 App 启动时(如 AppDelegate 的 didFinishLaunching)调用:UIView.swizzleDragDropMethods()通过上述方法,可在 SwiftUI 中利用 Swizzling 为系统对象插入自定义逻辑,实现原生框架未提供的功能(如拖放取消回调)。但需谨慎评估风险,优先探索官方支持的替代方案。