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
andout
in Oxygene,ref
andout
in C# andinout
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 returnfalse
, even if the reference itself isnil
. - It will always be safe to evaluate or assign to the
var
parameter, even ifnil
was passed in. - The Oxygene [Colon Operator](/Oxygene/Expressions/MemberAccess (
:
) and C#/Swift "Elvis" Operator (?.
) can be safely used on parameters, soobj:description
orobj?.description
respectively will validate that bothassigned
(@obj)
andassigned
(obj)
are true, before calling intodescription
.
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.