Pointer References on Cocoa

There are essentially three ways in which Objective-C APIs pass objects references.

ObjC Oxygene C# Swift
NSObject *obj obj: NSObject NSObject obj obj: NSObject
NSObject **obj var obj: NSObject ref NSObject obj var obj: NSObject
NSObject *obj[] obj: ^NSObject NSObject *obj obj: UnsafePointer<NSObject>

Like most modern languages, all Elements languages omit the explicit "pointer" syntax (^ in Pascal, * in C) on class pointers, using just the class name to represent the type and implying automatically that the type is heap based. This comes natural to today's Pascal developers and matches how Oxygene and C# behave on .NET and Java, and how Swift behaves. Delphi too handles class types this way. By contrast, Objective-C, C++ and older Borland Pascal/Turbo Pascal dialects used or still use ^ (or *) to denote heap-based objects.

This topic explains how Objective-C-style pointer references map to the Elements languages.

1. Plain Object References

Therefore, the first reference type listed above is the standard way of passing of an object to a function, and NSObject * simply maps to, say,

method foo(obj: NSObject);
void foo(NSObject obj) {
func foo(obj: NSObject) {

2. var/ref`inout` Parameters

The second syntax is used by Objective-C to pass objects "by reference", usually in order let the called function replace the object, or return a new object where none was passed in. All Elements languages have their unique keywords for expressing this concept. The second variant, out/__out, only differs in semantics to emphasize the unidirectional nature of the by-reference variable.

  • var and out in Oxygene,
  • ref and out in C# and
  • inout and __out in Swift.

So the NSObject ** syntax maps to, say:

method foo(var obj: NSObject);
void foo(ref NSObject obj) {
func foo(inout obj: NSObject) {

So note:

  • Elements will allow nil to be passed to by-reference parameters on the Cocoa platforms only. On .NET and Java, a valid variable must be passed.
  • You can use assigned(@obj) to verify if a valid reference value was passed. This will return false, even if the reference itself is nil.
  • It will always be safe to evaluate or assign to the var parameter, even if nil was passed in.
  • The Oxygene [Colon Operator](/Oxygene/Expressions/MemberAccess (:) and C#/Swift "Elvis" Operator (?.) can be safely used on parameters, so obj:description or obj?.description respectively will validate that both assigned(@obj) and assigned(obj) are true, before calling into description.

3. True Object Pointer Parameters

The third Objective-C syntax above is equivalent to the previous on a technical level, but has different implications in how the passed reference will be accessed inside the called method, in that commonly not just a single object reference is passed in, but an in-memory array of consecutive object pointers. The NSObject *obj[] syntax maps to:

method foo(obj: ^NSObject);
void foo(NSObject *obj) {
func foo(obj: UnsafePointer<NSObject>) {

Both the address of an object (@someObject in Oxygene, &someObject in C# and Swift) or a dynamic array of objects can be passed into this type of parameter.

4. Dynamic Array Parameters

In addition, Elements of course also allows the declaration of true dynamic array parameters such as:

method foo(obj: array of NSObject);
void foo(NSObject[] obj) {
func foo(obj: NSObject[]) { // not to be confused with [NSObject]

Here, a true reference-counted dynamic array is passed into the function, and this call has no equivalent in Objective-C, since dynamic arrays are unique to Elements.