Racket Objective-C FFI - avoid redefining a class
racket
Solution
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.
Problem
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))) ```