• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Newbie question on Methods
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Newbie question on Methods


  • Subject: Re: Newbie question on Methods
  • From: Erik Buck <email@hidden>
  • Date: Sun, 12 Mar 2006 13:00:00 -0500

There is one concept I'm not understanding. In the
NSOpenPanelWithFileTypes example (on CocoaDev.com) there is the following code:


NSArray *fileTypes = [NSArray arrayWithObject:@"td"];
NSOpenPanel *oPanel = [NSOpenPanel openPanel];

This is the central concept of Objective-C. I am unlikely to be able to improve on the documentation and many available books in this email. Nevertheless, I will try :)


As a C programmer, perhaps you need the "magic" removed so you can see what is happening in Objective-C.


Objective-C adds the concepts of objects and message sending to the C language. Any message may be sent to any object. By default, there is a runtime error if the receiver of a message does not understand the message, although some receivers may suppress the error or handle the unrecognized message my passing it on to an object that does understand it.


Because you are an avowed C programmer, I intend to describe the concept of Objective-C objects from a C point of view. But first, let me propose these implementation neutral definitions: An Objective- C object is anything that can receive a message. A message is just a request for the receiver to do something using arguments that may be provided with the message. In some cases, sending a message may return a value to the sender.

Those definitions may seem vague, but it is that simple, and there are huge implications to this. Just to whet you appetite, let me start by saying that neither the receiver nor the message needs to be known at compile time, and this is the great strength (flexibility) of Objective-C and similar languages like Smalltalk, Ruby, and Python but not like C++ or Java.


So, for a C programmer, what is an Objective-C object ? In implementation, and Objective-C object is any C structure whose first element is a variable of type Class. In objc.h on you hard drive, you will find the C type Class is declared as


typedef struct objc_class *Class;

Another fun C typedef is the id type used to store a pointer to any Objective-C object:

typedef struct objc_object {
	Class isa;
} *id;

So, any variable of type id is just a pointer to any structure that contains as its first element a pointer to a variable of type Class.

Now that you know exactly what an Objective-C object is from a C programmer's point of view, what is a message ?

Objective-C's implementation provides a couple of C functions:

id objc_msgSend(id self, SEL op, ...);
id objc_msgSendSuper(struct objc_super *super, SEL op, ...);

The SEL type is the C type that identifies what message is being sent. In objc_msgSend(id self, SEL op, ...), self is the receiver of the message, SEL identifies the message being sent, and any number of arguments may follow.

objc_msgSendSuper() is similar to objc_msgSend(). The only relevant difference between the two is where the function looks first to find an IMP to call in response to the message. What's an IMP you ask ?

typedef id (*IMP)(id, SEL, ...);

IMP is a C typedef for a pointer to a function that takes the same arguments as objc_msgSend() and returns the same type. The code that is executed in response to receipt of an Objective-C message is compiled into a C function by the Objective-C compiler. Pointers to those functions are then associated with messages using a hash table that maps SEL to IMP.

objc_msgSend() and objc_msgSendSuper() simply use the provided SEL argument to look-up the corresponding IMP and than call the IMP passing the same arguments that were passed to objc_msgSend() and objc_msgSendSuper().

That is Objective-C.

---------------------
Now that you know what an object is, let's look at your question again.

NSArray *fileTypes = [NSArray arrayWithObject:@"td"];
NSOpenPanel *oPanel = [NSOpenPanel openPanel];

NSArray * and NSOpenPanel * are both synonyms for the C type id.

The following code will produce EXACTLY the same machine code when compiled with Objective-C as the code in your example:

id fileTypes = [NSArray arrayWithObject:@"td"];
id oPanel = [NSOpenPanel openPanel];

So you know that fileTypes is a variable that points to a struct objc_object.

You wrote:
I understand that in the first line you are declaring an instance of
the class (fileTypes) of the NSArray object.  But I don't understand

***** You misunderstood! You were not declaring an instance of class fileTypes. In fact, your statement of understanding was completely non-sensical. All you did was declare a variable that will point to a struct objc_object and then initialize that variable with whatever the result of [NSArray arrayWithObject:@"td"] turns out to be.


id fileTypes = [NSArray arrayWithObject:@"td"]; is a synonym for

id fileTypes = objc_msgSend(objc_lookUpClass("NSArray"), sel_getUid ("arrayWithObject:"), @"td");

For reference: In objc.h see the declaration SEL sel_getUid(const char *str);
In objc-runtime.h see the declaration id objc_lookUpClass(const char *name);



ignoring @"td" for a moment (it was another of your questions)...

you now see that id fileTypes = [NSArray arrayWithObject:@"td"]; is just a syntactically nicer way of writing id fileTypes = objc_msgSend (objc_lookUpClass("NSArray"), sel_getUid("arrayWithObject:"), @"td");.

In reality, the Objective-C compiler can optimize things a bit to eliminate some of the function calls at run-time, but that is beside the point right now.

What is the significance of the string "NSArray" ? There is an Objective-C class named NSArray provided by the Cocoa framework. As you can guess from the C language implementation of Objective-C, objc_lookUpClass() just returns an id type value that was associated with the string "NSArray" by the Objective-C compiler. Yes, that's right, just like the compiler generates a hash table to associate IMP with SEL, it generates a hash table to associate ids with Objective-C class names like "NSArray." So, when the compiler compiled the class NSArray, the compiler generated the following things:

1) the compiler generated a static C structure whose first element is of type Class.
2) the compiler generated a hash table entry associating a pointer to the static structure with the string "NSArray."
3) the compiler generated a hash table entry associating a SEL with the string "arrayWithObject:"
3) The compiler generated a C function containing code to be executed in response to the arrayWithObject: message selector.
4) the compiler generated a hash table entry associating a pointer to the generated function with the SEL previously associated with the string "arrayWithObject:".


All that stuff generated by the compiler makes id fileTypes = objc_msgSend(objc_lookUpClass("NSArray"), sel_getUid ("arrayWithObject:"), @"td") work at run-time.

Stay tuned for more...






_______________________________________________ Do not post admin requests to the list. They will be ignored. Cocoa-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
  • Prev by Date: Re: transparent overlay NSWindow
  • Next by Date: Re: Help on NSToolbar
  • Previous by thread: Re: Newbie question on Methods
  • Next by thread: transparent overlay NSWindow
  • Index(es):
    • Date
    • Thread