Я пытаюсь перенести весь свой код SpriteKit в контейнер SwiftUI SpriteView. Моя программа представляет собой смесь SwiftUI и SpriteKit на MacOS для торговли криптовалютой.
У меня проблема в том, что функция scrollWheel(with event: NSEvent) внутри моего объекта SKScene не срабатывает, когда я прокручиваю колесо мыши.
Ранее я решил эту проблему, сделав SKScene nextResponder, который отлично работал, когда я использовал Cocoa.
Ниже показано, как выглядит моя основная точка входа в SwiftUI.
@main
struct ManualTradingApp: App {
var exchangeManger: ExchangeManager = BinanceManager()
var chartScene: ChartScene {
let scene = ChartScene(size: CGSize(width: 600, height: 600), manager: exchangeManger)
scene.scaleMode = .resizeFill
return scene
}
var body: some Scene {
WindowGroup {
ContentView(manager: exchangeManger, chartScene: chartScene)
}
}
}
Вот функция внутри созданного мной класса ChartScene, которая должна получать события колеса прокрутки.
override func scrollWheel(with event: NSEvent) {
if chartNode.contains(event.locationInWindow) {
chartNode.scrollWheel(with: event)
} else if chartNode2.contains(event.locationInWindow) {
chartNode2.scrollWheel(with: event)
}
if symbolRowContainer.contains(event.locationInWindow) {
moveSymbolContainer(deltaY: -event.scrollingDeltaY * 10.0)
}
}
Вы можете захватывать события scrollWheel через NSView, а затем публиковать их в виде уведомлений, которые могут быть получены SKScene.
Сначала добавьте наблюдателя уведомлений в свой SKScene
class GameSceneScrollWheel: SKScene {
override func didMove(to view: SKView) {
NotificationCenter.default.addObserver(self,
selector: #selector(self.scrollWheelWithEvent(notification:)),
name: Notification.Name("scrollWheelWithEvent"),
object: nil)
}
//receive notification and passthrough to normal `scrollWheel` function
@objc func scrollWheelWithEvent(notification: Notification) {
guard let event = notification.object as? NSEvent else { return }
self.scrollWheel(with:event)
}
override func scrollWheel(with event: NSEvent) {
print("event.deltaY: \(event.deltaY)") //success!
}
}
Во-вторых, перехватывать события в NSView и публиковать уведомления
struct ScrollWheelEventView : NSViewRepresentable {
class ScrollWheelView : NSView {
override var acceptsFirstResponder: Bool { true }
override func acceptsFirstMouse(for event: NSEvent?) -> Bool { return true }
override func scrollWheel(with event: NSEvent) {
NotificationCenter.default.post(name: Notification.Name("scrollWheelWithEvent"), object: event)
}
}
func makeNSView(context: Context) -> some NSView {
return ScrollWheelView()
}
func updateNSView(_ nsView: NSViewType, context: Context) {}
}
И, наконец, добавьте NSViewRepresentable в SwiftUI.
struct ScrollWheel: View {
@State private var scene = GameSceneScrollWheel()
var body: some View {
ZStack {
SpriteView(scene: scene)
ScrollWheelEventView()
}
}
}
Спасибо, это сработало! Мне пришлось удалить эти строки, потому что они не позволяли нажимать клавиши в SKScene override var acceptsFirstResponder: Bool { true } override func acceptsFirstMouse(for event: NSEvent?) -> Bool { return true }