Objective-C for Swift Developers (Part 1)

Written by: Reinder de Vries, February 24 2017, in App Development

Objective-C for Swift Developers

Is Objective-C officially dead? If you look at the rise in popularity of programming language Swift since 2014, you’d most certainly think so.

Swift is easier to learn than Objective-C, it has a compelling syntax and thanks to it being open-source, it has the potential to break free from the Apple ecosystem.

Has it replaced Objective-C? Absolutely not! Although beginner app developers are picking up Swift en masse, it definitely pays dividends to get smart in Objective-C as well.

After all, Objective-C is still widespread in:

  • Pretty much every important framework in the Cocoa and Cocoa Touch SDKs, ranging from UIKit to Auto Layout. It’s all still written in Objective-C.
  • A lot of major open source libraries, including AFNetworking, MBProgressHUD and ParseUI.
  • Apps pre–2014, especially corporate apps, are still Objective-C because they were initially coded with it! It’s tough rewriting an entire app just for the sake of using a new language.

You will definitely find Objective-C in the field, still. Whether it’s frameworks that have no Swift counterpart, older apps that need updating, or simply because a colleague doesn’t speak Swift yet.

You can bridge Objective-C with Swift of course. With a so-called Bridging Header you can tap into any Objective-C SDK or framework, and write Swift code worry-free, and forget about Objective-C.

A good example of where that could go wrong is the ParseUI framework, a wrapper around the Parse for iOS SDK that couples nicely with UI components such as table views and collection views.

What if you get stuck and need to inspect the original source of ParseUI, in Objective-C? You’d stay stuck if you don’t know Objective-C!

It’s smart to code in Swift, and still know a bit of Objective-C, enough to get around. That’s why I wrote this article: to help you, as a Swift developer, to get to know Objective-C better.

Enjoy!

Note: You can download the sample project for this guide on GitHub.

Grab My Free iOS Development Course

Get complementary access to my course, Zero to App Store, and learn how you can build a real-time chat app with Firebase and Swift!

Yes, Send Me The Free Course!

A Bit Of Objective-C History

Objective-C was created in the early 1980s, and became part of Apple’s Mac and iOS platforms when Apple acquired NeXT, the company Steve Jobs founded when he left Apple in 1985. NeXT had licensed Objective-C from its creators, Brad Cox and Tom Love, from the company Stepstone.

When coding apps you’re still confronted daily with Apple’s past. The “NS” prefix many Cocoa and Cocoa Touch classes have is an abbreviation of “NeXTSTEP,” the operating system NeXT built.

It’s also fascinating that Interface Builder’s creation, which is now part of Xcode, coincided with the creation of NeXTSTEP and Objective-C. Xcode itself was created much later, in 2003, although it was based on the Project Builder – again, made for NeXTSTEP.

Just like in our age, where Instagram is now part of Facebook, Steve Job’s NeXTSTEP acquired many of its surrounding technologies.

Crash-Course Objective-C Programming

What is programming? It’s telling a computer what to do. It’s an ordered list of commands – the code lines that make up a software program. The computer, or iPhone, will execute all lines of code after one another.

Programs used to be procedural, for which lines of code are executed one by one. A typical statement for procedural programming languages is goto, which took the program to an arbitrary line of code, or gosub, which would take your code into a subroutine. Subroutines are like functions: individual blocks of code that take input and make output.

Procedural programming has no other way of reusing a piece of code multiple times, and no way of organizing code more sensibly. A better way of organizing your code is called Object-Oriented Programming, or “OOP.”

Object-Oriented is a way of programming which divides programming code in classes and methods. Classes are structures for your code, as you’ll see next.

Objective-C is an Object-Oriented language, and so is Swift. It’s a tough language to learn and it’s bracket-style messaging syntax looks intimidating.

Learning #Swift? Be smart, know a bit of #Objective-C too: https://learnappmaking.com/objective-c-swift-developers-part-1/Click To Tweet

The Valet Program

Did you see The Matrix movie from 1999?

In the movie, Neo (Keanu Reeves) “exits” our physical world to be reborn in the actual “real” world. The premise of The Matrix is that we all live in a computer, and that people, events and physical things are controlled by computer programs.

Take for instance The Valet Program, that’s out here in our computer world. Whenever you go up to The Valet, he takes your keys and parks your car. When you return, you get back your car and drive away.

We’re going to write a small program that makes up the actions The Valet Program does.

We’ll be working with two different files, called AppDelegate and Valet.

The AppDelegate is our “starting point”, it’s what the iPhone loads into it’s memory when we start The Valet Program. The Valet holds the actions, memory and logic for the program.

Declaration, Allocation and Initialization

The code that creates the valet, and makes it run, is this:

Valet *valet = [[Valet alloc] init];  
[valet run];

In the code, this happens:

  1. Create a new object of the type Valet. This particular object is a so-called instance of the class Valet. First, we tell the Valet class to allocate a piece of memory for this instance with alloc, and then we tell it to initialize the Valet instance with init.
  2. Then we give our valet object a command: run.

In Swift, the same code is this:

let valet = Valet()  
valet.run()

Can’t get your head around an instance and a class?

Think of it like architecture. You have a blueprint of a house, that’s the class, and a house that the workers build: an instance.

The blueprint defines where the walls, doors and windows of the house are, but you can’t live in it! That’s what you need the actual house for, the instance of the class.

In the Objective-C example, the way of coding (called syntax), with the square brackets, is very unique. It’s called a messaging system. It’s the Objective-C way of telling objects what they should do.

Objective-C’s Messaging Syntax

Let’s break down the above code sample a bit further. The first line in the Objective-C code sample is identical to this.

Valet *valet = [Valet alloc];  
valet = [valet init];

Do you see that instead of writing alloc and init on one line, they’re now separated on two lines of code?

This is what it does:

  • Valet *valet means: create a new object with the name valet. It must be of class Valet. That asterisk * is a pointer, Objective-C’s syntax for indicating a reference type (as opposed to a value type).
  • The = sign is the assignment operator. It says, whatever is left of the = sign, is assigned to what’s right of it. You store the result of [Valet alloc] into variable valet.
  • The command we’re executing first is called alloc, it allocates memory for the object valet. Whatever you store on an iPhone needs memory! This alloc command is called a method.
  • There’s a catch: the Valet inside the brackets (near alloc) is written with a capital character! Any word that starts with a capital character, like this one, is a class. alloc in this sense is then a class method.
  • Next line: valet = [valet init]. Another method, named init. It is called on the object valet, and stored inside the object valet with the equals sign. Note that it’s written without a capital first character, because it’s an object (and not a class). Then, the method init is called an instance method. Why? Remember this: object valet is an instance of the class Valet. init is therefore an instance method, because it is called on the instance of the class, not on the class itself.

So what about that pointer?

Picture the iPhone’s computer memory in your head like a city. Each memory block has an address, like a house. In each house you can store 1 object.

We’ve just stored an instance of class Valet in variable valet. We can retrieve our object later, because we know it’s name valet. The iPhone memory however stores it under a different address, like 0x00ad6f88.

We can’t write our program with names like that! It’s too complicated. In order to work with readable names, we create a pointer. Our name valet points to 0x00ad6f88 for the computer, which in turn is the address for the actual contents of the object. The contents can include the valet’s name, how many cars he’s stored and the time he can go home. So, a pointer is a reference, a readable reference for us, and a memory address for the iPhone computer.

So, what’s the big difference between the two Objective-C code samples above?

No difference at all. But why do we write them differently and which is better? The first one, because it’s shorter. We utilize the messaging system to “chain” the results of methods to one another.

Picture this: you’re waking up and then making breakfast. First we create an object called you, and then we do this:

you = [you wakeUp];  
you = [you goDownStairsToKitchen];  
you = [you getKnifeBreadButter];  
you = [you makeSandwich];  
you = [you eatSandwich];

As you can see, we’ve used several instance methods to get from bed to a full stomach. We assign to the variable you temporarily, so we can save the results of each of your actions. Each time we write = and perform an action, it overwrites the previous action.

We can also write it like this:

[[[[[you wakeUp] goDownStairsToKitchen] getKnifeBreadButter] makeSandwich] eatSandwich];

This doesn’t mean you did all of that at the same time. No, all methods are still executed in after one another. However, we’ve chained all the results.

You can’t get the knife, bread and butter before getting down to the kitchen. The result of getting the knife etc. is chained to the result of going down to the kitchen.

In the first code sample we’ve stored the result of each of the commands inside you with the assignment operator. In the second sample we’ve omitted the equal sign and put it all in one line, all held together by square brackets. The result of a method is used as the basis for the next, without storing it in a temporary object (like you = ...).

In Swift, the first code sample would look like this:

you = you.wakeUp()  
you = you.goDownStairsToKitchen()  
you = you.getKnifeBreadButter()  
you = you.makeSandwich()  
you = you.eatSandwich()

The condensed way of coding, in Swift, is this:

you.wakeUp().goDownStairsToKitchen().getKnifeBreadButter().makeSandwich().eatSandwich()

You can clearly see the differences between Objective-C syntax and Swift syntax. Objective-C calls methods and properties with those square brackets [], whereas Swift uses dot-syntax.

The most significant difference between Objective-C and many other languages, including Swift, is this []-style messaging syntax. Of course, the syntaxes differ in many more ways, but it’s a relief to know that the worst is behind you now!

Coding The Objective-C Valet

Alright, let’s put all that Objective-C to good use. Add the following files and code to your own Xcode project, or download the Xcode project source code on GitHub

File: Valet.h (Header)

@interface Valet : NSObject  
{    

}

@property (copy) NSString *name;  

- (id) initWithName:(NSString *)aName;  
- (void) run;  

@end

File: Valet.m (Implementation)

#import "Valet.h"  

@implementation Valet;

@synthesize name;  

- (id) initWithName:(NSString *)aName  
{
    self = [super init];  
    if (self)  
    {
        self.name = aName;  
    }

    return self;  
}

- (void) run  
{
    NSLog(@"Running valet with name %@", self.name);  
}

@end;

Header and Implementation

First, we used two files: a header file and an implementation file. The header file is used to declare our class, which means that we tell the iPhone which objects, methods and so on we’re going to use inside our class Valet.

As you can imagine, an object can store objects (kind of like sub-objects) inside itself. That’s the whole deal with Object-Oriented Programming!

The implementation file is used to write out the things we declared in the header, so the contents and logic of our code.

If you compare it to a cooking recipe, the header would be the ingredients list and the implementation the steps to cook the meal.

A header file has the filename extension .h, an implementation file the extension .m. If you want to use a class you’ve coded in another file you have to import that class at the top of the file, with the #import keyword.

Moreover, you have to “link” a header and implementation of the same class by including an import for the header file in the implementation file, like #import "Valet.h" in Valet.m.

In Swift you don’t have separate header and implementation files. Any Swift class is just saved in a .swift file. Moreover, you typically only have to import external frameworks and libraries with the import statement. In Objective-C you have to import pretty much every file or class you want to use.

Breaking Down The Code

Let’s start with the header file Valet.h

  • We start with @interface Valet : NSObject {}.
    You use an interface to declare a class. An interface is like a human face, you say: this is a face with eyes and a nose and a mouth. You use the word @interface to tell the iPhone you’re declaring a class. The colon (double point) is used to inherit NSObject, we’re telling the iPhone that we want to make a class based on the properties of NSObject – another parent class. Then, the curly braces are required, but today we won’t use them. (Normally, you define instance variables inside the curly braces.)
  • Second, we write @property (copy) NSString *name;.
    This is an easy one: we declare an object with name name, of class NSString. We want to use this object, we tell the iPhone. To be able to use it later, we give it a name: name. You see that once more we use a pointer with *, a reference address.
    We end this line with a semi-colon (dot comma) ;, it’s to tell the program that this line has ended. Now, there’s something interesting here: @property (copy). We declare this object as a property, we attach this object to the class we’re writing (Valet class). You can literally see that a name is a property of a real-world valet. Forget the (copy) for now.
  • Then, - (void) run;.
    This is a declaration of a method, named run. It has no result (methods can return results), indicated by the (void). The minus - indicates that we’re writing an instance method, and not a class method (indicated by +). Again, the ; for the line ending.
  • We close the file with @end, to indicate this is the end of the file. All files need that. No, no ; here!

Got it? We’ve declared one property called name and one method called run.

Now, for the implementation file Valet.m.

  • We start with telling the iPhone it should import our header file, with #import "Valet.h". This way the iPhone knows where to look for the header file of this implementation.
  • Second, we write @implementation Valet;. This is an indication that the code that follows is the implementation of the Valet class.
  • Then, we write @synthesize name;. It’s for telling the iPhone we want to use the name property in this implementation. It kind of connects the property from the header to the implementation. It also creates setter and getter methods for us. We can use those methods to set the name property (to your name for instance) and read out its contents. We could write those methods ourselves, but using @synthesize is easier.
  • Then, the entire - (id) initWithName:(NSString *)aName { ... block. It is a convenience method for initializing this Valet class with a name, all in one. Remember when we wrote Valet *valet = [[Valet alloc] init];? Now we can write Valet *valet = [[Valet alloc] initWithName:@"Steve"]; instead of first initializing it, and then setting its name on 2 lines. The code block first runs self = [super init];, which calls the init method of NSObject. That’s because we inherited it in our header. Then, the if-statement is executed when self has correctly initialized. Only then it executes self.name = aName;. See aName in the start of this code block? The object aName is copied and stored into self.name. When we use Valet *valet = [[Valet alloc] initWithName:@"Arthur"];, the @"Arthur" is copied into self.name. Double check that! Do you understand why? Finally, the method gives a result back with return self. The result is self, the entire object itself. And when we write Valet *valet = [[Valet alloc] initWithName:@"Arthur"];, guess what the contents of valet is? It’s returned with return self, so it’s self!
  • Then there is the - (void) run { ... block. This has the contents of the run method. It doesn’t return anything (void means “empty”). The contents of our run method is NSLog( ..., it shows some debug output with the function NSLog to our debug screen in Xcode. The @"Running valet with name %@", self.name inside the parentheses is called a format string, it inserts the contents of self.name at the position of %@.
  • And again, we end with @end.

Note that in Objective-C string literals like @"Steve" start with an @-sign. In Swift, you just write "Steve".

Remember we started with the AppDelegate? The code we used was:

Valet *valet = [[Valet alloc] init];  
[valet run];

As you can see, something’s missing, it should be:

Valet *valet = [[Valet alloc] initWithName:@"Arthur"];  
[valet run];

The output of this code, when used in conjunction with the class Valet we wrote, is:

Running valet with name Arthur

The Same Valet Class In Swift 3

The Valet class in Swift is surprisingly simple…

class Valet  
{
    var name = ""

    init(name:String)  
    {
        self.name = name  
    }

    func run()  
    {
        print("Running valet with name \(name)")  
    }
}

Like before we’re declaring a class called Valet. It has one initializer init(name:String) that takes parameter name and assigns it to the property self.name. When the method run() is called, it prints out "Running valet with and the value of name.

You can call this Swift class like this:

let valet = Valet(name: "Arthur")  
valet.run()

Easy, right? Now you understand why it’s smarter to learn Swift compared to Objective-C, although it’s even smarter to know a bit of Objective-C next to Swift.

Conclusion

Hooray! These are the basics of Objective-C programming. Most Objective-C from here on out is based on what you’ve learned in this article. It might seem like a lot to comprehend, but now you know that this is it.

Enjoyed this article? Share with friends!

Learning #Swift? Be smart, know a bit of #Objective-C too: https://learnappmaking.com/objective-c-swift-developers-part-1/Click To Tweet

Written By: Reinder de Vries

Reinder de Vries is an indie app developer who teaches aspiring app developers and marketers how to build their own apps at LearnAppMaking.com. Since 2009 he has developed over 50 apps for iOS, Android and the web, and his code is used by millions of users all over the globe. When Reinder isn't building apps, he enjoys strong espresso and traveling.

Grab My Free iOS Development Course

Get complementary access to my course, Zero to App Store, and learn how you can build a real-time chat app with Firebase and Swift!

Yes, Send Me The Free Course!

Comments & Thoughts


  • DewDew

    Thanks for the intro. Objective C seems like hell compared to swift. Like night and day difference. And do we have to deal with deallocating that memory ourselves? Ah hell no.