Appendix     A

Language Elements

Appendix A provides a concise summary of the basic elements of the Objective-C language. Its scope is the Objective-C language extensions to ANSI C. The fundamental elements of the C programming language are not covered here; they can be found in numerous other references.

Variables

The lexical rules for variable names in Objective-C are identical to those for ANSI C—a variable is defined with a letter or underscore, followed by any combination of letters, underscores, and the digits 0–9. Uppercase and lowercase letters are distinct.

Objective-C Reserved Words

In a programming language, a reserved word is a symbol that has a special meaning in the language, and hence should not be used as a variable name. Objective-C adds a number of reserved words to those already defined for ANSI C; these are listed in Table A-1.

Table A-1. Objective-C Reserved Words Not Used for Variable Names

table

Variable Scope

The visibility and accessibility of a variable is dependent on its scope. A variable may exist within a statement block, a function, a method, an object instance (or related objects), throughout a file, or across multiple files. ANSI C defines four kinds of scope:

  • block: A variable declared within a statement block has block scope. Variables declared within a block are only visible and accessible within this block.
  • file: A variable that has file scopeis visible and accessible only to code within the file where the variable is declared.
  • function: A variable declared within a function/method has function scope.These variables are only visible and accessible within the associated function/method.
  • function prototype: A variable declared within the list of parameters in a function/method prototype has function prototype scope. These variables are visible and accessible within the associated function/method.

Objective-C adds a set of access modifier directives that enable you to provide fine-grained access control to instance variables.

Access Modifiers

Objective-C defines several compiler directives to control the scope of instance variables; that is, the visibility of variables throughout a program.

  • @private: The instance variable is only accessible within the class that declares it and other instances of this class type.
  • @protected: The instance variable is accessible within the class that declares it and the instance methods of any of its subclasses. This is the default scope if a protection level is not specified for an instance variable.
  • @public: The instance variable is accessible from everywhere.
  • @package: The instance variable is accessible from any other class instance or function, but outside of the package, it is treated as private. This scope can be useful for libraries or framework classes.

These directives are referred to as access modifiers, and are used on instance variables declared within an instance variable declaration block. The class instance variable declaration of Listing A-1 declares a counter variable of type int that is accessible everywhere, a temperature variable of type float that is accessible within the declaring class and any subclasses, and a description variable of type NSString* that is accessible only within the declaring class.

Listing A-1.  Instance Variable Declaration with Access Modifiers

{
  @public int counter;
  @protected float temperature;
  @private NSString *description;
}

Data Types

As Objective-C is a strict superset of the C programming language. It supports all of the standard ANSI C data types and type qualifiers. Objective-C also defines a number of language-specific data types (BOOL type, class instance types, id type, class definition types, block type). These are discussed in the following paragraphs.

BOOL Type

BOOL is an Objective-C type used to hold a Boolean value that can hold only two possible values: true or false. For the Objective-C BOOL type, these values are defined as YES and NO rather than true (1) or false (0). The amount of storage allocated for a BOOL is 1 byte. Objective-C also supports the C99 types _Bool and bool, although BOOL is the preferred Boolean type to use in Objective-C programs.

Class Instance Types

The class instance types represent objects, classes, and superclasses. The Objective-C runtime has several class instance types, of which the most commonly used is the id type.

id Type

The id type is the final supertype of all Objective-C object pointers and can be used to hold a reference to any Objective-C object, regardless of its type. The following statement declares a variable named myObject of type id.

id myObject;

The object instantiated for this variable can be of any type.

The runtime equivalent for the Objective-C id type is a C struct defined as a pointer to an objc_object (as shown in Listing A-2).

Listing A-2.  id Type Definition

typedef struct objc_object
{
  Class isa;
} *id;

In other words, an id is just a pointer to a C struct with the identifier objc_object.

instancetype Keyword

The instancetype keyword is a contextual keyword that can be used as the result type of a method; it signals that the method returns a related result type. In Chapter 3, you learned that when a method returns a related result type, it returns an object that is an instance of the receiving class’s type. A related result type can be inferred for the following types of methods:

  • Class methods that begin with the words alloc or new.
  • Instance methods that begin with the words autorelease, init, retain, or self.

The following statement creates an OrderItem object using the new keyword.

OrderItem *item = [OrderItem new];

Although the NSObject new method specifies id as the return type, the compiler infers the correct result type (in this case OrderItem *) based on the type of the receiving class instance named item.

The instancetype keyword can be used to explicitly indicate that a method returns a related result type. Listing A-3 provides an example of a class named OrderItem, whose interface declares a method that returns a related result type.

Listing A-3.  Use of the instancetype Keyword to Return a Related Result Type

@interface OrderItem : NSObject
+ (instancetype)orderItemWithDescription:(NSString *)description price:(float)cost;
@end

Class Definition Types

The class definition types define Objective-C runtime data structures. They include the SEL, IMP, Class, and objc_object types.

SEL Type

The SEL type represents a method selector, a type that represents the name of a method in the Objective-C runtime. A variable of type SEL for a method selector named helloWorld can be created using the @selector compiler directive.

SEL myHelloMethod = @selector(helloWorld);

This selector can be used to invoke the helloWorld method on an object.

IMP Type

The IMP type represents a method pointer that points to the beginning address in memory for a function that implements a method. An IMP is defined as follows:

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

As shown by the preceding type definition, the function pointed to by an IMP takes as its parameters an id, a method selector (SEL), variable arguments (represented by the variadic arguments ... symbol), and returns an id.

Class Type

The Class type represents an Objective-C class instance (i.e., an object) and is composed of various data elements. The Class data type is defined as follows:

typedef struct objc_class *Class;

As shown by the preceding type definition, the Class data type is a pointer to an opaque type with an identifier of objc_class. The members of the objc_class struct can only be accessed through functions defined specifically for it, specifically using the Objective-C runtime library functions.

objc_object Type

Objective-C objects have a corresponding runtime data type. When the compiler parses Objective-C code for objects, it generates code that creates a runtime object type, the objc_object type. This data type, declared in Listing A-4, is a C struct type with an identifier of objc_object.

Listing A-4.  objc_object Data Type

struct objc_object
{
  Class isa;
  /* ...variable length data containing instance variable values...  */
};

The objc_object type contains a variable named isa of type Class; in other words, a pointer to a variable of type objc_class.

Block Type

Blocks provide a way to create a group of statements (i.e., a block of code) and assign those statements to a variable, which can subsequently be invoked. They are similar to standard C functions, but in addition to executable code, they may also contain variable bindings to stack or heap memory. A block is an Objective-C object (of block type), and like all Objective-C objects, it is accessed via a pointer. As with Objective-C objects, the id type can be used to refer to a block object. The following statement declares a Block variable named incrementSum that has a single parameter of type int and returns nothing.

void (^incrementSum)(int);

The __block storage modifier can be used to create mutable block variables. It is applied to a variable outside of a Block literal but within the same lexical scope, and enables this variable to be modified within the Block. This storage modifier cannot be combined with the local storage modifiers auto, register, and static on the same variable. Listing A-5 illustrates the use of a __block variable.

Listing A-5.  Correct Use of __block Storage

__block int totalSum = 0;
void (^incrementSum)(int) = ^(int amount){
  totalSum += amount;
  NSLog(@"Current total = %d", totalSum);
};
incrementSum(5);

When the code fragment displayed in Listing A-5 is executed, it outputs the following:

Current total = 5

Hence, the block variable totalSum is initialized with a value of 0 and then modified when the block literal is invoked.

Enumeration Types

Objective-C supports the standard C enumeration types and also provides support for specifying the type for an enumeration. An enumeration type consists of a set of named values (aka enumerators) that are defined using the enum keyword. A variable declared as an enumeration can be assigned any of the enumerator values. Listing A-6 defines an enumeration with a set of values: Red, Green, and Blue for the variable named color .

Listing A-6.  Example enum Type Definition

enum
{
  Red,
  Green,
  Blue
} color;

The default type for enumerators is int. Objective-C provides support for explicitly specifying the type for an enumeration, also referred to as enumerations with a fixed underlying type. The types supported for an enumeration are any signed or unsigned integer type (char, short, int, and long). The type should be specified after the enum keyword, prefixed by a colon. Listing A-7 defines an enumeration with a set of values Red, Green, and Blue whose type is unsigned char for the variable named color.

Listing A-7.  Example enum with a Fixed Underlying Type

enum : unsigned char
{
  Red,
  Green,
  Blue
} color;

Typically, a type definition is used to declare an enumeration type. Listing A-8 declares a type definition for an enumeration with a set of values Red, Green, and Blue (whose type is unsigned char), and then declares a variable named color of that type.

Listing A-8.  Example typedef enum with a Fixed Underlying Type

typedef enum : unsigned char
{
  Red,
  Green,
  Blue
} ColorType;
ColorType color;

The preferred approach in Objective-C for defining enumeration types is to use the NS_ENUM macro. This provides a convenient mechanism to declare the underlying type for the enumeration values and define the name of the new type in a single statement. Listing A-9 illustrates use of the NS_ENUM macro to define the enumeration type previously defined in Listing A-8.

Listing A-9.  Example enum Definition Using the NS_ENUM Macro

typedef NS_ENUM(unsigned char, ColorType)
{
  Red,
  Green,
  Blue
};

Listing A-9 shows that the first argument for the macro is the underlying type; whereas the second argument is the name of the new type. The values are stored inside the block, as usual.

Operators

Objective-C supports the operators defined for ANSI C, specifically

  • Assignment operators
  • Arithmetic operators
  • Compound assignment operators
  • Increment and decrement operators
  • Logical comparison operators
  • Logical Boolean operators
  • Bitwise operators
  • Compound bitwise operators
  • Ternary operators
  • Type cast operators
  • sizeof operators
  • Address (&) operators
  • Indirection (*) operators
  • Comma operators

The rules for arithmetic conversions, along with those for operator precedence and associativity, are as specified for ANSI C.

The caret (^) operator is used with block objects; specifically to declare objects of block type and to define block literals.

Statements

Objective-C supports the conditional, looping, and jump statements defined for ANSI C, specifically

  • Conditional statements (if, if else, if else if, switch)
  • Loop statements (for, while, do while)
  • Jump statements (return, goto, break, continue)

Class Elements

An Objective-C class is comprised of several structural elements, which are logical organized into sections. This section provides an overview of these fundamental class elements.

Instance Variables

Instance variables, sometimes referred to as ivars, are variables declared for a class that exist and hold their value throughout the life of a class instance. The memory used for instance variables is allocated when an object is first created, and freed when the object is dellocated. Instance variables have an implicit scope and namespace corresponding to the object. Instance variables can be declared within the instance variable declaration block of a class interface, implementation, or extension. The ivar declaration block must be placed immediately below the corresponding interface, implementation, or class extension declaration. Listing A-10 depicts an example ivar declaration block for the Hello class.

Listing A-10.  Hello Class Implementation Instance Variable Declaration Block

@implementation Hello
{
  // declare instance variables here.
  ...
}
...
@end

The recommended practice is to declare instance variables in the class implementation (rather than the public class interface). Instance variables are commonly declared in an extension for variables solely used within the corresponding class implementation file.

Instance Variables Ownership Qualifiers

An Objective-C ownership qualifier is a type qualifier that applies only to retainable object pointer types. An ownership qualifier is placed before an object pointer type in a variable declaration to specify the variable’s ownership rules. Table A-2 lists the four ownership qualifiers.

Table A-2. Object Pointer Variable Ownership Qualifiers

Qualifier Description
__autoreleasing When the variable is assigned a new value, the new value is retained and autoreleased, and the previous value is sent a release message.
__weak The variable uses simple assignment (i.e., the input value is not copied or retained). If the object is deallocated, the corresponding variable value is set to nil.
__unsafe_unretained The variable uses simple assignment (i.e., the input value is not copied or retained).
__strong When the variable is assigned a new value, the new value is retained and the previous value is sent a release message.

The default ownership qualifier (if none is provided) is __strong. The following statement declares a variable named hello (of type Hello *) with an ownership qualifier of __weak.

__weak Hello *hello;

Properties

In Objective-C a property provides a convenient mechanism, in the form of accessor methods (i.e., getters and setters), for accessing an object’s shared state. A property differs from an instance variable in that it doesn’t directly access an object’s internal state. Objective-C declared properties enable the compiler to generate these methods automatically according to your provided specification.

A property is declared using the @property keyword, followed by an optional set of attributes (enclosed within parentheses), the property type, and its name.

@property (attributes) type propertyName;

Property declaration attributes are used to specify the storage semantics and other behaviors associated with a property. Table A-3 provides a list of the available property attributes.

Table A-3. Property Attributes

Attribute Description Comments
readwrite Required. Access qualifier. The default setting.
readonly Required. Access qualifier. Cannot select both readwrite and readonly.
assign The setter method uses simple assignment (i.e., the input value is not copied or retained). Ownership qualifier. Used under Manual Retain-Release (MRR) memory management. The default setting under MRR.
weak The setter method uses simple assignment (i.e., the input value is not copied or retained). If the property instance is deallocated, its value is set to nil. Ownership qualifier. Used under ARC memory management.
unsafe_unretained The setter method uses simple assignment (i.e., the input value is not copied or retained). Ownership qualifier. Used under ARC memory management.
copy In the setter method, a copy method should be called for assignment and the old value should be sent a release message. Ownership qualifier.
retain In the setter method, the previous value will be sent a release message and the property uses retain on assignment. Ownership qualifier. Similar to the strong attribute (used under Manual Retain-Release memory management).
strong In the setter method, the previous value will be sent a release message and the property uses retain on assignment. Ownership qualifier Used under ARC memory management. The default setting under ARC.
getter=getterName Names the getter method the specified getterName.
setter=setterName Names the setter method the specified setterName.
nonatomic Specifies that the accessor methods for this property are not atomic (the default). The nonatomic property setting has better performance, but does not guarantee that a whole value is always returned from a property getter or setter when being accessed by multiple threads.

A property definition is performed in the implementation section of a class. In most cases, a property is backed by an instance variable, hence the property definition includes defining getter and setter methods for the property, declaring an instance variable, and using that variable in the getter/setter methods. Objective-C provides three methods for defining a property: explicit definition, synthesis via keyword, or autosynthesis.

Methods

Objective-C supports both instance methods and class methods. Instance methods are invoked on class instances (objects); as such, instance methods have direct access to an object’s instance variables. Class methods are invoked on classes. Methods can be declared in a class interface, a protocol, and/or a category. Methods thus declared are defined in a corresponding class/category implementation.

A method declaration specifies the method type, a return type, its name, its parameter(s), and the corresponding parameter types. The method type identifier specifies whether the method is a class or instance method. A class method is declared with a plus (+) sign and indicates that the method has class scope, meaning that it operates at the class level and does not have access to the instance variables of the class (unless they are passed as parameters to the method). An instance method is declared with a minus (–) sign and indicates that the method has object scope. It operates at the instance level and has direct access to the instance variables of the object and its parent objects (subject to the access controls on the instance variables).

The method name includes parameters as part of its name, using colons. For each parameter, its type is specified in parentheses, followed by the method prototype parameter. The parameter name and type are separated by a colon; for example, in the following method declaration:

- (void)incrementSum:(int)value;

The method name is incrementSum: and it has a single parameter of type int named value. Multiple parameters require multiple name-parameter pairs; for example, the method declaration

- (int)addAddend1:(int)a1 addend2:(int)a2;

The method name is addAddend1:addend2: and it has two parameters of type int named a1 and a2.

The return typeindicates the type of the returned variable from the method, if any. The return type is specified within parentheses, following the method type. If the method does not return anything, its return type is declared as void.

The following statement provides an example class method declaration for a method named hydrogenWithProtons:neutrons: that has two parameters of type unsigned int named nProtons and nNeutrons.

+ (id) hydrogenWithProtons:(unsigned)nProtons neutrons:(unsigned)nNeutrons;

Interface

A class interface specifies state and behavior of a class; encapsulated in its instance variables, properties and methods. A class interface declaration begins with the @interface directive and the name of the class; it ends with the @end directive. The formal syntax for declaring a class interface is shown in Listing A-11.

Listing A-11.  Class Interface Syntax

@interface ClassName : SuperclassName
{
  // instance variable declarations
}

// Property and method declarations
@end

A superclass establishes a common interface and implementation, which specialized subclasses can inherit, modify, and supplement. Most classes inherit from the NSObject class, the root (i.e., base) class of most Foundation Framework class hierarchies, which provides a basic interface to the Objective-C runtime.

Forward Declarations

The @class directive is used to declare a class (in a class interface) prior to obtaining its complete specification. This tells the compiler that a class exists (and thus enables it to perform static type checking) without having to import its corresponding header file. Forward declarations can be useful in resolving circular dependencies between files.

Implementation

A class implementation defines a class’s behavior by implementing defining its properties and implementing its methods. A class implementation declaration begins with the @implementation directive and the name of the class; it ends with the @end directive. The formal syntax for declaring a class implementation is shown in Listing A-12.

Listing A-12.  Class Implementation Syntax

@implementation ClassName
{
  // instance variable declarations
}

// Property and method definitions
@end

The methods defined in a class implementation must directly map to its corresponding interface; for example, Listing A-13 depicts a Greeting class interface and its corresponding implementation.

Listing A-13.  Greeting Class Interface and Implementation

#import <Foundation/Foundation.h>
@interface Greeting : NSObject

@property(readwrite) NSString *salutation;
- (void)hello:(NSString *)user;

@end

#import "Greeting.h"
@implementation Greeting
- (void)hello:(NSString *)user
{
  NSLog(@"%@, %@", self.salutation, user);
}
@end

Protocol

A protocol declares methods and properties that can be implemented by any class. A protocol declaration begins with the @protocol directive followed by the name of the protocol. It ends with the @end directive. Protocols can have both required and optional methods; optional methods do not require that an implementation of the protocol implement these methods. The directives @required and @optional (followed by the method name(s)) are used to mark a method appropriately. If neither keyword is specified, the default behavior is @required. The syntax of a protocol declaration is shown in Listing A-14.

Listing A-14.  Protocol Declaration Syntax

@protocol ProtocolName
// Property declarations
@required
// Method declarations
@optional
// Method declarations
@end

One protocol can incorporate other protocols by specifying the name of each declared protocol within braces; this is referred to as adopting a protocol. Commas are used to separate multiple protocols (as shown in Listing A-15).

Listing A-15.  Incorporating Other Protocols

@protocol ProtocolName<ProtocolName(s)>
// Method declarations
@end

An interface can adopt other protocols using similar syntax (shown in Listing A-16).

Listing A-16.  Interface Adopting a Protocol

@interface ClassName : Parent <ProtocolName(s)>
// Method declarations
@end

Typically, a class interface and its corresponding implementation are physically organized in separate files; the interface in a header file suffixed with .h, and an implementation file suffixed with .m.

Category

A category enables the addition of new functionality to an existing class without subclassing it. The methods in a category become part of the class type (within the scope of the program) and are inherited by all its subclasses.

A category interface declaration begins with the @interface keyword, followed by the name of the existing class, and the category name in parentheses, followed by the protocols it adopts (if any). It ends with the @end keyword. Between these statements the method declarations are provided. The syntax of a category declaration is shown in Listing A-17.

Listing A-17.  Category Declaration Syntax

@interface ClassName (CategoryName)
// Method declarations
@end

A category implementation is comparable to a class implementation, defining methods declared in a category interface. Its syntax is

@implementation ClassName (CategoryName)
// Method declarations
@end

Class Extension

A class extension can be considered as an anonymous (i.e., unnamed) category. The methods declared in an extension must be implemented in the main @implementation block for the corresponding class. As opposed to a category, an extension can declare instance variables and properties. The syntax of a class extension is shown in Listing A-18.

Listing A-18.  Extension Declaration Syntax

@interface ClassName ()
{
  // Instance variable declarations
}

// Property declarations
// Method declarations
@end

A class extension is commonly placed in the same file as the class implementation file, and is used to group and declare additional required, private methods (e.g., not part of the publicly declared API) for use solely within a class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.140.204