Objective-C in,out,inout,byref,byval, .. and so on. What are they?
Asked Answered
T

4

67

I discovered something unfamiliar while reading Objective-C manual for @encoding.

Table 6-2  Objective-C method encodings
Code Meaning
r    const
n    in
N    inout
o    out
O    bycopy
R    byref
V    oneway

The only thing I know is oneway. What are the others?

Taxaceous answered 10/4, 2011 at 3:23 Comment(0)
H
88

Those are annotations for method parameters and return values which were used by Distributed Objects. I say were because apparently there’s no sign of them in Apple’s documentation any longer. There used to be a Remote Messaging section in The Objective-C Programming Language document, which is still referenced by the Distributed Objects Programming Topics document.

  • in: argument is an input argument only and won’t be referenced later
  • out: argument is an output argument only, used to return a value by reference
  • inout: argument is both an input and output argument
  • const: the (pointer) argument is constant
  • bycopy: instead of using a proxy/NSDistantObject, pass or return a copy of the object
  • byref: use a proxy object (default)
Habile answered 10/4, 2011 at 4:58 Comment(7)
Thanks a lot! Especially, the documentation is no more available. In fact, I have been looked for the documentation but all links were broken.Taxaceous
FWIW, Apple used inout in the new UIScrollViewDelegate method. (targetContentOffset:(inout CGPoint *)targetContentOffset. That's way I came here, anyways.Hardiness
Actually me too. If they can use inout, why the hell they need to do something complicated like doing double pointer to get error? Actually given that they pass CGPOINT * they do not need to specify inout at all. It's a pointer. CGPOINT is a struct. As long as you put the new CGPOINT to the address pointed by targetContentOffset, you'll do fine.Overjoy
More references in NSDateFormatter.hDumps
apple uses inout,out in validation valus for keys. -(BOOL)validateValue:(inout __autoreleasing id *)ioValue forKey:(NSString *)inKey error:(out NSError *__autoreleasing *)outErrorObbligato
inout is also used UIPopoverViewController: -popoverController:willRepositionPopoverToRect:inView:Involuntary
@AnonymousWhite There is nothing special about inout - it is simply an informational directive to other programmers. It can only be used in protocols. It cannot replace parameters of type NSError **error and the like: in fact, in this case the parameter in question (CGPoint *) used in exactly the same way.Pallette
Y
27

Beyond Distributed Objects, one of these annotations appears to be used by ARC. I came across the following in clang's description of passing to an out parameter by writeback:

If the parameter is not an Objective-C method parameter marked out, then *p is read, and the result is written into the temporary with primitive semantics.

This has to do with methods like - (BOOL)executeWithError:(out NSError **)error.

Ignoring the out keyword, ARC has a well-defined behavior of treating by-reference object passing as __autoreleasing, so ARC treats the error parameter as having a type of NSError * __autoreleasing *. If you use an otherwise qualified variable, ARC will add a temporary autoreleasing variable pass into the function (for coherence):

Original code

NSError *error;
[obj executeWithError:&error];

Pseudotransformed code

NSError * __strong error;
NSError * __autoreleasing temp;
temp = error;
[obj executeWithError:&temp];
error = temp;

With the above code, the line temp = error would be unnecessary if we could somehow know that temp will never be read. This is where the out annotation comes into play. Per the quoted description if out is missing the compiler must add the line temp = error but if it does contain out it can exclude the line and make the code just a little bit smaller/faster. With out the transformed code becomes:

NSError * __strong error;
NSError * __autoreleasing temp;
[obj executeWithError:&temp];
error = temp;

Of course, if you're that worried about binary size and speed, you should just code the following:

NSError * __autoreleasing error;
[obj executeWithError:&error];

It is entirely possible that these annotations are used other places throughout the compiler and runtime, and may be used in more places in the future. Personally, I like using out as a hint to other developers that I'm not going to read the value.

Yugoslav answered 23/9, 2013 at 22:49 Comment(10)
Original Code seems lacking one address-of operator. executeWithError:&error];Taxaceous
@BrianNickel so (out NSError **) and (NSError * __autoreleasing *) are the same ?Superpose
@Superpose No. (out NSError **) is the same as (out NSError * __autoreleasing *) and (NSError **) is the same type as (NSError * __autoreleasing *). The injection of __autoreleasing is part of ARC's design, similar to how all variables are __strong unless specified. out isn't part of the type but an annotation that the compiler can use to optimize.Yugoslav
@BrianNickel so what does "out" keyword do? It only removes this line of code: temp = error; Or it does something more ?Superpose
It just removes that one line. I'll update the answer to clarify.Yugoslav
@BrianNickel what does "out" keyword does in general. When would I possibly use it (other than distributed objects, which I haven't learned yet)Superpose
@BrianNickel what do you mean by saying: "if we could somehow know that temp will never be read. This is where the out annotation comes into play." If the code with "out" is faster, why almost nobody is using it ?Superpose
@Superpose it's optional, obscure, and such a minor savings in the grand scheme of things that pretty much no one should ever need it.Yugoslav
I believe that the out keyword is crucial if one is using the objective-C bridgesupport metadata parser. In particular, I know that pyobjc treats out parameters specially and without such designation any particular API with an out parameter can not be used out of the box without manually adding the notation to the method call at runtime.Sub
@Superpose It tells compiler to assume that current value of the object pointer passed as out is of no importance and can be ignored. However, if you search for OBJC_TQ_Out in clang's source code you'll find that its only use is to elide an assignment Brian referred to. Very little gain.Volkslied
M
0

Incase anyone has stumbled across this post and has the same confusion as me, the 'in' argument can also be a keyword that represents fast enumeration. See here for more details.

Muller answered 25/1, 2012 at 13:30 Comment(1)
Such a common construct in other current languages, like Java and Python, but virtually never used in Obj-C. Personally, I tend to use blockEnumerators when I need this sort of thing even though it involves a lot more typing... IDK, I feel anyone reading my code is more likely to instantly get it that way.Mccandless
M
-3

You can read the Objective-C runtime sources http://www.opensource.apple.com/source/objc4/objc4-437.1/ to understand what these annotations mean.

Mission answered 10/4, 2011 at 9:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.