Ich verwende das Racket Objective-C FFI, um ein WebKit WebView in eine App einzubetten.Racket Objective-C FFI - Erneute Definition einer Klasse vermeiden
Um Benachrichtigungen über den Seitenladevorgang zu erhalten, erstelle ich eine neue ObjC-Klasse in Racket, die als Frameload-Delegat der Webansicht festgelegt ist.
Die Klasse sieht ungefähr so aus:
(define-objc-class MyWebFrameLoadDelegate NSObject
[]
(- _void (webView: [_id wv] didFinishLoadForFrame: [_id wf])
(send frame set-status-text "Page Loaded")))
Wenn der Code ausgeführt wird innerhalb DrRacket es toll das erste Mal funktioniert. Weitere Iterationen bewirken, dass der Prozess sterben:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000020
...
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x00007fff8511e299 objc_registerClassPair + 63
1 Racket 0x00000001002d329c ffi_call_unix64 + 76
2 Racket 0x00000001002d3eb4 ffi_call + 644
3 Racket 0x00000001002c612f ffi_do_call + 1599
4 ??? 0x00000001004b50cc 0 + 4299903180
...
... das scheint darauf hinzudeuten, dass es die Neudefinition der ObjC Klasse ist, die die Ursache ist.
Gibt es einen sauberen Weg mit den FFI, oder allgemeinere Racket-Funktionen, um zu vermeiden, die Klasse neu zu definieren, wenn sie bereits existiert?
Ich habe versucht, define-objc-class
in einem bedingten, aber es muss ein Top-Level-Formular sein.
Ich könnte zu den rohen ObjC-Laufzeitfunktionen und definieren Sie die Delegate-Klasse im laufenden Betrieb - aber es wäre schön, das zu vermeiden.
Lösung - wickeln Sie die define-objc-class
in einem let
die Klasse in einem verschachtelten Bereich innerhalb eines bedingten zu definieren:
(define MyWebFrameLoadDelegate
(or (objc_lookUpClass "MyWebFrameLoadDelegate")
(let()
(define-objc-class MyWebFrameLoadDelegate NSObject
[]
(- _void (webView: [_id wv] didFinishLoadForFrame: [_id wf])
(send frame set-status-text "Page Loaded")))
MyWebFrameLoadDelegate)))
Volle Quelle des Testbed: https://gist.github.com/nickmain/5136923 –