Skip to content

Commit 8e44c03

Browse files
fix(ds): guard swapScreen KVC access with responds(to:) to prevent crash
The dual-screen viewport code accessed `swapScreen` via KVC without checking whether the bridge implements it, causing an NSUndefinedKeyException for melonDS, DeSmuME2015 and ThinLibretro DS bridges. - Use responds(to:) before value(forKey: "swapScreen") in isScreenSwapped - Replace hardcoded "com.provenance.ds" with SystemIdentifier.DS.rawValue Fixes Copilot review issues on PR #3377. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 341c823 commit 8e44c03

2 files changed

Lines changed: 6 additions & 4 deletions

File tree

PVCoreBridgeRetro/Sources/PVLibRetro/PVThinLibretroCore.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class PVThinLibretroCore: PVEmulatorCore {
8989
/// DS (NDS) cores output a combined 256×384 framebuffer (top screen + bottom screen).
9090
/// The DefaultDeltaSkin NDS layout splits this into two independently positioned viewports.
9191
public override var supportsDualScreens: Bool {
92-
systemIdentifier == "com.provenance.ds"
92+
systemIdentifier == SystemIdentifier.DS.rawValue
9393
}
9494

9595
required init() {

PVUI/Sources/PVUIBase/PVEmulatorVC/PVEmulatorViewController+DualScreen.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ extension PVEmulatorViewController {
2424

2525
/// Get swap screen state from emuThreeDS core
2626
private var isScreenSwapped: Bool {
27-
guard let bridge = emuThreeBridge else { return false }
28-
// Access swapScreen property via runtime
29-
if let value = (bridge as AnyObject).value(forKey: "swapScreen") as? Bool {
27+
guard let bridge = emuThreeBridge as? NSObject else { return false }
28+
// Guard against NSUndefinedKeyException for bridges that don't expose swapScreen
29+
let sel = NSSelectorFromString("swapScreen")
30+
guard bridge.responds(to: sel) else { return false }
31+
if let value = bridge.value(forKey: "swapScreen") as? Bool {
3032
return value
3133
}
3234
return false

0 commit comments

Comments
 (0)