1

i'm trying to understand this in objective-c :

in this example, indexPath is a pointer but we use it "as is" in the function : indexPath.section, instead of (for example) *indexPath.section(with a *) :

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    return (indexPath.section == 0) ? nil : indexPath;
}

so, in objective-c, we don't need to add a * to get the content of the variable where the pointer points to...?

but i found this function, where they use a * on the pointer inside the function (on reverse ) :

NSInteger lastNameFirstNameSort(id person1, id person2, void *reverse)
{
    NSString *name1 = [person1 valueForKey:LAST];

    //...

    if (*(BOOL *)reverse == YES) {
        return 0 - comparison;
    }

and for the id variables, they are using the variable name as is : for example here : person1

So, could someone explain me the differences between those 2 examples :
why on the first example, we don't add a * on indexPath,
why we don't add this * on the id variables, and we use it with *reverse in the second example?

Thanks

Paul
  • 6,108
  • 14
  • 72
  • 128

2 Answers2

5

You are confusing dot-notation with reading a structure. This is not surprising, since Apple made them ambiguous.

indexPath.section does not mean "the section structure element in indexPath. It doesn't even mean "the property section in indexPath." It means [indexPath section]. It just calls the method section and returns the result.

Similarly, foo.bar = baz does not literally mean "set the property bar to baz." It literally means [foo setBar:baz]. Whatever setBar: does will be done. In most cases, it sets an ivar.

Since indexPath is also technically a struct pointer, it is possible in some cases (but not always, and not often if you code correctly) to say indexPath->section. You should never do this. (There are some extremely rare exceptions, but you are unlikely to encounter them.)

The frustrating thing about all of this is that foo.bar might be a structure reference or it might be a method call. Without knowing what foo is, you can't know. This is one of the problems with dot notation.

If you find it confusing, don't use dot notation (it continues to be a controversial feature among experienced developers). It is never required. It's just a shortcut for the more explicit [foo bar] and [foo setBar:baz].

*(BOOL *)result means "cast result from void* to BOOL * and then dereference it as a BOOL. It's unrelated to dot notation.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • thanks Rob for this great explanation, i asked this question to Oddity, but maybe you have a good answer to it : if we want to call a method from the pointer, using the pointer is enough, but if we want the content where the pointer points to, we dereference the pointer with * , is it correct? why don't we do [*person1 valueForKey:LAST]; for example? – Paul Apr 02 '12 at 21:39
  • 1
    @Paul: Objects are messaged through pointers. In general, they aren't even allowed to be allocated on the stack. In short, you don't dereference them. It works basically the same way in Java and Ruby and many other languages — they just don't have special syntax for pointers. – Chuck Apr 02 '12 at 21:43
  • 2
    You might find these answers interesting: http://stackoverflow.com/questions/1304176/objective-c-difference-between-id-and-void/1304277#1304277 and http://stackoverflow.com/questions/2189212/why-object-dosomething-and-not-object-dosomething/2214980#2214980 – bbum Apr 02 '12 at 21:53
  • @Chuck : thanks Chuck, one thing though : BOOL can be considered as an object, if we do `(BOOL *)result`, isn't it? ( but if we use one of its method, for the different reasons explained in the links gave by @bbum (thanks for the links bbum) we don't dereference them - i'm trying to make this clear to me :-) ) – Paul Apr 02 '12 at 23:45
  • 1
    BOOL is never an object. BOOL is a char. ObjC is still C; you can take pointers to arbitrary types. But that doesn't make them objects. An object is a pointer to an objc_object. – Rob Napier Apr 02 '12 at 23:50
  • @Rob Napier : thanks Rob, okay i better understand, thank you! – Paul Apr 03 '12 at 13:22
2

Dot-syntax on ObjC objects (pointers to objects) is a way of accessing methods of the forms [object getter] and [object setter: value], using java/c#/javascript like notation (object.property) While the syntax isn't exactly consistent, object->property is already taken by direct property access. reverse is just a normal void pointer, and so the (BOOL*) converts it to a BOOL pointer, and the * before it dereferences it. id types are still pointers, it's just that the syntax for property access in ObjC isn't consistent with the existing C syntax.

Oddity0x0
  • 71
  • 3
  • thanks Oddity0x0, so if we want to call a method from the pointer, using the pointer is enough, but if we want the content where the pointer points to, we dereference the pointer with `*` , is it correct? why don't we do `[*person1 valueForKey:LAST];` for example? – Paul Apr 02 '12 at 21:37
  • 2
    [object method] is a shortcut for objc_msgSend(object, @selector(method)), the first argument to objc_msgSend is a pointer, and so object in [object method] must be a pointer as well. I've never tried it, but [&(*object) method] should theoretically work – Oddity0x0 Apr 02 '12 at 22:21
  • Note that `[object method]` is *logically* a shortcut for `objc_msgSend()`. It may actually be translated into one of several functions depending on the target, the types involved, and the architecture you're building for. This is one of the reasons you should not call `objc_msgSend()` directly, even though you theoretically can. – Rob Napier Apr 02 '12 at 23:57