As we discussed already, Objective-C was previously the primary language for developing on Apple's platforms. This means that Objective-C had a lot of influence on Swift; the largest of which is that Swift was designed to interoperate with Objective-C. Swift code can call Objective-C code and, likewise, Objective-C code can call Swift code.
Before we can talk about the details of Objective-C, we need to acknowledge its history. Objective-C is based on a language called simply "C". The C programming language was one of the first highly portable languages. Portable means that the same C code could be compiled to run on any processor as long as someone writes a compiler for that platform. Before that, most of the code was written in Assembly; which always had to be written specifically for each processor it would run on.
Now, we are ready to dive into the basics of the Objective-C language. Objective-C has constants and variables very similar to Swift but they are declared and worked with slightly differently. Let's take a look at declaring a variable in both Swift and Objective-C:
The first line should look familiar, as it is Swift. The Objective-C version doesn't actually look all that different. The important difference is that the type of the variable is declared before the name instead of after. It is also important to note that Objective-C has no concept of type inference. Every time a variable is declared, it must be given a specific type. You will also see that there is a semicolon after the name. This is because every line of code in Objective-C must end with a semicolon. Lastly, you should notice that we have not explicitly declared number
as a variable. This is because all information is assumed to be variable in Objective-C unless specified otherwise. To define number
as a constant, we will add the const
keyword before its type:
The number we declared above is a value type in both languages. They are copied if they are passed to another function and there cannot be more than one variable referencing the exact same instance.
Objective-C actually allows you to make any type a reference type by adding an asterisk:
A pointer can also always be tested for nil:
To access the referenced value, you must dereference it:
You can dereference a pointer by adding an asterisk before it.
This is how pointers are similar to optionals in Swift. The difference is that there is no way to declare a non-optional reference type in Objective-C. Every reference type could technically be nil, even if you design it to never actually be nil. This can often add a lot of unnecessary nil checking and means every function you write that accepts a reference type should probably deal with the nil case.
Objective-C actually allows you to make any type a reference type by adding an asterisk:
A pointer can also always be tested for nil:
To access the referenced value, you must dereference it:
You can dereference a pointer by adding an asterisk before it.
This is how pointers are similar to optionals in Swift. The difference is that there is no way to declare a non-optional reference type in Objective-C. Every reference type could technically be nil, even if you design it to never actually be nil. This can often add a lot of unnecessary nil checking and means every function you write that accepts a reference type should probably deal with the nil case.
actually allows you to make any type a reference type by adding an asterisk:
A pointer can also always be tested for nil:
To access the referenced value, you must dereference it:
You can dereference a pointer by adding an asterisk before it.
This is how pointers are similar to optionals in Swift. The difference is that there is no way to declare a non-optional reference type in Objective-C. Every reference type could technically be nil, even if you design it to never actually be nil. This can often add a lot of unnecessary nil checking and means every function you write that accepts a reference type should probably deal with the nil case.
Objective-C has the same exact core containers that Swift does, with the two exceptions being that they are named slightly differently, and all of the containers in Objective-C are reference types because of the basic requirement that all Objective-C types must be reference types.
In Objective-C arrays are called NSArray
. Let's take a look at the initialization of an array in both Swift and Objective-C side-by-side:
There is also an alternative to calling alloc
and init
; it's called simply new
:
You may have noticed that we have not specified what type this array is supposed to hold. This is because it is actually not possible. All arrays in Objective-C can contain any mix of types as long as they are not C types. This means that an NSArray
cannot contain an int
(there is an NSNumber
class instead), but it can contain any mix of NSStrings
, NSArrays
, or any other Objective-C type. The compiler will not do any form of type checking for you, which means that we can write code expecting the wrong type to be in the array. This is yet another classification of bug that Swift makes impossible.
We can also use square brackets, similar to Swift:
Lastly, to remove an object from a mutable array, we can use the removeObjectAtIndex:
method:
Array literals start with an @
symbol just like a string, but then it is defined by a list of objects within square brackets just like Swift.
Following the same pattern as arrays, dictionaries in Objective-C are called NSDictionary
and NSMutableDictionary
. A dictionary is initialized in the exact same way as shown:
To set a value, we use the setObject:forKey:
method:
Now to access a value we can use the objectForKey:
method or square brackets again:
Lastly, to remove an object, we can use the removeObjectForKey:
method:
Again, we have to start our literal with an @
symbol. We can also see that we can use numbers as objects in our containers as long as we put an @
symbol before each one. Instead of creating something such as an int
type, this creates an NSNumber
instance. You shouldn't need to know much about the NSNumber
class except that it is a class to represent many different forms of numbers as objects.
There is also an alternative to calling alloc
and init
; it's called simply new
:
You may have noticed that we have not specified what type this array is supposed to hold. This is because it is actually not possible. All arrays in Objective-C can contain any mix of types as long as they are not C types. This means that an NSArray
cannot contain an int
(there is an NSNumber
class instead), but it can contain any mix of NSStrings
, NSArrays
, or any other Objective-C type. The compiler will not do any form of type checking for you, which means that we can write code expecting the wrong type to be in the array. This is yet another classification of bug that Swift makes impossible.
We can also use square brackets, similar to Swift:
Lastly, to remove an object from a mutable array, we can use the removeObjectAtIndex:
method:
Array literals start with an @
symbol just like a string, but then it is defined by a list of objects within square brackets just like Swift.
Following the same pattern as arrays, dictionaries in Objective-C are called NSDictionary
and NSMutableDictionary
. A dictionary is initialized in the exact same way as shown:
To set a value, we use the setObject:forKey:
method:
Now to access a value we can use the objectForKey:
method or square brackets again:
Lastly, to remove an object, we can use the removeObjectForKey:
method:
Again, we have to start our literal with an @
symbol. We can also see that we can use numbers as objects in our containers as long as we put an @
symbol before each one. Instead of creating something such as an int
type, this creates an NSNumber
instance. You shouldn't need to know much about the NSNumber
class except that it is a class to represent many different forms of numbers as objects.
To set a value, we use the setObject:forKey:
method:
Now to access a value we can use the objectForKey:
method or square brackets again:
Lastly, to remove an object, we can use the removeObjectForKey:
method:
Again, we have to start our literal with an @
symbol. We can also see that we can use numbers as objects in our containers as long as we put an @
symbol before each one. Instead of creating something such as an int
type, this creates an NSNumber
instance. You shouldn't need to know much about the NSNumber
class except that it is a class to represent many different forms of numbers as objects.
Objective-C has many of the same control flow paradigms as Swift. We will go through each of them quickly, but before we do, let's take a look at the Objective-C equivalent of print
:
Now, we are ready to look at the different methods of control flow in Objective-C.
A conditional looks exactly the same in both Swift and Objective-C except parentheses are required in Objective-C:
You can also include those parentheses in Swift, but they are optional. Here, you also see that Objective-C still has the idea of the dot syntax for calling some methods. In this case, we have used invitees.count
instead of [invitees count]
. This is only an option when we are accessing a property of the instance or we are calling a method that takes no arguments and returns something, as if it were a calculated property.
Switches in Objective-C are profoundly less powerful than switches in Swift. In fact, switches are a feature of strict C and are not enhanced at all by Objective-C. Switches cannot be used like a series of conditionals; they can only be used to do equality comparisons:
Just like conditionals, loops in Objective-C are very similar to Swift. While-loops are identical except that the parentheses are required:
This loop is made up of three parts: an initial value, a condition to run until, and an operation to perform after each loop. This version loops through the numbers 1 to 10 just like the Swift version. Clearly, it is still possible to translate the Swift code into Objective-C; it just isn't as clean.
You can also include those parentheses in Swift, but they are optional. Here, you also see that Objective-C still has the idea of the dot syntax for calling some methods. In this case, we have used invitees.count
instead of [invitees count]
. This is only an option when we are accessing a property of the instance or we are calling a method that takes no arguments and returns something, as if it were a calculated property.
Switches in Objective-C are profoundly less powerful than switches in Swift. In fact, switches are a feature of strict C and are not enhanced at all by Objective-C. Switches cannot be used like a series of conditionals; they can only be used to do equality comparisons:
Just like conditionals, loops in Objective-C are very similar to Swift. While-loops are identical except that the parentheses are required:
This loop is made up of three parts: an initial value, a condition to run until, and an operation to perform after each loop. This version loops through the numbers 1 to 10 just like the Swift version. Clearly, it is still possible to translate the Swift code into Objective-C; it just isn't as clean.
Just like conditionals, loops in Objective-C are very similar to Swift. While-loops are identical except that the parentheses are required:
This loop is made up of three parts: an initial value, a condition to run until, and an operation to perform after each loop. This version loops through the numbers 1 to 10 just like the Swift version. Clearly, it is still possible to translate the Swift code into Objective-C; it just isn't as clean.
This loop is made up of three parts: an initial value, a condition to run until, and an operation to perform after each loop. This version loops through the numbers 1 to 10 just like the Swift version. Clearly, it is still possible to translate the Swift code into Objective-C; it just isn't as clean.
So far we have called some Objective-C functions but we have not defined any yet. Let's see what the Objective-C versions are of the functions we defined in Chapter 2, Building Blocks – Variables, Collections, and Flow Control.
Our most basic function definition didn't take any arguments and didn't return anything. The Objective-C version looks similar to the following code:
func sayHello() { print("Hello World!"); } sayHello() void sayHello() { NSLog(@"Hello World!"); } sayHello();
Objective-C functions always starts with the type that the function returns instead of the keyword func
. In this case, we aren't actually returning anything, so we use the keyword void
to indicate that.
Functions that take arguments and return values have more of a disparity between the two languages:
func addInviteeToListIfSpotAvailable ( invitees: [String], newInvitee: String ) -> [String] { if invitees.count >= 20 { return invitees } return invitees + [newInvitee] } addInviteeToListIfSpotAvailable(invitees, newInvitee: "Roana") NSArray *addInviteeToListIfSpotAvailable ( NSArray *invitees, NSString *newInvitee ) { if (invitees.count >= 20) { return invitees; } NSMutableArray *copy = [invitees mutableCopy]; [copy addObject:newInvitee]; return copy; } addInviteeToListIfSpotAvailable(invitees, @"Roana");
Again, the Objective-C version defines what it is returning at the beginning of the function. Also, just like variables, parameters to functions must have their type defined before their name instead of after. The rest however, is pretty similar: the arguments are contained within parentheses and separated by commas; the code of the function is contained within curly brackets and we use the return
keyword to indicate what we want to return.
The type system in Objective-C is a little bit more disparate than Swift. This is because the structures and enumerations in Objective-C come from C. Only classes and categories come from the Objective-C extension.
In Swift, structures are very similar to classes, but in Objective-C, they are much more different. Structures in Objective-C are essentially just a way of giving a name to a collection of individual types. They cannot contain methods. Even more restrictive than that, structures can't contain Objective-C types. This leaves us with only basic possibilities:
Enumerations are also much more restrictive in Objective-C. They are really just a simple mechanism to represent a finite list of related possible values. This allows us to still represent possible primary colors:
Just like with structures, Objective-C enumerations start with the keyword typedef
followed by enum
with the name at the end of the definition. Each case is contained within the curly brackets and separated by a comma.
Unlike Objective-C structures and enumerations, classes are very similar to their Swift counterparts. Objective-C classes can contain methods and properties, use inheritance, and get initialized. However, they look pretty different. Most notably, a class in Objective-C is split into two parts: its interface and its implementation. The interface is intended to be the public interface to the class, while the implementation includes the implementation of that interface in addition to any other private methods.
Let's start by looking again at our contact class from Chapter 3, One Piece at a Time – Types, Scopes, and Projects and what it looks like in Objective-C:
class Contact { var firstName: String = "First" var lastName: String = "Last" } @interface Contact : NSObject { NSString *firstName; NSString *lastName; } @end @implementation Contact @end
Already Objective-C is taking a lot more lines of code. First, we have the interface declaration. This begins with the @interface
keyword and ends with the @end
keyword. Within the square brackets is a list of attributes. These are essentially the same as the attributes of a structure, except that you can include Objective-C objects in the attributes. These attributes are not commonly written like this because using the properties will create these automatically, as we will see later.
You will also notice that our class is inheriting from a class called NSObject
, as indicated by : NSObject
. This is because every class in Objective-C must inherit from NSObject
, which makes NSObject
the most basic form of class. However, don't let the term "basic" fool you; NSObject
provides a lot of functionality. We won't really get into that here, but you should at least be aware of it.
The other part of the class is the implementation. It starts with the @implementation
keyword followed by the name of the class we are implementing and then ends again with the @end
keyword. Here, we have not actually added any extra functionality to our contact class. However, you may notice that our class is missing something that the Swift version has.
Objective-C does not allow specifying default values for any attributes or properties. This means that we have to implement an initializer that sets the default values:
In Objective-C, initializers are the exact same as a method, except that by convention they start with the name init
. This is actually just a convention but it is important, as it will cause problems down the line with memory management and interacting with the code from Swift.
The Objective-C version of the contact class still isn't exactly like the Swift version because the firstName
and lastName
attributes are not accessible from outside the class. To make them accessible we need to define them as public properties and we can drop them from being explicit attributes:
Alternatively, you can just set the values using self
:
Also, just as you can define weak references in Swift, you can do so in Objective-C:
In addition to weak
or strong
, you can also specify that a property is readonly
or readwrite
:
Each property attribute should be written inside the parentheses separated by a comma. As the readonly
name implies, this makes it so that the property can be read but not written to. Every property is read-write by default, so normally it is not necessary to include it.
We have already seen an example of a method in the form of an initializer, but let's take a look at some methods that take parameters:
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Enumerations are also much more restrictive in Objective-C. They are really just a simple mechanism to represent a finite list of related possible values. This allows us to still represent possible primary colors:
Just like with structures, Objective-C enumerations start with the keyword typedef
followed by enum
with the name at the end of the definition. Each case is contained within the curly brackets and separated by a comma.
Unlike Objective-C structures and enumerations, classes are very similar to their Swift counterparts. Objective-C classes can contain methods and properties, use inheritance, and get initialized. However, they look pretty different. Most notably, a class in Objective-C is split into two parts: its interface and its implementation. The interface is intended to be the public interface to the class, while the implementation includes the implementation of that interface in addition to any other private methods.
Let's start by looking again at our contact class from Chapter 3, One Piece at a Time – Types, Scopes, and Projects and what it looks like in Objective-C:
class Contact { var firstName: String = "First" var lastName: String = "Last" } @interface Contact : NSObject { NSString *firstName; NSString *lastName; } @end @implementation Contact @end
Already Objective-C is taking a lot more lines of code. First, we have the interface declaration. This begins with the @interface
keyword and ends with the @end
keyword. Within the square brackets is a list of attributes. These are essentially the same as the attributes of a structure, except that you can include Objective-C objects in the attributes. These attributes are not commonly written like this because using the properties will create these automatically, as we will see later.
You will also notice that our class is inheriting from a class called NSObject
, as indicated by : NSObject
. This is because every class in Objective-C must inherit from NSObject
, which makes NSObject
the most basic form of class. However, don't let the term "basic" fool you; NSObject
provides a lot of functionality. We won't really get into that here, but you should at least be aware of it.
The other part of the class is the implementation. It starts with the @implementation
keyword followed by the name of the class we are implementing and then ends again with the @end
keyword. Here, we have not actually added any extra functionality to our contact class. However, you may notice that our class is missing something that the Swift version has.
Objective-C does not allow specifying default values for any attributes or properties. This means that we have to implement an initializer that sets the default values:
In Objective-C, initializers are the exact same as a method, except that by convention they start with the name init
. This is actually just a convention but it is important, as it will cause problems down the line with memory management and interacting with the code from Swift.
The Objective-C version of the contact class still isn't exactly like the Swift version because the firstName
and lastName
attributes are not accessible from outside the class. To make them accessible we need to define them as public properties and we can drop them from being explicit attributes:
Alternatively, you can just set the values using self
:
Also, just as you can define weak references in Swift, you can do so in Objective-C:
In addition to weak
or strong
, you can also specify that a property is readonly
or readwrite
:
Each property attribute should be written inside the parentheses separated by a comma. As the readonly
name implies, this makes it so that the property can be read but not written to. Every property is read-write by default, so normally it is not necessary to include it.
We have already seen an example of a method in the form of an initializer, but let's take a look at some methods that take parameters:
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Just like with structures, Objective-C enumerations start with the keyword typedef
followed by enum
with the name at the end of the definition. Each case is contained within the curly brackets and separated by a comma.
Unlike Objective-C structures and enumerations, classes are very similar to their Swift counterparts. Objective-C classes can contain methods and properties, use inheritance, and get initialized. However, they look pretty different. Most notably, a class in Objective-C is split into two parts: its interface and its implementation. The interface is intended to be the public interface to the class, while the implementation includes the implementation of that interface in addition to any other private methods.
Let's start by looking again at our contact class from Chapter 3, One Piece at a Time – Types, Scopes, and Projects and what it looks like in Objective-C:
class Contact { var firstName: String = "First" var lastName: String = "Last" } @interface Contact : NSObject { NSString *firstName; NSString *lastName; } @end @implementation Contact @end
Already Objective-C is taking a lot more lines of code. First, we have the interface declaration. This begins with the @interface
keyword and ends with the @end
keyword. Within the square brackets is a list of attributes. These are essentially the same as the attributes of a structure, except that you can include Objective-C objects in the attributes. These attributes are not commonly written like this because using the properties will create these automatically, as we will see later.
You will also notice that our class is inheriting from a class called NSObject
, as indicated by : NSObject
. This is because every class in Objective-C must inherit from NSObject
, which makes NSObject
the most basic form of class. However, don't let the term "basic" fool you; NSObject
provides a lot of functionality. We won't really get into that here, but you should at least be aware of it.
The other part of the class is the implementation. It starts with the @implementation
keyword followed by the name of the class we are implementing and then ends again with the @end
keyword. Here, we have not actually added any extra functionality to our contact class. However, you may notice that our class is missing something that the Swift version has.
Objective-C does not allow specifying default values for any attributes or properties. This means that we have to implement an initializer that sets the default values:
In Objective-C, initializers are the exact same as a method, except that by convention they start with the name init
. This is actually just a convention but it is important, as it will cause problems down the line with memory management and interacting with the code from Swift.
The Objective-C version of the contact class still isn't exactly like the Swift version because the firstName
and lastName
attributes are not accessible from outside the class. To make them accessible we need to define them as public properties and we can drop them from being explicit attributes:
Alternatively, you can just set the values using self
:
Also, just as you can define weak references in Swift, you can do so in Objective-C:
In addition to weak
or strong
, you can also specify that a property is readonly
or readwrite
:
Each property attribute should be written inside the parentheses separated by a comma. As the readonly
name implies, this makes it so that the property can be read but not written to. Every property is read-write by default, so normally it is not necessary to include it.
We have already seen an example of a method in the form of an initializer, but let's take a look at some methods that take parameters:
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Objective-C structures and enumerations, classes are very similar to their Swift counterparts. Objective-C classes can contain methods and properties, use inheritance, and get initialized. However, they look pretty different. Most notably, a class in Objective-C is split into two parts: its interface and its implementation. The interface is intended to be the public interface to the class, while the implementation includes the implementation of that interface in addition to any other private methods.
Let's start by looking again at our contact class from Chapter 3, One Piece at a Time – Types, Scopes, and Projects and what it looks like in Objective-C:
class Contact { var firstName: String = "First" var lastName: String = "Last" } @interface Contact : NSObject { NSString *firstName; NSString *lastName; } @end @implementation Contact @end
Already Objective-C is taking a lot more lines of code. First, we have the interface declaration. This begins with the @interface
keyword and ends with the @end
keyword. Within the square brackets is a list of attributes. These are essentially the same as the attributes of a structure, except that you can include Objective-C objects in the attributes. These attributes are not commonly written like this because using the properties will create these automatically, as we will see later.
You will also notice that our class is inheriting from a class called NSObject
, as indicated by : NSObject
. This is because every class in Objective-C must inherit from NSObject
, which makes NSObject
the most basic form of class. However, don't let the term "basic" fool you; NSObject
provides a lot of functionality. We won't really get into that here, but you should at least be aware of it.
The other part of the class is the implementation. It starts with the @implementation
keyword followed by the name of the class we are implementing and then ends again with the @end
keyword. Here, we have not actually added any extra functionality to our contact class. However, you may notice that our class is missing something that the Swift version has.
Objective-C does not allow specifying default values for any attributes or properties. This means that we have to implement an initializer that sets the default values:
In Objective-C, initializers are the exact same as a method, except that by convention they start with the name init
. This is actually just a convention but it is important, as it will cause problems down the line with memory management and interacting with the code from Swift.
The Objective-C version of the contact class still isn't exactly like the Swift version because the firstName
and lastName
attributes are not accessible from outside the class. To make them accessible we need to define them as public properties and we can drop them from being explicit attributes:
Alternatively, you can just set the values using self
:
Also, just as you can define weak references in Swift, you can do so in Objective-C:
In addition to weak
or strong
, you can also specify that a property is readonly
or readwrite
:
Each property attribute should be written inside the parentheses separated by a comma. As the readonly
name implies, this makes it so that the property can be read but not written to. Every property is read-write by default, so normally it is not necessary to include it.
We have already seen an example of a method in the form of an initializer, but let's take a look at some methods that take parameters:
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
by looking again at our contact class from Chapter 3, One Piece at a Time – Types, Scopes, and Projects and what it looks like in Objective-C:
class Contact { var firstName: String = "First" var lastName: String = "Last" } @interface Contact : NSObject { NSString *firstName; NSString *lastName; } @end @implementation Contact @end
Already Objective-C is taking a lot more lines of code. First, we have the interface declaration. This begins with the @interface
keyword and ends with the @end
keyword. Within the square brackets is a list of attributes. These are essentially the same as the attributes of a structure, except that you can include Objective-C objects in the attributes. These attributes are not commonly written like this because using the properties will create these automatically, as we will see later.
You will also notice that our class is inheriting from a class called NSObject
, as indicated by : NSObject
. This is because every class in Objective-C must inherit from NSObject
, which makes NSObject
the most basic form of class. However, don't let the term "basic" fool you; NSObject
provides a lot of functionality. We won't really get into that here, but you should at least be aware of it.
The other part of the class is the implementation. It starts with the @implementation
keyword followed by the name of the class we are implementing and then ends again with the @end
keyword. Here, we have not actually added any extra functionality to our contact class. However, you may notice that our class is missing something that the Swift version has.
Objective-C does not allow specifying default values for any attributes or properties. This means that we have to implement an initializer that sets the default values:
In Objective-C, initializers are the exact same as a method, except that by convention they start with the name init
. This is actually just a convention but it is important, as it will cause problems down the line with memory management and interacting with the code from Swift.
The Objective-C version of the contact class still isn't exactly like the Swift version because the firstName
and lastName
attributes are not accessible from outside the class. To make them accessible we need to define them as public properties and we can drop them from being explicit attributes:
Alternatively, you can just set the values using self
:
Also, just as you can define weak references in Swift, you can do so in Objective-C:
In addition to weak
or strong
, you can also specify that a property is readonly
or readwrite
:
Each property attribute should be written inside the parentheses separated by a comma. As the readonly
name implies, this makes it so that the property can be read but not written to. Every property is read-write by default, so normally it is not necessary to include it.
We have already seen an example of a method in the form of an initializer, but let's take a look at some methods that take parameters:
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
In Objective-C, initializers are the exact same as a method, except that by convention they start with the name init
. This is actually just a convention but it is important, as it will cause problems down the line with memory management and interacting with the code from Swift.
The Objective-C version of the contact class still isn't exactly like the Swift version because the firstName
and lastName
attributes are not accessible from outside the class. To make them accessible we need to define them as public properties and we can drop them from being explicit attributes:
Alternatively, you can just set the values using self
:
Also, just as you can define weak references in Swift, you can do so in Objective-C:
In addition to weak
or strong
, you can also specify that a property is readonly
or readwrite
:
Each property attribute should be written inside the parentheses separated by a comma. As the readonly
name implies, this makes it so that the property can be read but not written to. Every property is read-write by default, so normally it is not necessary to include it.
We have already seen an example of a method in the form of an initializer, but let's take a look at some methods that take parameters:
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Alternatively, you can just set the values using self
:
Also, just as you can define weak references in Swift, you can do so in Objective-C:
In addition to weak
or strong
, you can also specify that a property is readonly
or readwrite
:
Each property attribute should be written inside the parentheses separated by a comma. As the readonly
name implies, this makes it so that the property can be read but not written to. Every property is read-write by default, so normally it is not necessary to include it.
We have already seen an example of a method in the form of an initializer, but let's take a look at some methods that take parameters:
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Just as all of our classes so far have inherited from NSObject
, any class can inherit from any other class just like in Swift and all the same rules apply. Methods and properties are inherited from their superclass and you can choose to override methods in subclasses. However, the compiler enforces the rules much less. The compiler does not force you to specify that you intend your method to override another. The compiler does not enforce any rules around initializers and whom they call. However, all the conventions exist because those conventions were the inspiration for the Swift requirements.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Categories in Objective-C are just like Swift extensions. They allow you to add new methods to existing classes. They look very similar to plain classes:
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
These types of properties are very similar to calculated properties. If you need to allow reading from a property, you must implement a method with the exact same name that takes no parameters and returns the same type. If you want to be able to write to the property you will have to implement a method that starts with set
, followed by the same property name with a capital first letter, that takes the property type as a parameter and returns nothing. This allows outside classes to interact with the property as if it were an attribute, when in fact it is just another set of methods. Again, this is possible within a class or a category.
Like Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Swift, Objective-C has the idea of protocols. Their definition looks similar to this:
Here, we are using the @protocol
keyword instead of @interface
and it still ends with the @end
keyword. We can define any properties or methods that we want. We can then say that a class implements the protocol similar to this:
Lastly, blocks are the Objective-C alternative to closures in Swift. They are actually a late addition to Objective-C so their syntax is somewhat complex:
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Note that the type id
signifies any Objective-C object and even though it doesn't have an asterisk, it is a reference type. The usage above looks exactly like a standalone block usage. However, the syntax looks somewhat different in a method:
Here we use the keyword __weak
(that has two underscores) to indicate that the weakBall
variable should only have a weak reference to ball
. We can then safely reference the weakBall
variable within the block and not create a circular reference.
Now that we have a pretty good understanding of Objective-C, let's discuss what Objective-C code looks like in a project. Unlike the Swift code, Objective-C is written in two different types of files. One of the types is called a header file and ends in the extension h
. The other type is called an implementation file and ends in the extension m
.
Before we can really discuss what the difference is between the two, we first have to discuss code exposure. In Swift, all the code you write is accessible to all other code in your project. This is not true with Objective-C. In Objective-C, you must explicitly indicate that you want to have access to the code in another file.
The header files are the types of files that can be included by other files. This means that header files should only contain the interfaces of types. In fact, this is why the separation exists between class interfaces and implementations. Any file can import a header file and that essentially inserts all the code of one file into the file that is importing it:
A lot of the time it isn't actually necessary for one header file to include another because all it needs to know about is the existence of the class. If it doesn't need to know any actual details about the class, it can simply indicate that the class exists using the @class
keyword:
As you might have guessed, implementation files are generally for the implementation of your types. These files are not imported into others; they simply fulfill the promises of what the interface files have defined. This means that header and implementation files generally exist in pairs. If you are defining a steering wheel class, you will most likely create a SteeringWheel.h
header and a SteeringWheel.m
implementation file. Any other code that needs to interact with the details of the steering wheel class will import the header and at compile time, the compiler will make all of the implementations available to the running program.
@interface SteeringWheel () @property NSString *somePrivateProperty; - (void)somePrivateMethod; @end
This brings up another point, that only methods that you intend to use from outside files should be declared in the header. You should always consider a header to be the public interface of your class and it should be as minimal as possible. It is always written from the perspective of outside files. This is the way that Objective-C implements access control. It isn't formally built into the language but the compiler will warn you if you try to interact with code that has not been imported. It is actually still possible to interact with these private interfaces, especially if you duplicate the interface declaration somewhere else, but it is considered best practice to not do that and Apple will actually reject your apps during review if you try to interact with private parts of their API.
Other than the obvious difference, the Objective-C projects will have two different types of files. They are organized in the exact same way as Swift files. It is still considered to be a good practice to create folders to group related files together. Most of the time you will want to keep header file and implementation file pairs together, as people will be switching between the two types of files a lot. However, people can also use the keyboard shortcuts Control/Command up arrow or Control/Command down arrow to quickly swap between a header file and its implementation file.
A lot of the time it isn't actually necessary for one header file to include another because all it needs to know about is the existence of the class. If it doesn't need to know any actual details about the class, it can simply indicate that the class exists using the @class
keyword:
As you might have guessed, implementation files are generally for the implementation of your types. These files are not imported into others; they simply fulfill the promises of what the interface files have defined. This means that header and implementation files generally exist in pairs. If you are defining a steering wheel class, you will most likely create a SteeringWheel.h
header and a SteeringWheel.m
implementation file. Any other code that needs to interact with the details of the steering wheel class will import the header and at compile time, the compiler will make all of the implementations available to the running program.
@interface SteeringWheel () @property NSString *somePrivateProperty; - (void)somePrivateMethod; @end
This brings up another point, that only methods that you intend to use from outside files should be declared in the header. You should always consider a header to be the public interface of your class and it should be as minimal as possible. It is always written from the perspective of outside files. This is the way that Objective-C implements access control. It isn't formally built into the language but the compiler will warn you if you try to interact with code that has not been imported. It is actually still possible to interact with these private interfaces, especially if you duplicate the interface declaration somewhere else, but it is considered best practice to not do that and Apple will actually reject your apps during review if you try to interact with private parts of their API.
Other than the obvious difference, the Objective-C projects will have two different types of files. They are organized in the exact same way as Swift files. It is still considered to be a good practice to create folders to group related files together. Most of the time you will want to keep header file and implementation file pairs together, as people will be switching between the two types of files a lot. However, people can also use the keyboard shortcuts Control/Command up arrow or Control/Command down arrow to quickly swap between a header file and its implementation file.
@interface SteeringWheel () @property NSString *somePrivateProperty; - (void)somePrivateMethod; @end
This brings up another point, that only methods that you intend to use from outside files should be declared in the header. You should always consider a header to be the public interface of your class and it should be as minimal as possible. It is always written from the perspective of outside files. This is the way that Objective-C implements access control. It isn't formally built into the language but the compiler will warn you if you try to interact with code that has not been imported. It is actually still possible to interact with these private interfaces, especially if you duplicate the interface declaration somewhere else, but it is considered best practice to not do that and Apple will actually reject your apps during review if you try to interact with private parts of their API.
Other than the obvious difference, the Objective-C projects will have two different types of files. They are organized in the exact same way as Swift files. It is still considered to be a good practice to create folders to group related files together. Most of the time you will want to keep header file and implementation file pairs together, as people will be switching between the two types of files a lot. However, people can also use the keyboard shortcuts Control/Command up arrow or Control/Command down arrow to quickly swap between a header file and its implementation file.
The last and possibly the most critical component of understanding Objective-C for our purpose is to be able to call Objective-C code from Swift. This is actually pretty straightforward in most circumstances. We will not take any time to discuss calling Swift code from Objective-C because this book assumes that you are only writing Swift code.
The most important part of being able to call Objective-C code from Swift is how to make the code visible to Swift. As we now know, Objective-C code needs to be imported to be visible to other code. This still holds true with Swift, but Swift has no mechanism to import individual files. Instead, when you add your first Objective-C code to a Swift project, Xcode is going to ask you if you want to add what is called a bridging header:
You should select Yes and then Xcode will automatically create a header file named after the project ending in Bridging-Header.h
. This is the file where you need to import any Objective-C headers that you want to expose to Swift. It will just be a file with a list of imports. You still do not need to import any of the implementation files.
most important part of being able to call Objective-C code from Swift is how to make the code visible to Swift. As we now know, Objective-C code needs to be imported to be visible to other code. This still holds true with Swift, but Swift has no mechanism to import individual files. Instead, when you add your first Objective-C code to a Swift project, Xcode is going to ask you if you want to add what is called a bridging header:
You should select Yes and then Xcode will automatically create a header file named after the project ending in Bridging-Header.h
. This is the file where you need to import any Objective-C headers that you want to expose to Swift. It will just be a file with a list of imports. You still do not need to import any of the implementation files.
After you have exposed the headers to Swift, it is very simple to call functions. You can simply call the functions directly as if they didn't have parameter names:
You can use types the same way you use functions. Once the proper header files are imported in the bridging header, you can just use the type as if it were a Swift type:
Again, from Swift's point of view, there is absolutely no difference between how we write the code that uses our Objective-C class and how we would write it if the class were implemented in Objective-C. We were even able to call the addToInviteeList:includeLastName:
method with the same parameter names. This makes it even more clear that Swift was designed with backwards compatibility in mind.
You may have also noticed that the NSString
and NSArray
types seem to translate transparently to String
and Array
classes in the preceding code. This is another wonderful feature of the bridge between Swift and Objective-C. These types, as well as dictionaries, translate almost perfectly. The only difference is that since Objective-C does require an element type when defining a container, they are translated into Swift as containing objects of type AnyObject
. If you want to treat them as a more specific type, you will have to cast them:
You will note that this acts as a pattern when Objective-C types are translated to Swift. Any reference type is going to be translated, by default, to an implicitly unwrapped optional because of the nature of Objective-C reference types. The compiler can't automatically know if the value returned could be nil or not, so it doesn't know if it should be translated as a regular optional or a non-optional. However, Objective-C developers can add annotations to let the compiler know if a value can be nil or not.
The first thing Objective-C developers can add annotations for is whether a specific variable can be null or not:
Again, from Swift's point of view, there is absolutely no difference between how we write the code that uses our Objective-C class and how we would write it if the class were implemented in Objective-C. We were even able to call the addToInviteeList:includeLastName:
method with the same parameter names. This makes it even more clear that Swift was designed with backwards compatibility in mind.
You may have also noticed that the NSString
and NSArray
types seem to translate transparently to String
and Array
classes in the preceding code. This is another wonderful feature of the bridge between Swift and Objective-C. These types, as well as dictionaries, translate almost perfectly. The only difference is that since Objective-C does require an element type when defining a container, they are translated into Swift as containing objects of type AnyObject
. If you want to treat them as a more specific type, you will have to cast them:
You will note that this acts as a pattern when Objective-C types are translated to Swift. Any reference type is going to be translated, by default, to an implicitly unwrapped optional because of the nature of Objective-C reference types. The compiler can't automatically know if the value returned could be nil or not, so it doesn't know if it should be translated as a regular optional or a non-optional. However, Objective-C developers can add annotations to let the compiler know if a value can be nil or not.
The first thing Objective-C developers can add annotations for is whether a specific variable can be null or not:
You will note that this acts as a pattern when Objective-C types are translated to Swift. Any reference type is going to be translated, by default, to an implicitly unwrapped optional because of the nature of Objective-C reference types. The compiler can't automatically know if the value returned could be nil or not, so it doesn't know if it should be translated as a regular optional or a non-optional. However, Objective-C developers can add annotations to let the compiler know if a value can be nil or not.
The first thing Objective-C developers can add annotations for is whether a specific variable can be null or not:
note that this acts as a pattern when Objective-C types are translated to Swift. Any reference type is going to be translated, by default, to an implicitly unwrapped optional because of the nature of Objective-C reference types. The compiler can't automatically know if the value returned could be nil or not, so it doesn't know if it should be translated as a regular optional or a non-optional. However, Objective-C developers can add annotations to let the compiler know if a value can be nil or not.
The first thing Objective-C developers can add annotations for is whether a specific variable can be null or not:
There is some debate in the Apple developer community about how relevant Objective-C will be moving forward. There are people that have jumped into Swift development full time and there are others that are waiting for Swift to mature even more before they commit energy to truly learning it. However, there is little debate over the fact that Objective-C knowledge is still going to be relevant for a while, most notably because of the vast resources that exist and the fact that all existing Apple APIs are written in Objective-C. We will put those APIs to use in our next chapter: Chapter 11, A Whole New World – Developing an App, when we will finally dive into some real app development.