Reputation: 1450
I am using the Racket Objective-C FFI to embed a WebKit WebView in an app.
In order to receive page-load notifications I am creating a new ObjC class in Racket that is set as the frame-load delegate of the web-view.
The class looks something like:
(define-objc-class MyWebFrameLoadDelegate NSObject
[]
(- _void (webView: [_id wv] didFinishLoadForFrame: [_id wf])
(send frame set-status-text "Page Loaded")))
When running the code within DrRacket it works great the first time. Further iterations cause the process to die:
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
...
... which seems to indicate that it is the re-definition of the ObjC class that is the cause.
Is there a clean way using the FFI, or more general Racket features, to avoid re-defining the class if it already exists ?
I tried wrapping define-objc-class
in a conditional but it needs to be a top-level form.
I could drop down to the raw ObjC runtime functions and define the delegate class on the fly - but it would be nice to avoid that.
Solution - wrap the define-objc-class
in a let
to define the class in a nested scope inside a conditional:
(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)))
Upvotes: 6
Views: 309
Reputation: 31145
Just in case you missed it:
https://github.com/shekari/racket-webkit/blob/master/webkit.rkt
Enjoy,
Upvotes: 1
Reputation: 10663
I don't think define-obj-class
must be used at top level. It is a definition form, though, so you can't use it as an expression. You should be able to do something like the following:
(define MyClass
(or ___ ;; find the class, if it already exists
(let ()
(define-objc-class MyClass ___)
MyClass)))
BTW, it looks like a fix for the crashing behavior was committed on March 7.
Upvotes: 4