The preceding sections covered the use of existing Objective-C classes. This section describes how to implement Objective-C classes in Lisp.
When an Objective-C class is implemented in Lisp, each Objective-C foreign object has an associated Lisp object that can obtained by the function objc-object-from-pointer. Conversely, the function objc-object-pointer can be used to obtain a pointer to the foreign object from its associated Lisp object.
subclass of standard-objc-object
The implementation of an Objective-C class in Lisp consists of a subclass of standard-objc-object and method definitions that become the Objective-C methods of the Objective-C class.
An Objective-C class implemented in Lisp and its associated subclass of standard-objc-object should be defined using the macro define-objc-class. This has a syntax similar to
cl:defclass, with additional class options including
:objc-class-name to specify the name of the Objective-C class.
(objc-object-pointer (find-class 'my-object))
When an instance of
my-object is made using
make-instance, an associated foreign Objective-C object of the class
MyObject is allocated by calling the class's
"alloc" method and initialized by calling the instance's
"init" method. The
:init-function initarg can be used to call a different initialization method.
Note: If you implement an Objective-C class in Lisp but its name is not referenced at run time, and you deliver a runtime application, then you need to arrange for the Lisp class name to be retained during delivery. See define-objc-class for examples of how to do this.
A class defined with define-objc-class has no methods associated with it by default, other than those inherited from its ancestor classes. New methods can be defined (or overridden) by using the macros define-objc-method for instance methods and define-objc-class-method for class methods.
Note that the Lisp method definition form is separate from the class definition, unlike in Objective-C where it is embedded in the
@implementation block. Also, there is no Lisp equivalent of the
@interface block: the methods of an Objective-C class are just those whose defining forms have been evaluated.
could be defined in Lisp for instances of the
MyObject class from Defining an Objective-C class using the form:
For certain types of argument, there is more than one useful conversion from the FLI value to a Lisp value. To control this, the argument specification can include an arg-style, which describes how the argument should be converted. If the arg-style is specified as
:foreign then the argument is converted using normal FLI rules, but by default certain types are converted differently:
Likewise, result conversion can be controlled by the result-style specification. If this is :
foreign then the value is assumed to be suitable for conversion to the result-type using the normal FLI rules, but if result-style is :
lisp then additional conversions are performed for specific values of result-type:
When a the return type of a method is a structure type such as ns-rect then the conversion specified in Special result conversion for define-objc-method can be used. Alternatively, and for any other structure defined with define-objc-struct, the method can specify a variable as its result-style. This variable is bound to a pointer to a foreign structure of the appropriate type and the method should set the slots in this structure to specify the result. For example, the following definitions show a method that returns a structure:
Defining an Objective-C class introduced the define-objc-class macro with the
:objc-class-name class option for naming the Objective-C class. Since this macro is like
cl:defclass, it can specify any number of superclasses from which the Lisp class will inherit and also provides a way for superclass of the Objective-C class to be chosen:
:objc-superclass-nameclass option can be used to specify the superclass explicitly.
NSObjectis used as the superclass.
Within the body of a define-objc-method or define-objc-class-method form, the local macro current-super can be used to obtain a special object which will make invoke call the method in the superclass of the defining class. This is equivalent to using
super in Objective-C.
An abstract class is a normal Lisp class without an associated Objective-C class. As well as defining named Objective-C classes, define-objc-class can be used to define abstract classes by omitting the
:objc-class-name class option.
The main purpose of abstract classes is to simulate multiple inheritance (Objective-C only supports single inheritance): when a Lisp class inherits from an abstract class, all the methods defined in the abstract class become methods in the inheriting class.
For example, the method
"size" exists in both the Objective-C classes
MyOtherData because the Lisp classes inherit it from the abstract class
my-size-mixin, even though there is no common Objective-C ancestor class:
In a few cases, for instance when using nib files created by Apple's Interface Builder, it is necessary to add Objective-C instance variables to a class. This can be done using the
:objc-instance-vars class option to define-objc-class. For example, the following class contains two instance variables, each of which is a pointer to an Objective-C foreign object:
Given an instance of
my-controller, the instance variables can be accessed using the function objc-object-var-value.
Objective-C uses reference counting for its memory management, but the associated Lisp objects are managed by the Lisp garbage collector. When an Objective-C object is allocated, the associated Lisp object is recorded in the runtime system and cannot be removed by the garbage collector. When its reference count becomes zero, the object is removed from the runtime system and the generic function objc-object-destroyed is called with the object to allow cleanup methods to be implemented. After this point, the object can be removed by the garbage collector as normal.
Classes defined by define-objc-class can be made to support Objective-C formal protocols by specifying the
:objc-protocols class option. All the standard formal protocols from Mac OS X 10.4 are predefined.
Note: It is not possible to define new protocols entirely in Lisp on Mac OS X 10.5 and later, but existing protocols can be declared using the define-objc-protocol macro.
LispWorks Objective-C and Cocoa Interface User Guide and Reference Manual - 21 Mar 2017