How does sending messages to classes work? - objective-c

I know that you send messages to objects using [ ], and it is then translated to objc_msgSend()which needs a pointer to object as its first argument and second argument needs a selector.
But what about messaging classes like
[myClass doSomething];
It is not a pointer to object, so how does it work?

I am assuming that myClass is (literally) the name of a class (though usually classes start with a capital letter; I'll assume this is a class that doesn't follow the naming convention).
There are two cases of the message sending syntax in Objective-C. One, which you referred to, is if the left side is an expression which evaluates to a pointer to an object; the message is sent to that object. The second, is if the left side is an identifier which is the name of a class, then the compiler will send the message to the class object for that class. More technically, the compiler will pass a pointer to the class object as the first argument to objc_msgSend(). This is possible since it is the compiler which arranges the structure and location of the class object for each class, so it knows the address of that class object.
Intuitively, you can think of [myClass doSomething]; as similar to
Class foo = objc_getClass("myClass");
[foo doSomething];
or
Class foo = NSClassFromString(#"myClass");
[foo doSomething];
except that it doesn't need to do a runtime lookup to get a pointer to the class object -- the compiler knows the pointer at compile time.

Mike Ash has a great explanation of how objc_msgSend works: Friday Q&A 2012-11-16: Let's Build objc_msgSend.

Actually, when you send a message to a class, you are actually sending that message to a class object, which behaves as any other object with some limitations.
From Apple's reference:
In Objective-C, a class is itself an object with an opaque type called
Class. Classes can’t have properties defined using the declaration
syntax shown earlier for instances, but they can receive messages.

The runtime converts the message to a SEL then checks to see if that class responds to a message with that SEL including superclass inherited methods. If it responds it will perform the method.

Related

why casting does not change isa pointer

id a = self->isa;
id b = ((NSObject*)self)->isa;
a and b holds same value.
Now given isa pointer is same, why does
[(Animal*)Person speakEnglish];
gives error? I thought casting will change isa pointer because if I cast a child class to it's parent class, I can not invoke the child's method anymore, and method invoke search is based on isa pointer.
I am interested to know how does method selector implemented, so that even isa pointer of an instance points to Person, If I call the Person's method of the instance, I will get an error.
I assume the Animal has no method -speakEnglish, but the original class of Person has.
Then, you get a compiler error, since the method is no declared. Please note, that (as #jrturton and #xlc0212 has mentioned) the compiler does not know anything about the runtime.
It may be possible that the object (at runtime) has a selector that can be called:
[(Animal*)Person performSelector: #selector(speakEnglish)];
This uses runtime data. More precisely, it checks if a method implementation is connected with this selector and calls this implementation.
However, there is no way the compiler can know since the compiler relies on static type information. Thus, you should provide the proper type information. But you do the opposite: you throw away the correct type.

why an accessor method in an ARC environment cannot have a name that begins with 'new'?

this document states that, in order to cooperates with codes written in a MRR(manual retain-release) environment, codes written in an ARC environment cannot have a accessor name that begins with "new", I can't figure out why ARC puts this restriction on method naming.
I believe the cause is because of this:
5.2.1. Semantics of init
Methods in the init family implicitly consume their self parameter and return a retained object. Neither of these properties can be altered through attributes.
A call to an init method with a receiver that is either self (possibly parenthesized or casted) or super is called a delegate init call. It is an error for a delegate init call to be made except from an init method, and excluding blocks within such methods.
As an exception to the usual rule, the variable self is mutable in an init method and has the usual semantics for a __strong variable. However, it is undefined behavior and the program is ill-formed, no diagnostic required, if an init method attempts to use the previous value of self after the completion of a delegate init call. It is conventional, but not required, for an init method to return self.
It is undefined behavior for a program to cause two or more calls to init methods on the same object, except that each init method invocation may perform at most one delegate init call.
Source: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#family.semantics.init
Method names starting with new by convention used to call both the alloc and init methods in the past and I believe there are still methods used in Apple's framwork with the 'new' convention. I guess ARC still takes this into account with regards to memory management.
Also read up on the following: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#family
An Objective-C method may fall into a method family, which is a conventional set of behaviors ascribed to it by the Cocoa conventions.
A method is in a certain method family if:
it has a objc_method_family attribute placing it in that family; or if not that,
it does not have an objc_method_family attribute placing it in a different or no family, and
its selector falls into the corresponding selector family, and
its signature obeys the added restrictions of the method family.
A selector is in a certain selector family if, ignoring any leading underscores, the first component of the selector either consists entirely of the name of the method family or it begins with that name followed by a character other than a lowercase letter. For example, _perform:with: and performWith: would fall into the perform family (if we recognized one), but performing:with would not.
The families and their added restrictions are:
alloc methods must return a retainable object pointer type.
copy methods must return a retainable object pointer type.
mutableCopy methods must return a retainable object pointer type.
new methods must return a retainable object pointer type.
init methods must be instance methods and must return an Objective-C pointer type.
Additionally, a program is ill-formed if it declares or contains a call to an init method whose return type is neither id nor a pointer to a super-class or sub-class of the declaring class (if the method was declared on a class) or the static receiver type of the call (if it was declared on a protocol).
I guess the above means you could call a method something like newobject instead of newObject to avoid the mechanisms of ARC, but that might not make much sense for anyone working with your code. Perhaps you could also avoid the usual memory rules by setting an attribute on your custom new* method that forces some other method family on the property.

Can an ObjC class object conform to a protocol?

Is there a way to indicate to the compiler that a class object conforms to a protocol?
As I understand, by creating +(void)foo class methods, an instance of that class object will have those methods as instance methods. So, as long as I create +(void)foo methods for all required protocol methods, I can have a class object act as a delegate.
My problem of course is that in the class's header file, I only know how to indicate that instances of the class conform to the protocol (as is typically the case). So, the best I've figured out is to cast the class object like so:
something.delegate = (id<SomethingDelegate>)[self class]
Any ideas?
Related, but different:
ObjC: is there such a thing as a "class protocol"?
What you're doing now is correct as it will silence warnings which is your goal. You will be sending the class object messages defined in the protocol for instances which is a bit confusing, but the runtime doesn't care.
Think about it this way: you want to set a delegate to an object that responds to the messages defined in the protocol. Your class does this, and your class is also an object. Therefore, you should treat your class like an object that conforms to that protocol. Therefore, what you've written is completely correct (based on what you're trying to do).
One thing to note, though, is this class will not properly respond to conformsToProtocol:. This is generally okay for a delegate setup anyway (delegates don't usually check if the class conforms — they just check if it can respond to a selector).
As a side note, one thing you can do syntactically is:
Class<SomethingDelegate> variable = (Class<SomethingDelegate>)[self class];
The difference here is that the compiler will use the class methods from the protocol instead of instance messages. This is not what you want in your case, though.
There is no Objective-C syntax to indicate that a metaclass conforms to a protocol.
I think you can do it at runtime, by using class_addProtocol on the metaclass. But I haven't tried it.
I guess you could also write a +conformsToProtocol: method on your class, and lie about your conformance. This could have unexpected side-effects, since there's already a +conformsToProtocol: on NSObject (in addition to -conformsToProtocol:).
Neither of these will eliminate the need for a cast to shut the compiler up. Just use a singleton.

Objective-C Find all init (constructor methods)

using the "Method * class_copyMethodList(Class cls, unsigned int *outCount)" function one can get a list of all methods that exist on an objective-C class.
I would like to know how to find which of these methods are constructors as I am writing an IOC container. I would like to determine the constructors and their parameter types.
I would like to know how to find which of these methods are
constructors as I am writing an IOC container. I would like to
determine the constructors and their parameter types.
In short, you can't. Or, at the least, you'll find that down this path lies madness.
First, Objective-C does not have constructors. It has initializers, sometimes many, and -- for a properly written class -- only one of which is the designated initializer. There is no way to identify the designated initializer at compile time or run time.
How do I use this with a Method * and no instantiated member of the
class?
You don't. First you allocate an instance of the class, then you initialize the instance.
Overall, this level of abstraction just isn't done in Objective-C outside of academic investigations. It can be done, but it is generally avoided because of the fragility of the resulting solution and the hairball of code-hell that is trying to dynamically support the underlying C ABI (go look at the source to libffi).
If you want to go down this path, then you are far better off either defining a custom abstract class that all of your containers will subclass that can provide the binding logic to the class behind it.
Or use protocols; i.e. a class could implement an IOCBean protocol and one method would be initIOCGoop that is the designated initializer goo.
Doing this generically for all classes is going to be rife with fragility, special cases, and will require a gigantic mess of code that will be difficult to maintain over time.
You can get the method signature by using the following method:
methodSignatureForSelector:
From the documentation:
An NSMethodSignature object records type information for the arguments and return value of a method. It is used to forward messages that the receiving object does not respond to—most notably in the case of distributed objects. You typically create an NSMethodSignature object using NSObject’s methodSignatureForSelector: instance method (on Mac OS X v10.5 and later you can also use signatureWithObjCTypes:). It is then used to create an NSInvocation object, which is passed as the argument to a forwardInvocation: message to send the invocation on to whatever other object can handle the message. In the default case, NSObject invokes doesNotRecognizeSelector:, which raises an exception. For distributed objects, the NSInvocation object is encoded using the information in the NSMethodSignature object and sent to the real object represented by the receiver of the message.

What's the difference between a method and a selector?

What the difference between a method, a selector and a message in Objective-C?
This is a great question.
Selector - a Selector is the name of a method. You're very familiar with these selectors: alloc, init, release, dictionaryWithObjectsAndKeys:, setObject:forKey:, etc. Note that the colon is part of the selector; it's how we identify that this method requires parameters. Also (though it's extremely rare), you can have selectors like this: doFoo:::. This is a method that takes three parameters, and you'd invoke it like [someObject doFoo:arg1 :arg2 :arg3]. There's no requirement that there be letters before each part of the selector components. As I said, this is extremely rare, and you will not find it used in the Cocoa frameworks. You can work with selectors directly in Cocoa. They have the type SEL: SEL aSelector = #selector(doSomething:) or SEL aSelector = NSSelectorFromString(#"doSomething:");
Message - a message is a selector and the arguments you are sending with it. If I say [dictionary setObject:obj forKey:key], then the "message" is the selector setObject:forKey: plus the arguments obj and key. Messages can be encapsulated in an NSInvocation object for later invocation. Messages are sent to a receiver. (ie, the object that "receives" the message).
Method - a method is a combination of a selector and an implementation (and accompanying metadata). The "implementation" is the actual block of code; it's a function pointer (an IMP). An actual method can be retrieved internally using a Method struct (retrievable from the runtime).
Some other related things that you didn't ask for:
Method Signature - a method signature represents the data types returned by and accepted by a method. They can be represented at runtime via an NSMethodSignature and (in some cases) a raw char*.
Implementation - the actual executable code of a method. Its type at runtime is an IMP, and it's really just a function pointer. iOS 4.3 includes a new ability to turn a block into an IMP. This is really cool.
One of the fun things to realize is that the name of a method (the selector) is distinct from the implementation of the method (the IMP). This means that you can swap them around, if you're feeling daring. You can also add and remove methods at runtime, because all you're doing is editing an entry in a hash table: the key is the selector, and the value is the IMP of the method. This allows you to do some really crazy and trippy stuff. It's not for the faint of heart. :)
A method is the implementation which is run when an object or class is asked to perform some action. It is in the scope of its containing class and is therefore different when referenced through some other class. A selector is an identifier which represents the name of a method. It is not related to any specific class or method, and can be used to describe a method of any class, whether it is a class or instance method.
Simply, a selector is like a key in a dictionary. It can tell you what method someone is talking about, but only if you also have the dictionary itself (the class or object). The method is what you get when you ask for the value from the dictionary using the selector as a key.
This site has a good overview of all the terminology in question: http://www.otierney.net/objective-c.html
Check out the link, but I'll give a quick summary:
A method is essentially like a method of function that you are used to in your favourite programming language.
A message (from the article) "A message can be dynamically forwarded to another object. Calling a message on an object in Objective-C doesn't mean that the object implements that message, just that it knows how to respond to it somehow via directly implementing it or forwarding the message to an object that does know how to."
Selectors can mean two things. It can refer to the name of a method, or "refers to the unique identifier that replaces the name when the source code is compiled. Compiled selectors are of type SEL." (from: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html)