4.Objective-C Runtime Programming Guide (Apple)

34
Objective-C Runtime Programming Guide Tools & Languages: Objective-C 2009-10-19

description

this is ebook of Shinichi

Transcript of 4.Objective-C Runtime Programming Guide (Apple)

Page 1: 4.Objective-C Runtime Programming Guide (Apple)

Objective-C Runtime Programming GuideTools & Languages: Objective-C

2009-10-19

Page 2: 4.Objective-C Runtime Programming Guide (Apple)

Apple Inc.© 2009 Apple Inc.All rights reserved.

No part of this publication may be reproduced,stored in a retrieval system, or transmitted, inany form or by any means, mechanical,electronic, photocopying, recording, orotherwise, without prior written permission ofApple Inc., with the following exceptions: Anyperson is hereby authorized to storedocumentation on a single computer forpersonal use only and to print copies ofdocumentation for personal use provided thatthe documentation contains Apple’s copyrightnotice.

The Apple logo is a trademark of Apple Inc.

No licenses, express or implied, are grantedwith respect to any of the technology describedin this document. Apple retains all intellectualproperty rights associated with the technologydescribed in this document. This document isintended to assist application developers todevelop applications only for Apple-labeledcomputers.

Apple Inc.1 Infinite LoopCupertino, CA 95014408-996-1010

Apple, the Apple logo, Cocoa, iPhone, Mac, MacOS, and Objective-C are trademarks of AppleInc., registered in the United States and othercountries.

Even though Apple has reviewed this document,APPLE MAKES NO WARRANTY OR REPRESENTATION,EITHER EXPRESS OR IMPLIED, WITH RESPECT TOTHIS DOCUMENT, ITS QUALITY, ACCURACY,MERCHANTABILITY, OR FITNESS FOR A PARTICULARPURPOSE. AS A RESULT, THIS DOCUMENT ISPROVIDED “AS IS,” AND YOU, THE READER, AREASSUMING THE ENTIRE RISK AS TO ITS QUALITYAND ACCURACY.

IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT,INDIRECT, SPECIAL, INCIDENTAL, ORCONSEQUENTIAL DAMAGES RESULTING FROM ANYDEFECT OR INACCURACY IN THIS DOCUMENT, evenif advised of the possibility of such damages.

THE WARRANTY AND REMEDIES SET FORTH ABOVEARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORALOR WRITTEN, EXPRESS OR IMPLIED. No Appledealer, agent, or employee is authorized to makeany modification, extension, or addition to thiswarranty.

Some states do not allow the exclusion or limitationof implied warranties or liability for incidental orconsequential damages, so the above limitation orexclusion may not apply to you. This warranty givesyou specific legal rights, and you may also haveother rights which vary from state to state.

Page 3: 4.Objective-C Runtime Programming Guide (Apple)

Contents

Introduction Introduction 7

Organization of This Document 7See Also 7

Chapter 1 Runtime Versions and Platforms 9

Legacy and Modern Versions 9Platforms 9

Chapter 2 Interacting with the Runtime 11

Objective-C Source Code 11NSObject Methods 11Runtime Functions 12

Chapter 3 Messaging 13

The objc_msgSend Function 13Using Hidden Arguments 15Getting a Method Address 16

Chapter 4 Dynamic Method Resolution 17

Dynamic Method Resolution 17Dynamic Loading 18

Chapter 5 Message Forwarding 19

Forwarding 19Forwarding and Multiple Inheritance 20Surrogate Objects 21Forwarding and Inheritance 22

Chapter 6 Type Encodings 25

Chapter 7 Declared Properties 29

Property Type and Functions 29Property Type String 30Property Attribute Description Examples 31

32009-10-19 | © 2009 Apple Inc. All Rights Reserved.

Page 4: 4.Objective-C Runtime Programming Guide (Apple)

Document Revision History 33

42009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CONTENTS

Page 5: 4.Objective-C Runtime Programming Guide (Apple)

Figures and Tables

Chapter 3 Messaging 13

Figure 3-1 Messaging Framework 14

Chapter 5 Message Forwarding 19

Figure 5-1 Forwarding 21

Chapter 6 Type Encodings 25

Table 6-1 Objective-C type encodings 25Table 6-2 Objective-C method encodings 27

Chapter 7 Declared Properties 29

Table 7-1 Declared property type encodings 30

52009-10-19 | © 2009 Apple Inc. All Rights Reserved.

Page 6: 4.Objective-C Runtime Programming Guide (Apple)

62009-10-19 | © 2009 Apple Inc. All Rights Reserved.

FIGURES AND TABLES

Page 7: 4.Objective-C Runtime Programming Guide (Apple)

The Objective-C language defers as many decisions as it can from compile time and link time to runtime.Whenever possible, it does things dynamically. This means that the language requires not just a compiler,but also a runtime system to execute the compiled code. The runtime system acts as a kind of operatingsystem for the Objective-C language; it’s what makes the language work.

This document looks at the NSObject class and how Objective-C programs interact with the runtime system.In particular, it examines the paradigms for dynamically loading new classes at runtime, and forwardingmessages to other objects. It also provides information about how you can find information about objectswhile your program is running.

You should read this document to gain an understanding of how the Objective-C runtime system works andhow you can take advantage of it. Typically, though, there should be little reason for you to need to knowand understand this material to write a Cocoa application.

Organization of This Document

This document has the following chapters:

● “Runtime Versions and Platforms” (page 9)

● “Interacting with the Runtime” (page 11)

● “Messaging” (page 13)

● “Dynamic Method Resolution” (page 17)

● “Message Forwarding” (page 19)

● “Type Encodings” (page 25)

● “Declared Properties” (page 29)

See Also

Objective-C RuntimeReference describes the data structures and functions of the Objective-C runtime supportlibrary. Your programs can use these interfaces to interact with the Objective-C runtime system. For example,you can add classes or methods, or obtain a list of all class definitions for loaded classes.

The Objective-C Programming Language describes the Objective-C language.

Organization of This Document 72009-10-19 | © 2009 Apple Inc. All Rights Reserved.

INTRODUCTION

Introduction

Page 8: 4.Objective-C Runtime Programming Guide (Apple)

Objective-C Release Notes describes some of the changes in the Objective-C runtime in the latest release ofMac OS X.

8 See Also2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

INTRODUCTION

Introduction

Page 9: 4.Objective-C Runtime Programming Guide (Apple)

There are different versions of the Objective-C runtime on different platforms.

Legacy and Modern Versions

There are two versions of the Objective-C runtime—“modern” and “legacy”. The modern version wasintroduced with Objective-C 2.0 and includes a number of new features. The programming interface for thelegacy version of the runtime is described in Objective-C 1 Runtime Reference; the programming interface forthe modern version of the runtime is described in Objective-C Runtime Reference.

The most notable new feature is that instance variables in the modern runtime are “non-fragile”:

● In the legacy runtime, if you change the layout of instance variables in a class, you must recompile classesthat inherit from it.

● In the modern runtime, if you change the layout of instance variables in a class, you do not have torecompile classes that inherit from it.

In addition, the modern runtime supports instance variable synthesis for declared properties (see DeclaredProperties in The Objective-C Programming Language).

Platforms

iPhone applications and 64-bit programs on Mac OS X v10.5 and later use the modern version of the runtime.

Other programs (32-bit programs on Mac OS X desktop) use the legacy version of the runtime.

Legacy and Modern Versions 92009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 1

Runtime Versions and Platforms

Page 10: 4.Objective-C Runtime Programming Guide (Apple)

10 Platforms2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 1

Runtime Versions and Platforms

Page 11: 4.Objective-C Runtime Programming Guide (Apple)

Objective-C programs interact with the runtime system at three distinct levels: through Objective-C sourcecode; through methods defined in the NSObject class of the Foundation framework; and through directcalls to runtime functions.

Objective-C Source Code

For the most part, the runtime system works automatically and behind the scenes. You use it just by writingand compiling Objective-C source code.

When you compile code containing Objective-C classes and methods, the compiler creates the data structuresand function calls that implement the dynamic characteristics of the language. The data structures captureinformation found in class and category definitions and in protocol declarations; they include the class andprotocol objects discussed in Defining a Class and Protocols in The Objective-C Programming Language, aswell as method selectors, instance variable templates, and other information distilled from source code. Theprincipal runtime function is the one that sends messages, as described in “Messaging” (page 13). It’s invokedby source-code message expressions.

NSObject Methods

Most objects in Cocoa are subclasses of the NSObject class, so most objects inherit the methods it defines.(The notable exception is the NSProxy class; see “Message Forwarding” (page 19) for more information.) Itsmethods therefore establish behaviors that are inherent to every instance and every class object. However,in a few cases, the NSObject class merely defines a template for how something should be done; it doesn’tprovide all the necessary code itself.

For example, the NSObject class defines a description instance method that returns a string describingthe contents of the class. This is primarily used for debugging—the GDB print-object command printsthe string returned from this method. NSObject’s implementation of this method doesn’t know what theclass contains, so it returns a string with the name and address of the object. Subclasses of NSObject canimplement this method to return more details. For example, the Foundation class NSArray returns a list ofdescriptions of the objects it contains.

Some of the NSObject methods simply query the runtime system for information. These methods allowobjects to perform introspection. Examples of such methods are the class method, which asks an objectto identify its class; isKindOfClass: and isMemberOfClass:, which test an object’s position in theinheritance hierarchy; respondsToSelector:, which indicates whether an object can accept a particularmessage; conformsToProtocol:, which indicates whether an object claims to implement the methodsdefined in a specific protocol; and methodForSelector:, which provides the address of a method’simplementation. Methods like these give an object the ability to introspect about itself.

Objective-C Source Code 112009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 2

Interacting with the Runtime

Page 12: 4.Objective-C Runtime Programming Guide (Apple)

Runtime Functions

The runtime system is a dynamic shared library with a public interface consisting of a set of functions anddata structures in the header files located within the directory /usr/include/objc. Many of these functionsallow you to use plain C to replicate what the compiler does when you write Objective-C code. Others formthe basis for functionality exported through the methods of the NSObject class. These functions make itpossible to develop other interfaces to the runtime system and produce tools that augment the developmentenvironment; they’re not needed when programming in Objective-C. However, a few of the runtime functionsmight on occasion be useful when writing an Objective-C program. All of these functions are documentedin Objective-C Runtime Reference.

12 Runtime Functions2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 2

Interacting with the Runtime

Page 13: 4.Objective-C Runtime Programming Guide (Apple)

This chapter describes how the message expressions are converted into objc_msgSend function calls, andhow you can refer to methods by name. It then explains how you can take advantage of objc_msgSend,and how—if you need to—you can circumvent dynamic binding.

The objc_msgSend Function

In Objective-C, messages aren’t bound to method implementations until runtime. The compiler converts amessage expression,

[receiver message]

into a call on a messaging function, objc_msgSend. This function takes the receiver and the name of themethod mentioned in the message—that is, the method selector—as its two principal parameters:

objc_msgSend(receiver, selector)

Any arguments passed in the message are also handed to objc_msgSend:

objc_msgSend(receiver, selector, arg1, arg2, ...)

The messaging function does everything necessary for dynamic binding:

● It first finds the procedure (method implementation) that the selector refers to. Since the same methodcan be implemented differently by separate classes, the precise procedure that it finds depends on theclass of the receiver.

● It then calls the procedure, passing it the receiving object (a pointer to its data), along with any argumentsthat were specified for the method.

● Finally, it passes on the return value of the procedure as its own return value.

Note: The compiler generates calls to the messaging function. You should never call it directly in the codeyou write.

The key to messaging lies in the structures that the compiler builds for each class and object. Every classstructure includes these two essential elements:

● A pointer to the superclass.

● A class dispatch table. This table has entries that associate method selectors with the class-specificaddresses of the methods they identify. The selector for the setOrigin:: method is associated withthe address of (the procedure that implements) setOrigin::, the selector for the display method isassociated with display’s address, and so on.

The objc_msgSend Function 132009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 3

Messaging

Page 14: 4.Objective-C Runtime Programming Guide (Apple)

When a new object is created, memory for it is allocated, and its instance variables are initialized. First amongthe object’s variables is a pointer to its class structure. This pointer, called isa, gives the object access to itsclass and, through the class, to all the classes it inherits from.

Note: While not strictly a part of the language, the isa pointer is required for an object to work with theObjective-C runtime system. An object needs to be “equivalent” to a struct objc_object (defined inobjc/objc.h) in whatever fields the structure defines. However, you rarely, if ever, need to create your ownroot object, and objects that inherit from NSObject or NSProxy automatically have the isa variable.

These elements of class and object structure are illustrated in Figure 3-1.

Figure 3-1 Messaging Framework

. . .

superclass

selector...addressselector...addressselector...address

. . .

superclass

selector...addressselector...addressselector...address

. . .

superclass

selector...addressselector...addressselector...address

isainstance variableinstance variable

. . .

The object’s superclass

The root class (NSObject)

The object’s class

14 The objc_msgSend Function2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 3

Messaging

Page 15: 4.Objective-C Runtime Programming Guide (Apple)

When a message is sent to an object, the messaging function follows the object’s isa pointer to the classstructure where it looks up the method selector in the dispatch table. If it can’t find the selector there,objc_msgSend follows the pointer to the superclass and tries to find the selector in its dispatch table.Successive failures cause objc_msgSend to climb the class hierarchy until it reaches the NSObject class.Once it locates the selector, the function calls the method entered in the table and passes it the receivingobject’s data structure.

This is the way that method implementations are chosen at runtime—or, in the jargon of object-orientedprogramming, that methods are dynamically bound to messages.

To speed the messaging process, the runtime system caches the selectors and addresses of methods as theyare used. There’s a separate cache for each class, and it can contain selectors for inherited methods as wellas for methods defined in the class. Before searching the dispatch tables, the messaging routine first checksthe cache of the receiving object’s class (on the theory that a method that was used once may likely be usedagain). If the method selector is in the cache, messaging is only slightly slower than a function call. Once aprogram has been running long enough to “warm up” its caches, almost all the messages it sends find acached method. Caches grow dynamically to accommodate new messages as the program runs.

Using Hidden Arguments

When objc_msgSend finds the procedure that implements a method, it calls the procedure and passes itall the arguments in the message. It also passes the procedure two hidden arguments:

● The receiving object

● The selector for the method

These arguments give every method implementation explicit information about the two halves of the messageexpression that invoked it. They’re said to be “hidden” because they aren’t declared in the source code thatdefines the method. They’re inserted into the implementation when the code is compiled.

Although these arguments aren’t explicitly declared, source code can still refer to them (just as it can referto the receiving object’s instance variables). A method refers to the receiving object as self, and to its ownselector as _cmd. In the example below, _cmd refers to the selector for the strange method and self tothe object that receives a strange message.

- strange{ id target = getTheReceiver(); SEL method = getTheMethod();

if ( target == self || method == _cmd ) return nil; return [target performSelector:method];}

self is the more useful of the two arguments. It is, in fact, the way the receiving object’s instance variablesare made available to the method definition.

Using Hidden Arguments 152009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 3

Messaging

Page 16: 4.Objective-C Runtime Programming Guide (Apple)

Getting a Method Address

The only way to circumvent dynamic binding is to get the address of a method and call it directly as if it werea function. This might be appropriate on the rare occasions when a particular method will be performedmany times in succession and you want to avoid the overhead of messaging each time the method isperformed.

With a method defined in the NSObject class, methodForSelector:, you can ask for a pointer to theprocedure that implements a method, then use the pointer to call the procedure. The pointer thatmethodForSelector: returns must be carefully cast to the proper function type. Both return and argumenttypes should be included in the cast.

The example below shows how the procedure that implements the setFilled: method might be called:

void (*setter)(id, SEL, BOOL);int i;

setter = (void (*)(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)];for ( i = 0; i < 1000, i++ ) setter(targetList[i], @selector(setFilled:), YES);

The first two arguments passed to the procedure are the receiving object (self) and the method selector(_cmd). These arguments are hidden in method syntax but must be made explicit when the method is calledas a function.

Using methodForSelector: to circumvent dynamic binding saves most of the time required by messaging.However, the savings will be significant only where a particular message is repeated many times, as in thefor loop shown above.

Note that methodForSelector: is provided by the Cocoa runtime system; it’s not a feature of the Objective-Clanguage itself.

16 Getting a Method Address2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 3

Messaging

Page 17: 4.Objective-C Runtime Programming Guide (Apple)

This chapter describes how you can provide an implementation of a method dynamically.

Dynamic Method Resolution

There are situations where you might want to provide an implementation of a method dynamically. Forexample, the Objective-C declared properties feature (see Declared Properties in TheObjective-C ProgrammingLanguage) includes the @dynamic directive:

@dynamic propertyName;

which tells the compiler that the methods associated with the property will be provided dynamically.

You can implement the methods resolveInstanceMethod: and resolveClassMethod: to dynamicallyprovide an implementation for a given selector for an instance and class method respectively.

An Objective-C method is simply a C function that take at least two arguments—self and _cmd. You canadd a function to a class as a method using the function class_addMethod. Therefore, given the followingfunction:

void dynamicMethodIMP(id self, SEL _cmd) { // implementation ....}

you can dynamically add it to a class as a method (called resolveThisMethodDynamically) usingresolveInstanceMethod: like this:

@implementation MyClass+ (BOOL)resolveInstanceMethod:(SEL)aSEL{ if (aSEL == @selector(resolveThisMethodDynamically)) { class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:"); return YES; } return [super resolveInstanceMethod:aSEL];}@end

Forwarding methods (as described in “Message Forwarding” (page 19)) and dynamic method resolution are,largely, orthogonal. A class has the opportunity to dynamically resolve a method before the forwardingmechanism kicks in. If respondsToSelector: or instancesRespondToSelector: is invoked, the dynamicmethod resolver is given the opportunity to provide an IMP for the selector first. If you implementresolveInstanceMethod: but want particular selectors to actually be forwarded via the forwardingmechanism, you return NO for those selectors.

Dynamic Method Resolution 172009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 4

Dynamic Method Resolution

Page 18: 4.Objective-C Runtime Programming Guide (Apple)

Dynamic Loading

An Objective-C program can load and link new classes and categories while it’s running. The new code isincorporated into the program and treated identically to classes and categories loaded at the start.

Dynamic loading can be used to do a lot of different things. For example, the various modules in the SystemPreferences application are dynamically loaded.

In the Cocoa environment, dynamic loading is commonly used to allow applications to be customized. Otherscan write modules that your program loads at runtime—much as Interface Builder loads custom palettesand the Mac OS X System Preferences application loads custom preference modules. The loadable modulesextend what your application can do. They contribute to it in ways that you permit but could not haveanticipated or defined yourself. You provide the framework, but others provide the code.

Although there is a runtime function that performs dynamic loading of Objective-C modules in Mach-O files(objc_loadModules, defined in objc/objc-load.h), Cocoa’s NSBundle class provides a significantlymore convenient interface for dynamic loading—one that’s object-oriented and integrated with relatedservices. See the NSBundle class specification in the Foundation framework reference for information onthe NSBundle class and its use. See Mac OS X ABI Mach-O File Format Reference for information on Mach-Ofiles.

18 Dynamic Loading2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 4

Dynamic Method Resolution

Page 19: 4.Objective-C Runtime Programming Guide (Apple)

Sending a message to an object that does not handle that message is an error. However, before announcingthe error, the runtime system gives the receiving object a second chance to handle the message.

Forwarding

If you send a message to an object that does not handle that message, before announcing an error theruntime sends the object a forwardInvocation: message with an NSInvocation object as its soleargument—the NSInvocation object encapsulates the original message and the arguments that werepassed with it.

You can implement a forwardInvocation: method to give a default response to the message, or to avoidthe error in some other way. As its name implies, forwardInvocation: is commonly used to forward themessage to another object.

To see the scope and intent of forwarding, imagine the following scenarios: Suppose, first, that you’redesigning an object that can respond to a message called negotiate, and you want its response to includethe response of another kind of object. You could accomplish this easily by passing a negotiate messageto the other object somewhere in the body of the negotiate method you implement.

Take this a step further, and suppose that you want your object’s response to a negotiate message to beexactly the response implemented in another class. One way to accomplish this would be to make your classinherit the method from the other class. However, it might not be possible to arrange things this way. Theremay be good reasons why your class and the class that implements negotiate are in different branches ofthe inheritance hierarchy.

Even if your class can’t inherit the negotiate method, you can still “borrow” it by implementing a versionof the method that simply passes the message on to an instance of the other class:

- negotiate{ if ( [someOtherObject respondsTo:@selector(negotiate)] ) return [someOtherObject negotiate]; return self;}

This way of doing things could get a little cumbersome, especially if there were a number of messages youwanted your object to pass on to the other object. You’d have to implement one method to cover eachmethod you wanted to borrow from the other class. Moreover, it would be impossible to handle cases whereyou didn’t know, at the time you wrote the code, the full set of messages you might want to forward. Thatset might depend on events at runtime, and it might change as new methods and classes are implementedin the future.

Forwarding 192009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 5

Message Forwarding

Page 20: 4.Objective-C Runtime Programming Guide (Apple)

The second chance offered by a forwardInvocation: message provides a less ad hoc solution to thisproblem, and one that’s dynamic rather than static. It works like this: When an object can’t respond to amessage because it doesn’t have a method matching the selector in the message, the runtime system informsthe object by sending it a forwardInvocation: message. Every object inherits a forwardInvocation:method from the NSObject class. However, NSObject’s version of the method simply invokesdoesNotRecognizeSelector:. By overriding NSObject’s version and implementing your own, you cantake advantage of the opportunity that the forwardInvocation: message provides to forward messagesto other objects.

To forward a message, all a forwardInvocation: method needs to do is:

● Determine where the message should go, and

● Send it there with its original arguments.

The message can be sent with the invokeWithTarget: method:

- (void)forwardInvocation:(NSInvocation *)anInvocation{ if ([someOtherObject respondsToSelector: [anInvocation selector]]) [anInvocation invokeWithTarget:someOtherObject]; else [super forwardInvocation:anInvocation];}

The return value of the message that’s forwarded is returned to the original sender. All types of return valuescan be delivered to the sender, including ids, structures, and double-precision floating-point numbers.

A forwardInvocation: method can act as a distribution center for unrecognized messages, parcelingthem out to different receivers. Or it can be a transfer station, sending all messages to the same destination.It can translate one message into another, or simply “swallow” some messages so there’s no response andno error. A forwardInvocation: method can also consolidate several messages into a single response.What forwardInvocation: does is up to the implementor. However, the opportunity it provides for linkingobjects in a forwarding chain opens up possibilities for program design.

Note: The forwardInvocation: method gets to handle messages only if they don’t invoke an existingmethod in the nominal receiver. If, for example, you want your object to forward negotiate messages toanother object, it can’t have a negotiate method of its own. If it does, the message will never reachforwardInvocation:.

For more information on forwarding and invocations, see the NSInvocation class specification in theFoundation framework reference.

Forwarding and Multiple Inheritance

Forwarding mimics inheritance, and can be used to lend some of the effects of multiple inheritance toObjective-C programs. As shown in Figure 5-1 (page 21), an object that responds to a message by forwardingit appears to borrow or “inherit” a method implementation defined in another class.

20 Forwarding and Multiple Inheritance2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 5

Message Forwarding

Page 21: 4.Objective-C Runtime Programming Guide (Apple)

Figure 5-1 Forwarding

isa. . .

– forwardInvocation: – negotiate

negotiate isa. . .

DiplomatWarrior

In this illustration, an instance of the Warrior class forwards a negotiate message to an instance of theDiplomat class. The Warrior will appear to negotiate like a Diplomat. It will seem to respond to the negotiatemessage, and for all practical purposes it does respond (although it’s really a Diplomat that’s doing the work).

The object that forwards a message thus “inherits” methods from two branches of the inheritancehierarchy—its own branch and that of the object that responds to the message. In the example above, itappears as if the Warrior class inherits from Diplomat as well as its own superclass.

Forwarding provides most of the features that you typically want from multiple inheritance. However, there’san important difference between the two: Multiple inheritance combines different capabilities in a singleobject. It tends toward large, multifaceted objects. Forwarding, on the other hand, assigns separateresponsibilities to disparate objects. It decomposes problems into smaller objects, but associates those objectsin a way that’s transparent to the message sender.

Surrogate Objects

Forwarding not only mimics multiple inheritance, it also makes it possible to develop lightweight objectsthat represent or “cover” more substantial objects. The surrogate stands in for the other object and funnelsmessages to it.

The proxy discussed in “Remote Messaging” in The Objective-C Programming Language is such a surrogate.A proxy takes care of the administrative details of forwarding messages to a remote receiver, making sureargument values are copied and retrieved across the connection, and so on. But it doesn’t attempt to domuch else; it doesn’t duplicate the functionality of the remote object but simply gives the remote object alocal address, a place where it can receive messages in another application.

Other kinds of surrogate objects are also possible. Suppose, for example, that you have an object thatmanipulates a lot of data—perhaps it creates a complicated image or reads the contents of a file on disk.Setting this object up could be time-consuming, so you prefer to do it lazily—when it’s really needed orwhen system resources are temporarily idle. At the same time, you need at least a placeholder for this objectin order for the other objects in the application to function properly.

Surrogate Objects 212009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 5

Message Forwarding

Page 22: 4.Objective-C Runtime Programming Guide (Apple)

In this circumstance, you could initially create, not the full-fledged object, but a lightweight surrogate for it.This object could do some things on its own, such as answer questions about the data, but mostly it wouldjust hold a place for the larger object and, when the time came, forward messages to it. When the surrogate’sforwardInvocation: method first receives a message destined for the other object, it would ensure thatthe object existed and would create it if it didn’t. All messages for the larger object go through the surrogate,so, as far as the rest of the program is concerned, the surrogate and the larger object would be the same.

Forwarding and Inheritance

Although forwarding mimics inheritance, the NSObject class never confuses the two. Methods likerespondsToSelector: and isKindOfClass: look only at the inheritance hierarchy, never at the forwardingchain. If, for example, a Warrior object is asked whether it responds to a negotiate message,

if ( [aWarrior respondsToSelector:@selector(negotiate)] ) ...

the answer is NO, even though it can receive negotiate messages without error and respond to them, in asense, by forwarding them to a Diplomat. (See Figure 5-1 (page 21).)

In many cases, NO is the right answer. But it may not be. If you use forwarding to set up a surrogate objector to extend the capabilities of a class, the forwarding mechanism should probably be as transparent asinheritance. If you want your objects to act as if they truly inherited the behavior of the objects they forwardmessages to, you’ll need to re-implement the respondsToSelector: and isKindOfClass: methods toinclude your forwarding algorithm:

- (BOOL)respondsToSelector:(SEL)aSelector{ if ( [super respondsToSelector:aSelector] ) return YES; else { /* Here, test whether the aSelector message can * * be forwarded to another object and whether that * * object can respond to it. Return YES if it can. */ } return NO;}

In addition to respondsToSelector: and isKindOfClass:, the instancesRespondToSelector:method should also mirror the forwarding algorithm. If protocols are used, the conformsToProtocol:method should likewise be added to the list. Similarly, if an object forwards any remote messages it receives,it should have a version of methodSignatureForSelector: that can return accurate descriptions of themethods that ultimately respond to the forwarded messages; for example, if an object is able to forward amessage to its surrogate, you would implement methodSignatureForSelector: as follows:

- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector{ NSMethodSignature* signature = [super methodSignatureForSelector:selector]; if (!signature) { signature = [surrogate methodSignatureForSelector:selector]; } return signature;}

22 Forwarding and Inheritance2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 5

Message Forwarding

Page 23: 4.Objective-C Runtime Programming Guide (Apple)

You might consider putting the forwarding algorithm somewhere in private code and have all these methods,forwardInvocation: included, call it.

Note: This is an advanced technique, suitable only for situations where no other solution is possible. It isnot intended as a replacement for inheritance. If you must make use of this technique, make sure you fullyunderstand the behavior of the class doing the forwarding and the class you’re forwarding to.

The methods mentioned in this section are described in the NSObject class specification in the Foundationframework reference. For information on invokeWithTarget:, see the NSInvocation class specificationin the Foundation framework reference.

Forwarding and Inheritance 232009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 5

Message Forwarding

Page 24: 4.Objective-C Runtime Programming Guide (Apple)

24 Forwarding and Inheritance2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 5

Message Forwarding

Page 25: 4.Objective-C Runtime Programming Guide (Apple)

To assist the runtime system, the compiler encodes the return and argument types for each method in acharacter string and associates the string with the method selector. The coding scheme it uses is also usefulin other contexts and so is made publicly available with the @encode() compiler directive. When given atype specification, @encode() returns a string encoding that type. The type can be a basic type such as anint, a pointer, a tagged structure or union, or a class name—any type, in fact, that can be used as an argumentto the C sizeof() operator.

char *buf1 = @encode(int **);char *buf2 = @encode(struct key);char *buf3 = @encode(Rectangle);

The table below lists the type codes. Note that many of them overlap with the codes you use when encodingan object for purposes of archiving or distribution. However, there are codes listed here that you can’t usewhen writing a coder, and there are codes that you may want to use when writing a coder that aren’tgenerated by @encode(). (See the NSCoder class specification in the Foundation Framework reference formore information on encoding objects for archiving or distribution.)

Table 6-1 Objective-C type encodings

MeaningCode

A charc

An inti

A shorts

A long

l is treated as a 32-bit quantity on 64-bit programs.

l

A long longq

An unsigned charC

An unsigned intI

An unsigned shortS

An unsigned longL

An unsigned long longQ

A floatf

A doubled

A C++ bool or a C99 _BoolB

252009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 6

Type Encodings

Page 26: 4.Objective-C Runtime Programming Guide (Apple)

MeaningCode

A voidv

A character string (char *)*

An object (whether statically typed or typed id)@

A class object (Class)#

A method selector (SEL):

An array[array type]

A structure{name=type...}

A union(name=type...)

A bit field of num bitsbnum

A pointer to type^type

An unknown type (among other things, this code is used for function pointers)?

Important: Objective-C does not support the long double type. @encode(long double) returns d, whichis the same encoding as for double.

The type code for an array is enclosed within square brackets; the number of elements in the array is specifiedimmediately after the open bracket, before the array type. For example, an array of 12 pointers to floatswould be encoded as:

[12^f]

Structures are specified within braces, and unions within parentheses. The structure tag is listed first, followedby an equal sign and the codes for the fields of the structure listed in sequence. For example, the structure

typedef struct example { id anObject; char *aString; int anInt;} Example;

would be encoded like this:

{example=@*i}

The same encoding results whether the defined type name (Example) or the structure tag (example) ispassed to @encode(). The encoding for a structure pointer carries the same amount of information aboutthe structure’s fields:

^{example=@*i}

However, another level of indirection removes the internal type specification:

^^{example}

262009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 6

Type Encodings

Page 27: 4.Objective-C Runtime Programming Guide (Apple)

Objects are treated like structures. For example, passing the NSObject class name to @encode() yields thisencoding:

{NSObject=#}

The NSObject class declares just one instance variable, isa, of type Class.

Note that although the @encode() directive doesn’t return them, the runtime system uses the additionalencodings listed in Table 6-2 for type qualifiers when they’re used to declare methods in a protocol.

Table 6-2 Objective-C method encodings

MeaningCode

constr

inn

inoutN

outo

bycopyO

byrefR

onewayV

272009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 6

Type Encodings

Page 28: 4.Objective-C Runtime Programming Guide (Apple)

282009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 6

Type Encodings

Page 29: 4.Objective-C Runtime Programming Guide (Apple)

When the compiler encounters property declarations (see Declared Properties in TheObjective-C ProgrammingLanguage), it generates descriptive metadata that is associated with the enclosing class, category or protocol.You can access this metadata using functions that support looking up a property by name on a class orprotocol, obtaining the type of a property as an @encode string, and copying a list of a property's attributesas an array of C strings. A list of declared properties is available for each class and protocol.

Property Type and Functions

The Property structure defines an opaque handle to a property descriptor.

typedef struct objc_property *Property;

You can use the functions class_copyPropertyList and protocol_copyPropertyList to retrieve anarray of the properties associated with a class (including loaded categories) and a protocol respectively:

objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)objc_property_t *protocol_copyPropertyList(Protocol *proto, unsigned int *outCount)

For example, given the following class declaration:

@interface Lender : NSObject { float alone;}@property float alone;@end

you can get the list of properties using:

id LenderClass = objc_getClass("Lender");unsigned int outCount;objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount);

You can use the property_getName function to discover the name of a property:

const char *property_getName(objc_property_t property)

You can use the functions class_getProperty and protocol_getProperty to get a reference to aproperty with a given name in a class and protocol respectively:

objc_property_t class_getProperty(Class cls, const char *name)objc_property_t protocol_getProperty(Protocol *proto, const char *name, BOOL isRequiredProperty, BOOL isInstanceProperty)

Property Type and Functions 292009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 7

Declared Properties

Page 30: 4.Objective-C Runtime Programming Guide (Apple)

You can use the property_getAttributes function to discover the name and the @encode type stringof a property. For details of the encoding type strings, see “Type Encodings” (page 25); for details of thisstring, see “Property Type String” (page 30) and “Property Attribute Description Examples” (page 31).

const char *property_getAttributes(objc_property_t property)

Putting these together, you can print a list of all the properties associated with a class using the followingcode:

id LenderClass = objc_getClass("Lender");unsigned int outCount, i;objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount);for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));}

Property Type String

You can use the property_getAttributes function to discover the name, the @encode type string of aproperty, and other attributes of the property.

The string starts with a T followed by the @encode type and a comma, and finishes with a V followed by thename of the backing instance variable. Between these, the attributes are specified by the following descriptors,separated by commas:

Table 7-1 Declared property type encodings

MeaningCode

The property is read-only (readonly).R

The property is a copy of the value last assigned (copy).C

The property is a reference to the value last assigned (retain).&

The property is non-atomic (nonatomic).N

The property defines a custom getter selector name. The name follows the G (for example,GcustomGetter,).

G<name>

The property defines a custom setter selector name. The name follows the S (for example,ScustomSetter:,).

S<name>

The property is dynamic (@dynamic).D

The property is a weak reference (__weak).W

The property is eligible for garbage collection.P

Specifies the type using old-style encoding.t<encoding>

30 Property Type String2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 7

Declared Properties

Page 31: 4.Objective-C Runtime Programming Guide (Apple)

For examples, see “Property Attribute Description Examples” (page 31).

Property Attribute Description Examples

Given these definitions:

enum FooManChu { FOO, MAN, CHU };struct YorkshireTeaStruct { int pot; char lady; };typedef struct YorkshireTeaStruct YorkshireTeaStructType;union MoneyUnion { float alone; double down; };

the following table shows sample property declarations and the corresponding string returned byproperty_getAttributes:

Property descriptionProperty declaration

Tc,VcharDefault@property char charDefault;

Td,VdoubleDefault@property double doubleDefault;

Ti,VenumDefault@property enum FooManChu enumDefault;

Tf,VfloatDefault@property float floatDefault;

Ti,VintDefault@property int intDefault;

Tl,VlongDefault@property long longDefault;

Ts,VshortDefault@property short shortDefault;

Ti,VsignedDefault@property signed signedDefault;

T{YorkshireTea-Struct="pot"i"lady"c},Vstruct-Default

@property struct YorkshireTeaStructstructDefault;

T{YorkshireTea-Struct="pot"i"lady"c},Vtypedef-Default

@property YorkshireTeaStructType typedefDefault;

T(Money-Union="alone"f"down"d),Vunion-Default

@property union MoneyUnion unionDefault;

TI,VunsignedDefault@property unsigned unsignedDefault;

T^?,VfunctionPointerDefault@property int (*functionPointerDefault)(char*);

Property Attribute Description Examples 312009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 7

Declared Properties

Page 32: 4.Objective-C Runtime Programming Guide (Apple)

Property descriptionProperty declaration

T@,VidDefault@property id idDefault;

Note: the compiler warns: no 'assign', 'retain', or'copy' attribute is specified - 'assign' isassumed"

T^i,VintPointer@property int *intPointer;

T^v,VvoidPointerDefault@property void *voidPointerDefault;

Ti,V_intSynthEquals@property int intSynthEquals;

In the implementation block:

@synthesize intSynthEquals=_intSynthEquals;

Ti,GintGetFoo,SintSetFoo:,VintSetterGetter

@property(getter=intGetFoo, setter=intSetFoo:)int intSetterGetter;

Ti,R,VintReadonly@property(readonly) int intReadonly;

Ti,R,GisIntReadOnlyGetter@property(getter=isIntReadOnlyGetter, readonly)int intReadonlyGetter;

Ti,VintReadwrite@property(readwrite) int intReadwrite;

Ti,VintAssign@property(assign) int intAssign;

T@,&,VidRetain@property(retain)ididRetain;

T@,C,VidCopy@property(copy)ididCopy;

Ti,VintNonatomic@property(nonatomic) int intNonatomic;

T@,R,C,VidReadonlyCopyNonatomic@property(nonatomic, readonly, copy) ididReadonlyCopyNonatomic;

T@,R,&,VidReadonlyRetainNonatomic@property(nonatomic, readonly, retain) ididReadonlyRetainNonatomic;

32 Property Attribute Description Examples2009-10-19 | © 2009 Apple Inc. All Rights Reserved.

CHAPTER 7

Declared Properties

Page 33: 4.Objective-C Runtime Programming Guide (Apple)

This table describes the changes to Objective-C Runtime Programming Guide.

NotesDate

Made minor editorial changes.2009-10-19

Completed list of types described by property_getAttributes.2009-07-14

Corrected typographical errors.2009-02-04

New document that describes the Objective-C 2.0 runtime support library.2008-11-19

332009-10-19 | © 2009 Apple Inc. All Rights Reserved.

REVISION HISTORY

Document Revision History

Page 34: 4.Objective-C Runtime Programming Guide (Apple)

342009-10-19 | © 2009 Apple Inc. All Rights Reserved.

REVISION HISTORY

Document Revision History