DelegateProxy(RxSwift/RxCocoa)实现求助:非默认代理字段及类型问题
Let's break down your problem into two key parts: handling non-default delegate property names (like contactDelegate instead of delegate) and resolving the PKPhysicsWorld factory missing error.
1. Fixing the Non-Standard Delegate Field Mapping
When your target object uses a delegate property that's not named delegate (like SKPhysicsWorld's contactDelegate), you can't rely on the default DelegateProxy behavior. You need to explicitly map the proxy to the correct property in your DelegateProxy subclass:
Step 1: Override the delegate Computed Property
In your RxSKPhysicsContactDelegateProxy, override the delegate property to directly interact with the target's contactDelegate:
public override var delegate: AnyObject? { get { guard let world = self.parentObject as? SKPhysicsWorld else { return nil } return world.contactDelegate } set { guard let world = self.parentObject as? SKPhysicsWorld else { return } world.contactDelegate = newValue as? SKPhysicsContactDelegate // Sync with DelegateProxy's internal forwarding logic self._setForwardToDelegate(newValue, retainDelegate: true) } }
Step 2: Initialize the Proxy Correctly
Make sure when your proxy is created, it replaces the original contactDelegate so all events flow through the Rx proxy:
public init(parentObject: SKPhysicsWorld) { super.init(parentObject: parentObject, delegateProxy: RxSKPhysicsContactDelegateProxy.self) // Preserve the original delegate and set self as the new contactDelegate let originalDelegate = parentObject.contactDelegate self.setForwardToDelegate(originalDelegate, retainDelegate: true) parentObject.contactDelegate = self }
2. Resolving the PKPhysicsWorld Factory Error
The error mentions PKPhysicsWorld because SpriteKit uses this private subclass of SKPhysicsWorld under the hood. Your current factory only registers for SKPhysicsWorld.self, so it can't find a proxy for the runtime type PKPhysicsWorld.
Option 1: Register the Factory for the Private Subclass (Runtime Hack)
Since PKPhysicsWorld is private, you can't reference it directly, but you can use runtime APIs to register the proxy for it:
// First, register for the public SKPhysicsWorld DelegateProxyFactory.registerProxy { RxSKPhysicsContactDelegateProxy(parentObject: $0) } for: SKPhysicsWorld.self // Then register for the private PKPhysicsWorld using NSClassFromString if let pkPhysicsWorldClass = NSClassFromString("PKPhysicsWorld") { DelegateProxyFactory.registerProxy { object in guard let world = object as? SKPhysicsWorld else { fatalError("Expected SKPhysicsWorld or its subclass") } return RxSKPhysicsContactDelegateProxy(parentObject: world) } for: pkPhysicsWorldClass }
Option 2: Use a Generic Factory That Matches Subclasses
Alternatively, you can adjust your factory registration to accept any instance of SKPhysicsWorld (including its subclasses) by using a more flexible registration block:
DelegateProxyFactory.registerProxy { object in guard let world = object as? SKPhysicsWorld else { fatalError("Object must be an SKPhysicsWorld instance") } return RxSKPhysicsContactDelegateProxy(parentObject: world) } for: SKPhysicsWorld.self
This works because DelegateProxyFactory will use this factory for any object that is an instance of SKPhysicsWorld (including private subclasses like PKPhysicsWorld).
Final Checks
- Ensure your
SKPhysicsWorldextension conforms toHasDelegatecorrectly:extension SKPhysicsWorld: HasDelegate { public typealias Delegate = SKPhysicsContactDelegate } - Verify that all delegate methods you want to observe are properly forwarded in your
RxSKPhysicsContactDelegateProxy(e.g.,didBegin(_:)anddidEnd(_:)).
内容的提问来源于stack exchange,提问作者Maxim Volgin

