Changes between Initial Version and Version 1 of CocoaBridgeTranslation


Ignore:
Timestamp:
08/26/10 19:26:04 (4 years ago)
Author:
pfeilgm
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • CocoaBridgeTranslation

    v1 v1  
     1Here are a bunch of conversions between Obj-C code and the equivalent Clozure CL Cocoa 
     2Bridge code, to show how different idioms are encoded. Some of these things are part of 
     3the Clozure CL FFI, and not specific to the bridge, but they are included here to give 
     4an overall view. 
     5 
     6== literals == 
     7 
     8T and NIL are mapped to the boolean values YES and NO, respectively. All numbers are 
     9also portable. NSStrings need to be explicitly created: 
     10 
     11{{{ 
     12@"some string" 
     13}}} 
     14 
     15becomes 
     16 
     17{{{ 
     18#@"some string" 
     19}}} 
     20 
     21If you need to convert between lisp strings and NSStrings, the following functions are 
     22what you want. 
     23 
     24{{{ 
     25(let ((a-lisp-string "foo")) 
     26  (ccl::%make-nsstring a-lisp-string)) 
     27}}} 
     28 
     29and you also need to convert NSStrings when you receive them: 
     30 
     31{{{ 
     32(ccl::lisp-string-from-nsstring (#/title some-object)) 
     33}}} 
     34 
     35Clozure CL used to autoconvert strings, but that caused issues with memory management. 
     36So make sure to retain/release any NSStrings you need to. 
     37 
     38{{{ 
     39nil 
     40NULL 
     41}}} 
     42 
     43Both of these are null pointers. Use 
     44 
     45{{{ 
     46ccl:+null-ptr+ 
     47}}} 
     48 
     49to represent them in Lisp. 
     50 
     51=== types === 
     52 
     53You may have to use type (not class) names as the return values of methods you define 
     54and in some other cases. 
     55 
     56{{{ 
     57NSInteger 
     58BOOL 
     59}}} 
     60 
     61becomes 
     62 
     63{{{ 
     64#>NSInteger 
     65#>BOOL 
     66}}} 
     67 
     68== constants, enumerations and variables == 
     69 
     70{{{ 
     71NSTitledWindowMask 
     72NSUTF8StringEncoding 
     73}}} 
     74 
     75{{{ 
     76#$NSTitledWindowMask 
     77#$NSUTF8StringEncoding 
     78}}} 
     79 
     80== selectors == 
     81 
     82{{{ 
     83@selector(someSelector:withParams:) 
     84}}} 
     85 
     86becomes 
     87 
     88{{{ 
     89(@selector "someSelector:withParams:") 
     90}}} 
     91 
     92== class definition == 
     93 
     94{{{ 
     95@interface SomeClass : SuperClass { 
     96    IBOutlet NSString *aString; 
     97} 
     98}}} 
     99 
     100{{{ 
     101(defclass some-class (super-class) 
     102  ((a-string :foreign-type :id)) 
     103  (:metaclass ns:+ns-object)) 
     104}}} 
     105 
     106== method definition == 
     107 
     108{{{ 
     109@implementation SomeClass // just included so we show the class name 
     110 
     111- (id) initWithFrame:(NSRect)frame andStuff:(id)stuff { 
     112    if ((self = [super initWithFrame:frame])) { 
     113        // body 
     114    } 
     115    return self; 
     116} 
     117 
     118- (void) viewDidAppear:(BOOL)animated { 
     119    [super viewDidAppear:animated]; 
     120    // body 
     121} 
     122}}} 
     123 
     124{{{ 
     125(objc:defmethod (#/initWithFrame:andStuff: :id) 
     126                ((self some-class) (frame #>NSRect) (stuff :id)) 
     127  (let ((new-self (#/initWithFrame: self frame))) 
     128    (when new-self 
     129      ;; body 
     130      ) 
     131    new-self)) 
     132 
     133(objc:defmethod (#/viewDidAppear: :void) ((self some-class) (animated #>BOOL)) 
     134  (call-next-method)) 
     135  ;; body 
     136  ) 
     137}}} 
     138 
     139There is the usual CALL-NEXT-METHOD (which works just as expected in Obj-C 
     140methods), but that doesn’t cover all the use cases you need in Obj-C. As in common in init methods, you sometimes 
     141need to call a super-method with a different name than the current method. This is 
     142where CALL-NEXT-METHOD breaks down. The easiest way to handle this yourself is to treat the call to super as a call to self, as in the above example. 
     143 
     144== instantiating objects == 
     145 
     146{{{ 
     147[[NSWindow alloc] initWithContentRect:NSRectMake(0, 0, 300, 300) 
     148                            styleMask:NSTitledWindowMask 
     149                              backing:NSBackingStoreBuffered 
     150                                defer:YES]; 
     151}}} 
     152 
     153{{{ 
     154(make-instance 'ns:ns-window 
     155  :with-content-rect (ns:make-ns-rect 0 0 300 300) 
     156  :style-mask #$NSTitledWindowMask 
     157  :backing #$NSBackingStoreBuffered 
     158  :defer t) 
     159}}} 
     160 
     161== method call == 
     162 
     163{{{ 
     164[self doSomethingToObject:anObject]; 
     165[NSDate date]; 
     166}}} 
     167 
     168{{{ 
     169(#/doSomethingToObject: self an-object) 
     170(#/date ns:ns-date) 
     171}}} 
     172 
     173== calling setters / setting properties == 
     174 
     175You can call setters the same way as any other method, of course, but to make them work 
     176more like properties or slots, you can also use SETF for them. 
     177 
     178{{{ 
     179[self setName:aName]; 
     180self.name = aName; // provided there is a @property defined 
     181}}} 
     182 
     183{{{ 
     184(#/setName: self aName) 
     185}}} 
     186 
     187or 
     188 
     189{{{ 
     190(setf (#/name self) a-name) 
     191}}} 
     192 
     193The SETF form will work regardless of whether there's a property defined, but a getter 
     194(IE (#/name self)) must exist. This is because users of SETF expect the stored value to 
     195be returned, but Cocoa setters generally have no return value.