Previous Section Next Section Table of Contents Glossary Index

Chapter 14. The Objective-C Bridge

14.3. Instantiating Objective-C Objects

Making an instance of an Objective-C class (whether the class in question is predefined or defined by the application) involves calling MAKE-INSTANCE with the class and a set of initargs as arguments. As with STANDARD-CLASS, making an instance involves initializing (with INITIALIZE-INSTANCE) an object allocated with ALLOCATE-INSTANCE.

For example, you can create an ns:ns-number like this:

      ? (make-instance 'ns:ns-number :init-with-int 42)
      #<NS-CF-NUMBER 42 (#x85962210)>
    

It's worth looking at how this would be done if you were writing in Objective C:

      [[NSNumber alloc] initWithInt: 42]
    

Allocating an instance of an Objective-C class involves sending the class an "alloc" message, and then using those initargs that don't correspond to slot initargs as the "init" message to be sent to the newly-allocated instance. So, the example above could have been done more verbosely as:

      ? (defvar *n* (ccl::send (find-class 'ns:ns-number) 'alloc))
      *N*

      ? (setq *n* (ccl::send *n* :init-with-int 42))
      #<NS-CF-NUMBER 42 (#x16D340)>
    

That setq is important; this is a case where init decides to replace the object and return the new one, instead of modifying the existing one. In fact, if you leave out the setq and then try to view the value of *N*, Clozure CL will freeze. There's little reason to ever do it this way; this is just to show what's going on.

You've seen that an Objective-C initialization method doesn't have to return the same object it was passed. In fact, it doesn't have to return any object at all; in this case, the initialization fails and make-instance returns nil.

In some special cases, such as loading an ns:ns-window-controller from a .nib file, it may be necessary for you to pass the instance itself as one of the parameters to the initialization method. It goes like this:

      ? (defvar *controller*
      (make-instance 'ns:ns-window-controller))
      *CONTROLLER*

      ? (setq *controller*
      (ccl::send *controller*
      :init-with-window-nib-name #@"DataWindow"
      :owner *controller*))
      #<NS-WINDOW-CONTROLLER <NSWindowController: 0x1fb520> (#x1FB520)>
    

This example calls (make-instance) with no initargs. When you do this, the object is only allocated, and not initialized. It then sends the "init" message to do the initialization by hand.

There is an alternative API for instantiating Objective-C classes. You can call OBJC:MAKE-OBJC-INSTANCE, passing it the name of the Objective-C class as a string. In previous releases, OBJC:MAKE-OBJC-INSTANCE could be more efficient than OBJC:MAKE-INSTANCE in cases where the class did not define any Lisp slots; this is no longer the case. You can now regard OBJC:MAKE-OBJC-INSTANCE as completely equivalent to OBJC:MAKE-INSTANCE, except that you can pass a string for the classname, which may be convenient in the case that the classname is in some way unusual.


Previous Section Next Section Table of Contents Glossary Index