Why do functions use -(void) and not -(nil) in Obj-C? - objective-c

In objective-C I often see functions that don't return anything declared as:
- (void)myFunction {…
But why aren't functions declared using nil, like this
- (nil)myFunction {…
Don't they both return "nothing"?

void is nothing. nil is something (0).
In other words, returning nil isn't the same as returning nothing.

Historically in languages belonging (syntactically) to the C-like language family, void indicates that there is no type being returned from a function.
More precisely, just as variables have (or belong to) a given type, functions also have types. For example, a function that returns a int, it is an int type function, or a function whose type is int. Same if it returns something else.
If the function does not return anything - it returns nothing - what type does it belongs to? It has no type, and the void type represents such a thing.
I'm not versed in Objective C, but if I understand correctly, nil is an typeless ID (or an id of any type), almost like a built-in implementation of the null pattern.
And null is a (void *) type, the later being a typeless pointer that can point to anything, just as it would in C and C++.
So a function that returns nil would imply that its type is an id of any type. Don't know if that even makes sense. So right then and there, (nil)myFunction is of a type completely different from (void)myFunction since the former has one type (any type?) whereas the later has no type at all.
Also, nil is a built-in constant. Returning nill is like saying that your function returns a specific number for instance ((1)myFunction). That wouldn't make any sense, would it?

Void is an object type. Void means there is no return value.
Nil is an object, not a type. It represents an empty value.

Related

Override truth or ! operator in Objective-C

How do I override the truth-value of my class instance, or its ! operator?
For example (simplified names/usage):
MyClass variable = [MyClass alloc] initWithValue: nil];
...
if (!variable) { NSLog(#"'Not variable value' works"); }
I've searched for two possible solutions but couldn't find anything useful. In some languages i would overload an isTrue, asBool, etc function; or override the unary ! operator FOR THAT CLASS (not the main NOT operator.
My initial reaction to this problem was: You don't need to in Objective-C, you're going at it wrong. While true, I have lost over hours debugging some code that had the above (!variable) instead of
if (!variable.value) { NSLog(#"'Not variable value' works"); }
MyClass has property value among many others, which you can set or not. It defines whether or not you do something so it is common to need if (!variable.value){ NSLog(#"Warning, value not set"); }
So I want to overload the ! or isTrue function to check whether or not variable.value is set instead of merely checking if variable is linked to an address. This would make my code more readable and make my class more useable.
To be clear, in this example, variable points to an alloc-init'ed object, where variable.value = nil for example.
For example this can be done in python by overloading __ nonzero __.
As a side question that would answer this question: How does the truth value of an object work in Objective-C?
You can't override these things in ObjC. ObjC behaves just like C in this regard-- object references are pointers, either valid or nil-- a nil value evaluates to NO in a boolean expression and any non-nil value will appear as YES.
The canonical check for "is this thing an invalid pointer" is if (!thing) { ... }.
If you are always doing this:
if (!variable.value) ...
then perhaps variable is of type NSNumber or some object container for a primitive? It's hard to tell without context what pattern you're using and whether there's a better idiom for this.
An object in Objective-C has the same meaning in a boolean expression as a pointer in C, because it is a C pointer. If the pointer is NULL -- or nil for an object -- then it's false; otherwise it's true.
You can't override operators in Objective-C.
This said, !variable.value does indeed test whether value is nil (assuming that value has an object type) -- the dot operator resolves to a message send [variable value] whose return value is then negated.

Usage of "id" in Objective-C?

I have a function that returns "id". Does this include a return of void? (as in nothing) Or does "id" require some kind of object/variable?
In Objective-C, id is a keyword that represents an untyped object pointer. It's kinda like void*, the untyped pointer, but it adds the restriction that the pointer must point to some sort of Objective-C object.
id is a general data type that can wrap most objects. If you can, you usually want to opt for coding specific data types, but if the situation (in a method for example) can use a wide range of data types, id is used.
This Stackoverflow post should help to explain what it is and when to use it. A simple Google search will also turn up information.
In Objective C, id means object of any type, akin to void* in C/C++. You can return nil for from a function returning id to indicate that you do not want to return anything in particular.
'id' is a pointer to an instance of an Objective-C class. So your method can return a pointer to an instance, or 'nil' (a zero pointer).

Should I be casting when returning id from an objective-c method or not?

For the Objective-C gurus:
Suppose I have a simple method like so:
-(id)getValue{ return [NSNumber numberWithDouble:5.0]; }
Now, suppose within some other method I call the (id)getValue method like so:
NSNumber* myValue = [self getValue];
or what if I call it like this instead:
NSNumber* myValue = (NSNumber*)[self getValue];
The question is: Obviously these lines are equivalent but one of them utilizes an explicit cast. So what is the correct or best-practice way of doing this. It seams to me the cast is unnecessary since when it is placed in the pointer myValue, it will be type-safe at this point anyways (which is something I want) so the cast is basically pointless.
Let me just add that I'm sure people will point out: Why don't you just return (NSNumber*) from the getValue method but in my case I want to have the flexibility to return whatever I want much like the built in NSDictionary class returns id when you call: objectForKey because it allows you to place any type of NSObject or subclass inside of it. In other words my getValue method will not always be returning an NSNumber. Also consider this example is contrived because I am just concerned about whether to cast or not.
Thank you in advance,
-Ralph
The only reason to cast objects is to make the compiler happy. (Sometimes it also helps readability.) For example, you have to cast when making a property access directly on an object you're getting out of an array or dictionary:
((Foo *)[myArray objectAtIndex:0]).bar;
If you don't do the cast, the compiler can't do the property lookup, and will complain.
When you're getting an object from a method that returns id, it's impossible for the compiler to know what its actual type is. There isn't really any "type-safety", because id is a generic pointer; all the compiler can and will enforce is that the method says it returns some Objective-C object. It is perfectly happy to assign a generic pointer to any typed pointer.* (This is actually an advantage for containers, obviously.) Since the type of the variable to which you're assigning already documents the actual return type, I'd say there's no need for the cast.
As an aside, you shouldn't be calling your method getX. That has a specific meaning in Cocoa; methods which "get" something pass in a pointer to a pointer, which is then filled by the method. See -[NSArray getObjects:range:] as an example.
*The type will be enforced at run-time, of course, in the sense that sending messages to which the object does not respond will cause an error.

What is the difference between *(id *)((char *)object + ivar_getOffset(ivar)) and object_getIvar(object, ivar)

According the Objective-C runtime reference:
ivar_getOffset
Returns the offset of
an instance variable.
ptrdiff_t ivar_getOffset(Ivar ivar)
Discussion For instance variables of
type id or other object types, call
object_getIvar and object_setIvar
instead of using this offset to access
the instance variable data directly.
Declared In runtime.h
Why is this? What does object_getIvar do to object types?
EDIT: changed question from subscripting (void *) to (id *).
There is no difference between those two approaches when it comes to getting the value of the ivar. You can verify this by looking at object_getIvar()'s implementation in Apple's open-source Obj-C runtime code.
object_setIvar() does more than just assign to an offset from the object pointer. It is careful to call through to the garbage-collection runtime function objc_assign_ivar() to perform the actual assignment.
More magic might be added to either of these functions in future; in general, you should use the highest-level API available at any given time.
Perhaps it's not that object_getIvar does something different, but that instance variables of type id or other object types are commonplace, and that calling ivar_getOffset and appending the result to the value of object and then casting to the appropriate type is much more cumbersome.
Note that you cannot reliably increment the value of a void *, based on the following information from the C99 standard (emphasis mine):
C99 §6.2.5 (1): (...) Types are partitioned into object types (types that fully describe objects), function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).
C99 §6.2.5 (19): The void type comprises an empty set of values; it is an incomplete type that cannot be completed.
C99 §6.5.6 (2): For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)
C99 §6.5.2.1 (1): One of the expressions shall have type “pointer to object type”, the other expression shall have integer type, and the result has type “type”.
To increment a pointer by an arbitrary number, you can use char * instead.

How does objective-c know what is going to be returned by an anonymous object?

- (void) doSomething: (id)with {
int a;
a = [with doSomething];
}
How does the compiler know what type [with doSomething] is going to return? Does it assume an int, since that's what I'm assigning to?
It doesn't know for sure what type is returned, because doSomething could be implemented with a different return type by several different classes.
I believe the compiler looks for all method implementations with that name, and makes sure at least one of them returns an int in the example above. If none of the "doSomething" signatures returned an int, it would give a warning.
The compiler knows all the methods that are currently visible. If it has a type for the message that you're sending, it uses that type. If it knows of multiple method types that all have that selector, it will arbitrarily choose one, leading to warnings and probably bugs. If it doesn't know a type for any such method, it will assume that the method returns an id.