IntroductionWelcome| 00:04 | Hi, this is Simon Allardice and welcome
to Objective-C Essential Training.
| | 00:08 | Sure! There are dozens of languages you
can choose from, but if you want to build
| | 00:12 | applications that run on the Mac, you
want to build applications that run on the
| | 00:16 | iPhone or the iPad, there is
one clear winner: Objective-C.
| | 00:21 | It is the language of choice for
building apps that run on Apple hardware.
| | 00:25 | We will begin with the basics.
| | 00:26 | Getting the tools that you need, the
structure of an Objective-C program, how to
| | 00:31 | get your first code up and running.
| | 00:32 | We will explore what's available in
the Foundation framework, a collection of
| | 00:37 | prewritten code that's there in
every Objective-C project you write.
| | 00:41 | You will see how to design and
create your own classes and there is a big
| | 00:44 | section on memory management, a huge
part of programming in Objective-C world.
| | 00:49 | And at the same time, we will explore
Xcode 4, the application you're going to
| | 00:54 | use to write, test and
debug your Objective-C programs.
| | 00:57 | We will wrap up with some more
advanced topics like dynamic typing.
| | 01:01 | So, let's see how Objective-C
works and the best way to work with it.
| | 01:05 | Welcome to Objective-C Essential Training.
| | Collapse this transcript |
| What you should know| 00:00 | In this course, I am starting with the
idea that a) you know you are where on
| | 00:04 | the Mac and b) you have some
programming experience. That's it.
| | 00:08 | You don't need to have done
any Mac or iPhone programming.
| | 00:12 | You might never have even
seen Objective-C before.
| | 00:15 | That's all fine, but I do
expect that you can write code.
| | 00:19 | To make the most of our time here, this
course is not an introduction to programming.
| | 00:24 | So I expect you're very familiar with
programming fundamentals already. Loops,
| | 00:28 | variables, conditions, functions, the
core pieces and concepts of programming
| | 00:33 | found in any language.
| | 00:35 | Now, you might've heard that if you
know a C-based object oriented language
| | 00:39 | like C#, Java or C++ that
you've got a head start with Objective-C.
| | 00:45 | Well, technically yes, those languages
are related. They all have curly braces,
| | 00:50 | they are all object oriented, yada,
yada, yada, but don't get cocky.
| | 00:55 | If you think that all you need to do
here is pick up a little syntax, you're
| | 00:59 | going to hit a brick wall.
| | 01:01 | In your first ten minutes with Objective-
C, you'll see things that will not make
| | 01:05 | sense and if you try and force them
into a piece of knowledge that you know
| | 01:10 | about C++ or a piece of knowledge that
you know about Java, you'll find this
| | 01:15 | journey very painful indeed.
| | 01:17 | Objective-C is different, sometimes
very different, and that difference is way
| | 01:23 | more than just syntax.
| | 01:25 | Over the years, Objective-C has
developed its own customs, its own ways of doing
| | 01:30 | things that are almost certainly
unlike anything you've seen before.
| | 01:34 | So whatever language that you know,
leave most of it behind and just bring those
| | 01:40 | core fundamentals to the table with you.
| | Collapse this transcript |
| Using the exercise files| 00:00 | If you're a premium member of lynda.com
or if you're watching this tutorial on
| | 00:04 | the DVD-ROM, you have access to
some exercise files used in this title.
| | 00:08 | I have them here on my desktop in this
folder and what you'll find is that some
| | 00:13 | of the chapters have their own folder
and inside of some of these folders there
| | 00:17 | are files that represent the
code that's written in the movies.
| | 00:21 | And sometimes you'll find files that
are just text files and this is just code
| | 00:25 | you can copy and paste into your own projects.
| | 00:29 | And other chapter folders might
contain subfolders that might be the starting
| | 00:34 | version of a project and the
finished version of a project.
| | 00:36 | If you find that the file that
you're looking for is the one that ends in
| | 00:40 | xcodeproj for Xcode project, you can
just double-click that to open it in the
| | 00:45 | Xcode coding environment.
| | 00:47 | Now these are all just for convenience.
If you don't have access to the exercise files,
| | 00:51 | you can follow along from
scratch or create your own assets.
| | 00:55 | There's nothing major created
as a starter file in this course.
| | Collapse this transcript |
|
|
1. Getting StartedInstalling the tools| 00:00 | We are ready to get started writing
some Objective-C. Now it is just text,
| | 00:04 | so we could write Objective-C using text edit
or even with the terminal prompt, but we're
| | 00:08 | not going to because I don't want to put
myself through that much pain and inconvenience.
| | 00:12 | We're going to use Xcode, and we will get it
from a Mac App Store. If it's not clear, yes,
| | 00:17 | you are going to need a Mac. The development
tools are not cross-platform here. It is technically
| | 00:23 | possible to write Objective-C on Linux or
Windows, but I'm assuming that you're watching
| | 00:27 | this course because you want to build apps
for iOS devices or for Mac Desktop and Laptops
| | 00:33 | and you will need a Mac for that.
| | 00:35 | You should be running a recent operating system,
Mac OS 10.7 Lion, or OS 10.8 Mountain Lion.
| | 00:43 | You can install Xcode on Snow Leopard OS 10.6,
but you certainly don't want to be any earlier
| | 00:49 | than that, and being on the latest operating
system is highly recommended if you're going
| | 00:54 | to developing on an Apple platform.
| | 00:55 | So I'll be using Lion as my operating system
right now for this movie, and I'll jump and
| | 01:01 | open up the App Store. Once this is open I am
going to find the category called Developer
| | 01:07 | Tools, and that's where we'll find Xcode. Xcode
is an IDE, or Integrated Development Environment.
| | 01:14 | Like Visual Studio or Eclipse or NetBeans,
and being an IDE just simply means it does
| | 01:20 | more than one thing. It's not just a text
editor. Yes, we do write our code using Xcode,
| | 01:27 | but we will also use it to test and debug
our applications, to organize our projects,
| | 01:32 | even later on to build interfaces
for iOS and Mac Desktop applications.
| | 01:38 | On some other languages in other environments
you might shop around and try a bunch of different
| | 01:43 | IDEs and code editors, before figuring out
which ones should suits you best, but really
| | 01:47 | with Objective-C, Xcode is the one to use.
| | 01:51 | In this course we will be using Xcode version 4,
and I am recording updates to this course
| | 01:56 | in June 2012, and right now the
specific version is Xcode 4.3.3.
| | 02:01 | Now if you use another programming
environment or development tool, you might be used to
| | 02:06 | a release cycle that's every one, two, or
even three years between major updates. Now
| | 02:11 | be aware that Apple release updates to Xcode
often. Every few months there is typically
| | 02:15 | a new version. Usually, it's just a point
release, but because it's free, when Apple
| | 02:20 | updates it, they just
release the update straightaway.
| | 02:23 | Now usually it's just some minor updates,
some additions, but it can include cosmetic
| | 02:28 | changes and make what you see a little
different from what I'm recording. You don't need to
| | 02:33 | have an identical version to mine. I suggest
just always having the latest released version.
| | 02:38 | Now this is a fairly large download if you
look over here in the Information section,
| | 02:43 | you can see it's 1.43 GB, and it's so big
because it isn't just one program just Xcode,
| | 02:49 | it's actually a whole suite of applications,
documentation tools, and code libraries.
| | 02:56 | Everything you need to develop Macintosh Desktop
Applications, to develop iOS applications for the iPhone
| | 03:02 | and iPad, all of that is bundled
together into this one download.
| | 03:07 | Now I already have it installed as I can see
here, but if you haven't, go ahead and grab
| | 03:11 | it, and after it's installed, you'll find it
in your Applications folder. Now one thing
| | 03:16 | to mention, before you go much further, you
should become a familiar with the web site
| | 03:20 | called developer.apple.com. This is the Apple Developer
Center, and you get a lot of technical resources here.
| | 03:28 | When you get here, you will find that it's
split into three main sections. With Objective-C,
| | 03:33 | we are usually interested in the first two,
the iOS Dev Center targeted at developers
| | 03:38 | working on iPhone and iPad and the Mac Dev
Center for developers working on Mac Desktop
| | 03:43 | or Laptop applications.
| | 03:46 | You can join Apple's iOS developer program
or their Mac developer program. In the US
| | 03:51 | that's currently $99 a year. The biggest reason
to join either of these programs is that when
| | 03:57 | you make an app, and you want to put it in
the App Store, either for iOS devices or for
| | 04:02 | the Mac, you will need to be a
member of one of these programs.
| | 04:06 | Now for this course you don't need to be a
member of either program, but you should register
| | 04:10 | as an Apple Developer if you haven't done
that already. Either in the iOS Dev Center
| | 04:15 | or the Mac Dev Center, you'll find a link
to register for free. Right now, it's up on
| | 04:21 | the top right-hand side, you can register
here as an Apple Developer, and this allows
| | 04:25 | you access to a lot of technical resources.
| | 04:28 | And we do it to get full access to the
documentation found on Apple's developer site.
| | 04:33 | We are going to get to that documentation through Xcode.
| | 04:37 | So once you have installed Xcode, and you have
registered as an Apple Developer, we will be ready to go.
| | 04:45 |
| | Collapse this transcript |
| Creating your first application| 00:00 | You're probably impatient to get
going. So we are going to jump into
| | 00:03 | Xcode, write a program, and then we are going
to jump right back out again. Because if you're
| | 00:07 | new to this, in just those few moments you
are likely to see quite a few things that
| | 00:12 | you will want explained.
| | 00:13 | Now there is a tradition in programming that
when you learn a new language, you write a
| | 00:18 | Hello World program, a really simple program
that just outputs those words, and it's kind
| | 00:24 | of corny, so I can assure you that in this
course we will never need to write the words
| | 00:29 | Hello World. We are not going to write those
words, because Apple is going to do it for us.
| | 00:35 | So once it's installed, we'd launch Xcode.
You will find it in your Applications folder,
| | 00:40 | the normal location. I have just created a shortcut to it in
my dock here, and we'll get the start window appearing.
| | 00:47 | And the first option you get here is to Create
a new Xcode project, and that's what we are
| | 00:52 | going to click here. The new project window
appears. This is not new file or new document
| | 00:57 | or new program. Xcode
organizes your content into projects.
| | 01:02 | Right now just think project equals application.
When I make an iPhone app, that's a project.
| | 01:08 | You want make a Mac Desktop App, that's a
project. You want to make a tiny simple app
| | 01:13 | just to test a piece of code you thought
this morning, that's a project. What that means
| | 01:17 | for you is that when we make a new project,
Xcode makes a folder on your hard drive and
| | 01:21 | puts all the relevant files inside that folder.
| | 01:24 | Xcode provides a variety of different project
templates, preconfigured examples suggesting
| | 01:30 | starting points. These help us make iPhone
applications and Desktop applications and
| | 01:35 | they will be very useful, but right now
they will get in the way of us focusing on the language.
| | 01:39 | So we are not going to start with
an iPhone application from this iOS section.
| | 01:44 | We are not going to work with any of these
system plug-ins or application plug-ins.
| | 01:49 | We're going to create an old-school command line
application, the simplest kind of UNIX or
| | 01:54 | DOS style command line app that runs from
the console. No user interface, no buttons,
| | 02:00 | no images, no text field. That's not
important right now. So under the Mac OS X section,
| | 02:05 | I am going to select the Application entry
on the left-hand side here, and then with
| | 02:10 | that I will select the Command Line tool option.
Tool is just a word that Apple uses for an
| | 02:17 | app without a user interface.
| | 02:19 | So then click Next. Now there are three things
on this next screen that we care about.
| | 02:26 | Most simply, what is our product name, which means
what do you want to call this program, this application?
| | 02:31 | I am going to call this FirstApp.
Now underneath that you'll have a Company
| | 02:37 | Identifier, and depending on the version of
Xcode you have, you may also have an Organization Identifier.
| | 02:42 | Those aren't really important for
our purposes here. You could write whatever
| | 02:47 | you wanted here, and it wouldn't make a
difference, but under this we have what's called a Type
| | 02:52 | and this does make a difference. This dropdown
box here has C, C++, Core Data, a few others.
| | 02:58 | Now we know that we are not doing C or C++,
this course is all about Objective-C, but
| | 03:04 | Objective-C doesn't seem to be written here.
Well, that's because in this course we will
| | 03:07 | need the option called Foundation, and this
would be our classic simple Objective-C program.
| | 03:13 | We will talk about what the word Foundation
means in a minute. In this course you will
| | 03:18 | always choose Foundation for the
type of project you're creating here.
| | 03:23 | Under that we have the Use Automatic
Reference Counting option, and as a developer you're
| | 03:29 | almost always going to have that checked,
because it will make your life significantly
| | 03:33 | easier if you do, and we will talk about
this particular check box a little later on.
| | 03:38 | So we give it a name, we check that the type
is Foundation, and not Core Foundation, but
| | 03:43 | Foundation, and we have Use
Automatic Reference Counting checked.
| | 03:47 | Then click Next, and it asks. Where do you
want to save this project? It could be pointing
| | 03:53 | to the Desktop, it could be in your
Documents folder. It really doesn't matter.
| | 03:57 | You can choose wherever you want to do this. There
is no magic location that you must save your
| | 04:02 | Xcode files. I'm going to point it to my
Documents folder, which is fine and under this we also
| | 04:08 | have an option for Source Control, a check box.
Do you want to create a local git repository
| | 04:13 | for this project? I am going to
make sure that, that is unchecked.
| | 04:17 | This all about Source Control, managing revisions
to our files and working with other people in teams.
| | 04:22 | It can be very useful later on, but
for the moment we don't need to bother about it.
| | 04:28 | So I then click Create, and Xcode appears
with our new project. Here is the super quick
| | 04:33 | breakdown of what we're looking at here.
The left-hand side over here is the navigator section.
| | 04:39 | It will show me everything in and
everything about the project, all the files,
| | 04:45 | the settings, the configuration options. I
see that my project that Xcode has created
| | 04:49 | seems to have a bunch of different folders
in them. I can expand some of these folders
| | 04:53 | and by single-clicking, I can
focus on one part of the project.
| | 04:58 | If I single-click on a file here that can
be edited what will happen is I'll see it
| | 05:02 | open up in this middle section over here.
And we'll spend a lot of time in this.
| | 05:08 | This is the editor section. I got this view by
single-clicking. If instead I had double-clicked
| | 05:13 | that file that said main.m, what will
happen is it will open in a separate window.
| | 05:18 | I don't need that. So as a general rule, I am
just going to single-click when I'm selecting
| | 05:22 | my files in my project. The toolbar at the top
of Xcode here will let me run this application,
| | 05:29 | select how to run it. This center section
here that currently says, Installing Xcode
| | 05:34 | Developer Library kind of looks like a
little LED screen and will in fact show messages
| | 05:38 | about anything that Xcode is doing as we are
working with our project. It's kind of like
| | 05:42 | how iTunes displays messages when you're copying or
syncing. You will see the same kind of thing here.
| | 05:48 | Over on the top right section you should
have two groups of three buttons, and right now
| | 05:53 | in the first group what's called the Editor
group we have the first one to press.
| | 05:57 | This is what's called the Standard Editor, and we
will see the others later. In the second section
| | 06:02 | we have three buttons that can be toggled
on or off. This first one has a highlighted
| | 06:07 | left section. If I click it, we will
actually see that navigator section come on or off
| | 06:12 | and as you might guess, if I do it with the
right-hand section, we will see that turn
| | 06:16 | on or off as well.
| | 06:18 | Now Xcode is not one of these programs
where you can detach these panels and rearrange
| | 06:23 | them as you see fit. The layout is the
layout of Xcode. You can turn certain sections on
| | 06:29 | or off, make them invisible, but you can't
move them around. The navigator section for
| | 06:34 | example will always be on the left-hand side.
We also have this middle button here that
| | 06:39 | can turn on a lower section which will
give us debug and diagnostic information.
| | 06:45 | I am just going to leave the Navigator section
turned on right now. Now we are going to cycle
| | 06:50 | back around into different parts of Xcode in
a little while and start to dive into some
| | 06:54 | of these other options and all the icons that
we see here. But right now just think of these
| | 06:58 | two main panes as on the left-hand side shows
us everything in our project. And this section
| | 07:05 | here, the Editor, shows us the one thing that
we are working on, and in a very simple Command
| | 07:10 | Line tool that we just created, we are really
interested in one file, which is main.m here.
| | 07:17 | .m is the suffix that means Objective-C, and we
can actually ignore all the other files right now.
| | 07:23 | So this is our program and all it does right
now is output the message Hello World.
| | 07:28 | And if I had to run this, I am going to go up
to the toolbar section and find the button
| | 07:32 | that says Run, and then click it.
| | 07:34 | And we get a message that says Build Succeeded.
Objective-C is a programming language that
| | 07:40 | needs to be compiled before we run it, and
build just means compile and link this program
| | 07:45 | together so it can be run. Now the question
is well, what did it do? And we can run it
| | 07:50 | multiple times, and if I decide to do that,
just by clicking the Run button again.
| | 07:55 | If you're scanning down here at the bottom
section, what we are seeing is this Output message.
| | 07:59 | It might not be all that visible,
but we are outputting the words Hello World!
| | 08:04 | The section here at the bottom is called the
debug area, and if you notice, the button up
| | 08:08 | at the top has become depressed or toggled
on because we need to see it just to see
| | 08:14 | the output of this program.
| | 08:16 | Because we have just made a command line tool,
I don't have any kind of Window or iPhone
| | 08:21 | application up here. I just get a message.
Now to make some of this more visible, I am
| | 08:25 | going to make a couple of changes right now
to the Xcode Preferences. You don't have to
| | 08:30 | do this, but you'll see why I'm going to.
| | 08:32 | So up in the Xcode menu I am going to come
down into Preferences, and I am going to do two things.
| | 08:37 | First in the Fonts & Color section
I'm going to select the theme called Presentation.
| | 08:43 | What that's going to do is make our code and
our Output messages a bit more visible and
| | 08:49 | then in the Text Editing section of this
preferences, I am going to check the box that says Line
| | 08:55 | numbers, which will give us line numbers in
this gutter section over here just so I can
| | 08:59 | talk about the lines as
we are going through them.
| | 09:02 | So back to the code, if you were to scan it,
it's not difficult to spot the one line that's
| | 09:07 | responsible for that Hello World! message.
Line 17 here says NSLog@"Hello, World!".
| | 09:16 | NSLog is the equivalent of printF in C or
system.out.printline in Java or console.rightline in C#.
| | 09:25 | It's just a way of getting a message
out of your program and onto the console.
| | 09:30 | But we have got a few other things going on
here. We have got this import line up on line 9.
| | 09:35 | We have got the line that says main on line 11
and particularly the rather cryptic @autoreleasepool
| | 09:44 | on line 14, and we're going to get into all
of this, but even from just scanning it, we
| | 09:48 | can see that we get color coding of the different
pieces of syntax showing the difference between
| | 09:53 | say comments on line 16
and keywords and variables.
| | 09:58 | Now this is not unusual. Most IDEs give us
the same thing. As you might imagine, like
| | 10:03 | most IDEs, if we click in here and start typing,
we will get automatic indentation.
| | 10:09 | We will also get code sense, which is Xcode auto-completion
feature. If I start typing, for example, I
| | 10:14 | type in the letters NSR, we are going to get
this pop-up, and as I type more things, it
| | 10:20 | might start to filter down
and give us even fewer options.
| | 10:25 | If I see many options, I can use my cursor
key move up and down to select the thing that
| | 10:29 | I'm interested in and just hit Return to
select something. This helps us a lot, particular
| | 10:34 | because you find that Objective-C in general
has a lot of very long names for its functions and methods.
| | 10:39 | Now I don't actually need to
use this piece of code at the moment, I'm
| | 10:43 | going to delete it in just a second. But you
will notice, already that I have this exclamation
| | 10:48 | mark appearing in the gutter section over
here for line 18. That's because Xcode 4 tries
| | 10:54 | to highlight issues with the code as you're
typing it, and it's often pretty quick about
| | 10:59 | it, and you haven't even finished a line before it
starts complaining about it, but you will see this a lot.
| | 11:04 | So I will just delete that line because we
don't need it. Now as you might expect, Xcode
| | 11:09 | does have a lot of other options. It has ways
to do test driven development and source control
| | 11:13 | and refactoring. There are Code Snippets,
ways to build interfaces and help you manage
| | 11:18 | your projects. But what we have seen so far
will be enough to help us get going, because
| | 11:22 | some of these options really aren't worth
bothering with, until we have got a bit more code.
| | 11:27 |
| | Collapse this transcript |
| Updates to this course| 00:00 | I originally recorded this Objective-C
Essential Training course in March
| | 00:03 | 2011, right when Xcode 4.0 was released. Now
since then Apple have made a few point releases
| | 00:10 | to Xcode, usually to coincide with
a new Mac or iOS operating system.
| | 00:15 | Those changes aren't big enough to require
an entirely new course, but right now mid
| | 00:20 | 2012, I'm recording a few updates and
additions to the course to include these new features.
| | 00:26 | What that means is you will see me using two
versions of Xcode during this course.
| | 00:30 | Xcode 4.0 from the original recording and Xcode 4.3
when I want to point out a new feature
| | 00:36 | or a significant change.
| | 00:37 | Now for the most part everything is exactly
the same because we're really focused here
| | 00:42 | on the essentials of the Objective-C
language rather than on Xcode itself, but there is
| | 00:47 | one main difference you're likely to see.
| | 00:49 | In some movies from this point on, you'll
see me working with projects created in Xcode
| | 00:53 | 4.0, and there will be some automatically generated code,
it looks like this, using the word NSAutoreleasePool.
| | 01:01 | Now, however, if I created that same project
in a more recent version of Xcode like 4.3
| | 01:07 | as I did a moment ago you'll see generated code that
looks like this, using the @autoreleasepool keyword instead.
| | 01:13 | Now in fact, there are actually two lines
that are different here. In Xcode 4.0, we
| | 01:18 | have that NSAutoreleasePool, and we also have
the words pool drain in square brackets right
| | 01:24 | before the line that says return.
| | 01:27 | In later versions of Xcode you would see the
@autoreleasepool keyword with an opening brace.
| | 01:34 | And instead of the words pool drain, you
would see the closing brace right before the word return.
| | 01:40 | The new way is a little simpler to
read, a bit more concise. Don't worry too much
| | 01:45 | about what exactly these lines mean, just
realize that you will see both ways in this course.
| | 01:50 | There are a few reasons why I didn't want
to rerecord every movie with a new way and
| | 01:54 | pretend the old way never existed. Well
reason number one is that these lines are
| | 02:00 | not the lines we care about. This code is
generated. We don't write it, and we don't
| | 02:05 | need to touch it. Everything that you're going
to be doing is here. Xcode even tells us where
| | 02:10 | to put our own code, and that's whether that's
using the old versions like I'm seeing here
| | 02:15 | or the new versions, the code we're interested
in is exactly the same, and more importantly
| | 02:21 | the older way still works
and it was used for years.
| | 02:24 | So, if you're going to continue with Objective-C,
you'll be reading code on websites and in
| | 02:28 | books, and you're going to see it the new
way and the old way, so you might as well get
| | 02:32 | familiar with seeing it. But the main
change that Apple made, since I originally recorded
| | 02:38 | this course, is with a feature called ARC or Automatic
Reference Counting, first made available with Xcode 4.2.
| | 02:47 | ARC is a good thing. It's a great addition
that makes working with Objective-C much easier
| | 02:52 | than it used to be, particularly for people new
to the language. I'm going to cover Automatic
| | 02:57 | Reference Counting later in the course when
it's most relevant, and there will also be
| | 03:01 | a couple of places where I'll point out
another new feature or best practice.
| | 03:05 | As I have mentioned, and, as you can see, from
this timeline, Xcode changes quite frequently,
| | 03:10 | and part of being an Apple Developer is
keeping abreast of those changes made to it and to
| | 03:15 | the various parts of the Apple developer
world, and that might sometimes sound like a pain,
| | 03:19 | but note that Apple don't tend to add new
features just for the sake of it.
| | 03:23 | When Apple change things they usually get easier. And
that's definitely been the case since the
| | 03:27 | course was first recorded
as we'll see shortly.
| | 03:37 |
| | Collapse this transcript |
|
|
2. Objective-C BasicsThe Objective-C language| 00:00 | So why Objective-C anyway?
| | 00:02 | Why not something more widespread
like Java or something more modern and
| | 00:05 | fashionable like Ruby or Python?
| | 00:07 | Well it's as much history as anything else.
| | 00:10 | Go back 40 years we get the C
programming language, enormously popular and
| | 00:16 | influential. A lot of languages
today owe their existence or at least
| | 00:19 | their appearance on C.
| | 00:21 | But fast-forward a few years into the
early 80s you had Smalltalk, the first real
| | 00:26 | object oriented language and people
thought an object-oriented version of C
| | 00:30 | would be a great idea.
| | 00:31 | Now some ways of doing this
were creating languages like C++ and
| | 00:36 | spawning off a new language with
these ideas, and other ways such as in
| | 00:40 | Objective-C we took some ideas from
Smalltalk and baked it into C, and that's
| | 00:45 | an important distinction.
| | 00:47 | There are languages like C++, Java, and
C#, which are all C-based object oriented
| | 00:53 | languages, but they were all
designed from the ground up as their own
| | 00:57 | independent language.
| | 00:58 | They have their own identity, they have
their own rules, their own lifetime, but
| | 01:03 | Objective-C was not designed from
the ground up as a new language.
| | 01:08 | It is simply the C programming languages
with stuff added to it, packed on top of it.
| | 01:14 | It's what's often referred to as a
strict superset of C. I could copy and paste
| | 01:19 | a bunch of C from the 1970s into
Xcode today and expect it to compile.
| | 01:24 | I couldn't do that with Java or C#.
| | 01:26 | Now why is that important?
| | 01:29 | Well, if you are going to have a new
language that's combined with an older
| | 01:32 | one, how do you indicate which parts
are old school C and which parts are the
| | 01:36 | new Objective-C parts?
| | 01:38 | If you're a C programmer, you could read
some code like this and it would strike
| | 01:42 | you as very strange.
| | 01:43 | Some of it would look very
natural; other parts wouldn't.
| | 01:46 | That's because we're going to give the
compiler some clues by marking these pieces.
| | 01:50 | You'll see a lot of square brackets used
in Objective-C, because these are added
| | 01:55 | Objective-C ways of doing things.
| | 01:58 | You'll see a lot of @ signs in
Objective-C, because we're indicating
| | 02:02 | the compiler that this isn't just regular C;
this is the new stuff. This is Objective-C.
| | 02:07 | You'll see the letters NS being used in
front of a lot of terms in Objective-C.
| | 02:12 | There are other words we'll run into.
@interface, @implementation, @property,
| | 02:17 | @synthesize, all telling the
compiler we want to do things that aren't
| | 02:21 | allowed in regular C.
| | 02:23 | And those two letters NS will
permeate everything we do in
| | 02:27 | Objective-C development.
| | 02:29 | Okay, but that doesn't
explain why we use it now.
| | 02:31 | Well in the 80s Objective-C was adopted
as the main language of the company NeXT
| | 02:36 | Computer, which Steve Jobs
founded after he left Apple in 85.
| | 02:40 | And they built everything including their
NeXTSTEP operating system on Objective-C.
| | 02:45 | That was first released in 89, and in 96
Apple bought NeXT and they roll over to
| | 02:50 | the NeXTSTEP operating system into
what would become Mac OS X in 2001.
| | 02:55 | And that's why we have this history,
and we use that NS term all the time,
| | 03:00 | because NS comes from NeXTSTEP.
| | 03:02 | The last version of NeXTSTEP, which was out
in 95. So Mac OS X is built on Objective-C.
| | 03:08 | The iPhone which came out in 2007,
it's operating system is built on Mac OS X.
| | 03:13 | In 2007 too, we had a new version of
the language, Objective-C 2.0, that had some
| | 03:18 | more modern features.
| | 03:20 | As we go forward we've got the current
OS that I'm using in this course,
| | 03:23 | Snow Leopard 10.6 released in 2009.
| | 03:26 | We have the iPad released in
2010, also built on this history.
| | 03:31 | And in 2011 right now Xcode 4, the
iPad 2, and OS 10.7, Lion, which will be
| | 03:37 | out during the summer.
| | 03:38 | You see, Objective-C is not some arbitrary
choice. It's a historical necessity.
| | 03:43 | Mac OS X is built on over 20 years of
layers of Objective-C history and the
| | 03:49 | iPhone OS or iOS is built on top of that.
| | 03:52 | You can't pull Objective-C from this
picture. It's woven through it at every level.
| | 03:57 | So yes, although the @ signs and the
square brackets can look a little strange
| | 04:01 | when you're coming from a pure C-based
language, hopefully now you know there is
| | 04:06 | a reason that they look that way and
there is a reason that this is what we're
| | 04:09 | going to forward with.
| | Collapse this transcript |
| The structure of an Objective-C program| 00:00 | Let's take a look at the
structure of a basic Objective-C program.
| | 00:04 | Opening up Xcode I'm going to make a new
project. I could also do this from the File menu.
| | 00:09 | And again the best choice for just
concentrating on the language is to make a
| | 00:13 | command line tool. Selecting Application under
Mac OS X, not under iOS, and Command Line Tool.
| | 00:20 | And then one you want is a Yype
of Foundation, not Core Foundation.
| | 00:23 | And just give it a name. I'll choose
Structure. Click Next and choose a place
| | 00:28 | to save it. I'll choose my Documents folder and
I'm leaving the Source Control box unchecked.
| | 00:33 | It jumps us into the rather
intimidating looking settings screen, but I can
| | 00:38 | ignore this. I don't need
to touch this right now.
| | 00:40 | What I'm interested over here on the
left-hand side in the project navigator is
| | 00:45 | the file called main.m. Our Objective-
C is stored in files that end in .m and
| | 00:50 | we've got only got one in this project.
| | 00:52 | Let's take it line by line.
| | 00:53 | Well, the first section all in green
are just comments. Objective-C being C
| | 00:58 | has C style comments. They begin with
two forward slashes and then you just
| | 01:02 | write whatever you want.
| | 01:03 | The first important line is this one
that says #import. This is pointing to the
| | 01:10 | Foundation framework header file.
| | 01:12 | Now what does that mean?
| | 01:14 | It simply means we're telling the
compiler that the code I'm about to write can
| | 01:18 | use the Foundation
framework and anything inside of it.
| | 01:21 | What that gives us is a little over
a hundred really useful files for working with
| | 01:27 | strings, and dates, and arrays, and
other types of collections. That will come in
| | 01:32 | very handy later on.
| | 01:34 | Officially, it's not part of the language.
| | 01:36 | It's little add-on, but it's an
add-on we're going to use in every single
| | 01:41 | project we write, whether it's
command line, desktop, or iPhone.
| | 01:44 | If you're coming from a C background,
the #import is like #include except this is
| | 01:50 | a little more error proof.
| | 01:52 | The next line on line 11 that
begins int main is the most important.
| | 01:56 | As in C, Java, C#, C++, to run an
Objective-C program that could be thousands
| | 02:02 | of lines across dozens or hundreds of
files of Objective-C, well it needs to
| | 02:06 | know where to start.
| | 02:08 | And Objective-C expects that somewhere
in your code there is one block of code
| | 02:13 | called main and this is it.
| | 02:15 | If you're new to C-based languages,
there might seem to be a lot going on here
| | 02:19 | after the parentheses, but most of it
we can pretty much ignore right now.
| | 02:23 | We're moving on. The braces on line 12.
| | 02:27 | These can puzzle people who are new
to C-based languages and they really
| | 02:30 | shouldn't. They have no meaning. They just
say where something begins and where it ends.
| | 02:35 | They just surround a block of code.
They're often referred to a statement blocks.
| | 02:39 | If you have an opening one, you must
have a closing one. They must pair up.
| | 02:44 | In fact by mousing over to this section
called the gutter on the left-hand side,
| | 02:49 | Xcode will actually highlight where
this one opens and where it closes.
| | 02:53 | Sure, it's pretty obvious right now,
but later when you have large amounts of
| | 02:56 | nested code this can be quite useful.
| | 02:59 | So main begins where the curly braces open.
| | 03:02 | It finishes where the curly braces
end and all the code we're going to
| | 03:06 | execute is between the two.
| | 03:08 | Do have a notice that main is written in
lowercase. Objective-C is case sensitive.
| | 03:13 | Let me say that again. Objective-C is
case sensitive! And if you are coming from
| | 03:18 | a case insensitive language you may
want to remind yourself of that on a
| | 03:22 | regular basis, or you will be reminded
regularly with a string of cryptic error
| | 03:27 | messages,that you'll spend much of
your life trying to figure out before you
| | 03:30 | realize you had a lowercase S where you
should have had an uppercase S or vice versa.
| | 03:34 | Now you shouldn't ever actually need
to write main yourself. It will be there
| | 03:38 | for you in any project you make an
Xcode, even when you write iPhone, iPad,
| | 03:42 | desktop applications. Your app will
start by looking for a block of code called
| | 03:47 | main that kicks everything off and
if it doesn't find it, it will crash.
| | 03:51 | So, moving into the block of main,
the first line of code that actually does
| | 03:55 | something as this one that
begins with NSAutoreleasePool.
| | 03:59 | This has to do with memory management and
we'll explore this quite a bit later on
| | 04:03 | for now we can just let it pass,
including the square brackets and what they do.
| | 04:07 | We hit another comment, and
then we have our output message.
| | 04:11 | Again NSLog is the equivalent of
printf or system.out.print line in Java or
| | 04:16 | console.write line in C#.
| | 04:17 | Now Objective-C is a
whitespace insensitive language.
| | 04:22 | What that means is if we want to split
lines of code onto multiple lines, we can
| | 04:27 | do that without worrying about it.
| | 04:29 | If I had a longer line like this one
at the top, I could just hit Return and
| | 04:33 | spread it to two lines if I
thought that I made it more readable.
| | 04:36 | Now obviously, you can put spaces in
the middle of words. You can put space in
| | 04:41 | the middle of operators.
| | 04:42 | In fact, the only place it's kind of
sensitive about them is within a string
| | 04:47 | within a block of text surrounded by
double quotes, just because there is a
| | 04:50 | difference between the words
Hello World and Hello, space space space, World.
| | 04:55 | The rest of the time it doesn't care.
| | 04:58 | So we output the message and then we
move on. Again with the square brackets
| | 05:02 | around pool and drain. We'll come
back to both memory management and square
| | 05:07 | brackets, which is what we're dealing with here.
| | 05:09 | And then finally, on line 21, return 0.
| | 05:13 | This is the last line of main and it's
effectively saying main was successful.
| | 05:18 | We end with the closing curly brace.
Our code is done, our program is finished.
| | 05:23 | But even in this simple code, we're
seeing these letters NS pop up allover the place.
| | 05:29 | Now these NS lines are actually
part on this Foundation framework.
| | 05:33 | Technically, they're not part of the
Objective-C language. They're extra pieces
| | 05:38 | that we're linking to.
| | 05:39 | But they're extra pieces that because
we link to the Foundation framework
| | 05:43 | we will have available in every single
line of code that we write. But this is the
| | 05:48 | entire structure of a basic Objective-C program.
| | 05:51 | But surely what about when it gets more complex?
| | 05:53 | Well, we could type 5000 lines of
code in-between the opening and closing
| | 05:58 | curly braces of main, but more likely we'll
split up our project into multiple code files.
| | 06:05 | However, we will always begin in main
and from main, we'll call into other parts
| | 06:11 | of our project, but we'll see that later on.
| | Collapse this transcript |
| Compiling and running your code| 00:00 | Objective-C is a language that
must be compiled before you run it.
| | 00:04 | Here are a couple of things you should
know about this and a couple tips and
| | 00:07 | tricks to make your life a little easier.
| | 00:09 | Now, the term we used to tackle our
Objective-C in a project, compile it, link
| | 00:14 | everything together with any frameworks
you're using, and end up with something
| | 00:18 | you can run on actual executable
program, and the term we use is Build.
| | 00:23 | When you run your program just by
clicking the Run button, if I hover over this,
| | 00:27 | I will see that really what's
happening is Build and then run.
| | 00:31 | We can also go to the
Product menu and just say Build.
| | 00:35 | It gives me a Build Succeeded or I can
use Command+B as the shortcut to build this.
| | 00:41 | Xcode doesn't actually
do the compilation itself.
| | 00:44 | It uses something in the background
called the LLVM Compiler to do it and feeds
| | 00:49 | it all your Objective-C,
but it manages that process.
| | 00:52 | If our only feedback here is Build
Succeeded, well it goes away and maybe I
| | 00:57 | want a bit more information. Well, I can get that.
| | 01:00 | If I come over to the Navigator on the
left hand side, and you have probably
| | 01:05 | seen there is a lot of little icons
along the top. There's seven of them.
| | 01:08 | We can click this one that looks like a
speech bubble on the far right-hand side
| | 01:12 | of the Navigator and this is the Log Navigator.
| | 01:15 | These are the log messages from our
project and they show all the builds and
| | 01:19 | runs of this project, the
most recent is at the top.
| | 01:22 | If I select this one, it says the
build succeeded. There were no issues.
| | 01:26 | Although this Navigator does have seven
different icons and feel free to explore them,
| | 01:32 | early on your most important parts
of the Navigator will be the first
| | 01:36 | button that shows the files in our project and
this last button that shows the log messages.
| | 01:41 | After that, you'll probably find that
the most important one will be this middle one,
| | 01:46 | the exclamation mark.
It represents issues with your project.
| | 01:50 | And the big issue of course is what
happens when you make a mistake with your code?
| | 01:55 | And notice that I say when you
make a mistake, not if you make a mistake.
| | 02:00 | Well, let's go back and run this again.
| | 02:03 | Before I do, I'm going to make a
mistake here and remove the closing double
| | 02:07 | quote and then click the Run button.
| | 02:11 | It says Build Failed and
highlights the line here.
| | 02:14 | Our program does not run
because there are build errors.
| | 02:19 | That highlights the line, but
depending on if I have a lot of code, that line
| | 02:23 | might be somewhere else off screen or
in another file and I might not see it.
| | 02:27 | Well, the top window also tells me
that there were issues here and if I
| | 02:32 | come over to the exclamation mark,
I can actually see what's called the
| | 02:36 | Issue Navigator that says there were
problems here. A missing terminating closing quote.
| | 02:42 | So, there are issues. A variety
of different ways to see them.
| | 02:46 | Now, sometimes but not always, Xcode
will make a guess as to what the problem is
| | 02:53 | and it's often worth clicking the icon
that you'll see in the gutter here as it
| | 02:57 | might suggest a fix.
| | 02:59 | This is called the fix-
it functionality of Xcode.
| | 03:01 | You won't always have a suggestion.
| | 03:03 | Sometimes Xcode has no idea
what you're trying to do there.
| | 03:07 | So, I'm going to fix that just by
adding that double quote back in and then
| | 03:12 | I will notice even before I actually do
an official build that that icon goes away.
| | 03:18 | In Xcode 4, you don't even need
to wait until you do a full build.
| | 03:22 | This fix-it functionality will check
your code as you type, showing you any
| | 03:25 | issues it's coming up with.
| | 03:27 | Sometimes that can get a little
annoying because if you're typing slowly for
| | 03:31 | example, it might flag a line before
you've even had the chance to finish it, as
| | 03:36 | it's just on here. But I'm going to
add something and finish this one off.
| | 03:40 | And what it's doing now is instead of
the red exclamation mark, I get a yellow
| | 03:44 | exclamation mark, which is a warning.
| | 03:47 | Technically, this is not as bad an error.
| | 03:49 | If I click the Run button, it will
go ahead and run the application.
| | 03:53 | I even get my Hello, World
message coming out there.
| | 03:55 | I will just make that debug area go
away, but I still have a warning that's
| | 04:00 | showing up on this line here.
| | 04:02 | It's showing up at the top with the
exclamation mark and it's showing over here
| | 04:06 | in the Issue Navigator.
| | 04:08 | Again, I can also see it in the Log
Mavigator for the most recent build where
| | 04:13 | the build succeeded but there was one warning.
| | 04:16 | Clicking that in the Issue Navigator,
we jump to that line and the warning is
| | 04:21 | in this case that this variable was unused.
| | 04:24 | I've created something
called X. I didn't use it.
| | 04:27 | But let me be plain. Even though this is a
warning, you should never ignore a warning.
| | 04:32 | I lose count of developers,
particularly new ones, who think that the only thing
| | 04:36 | worth paying attention to are errors
and the warnings are somehow optional.
| | 04:40 | It really is detected that even though
this code might be correct in syntax,
| | 04:45 | something weird is going on and I
have probably made a logical mistake.
| | 04:48 | So, never ignore a warning, particularly in
simple code like we are going to do in this course.
| | 04:53 | You should have no issues at all.
| | 04:55 | If you're following along and you have
a warning and I don't, there's a problem
| | 04:59 | with your code that needs to be fixed.
| | 05:01 | Now, what you might find useful is a
preference change or at least something
| | 05:05 | worth taking a look at.
| | 05:06 | I am going to open up the preferences
of Xcode and the second section along the
| | 05:12 | top is something called Behaviors and
this drives what happens in Xcode under
| | 05:17 | these events, such as when a build
starts, when a build fails, when a build
| | 05:21 | succeeds, when a build generates new issue,
which is a very useful one. We can check.
| | 05:27 | Well, when it generates a new issue,
should I show the Navigator? Yes. Which part?
| | 05:33 | Well, let's go to the Issue
Navigator that's the default.
| | 05:35 | That's a useful one.
| | 05:36 | You could even make it play a sound or
even speak an announcement using one of
| | 05:40 | the built-in voices.
| | 05:41 | If you select this, every
time Xcode detects a new issue
| | 05:46 | it will make this announcement.
Build has generated issues.
| | 05:49 | Now, bear in mind, I am selecting this
for Build generates new issue, so if you
| | 05:54 | get a warning, it will tell you the
first time and if you then continue to
| | 05:58 | compile, it won't speak a message
because it will not be considered a new issue.
| | 06:03 | It's presuming you just want to ignore it.
| | 06:05 | Not a good idea but you could.
| | 06:07 | So, there are two more things
that I am going to talk about.
| | 06:09 | Now, these last two are not really
drastically important right now but you
| | 06:13 | might have seen them and you
might be wondering about them.
| | 06:17 | First off, at the top of the toolbar is
this dropdown box. This is what's known
| | 06:22 | as the scheme and it affects
how your project is built and run.
| | 06:25 | In this case, it's giving us the option
for compiling 64-bit versus compiling 32-bit.
| | 06:32 | If I was creating an iOS project for
an iPhone or iPad, this dropdown would
| | 06:36 | give me the option of running on a
simulator or running on a device that I
| | 06:41 | might have plugged into my machine.
| | 06:43 | So, by using schemes, Xcode supports
multiple ways to build and run your application.
| | 06:50 | Now one last thing on compiling.
| | 06:52 | That screen you first saw
when you first created a project.
| | 06:55 | Now, to get back to it, I am going to
go to the file section of my Navigator,
| | 06:59 | what's called the Project Navigator.
| | 07:01 | Highlight the project icon itself and
we get this screen here with a lot of
| | 07:05 | different settings on it.
| | 07:06 | A lot of these settings are to do with
compiling and building our application
| | 07:11 | and most of it is fairly specialized
technical options that you can safely
| | 07:15 | ignore, although there are a couple of
things that you will be able to do later on here.
| | 07:21 | One is what's known as the Base SDK,
which is what am I compiling this against.
| | 07:27 | In fact if I take a look at the Build
settings, I see that I have got a Base SDK
| | 07:32 | that says what version of the
Macintosh OS am I compiling against.
| | 07:37 | I am on Snow leopard, so I am seeing
10.6, the latest version and you typically
| | 07:43 | want to build with the latest version
of the SDK that you have as a developer.
| | 07:47 | But what you'll find is you also have
something called a Deployment Target and
| | 07:53 | that's what OS do I need my users
to have, because you might have an
| | 07:57 | up-to-the-minute system but want to
allow your users to go back to say 10.4 of
| | 08:02 | Mac OS or 4.0 of IOS if
you're building an iPhone project.
| | 08:07 | That can be done here too and in
fact because these are some of the most
| | 08:12 | common things you'll select, you'll
often find them being targeted here on the
| | 08:16 | Info section, which is kind of a cut-down version
of all the different settings that you can pick.
| | 08:21 | Now, in this course, we are going to be
using the default scheme pretty much all
| | 08:25 | the time and I am not going to be
worrying about different deployment targets,
| | 08:30 | because all the code we are going to
write will be as general as possible to
| | 08:35 | really learn the language.
| | Collapse this transcript |
|
|
3. Program FlowLogging messages to the command line| 00:00 | I get it. You're bored with Hello,
World, I'm bored with Hello, World.
| | 00:04 | So, let's get into this language,
variables and operations that will take us
| | 00:08 | into loops and conditions
and data types and scope.
| | 00:12 | Over the next few movies, we will
cover the core language constructs of
| | 00:16 | Objective-C, much of which of course
is based on C. So, if you have spent
| | 00:22 | the last five years living in C and C++,
you're likely to find some of this remedial.
| | 00:27 | Yes, I agree, you know this already.
| | 00:30 | Objective-C did not try to invent
its own way to do an If statement.
| | 00:34 | The one in C was perfectly fine.
| | 00:36 | So, you can jump ahead or I invite you
to sit back can sing along. We all need
| | 00:41 | a recap form time to time.
| | 00:43 | Now, if you are coming from something
that's more C influenced like JavaScript
| | 00:47 | or Action Script, well, then I suggest
you go through all of it because even
| | 00:52 | though there are significant
similarities, it's the little differences that you
| | 00:55 | need to focus on now.
| | 00:57 | The things you take for granted but aren't
true in this language. So let's get to it.
| | 01:02 | So, we're still in the main function
here and of course we are going to start
| | 01:05 | simple and if you wonder where to put
your code, well, Xcode of course does tell
| | 01:09 | you to insert code here.
| | 01:11 | Let me type a few lines and
then I'm going to go through it.
| | 01:17 | So, we have our first variables, our
first calculation and our first slightly
| | 01:21 | interesting output message, but still
probably raising a few questions if you're
| | 01:26 | new to this language, like what's
the @ sign is for and what does the %i mean.
| | 01:31 | So, let's take this one by one.
| | 01:34 | Variables in Objective-C are declared
as in other C based languages: first the
| | 01:39 | type and then the name and then a semi-colon.
| | 01:43 | Optionally, you can give it a value at
the same time that you declare the variable.
| | 01:47 | In Objective-C, we give our variables a type.
| | 01:51 | If you are coming from a language
where the same variable can first be an
| | 01:54 | integer and then a floating point
number and then a string or a button or a
| | 01:58 | block of HTML, it's not the case here.
| | 02:01 | You pick your type when you define the variable.
| | 02:04 | Now, way down the line, there is
something in Objective-C called Dynamic Typing
| | 02:08 | but that's for much more complex
situations and it's not what we do here.
| | 02:12 | So, we begin here by declaring three
variables, one for minutes equal to 60, one for
| | 02:17 | hours, 24 and one for days, 365.
| | 02:20 | These are integer variables, whole
numbers with nothing after the decimal point.
| | 02:25 | We do have other data types for
floating point characters, Booleans, that kind
| | 02:29 | of thing but we will get to those later.
| | 02:32 | As in just about any programming
language I can think of except maybe COBOL,
| | 02:36 | we multiply with an asterisk.
| | 02:39 | So, I'm creating the value of the
fourth variable, minutes in a year, by
| | 02:44 | multiplying minutes asterisk hours
asterisk days and then on this line 23,
| | 02:50 | I spit the value out that there
are so many minutes in a year.
| | 02:54 | So, let's run it and test it.
| | 02:56 | Build Succeeded and apparently
there are 525,600 minutes in a year.
| | 03:02 | So, let's break down that NSLog message
because that might look a little odd to
| | 03:07 | you as well depending on what
language you are coming from.
| | 03:10 | Two things going on here.
| | 03:14 | In Objective-C, strings are represented
not just as some value in between double
| | 03:19 | quotes but double quotes with an @ sign
at the front of them and this @ sign is yet
| | 03:23 | another indicator to the compiler that
this isn't regular C and it harkens back
| | 03:28 | to the days when C didn't really have strings.
| | 03:31 | It just had null-terminated character arrays.
| | 03:33 | It's something that trips up most
programmers coming to Objective-C. At some
| | 03:37 | point you're going to forget the @ before
the double quotes and you'll get an error.
| | 03:42 | That's it.
It's not complicated.
| | 03:44 | It's just something to remember.
| | 03:46 | When you're thinking about a string
literal idea like this, it needs an @ sign
| | 03:50 | before the opening double quote.
| | 03:50 | But we are doing something else with
that string. We are trying to output a
| | 03:55 | message that contains a calculated value.
| | 03:58 | In other languages, you might
create a message by combining or
| | 04:01 | concatenating different pieces.
| | 04:03 | Something like this. A string with
There are and then a variable minutes and
| | 04:07 | then another string with in a year;
you might use plus signs of ampersands.
| | 04:11 | But that's not what we do here in Objective-C.
| | 04:14 | Instead we create our message and we
put a placeholder in the middle of it.
| | 04:20 | It's within the string itself.
| | 04:22 | In this case, it's this %i. Now,
placeholders always begin with a percent sign
| | 04:28 | and then we are telling Objective-C
what kind of data is going to go here.
| | 04:32 | Since it's an integer, so we
follow the percent with an i.
| | 04:36 | And now knows there's going to be an
integer in this message, but which one?
| | 04:40 | We follow the string with a coma and
then the variable that we want to replace
| | 04:45 | the placeholder with.
| | 04:47 | Now, if we had multiple placeholders, it
expects multiple variables. So if I had
| | 04:52 | two placeholders in my message, there
are so many minutes in a so many a day year,
| | 04:58 | I'd have two placeholders here and I'd
follow this string with ,minutes,days,
| | 05:05 | the two variables that I would
want to replace those positions.
| | 05:09 | They just go in order. The first
variable after the comma would replace the
| | 05:13 | first placeholder with the %i because
it's an integer and the second one would
| | 05:18 | replace the second %i.
| | 05:19 | Now, as just as there are different
types of variables, there are different
| | 05:23 | placeholder indicators.
| | 05:25 | We have %i for an integer, there %f for a
floating-point variable, %c for single characters.
| | 05:32 | We will see these and more later, but
just for now, just remember that all our
| | 05:36 | placeholders begin with the percent sign.
| | 05:40 | And understanding the use of these what
are called format specifiers in a format
| | 05:45 | string will let us output more useful
messages to the console, because we are
| | 05:50 | always interested in manipulating output.
| | 05:54 | Even when you start to move away from
console apps to writing desktop apps and
| | 05:59 | iPhone apps, you will still be using
NSLog time and time again to write your own
| | 06:04 | messages when developing and testing.
| | Collapse this transcript |
| Writing conditional code| 00:00 | Let's talk about
conditional code and if statements.
| | 00:03 | Now if you have made it through any
programming language without knowing the
| | 00:07 | word if, I'd be very surprised.
| | 00:09 | This is the classic if statement. How do
you make a decision about whether to do
| | 00:13 | one thing or another?
| | 00:14 | Well in Objective-C is written as in
other C-based languages with this format.
| | 00:21 | We use the word if, we open
parentheses that contains our condition, and then
| | 00:27 | between the opening and closing curly
brace, we write our code. We do whatever
| | 00:32 | is between the braces.
| | 00:33 | Now, whatever is inside the parentheses, the
condition itself must evaluate as true or false.
| | 00:40 | So if a is less than 5, if b is greater than 20.
| | 00:44 | We are not really caring by how much b is
greater than 20 but this has to be true or false.
| | 00:52 | We can check equality.
| | 00:54 | We can say have we got a variable
called C and is it equal to the number 99.
| | 00:59 | If you want to check equality in
Objective-C like other C-based languages,
| | 01:03 | it's the double equal sign
and no spaces in between them.
| | 01:07 | A single equal sign after
all is an assignment operation.
| | 01:12 | A single equal sign would
set a value, not check a value.
| | 01:16 | And you will get a warning in Xcode 4
if it detects you may be doing this.
| | 01:21 | In this simple Command Line application,
I'll just create a new variable called
| | 01:25 | C and set it equal to the value of
100 using the single equal sign,
| | 01:30 | the assignment operator to set the value.
| | 01:33 | Xcode is complaining that C is being unused.
| | 01:36 | That's okay. I haven't finished my
code yet. So I am going to write an if
| | 01:39 | statement to which we can
imagine as little later on.
| | 01:42 | Opening the parentheses, I
am going to ask is C=100.
| | 01:45 | I am going to make a mistake
of only using one equal sign.
| | 01:49 | Close my parentheses, I am going to
open the curly brace, hit Return, and it
| | 01:55 | will automatically enter the
closing curly brace, which is nice.
| | 01:58 | It helps me do that.
| | 01:59 | But you can see it's already kind of
complaining about something. It is detecting
| | 02:03 | there is something weird going on.
| | 02:05 | If I click over here to the gutter,
it says I'm using the result of an
| | 02:10 | assignment as a condition without parentheses.
| | 02:12 | Wonderful little phrase there, but
it's suggesting, do you want to turn this
| | 02:16 | assignment into an equality comparison?
| | 02:19 | Yeah, that will be a good idea.
So a nice little reminder here.
| | 02:22 | So I am just going to double-click and
it will say now we would be checking if
| | 02:25 | C is equal to that value. We could do a
simple NSLog message, making sure to get the @ sign.
| | 02:32 | Yes it is. Save that, run it.
| | 02:36 | Not a particularly dramatic application
but the build has succeeded and we can
| | 02:40 | see yes it is, we are hitting that code.
| | 02:43 | There is particularly something to pay
attention to if you're not coming from a
| | 02:47 | C-based language, that double
equal sign for checking equality.
| | 02:51 | What if we are more interested in a
variable not being equal to something?
| | 02:56 | Well, this is the format that we
usually use. We use the exclamation mark equals sign
| | 03:00 | to say in this case, if the variable d
is not equal to 100 then we are going to
| | 03:05 | execute the code inside the braces.
| | 03:07 | Now, quick word about curly braces here.
| | 03:10 | You're likely to see braces being
used in a couple of different styles.
| | 03:14 | They always mean the same thing. They
surround a block of code, whether that's
| | 03:18 | one line or a dozen or hundred, but as
an example with the main method here,
| | 03:23 | I can see that I have the opening curly
brace on its own line and it closes on its
| | 03:29 | own line and they're in the same
position that they match up and again if we
| | 03:32 | hover here, we can see this
statement block being highlighted by Xcode.
| | 03:38 | But you'll also see it this way.
| | 03:39 | If I come down a little bit and move
over, we can see that the if statement
| | 03:44 | block begins and ends here but we've
got the opening curly brace on the same
| | 03:49 | line as the if statement and
then not exactly aligning up.
| | 03:53 | This is also a very common way to see
the opening and closing curly braces,
| | 03:57 | very common for classic C and C++ programmers.
| | 04:01 | Now, people get religious about brace
styles. Objective-C of course doesn't care.
| | 04:06 | These are regarded as insignificant white space.
| | 04:09 | If I put this curly brace on its own
line, it would be fine with it there.
| | 04:13 | It can also be opening
right after the if statement.
| | 04:17 | Technically, if after your if
statement, you just want to execute one line
| | 04:22 | of code such as this case,
I actually don't need to have the opening and
| | 04:26 | closing curly braces.
| | 04:28 | That would actually work just fine.
But I always use opening and closing curly
| | 04:34 | braces after an if statement.
| | 04:36 | I believe that it makes the code more
readable and it makes it less prone to
| | 04:40 | errors in case you come along and add some
lines later. So I am always going to use the braces.
| | 04:46 | What happens if I want to check
multiple conditions to be true?
| | 04:49 | I can do that as well.
| | 04:50 | Let's say we've got a couple of
different variables and I want to check
| | 04:55 | the values of them.
| | 04:57 | So in my if statement, I want my
condition to be if c=100 and d>50.
| | 05:04 | Well, the way that I do an And or a
logical And operator is two ampersands,
| | 05:10 | so if C is equal to 100, && d>50.
| | 05:16 | That's very common of course to
also take these and surround them with
| | 05:21 | parentheses, just to make it a bit more
obvious that these really are their own
| | 05:26 | pieces, their own kind of
sub-conditions in there.
| | 05:29 | But again, the whole thing, the
whole condition must evaluate as true.
| | 05:35 | So if C=100 and d>50, then we should be
writing out that error message, Yes it is.
| | 05:43 | If I wanted to do an or operation,
that's the two vertical bar or pipe symbol.
| | 05:50 | On a US keyboard, it's the
Shift+\ above the Return key.
| | 05:56 | So in this case the whole condition that
evaluates is true would be if C==100 or d>50.
| | 06:03 | We would then write out the message.
| | 06:05 | But what happens if that's not the case?
| | 06:08 | Well after our if statement, we can
follow it with an else statement, which has
| | 06:12 | its own statement block.
| | 06:14 | Of course, the else doesn't need
parentheses because we are not checking a
| | 06:17 | condition. We are just saying if it's
anything other than the condition that was
| | 06:21 | true, we are going to do
something else, so it's otherwise.
| | 06:25 | And we can even decide to nest if
statements inside that, so I could have
| | 06:30 | another if statement nested inside
my else, but of course, if statements
| | 06:34 | themselves will need conditions for all of them.
| | 06:37 | You can of course do this. Don't nest
to deep. Objective-C can handle it quite
| | 06:41 | fine, but lots of nested if statements,
say beyond two or three levels, can be
| | 06:45 | quite difficult to read and to make sense of.
| | 06:47 | So if we do have to have more complex
logic, we will break things apart into
| | 06:52 | their own functions.
| | 06:53 | And as we'll see, if we are checking
the same kind of variables, there are some
| | 06:57 | different ways to write
conditional code that may make more sense.
| | Collapse this transcript |
| The switch statement| 00:00 | It's very common to realize that a lot
of your if statements are checking the
| | 00:04 | same variable or the same
conditions, just multiple values.
| | 00:09 | In this case, for example, we have got
an integer called category = 47 and then
| | 00:14 | I have got an if statement that
checks is it equal to 40. And if isn't, well
| | 00:18 | then is it equal to 41?
| | 00:20 | And if it isn't, well, then is it equal to 42?
| | 00:23 | And it's very easy to create fairly
convoluted and dull-looking if statements
| | 00:29 | that are really just checking the same thing.
| | 00:31 | So, there is another way,
using the switch statement.
| | 00:34 | I am going to delete all that if
statement nested garbage and replace it with
| | 00:40 | something called switch.
| | 00:42 | Now, when we do a switch, we are always
checking or testing the same thing again and again.
| | 00:48 | So, I use the switch and
I say what are we switching on?
| | 00:52 | What expression are we checking?
| | 00:53 | I am going to say in this case, the category.
| | 00:58 | And a switch block kind of looks a
little bit like an if statement here but
| | 01:02 | instead of if, parenthesis, open curly brace,
close brace, we just use the word switch.
| | 01:09 | Within the block, we then have to say what
are the possible values that I'm interested in.
| | 01:14 | And the way that we do that
is by using the keyword case.
| | 01:19 | So, in the case that category
is 40, I want to do one thing.
| | 01:24 | In the case that category is
41, I will do something else.
| | 01:27 | Now, when we use this case
statement, we end it with a colon.
| | 01:31 | Not a semi-colon, but a colon.
| | 01:34 | It's one of the few cases that we would do this.
| | 01:36 | So, I could write in multiple cases,
case 41, case 42, case 43, and so on.
| | 01:44 | Now, I am going to go back and fill
these out a little bit but it makes it a
| | 01:49 | bit more easy to read.
| | 01:51 | So, after the case 40, without the curly braces,
I can just execute the code I want it to do.
| | 01:57 | In this case, let's just do
a simple NSLog message.
| | 02:00 | It's a category 41 or 40.
| | 02:04 | What's very important that you do after
each of your cases, because we are not
| | 02:09 | enclosing these with curly braces,
we have to say now we are done and the way
| | 02:15 | that we do that is by using the keyword break.
| | 02:18 | What break will do will take us from
this case, line 14, and just jump us outside
| | 02:24 | of the closing curly brace.
| | 02:26 | We are done, the case was 40.
| | 02:29 | We execute our code, whether that was one
line such as this case or ten lines, and
| | 02:34 | then we jump out. We are
done with the switch statement.
| | 02:37 | I could take this code and do
something very similar for the next one.
| | 02:44 | And the reason why we use break is
that a switch statement suffers from
| | 02:48 | something called fall through, which
means if we don't break, we will continue
| | 02:52 | to move our way down the statements.
| | 02:55 | I will show you the example here.
| | 02:57 | I'm going to leave individual
statements for the case 42, 43, 44 and then just
| | 03:04 | put a little NSLog message here
that says this is a 42 or 43 or 44.
| | 03:14 | So, in any of these three cases,
we are going to execute the same code.
| | 03:19 | Now finally, while you don't have to do
it, there is one other word we can use
| | 03:25 | called default, and this is found at the
end typically and it's basically saying
| | 03:31 | none of the particular
case statements were true.
| | 03:34 | So, I might write another little NSLog
message and again, being good about it.
| | 03:42 | While break doesn't really make
much of a difference here, it's a good
| | 03:45 | practice to put it in there.
| | 03:46 | So, right now, I'm setting that
equal to 47, so this is the message I
| | 03:51 | would expect to see.
| | 03:52 | Let's run it and see what happens.
| | 03:53 | It says I don't know what it was. Yup!
| | 03:56 | No surprise there.
| | 03:57 | If I change the variable itself to, say,
case 41, we run it again and it will
| | 04:04 | say yes its category 41, and
now I am going to change it to 43.
| | 04:09 | Run it and we should have the more
generic message that's being spat out.
| | 04:14 | One more thing-- I'm going to go
through with this-- is something that's a bit
| | 04:19 | pernicious and can cause quite a bit on
a weird issue with people, which is if I
| | 04:24 | put in another NSLog message
here saying it's a case 42.
| | 04:33 | Now, I'm going to change the value of
this variable to 42. We are going to
| | 04:38 | come into the switch.
| | 04:40 | We are going to check the different
values and this will be the first one that
| | 04:43 | should be regarded as true.
| | 04:46 | So, I will execute it.
| | 04:48 | Click Run and if I take a look at the
message that I get, you can notice here
| | 04:52 | I am actually getting two messages being output.
| | 04:55 | It's case 42 and then it's 42, 43 or 44.
| | 05:00 | The reason for having that is
because I didn't have a break here.
| | 05:05 | So, while we did hit this line and
execute this line, we then fell right
| | 05:10 | through to the next one as well. That
may have been what I wanted, that may not
| | 05:14 | have been what I wanted.
| | 05:16 | And as a general rule, breaks
are really good things to have.
| | 05:20 | You will find, in fact, in other C
based languages like C#, they actually
| | 05:25 | don't allow you to fall through and
so you have to have breaks after them.
| | 05:29 | Otherwise it causes a compile error,
simply because over the years fall through
| | 05:33 | has been the cause of many bugs that
are quite hard to find, because the
| | 05:37 | compiler will never complain about them.
| | 05:39 | Most old-school C programmers become
very conscious of always taking a second
| | 05:43 | look at any switch statement just to
make sure it's got enough breaks in it.
| | 05:47 | But as you can see, because this is
really all working at the same level that
| | 05:51 | becomes a very scannable, very
readable way of checking multiple values for
| | 05:56 | the same condition.
| | Collapse this transcript |
| Code snippets| 00:00 | If you're new to C-based languages
and not yet confident of your braces and
| | 00:04 | parentheses and semicolons all being in the
right place, here's an easy way to see the syntax.
| | 00:09 | We are going to use something that's
baked into Xcode called code snippets.
| | 00:13 | These are part of the utilities section that
will appear on the right-hand side of Xcode.
| | 00:17 | So to bring them up, I am going to
click this third button in the View section
| | 00:22 | that toggles the Utilities panel on and off.
| | 00:25 | And all you will find is down here at
the bottom, we have another section that's
| | 00:29 | broken up into four pieces that gives
us templates, and then if I mouse over the
| | 00:33 | curly braces, we have the Code Snippet library.
| | 00:37 | I am going to drag this up to make it a
bit more viewable here. And there are a
| | 00:41 | whole bunch of built-in code snippets
that Apple has already defined for us,
| | 00:46 | including things like an if
statement or an if else statement.
| | 00:50 | Now, if I mouse over one of those,
it can show me that this is showing an
| | 00:55 | if-else Statement, if condition
statements-if-true, else statements-if-false.
| | 00:59 | So let's say that's what I wanted.
| | 01:01 | I can grab this and just with my
mouse held down just drag it over to the
| | 01:06 | position that I want to have it.
| | 01:07 | Let's say below the NSLog and let go.
| | 01:11 | Now, it drags it in with little
placeholders for the condition that I'm asking for.
| | 01:16 | Now, the whole thing is actually
selected right now as you can see by the blue
| | 01:21 | outlines, so typically the best thing
to do is just press your left cursor key
| | 01:26 | to go right to the start of the If
Statement and then by hitting Tab I can just
| | 01:31 | jump to the condition.
| | 01:33 | So let's say I had a variable called A
and I wanted to see if A was less than 10.
| | 01:37 | I could do that. I could
then hit Tab again, jump down to
| | 01:41 | statements-if-true, I will just put
some simple comment here and hit Tab again
| | 01:47 | put the statements-if-false to some other stuff.
| | 01:50 | It's a very easy way to start to bake that out.
| | 01:53 | Now, you will often find that right now,
at least with Xcode, it kind of messes
| | 01:57 | up the indentation a little bit.
| | 02:00 | So what you can do is grab that whole
if statement, or any block of code,
| | 02:05 | and then you can right-click it or
Ctrl+Click and here in the Structure
| | 02:09 | section you have something called Re-
indent, which you can also use Ctrl+I as
| | 02:15 | a shortcut and what that will do is
bring that into line with the rest of your
| | 02:20 | code with proper indentation levels.
| | 02:22 | Again, it doesn't have to be a code
snippet to use that on. You can do that
| | 02:25 | with any block of code.
| | 02:26 | So if you mess your own code up, you can
just hit Ctrl+I after you have selected
| | 02:31 | it to re-indent everything.
| | 02:33 | Now, right now it's complaining
about the fact that I don't actually have
| | 02:36 | a variable called a, which is fine,
because I just wanted to show that as an example.
| | 02:41 | So we have if-else
statements, we have if statements.
| | 02:44 | If I come down to the bottom to the
little search box here, I could say type in
| | 02:49 | the word switch and it says, yup, we
have got a switch statement as well.
| | 02:52 | I can grab that across and drop that in
and it gives me now the good reminder.
| | 02:57 | Again hitting the left cursor, just go
the start, I can hit Tab and switch on
| | 03:02 | the expression and then just hit Tab
to jump between the different pieces, but
| | 03:07 | it gives me a reminder to break each case
statement and to break the default case statement.
| | 03:13 | Going back over to the Code Snippet
library, I am just going to come down and
| | 03:16 | get rid of the search, the
little thing that I am filtering on.
| | 03:20 | And you might notice that some on the
snippets say C Block, C Inline, C++, Core
| | 03:28 | Data, Objective-C, and some snippets
don't actually have a language. In fact,
| | 03:34 | the switch statement that I use,
doesn't say Objective-C, doesn't say C++,
| | 03:38 | doesn't say C. That's simply because
it doesn't matter at all. Things like a
| | 03:43 | switch statement and if-else statement
are written exactly the same way in C
| | 03:47 | and C++ and Objective-C.
| | 03:49 | Now, after a while of course, you
won't need snippets for simple things like
| | 03:53 | switches and if-else statements but
there are also pretty big code snippets if I
| | 03:58 | come into say the Core Data Fetch
with a Predicate, which right now I would
| | 04:03 | fully expect you to have no idea what
that meant. But if I drag that across,
| | 04:07 | we can see that it's adding a whole bunch
of code that would be quite nice not to
| | 04:11 | have to manually type ourselves.
| | 04:13 | Now, I certainly don't need that
right now, so I am just going to hit my
| | 04:16 | Delete key to get rid of it.
| | 04:17 | Now, one of the things you can
actually do is create your own.
| | 04:20 | You can find any piece of code
that you have that you want to save.
| | 04:24 | So, when you're learning Objective-C
and you want to remember certain pieces
| | 04:28 | that you're trying, you can simply
grab it, hit your key, hold down the mouse
| | 04:32 | button, and drag it over
into the Code Snippet library.
| | 04:35 | What it's going to do is give you your
own code snippet here that you can edit
| | 04:41 | and give it a title.
| | 04:42 | I can just call that one Hello World,
not that I really need a snippet for that.
| | 04:46 | I'm just going to leave the rest of it
because we'll come back to code snippets
| | 04:50 | a little later when we are doing some
more advanced code and you'll now find
| | 04:53 | that you have a Hello World code
snippet that you can just come along and drop
| | 04:58 | into any program that you have.
| | 05:00 | So they can be used a lot for just
reminding yourself of syntax while you're
| | 05:04 | learning this language and then as we
get into more advanced pieces of the
| | 05:08 | language, they're certainly great
shortcuts for creating some more complex
| | 05:12 | code that needs to be repeated all the time.
| | Collapse this transcript |
| Operators and expressions| 00:00 | As in any programming language, we spend
much of our time in Objective-C writing
| | 00:04 | expressions, using operations to
calculate, move, add, subtract, or compare, and
| | 00:10 | to perform these operations we need operators.
| | 00:14 | One of the most obvious are probably
the arithmetic operators and we have the
| | 00:17 | usual suspects here: the plus sign for
addition, minus for subtraction, asterisk
| | 00:22 | for multiplication and forward slash
for division, often of course used in
| | 00:26 | conjunction with the assignment operator
or equal sign to evaluate an expression
| | 00:32 | on the right-hand side, in this case,
a+b, and then take that and put it in
| | 00:37 | whatever's on the left-hand side, in
this case a variable called result.
| | 00:41 | You can of course use the same variable
names on either side of the equal sign.
| | 00:46 | In this case, we are saying that we
want to set score to whatever it currently
| | 00:51 | is +10, and this kind of operation is so
common that we have a shorthand for it,
| | 00:56 | which is the plus equals operator
simply to add 10 to the variable score.
| | 01:01 | Now, it makes sense that if we have a
plus equals operator, we also have a minus
| | 01:06 | equals and a multiplication
equals and a division equals.
| | 01:10 | And bear in mind that these
are considered single operators.
| | 01:13 | There is no space between the plus and
the equals or the minus and the equals
| | 01:18 | and son on, but they can be a useful shorthand.
| | 01:21 | Now, as with most languages, there
is operator precedence in Objective-C.
| | 01:26 | Simply speaking that means some of
these operators are treated as more
| | 01:30 | important than others.
| | 01:31 | The classic being that the
multiplication and division are regarded as more
| | 01:36 | important than addition or subtraction.
| | 01:38 | What that means in this example is that
if you simply read the expression left
| | 01:43 | to right, you might think
that 5+5 is 10*10 is 100.
| | 01:49 | So, results should be set equal to 100
but no, of course, the multiplication is
| | 01:54 | regarded as more important.
| | 01:55 | So, we would first do the 5*10 as 50
then we would add 5 to it and the result
| | 02:01 | would actually be 55.
| | 02:03 | If instead, I want to impose my own
order on how this is evaluated, I simply
| | 02:09 | take the important pieces and
surround them with parentheses.
| | 02:13 | In this case, I want to say that
(5+5) needs to be evaluated by itself.
| | 02:18 | That will impose our own order on it.
| | 02:20 | We will have 10*10 and the result will be 100.
| | 02:24 | So, the parentheses not only used to
make these expressions more readable, but
| | 02:28 | to impose our own order on operator precedence.
| | 02:32 | Moving on we have comparison
operators via quality check.
| | 02:36 | Again, if we are asking a question,
if we're checking that one thing is equal to
| | 02:41 | something else, we are using two equal signs.
| | 02:44 | Two equal signs is when you're asking,
one equal sign is when you're telling.
| | 02:49 | If we want to know if something is
not equal to, we have got the inequality
| | 02:53 | operator, which is the
exclamation mark equal sign.
| | 02:56 | Again, both of these are
regarded as single operators.
| | 02:59 | They cannot have a space between them.
| | 03:02 | While we are talking about comparisons,
we also have the greater than sign,
| | 03:05 | we have the less than, we have greater
than or equal to or less than or equal to.
| | 03:10 | All of these operators will perform
these actions and simply return a true or
| | 03:15 | false or a yes or no, positive or negative,
whatever way you want to think about it.
| | 03:19 | Well, if we are interested in
conditions, oftentimes we will have multiple
| | 03:23 | conditions where we'll use
the logical And and logical Or.
| | 03:27 | In this case, I have got an if statement.
| | 03:28 | I want to save if a = b and c = d, then
I am going to perform some code, so we
| | 03:35 | will use the two ampersands for the logical And.
| | 03:39 | For the logical Or where either of
these can be true to succeed, we are
| | 03:43 | using the logical Or.
| | 03:44 | It's the two vertical bars or pipe symbols.
| | 03:47 | Again, these are single operators.
| | 03:48 | There is no space in between
the ampersands or the pipes.
| | 03:52 | Complex statements like this are often
spread on to either multiple lines or
| | 03:57 | surrounded with parentheses.
| | 03:59 | Again, this makes it easier to read and
it's one of the benefits of white space
| | 04:03 | being insignificant here.
| | 04:05 | Now, a couple more operators to cover.
| | 04:07 | One is called the modulus operator.
| | 04:09 | It really just looks like the percent sign.
| | 04:11 | I still run into a few folks
that haven't used this one.
| | 04:14 | This is used to calculate a remainder.
| | 04:16 | Let's say we have an integer
variable called year set equal to 2003.
| | 04:19 | I am going to create another integer variable
called remainder and set it equal to year % 4.
| | 04:27 | What this does is, it divides the
variable year, the value of 2003 by 4 and then
| | 04:32 | gives us the remainder.
| | 04:33 | It doesn't give us the result.
| | 04:35 | If I just use the forward
slash, the result would be 500.
| | 04:39 | If I use the percent sign, we throw away
the 500 and say well, we got a remainder of 3.
| | 04:45 | The modulus operator only works on integers.
| | 04:48 | The classic example of using this is to
calculate leap years or calculate odd or even numbers.
| | 04:54 | Next up, we have the ability to increment or
decrement and we have kind of done this already.
| | 04:59 | We have already seen that we have the plus sign.
| | 05:02 | We could say a=a+1. We are
incrementing the variable a. And we have even seen
| | 05:08 | there is a shorthand for this plus
equals but we have even more of a shorthand,
| | 05:12 | which is just plus plus.
| | 05:15 | a++ is regarded as a unary operator.
| | 05:18 | What that means is it just
needs one thing to work on.
| | 05:21 | all the other operators we have
talked about so far are binary operators.
| | 05:25 | They need to things to work on.
| | 05:27 | We can write this as a++ or ++a. If I
was writing them on their own lines,just
| | 05:34 | like this, they'd both do exactly the
same thing. They are adding 1 to a.
| | 05:38 | That makes sense that if we have got
increment operators for plus plus, we also
| | 05:43 | have the ability to decrement.
| | 05:44 | Yes, we could do it by saying a=a-1 or
a-=1 but we have the shorthand a-- or --a.
| | 05:55 | Again, on their own lines like this,
they would do exactly the same thing.
| | 05:59 | They are just simply going to subtract 1 from a.
| | 06:03 | The question might be well, why do
they have two different versions?
| | 06:06 | Why do they have the minus minus
before and the minus minus after or the plus
| | 06:10 | plus before and the plus plus after?
| | 06:12 | And if you want to get geeky about this, this
is known as the prefix and postfix operators.
| | 06:18 | And there is a little tricky impact
to them because there's a difference if
| | 06:22 | these are used embedded in another statement
say in an if statement or an NSLog message.
| | 06:28 | Let me explain the difference here.
| | 06:30 | Let's say we set up by creating an
integer variable called a, set it equal to 5.
| | 06:34 | That's going to carve about 4 bytes of
space in memory and put the value 5 in it.
| | 06:40 | I then write another statement, an
NSLog message that says the value of a is,
| | 06:45 | comma, and we give it ++a.
This is the increment operator.
| | 06:50 | it's the prefix version
that's before the variable name.
| | 06:53 | What happens is when we are running
this program, we hit the NSLog line.
| | 06:58 | It looks at that ++a and it says, ah, I
add 1 to a. So it first adds 1 to a, a
| | 07:04 | becomes 6, and then it executes the rest
of the line and says the value of a is 6.
| | 07:11 | This is the prefix version
of the increment operator.
| | 07:15 | If I back this out, let's go back to
having a = 5 again and instead I use an
| | 07:21 | almost identical line, but I use a ++,
the postfix version of this where the ++
| | 07:27 | is after the variable name,
| | 07:29 | well, what happens is the line will
execute but we will first output the
| | 07:35 | message and only after the line has been
interpreted we will then add 1 to a and a becomes 6.
| | 07:43 | The prefix and postfix versions of
increment and detriment are one of these
| | 07:47 | little things that can cause
bugs that are quite hard to find.
| | 07:51 | So, I tend to only use these
operators by themselves on their own line.
| | 07:56 | Then it really doesn't matter.
| | 07:58 | When we have executed the line of code,
it's either been incremented or decremented.
| | 08:02 | Just be aware that if they are inside a
say an if statement or a statement like
| | 08:06 | this NSLog message, that you might
not get exactly what you expect.
| | 08:11 | And finally, this last one is a great
little useful one called the ternary operator.
| | 08:16 | We have unary operators that work on
one element, binary operators that work on two,
| | 08:21 | and ternary that work on three.
| | 08:24 | So, what happens is the ternary
operator has three parts to it and two symbols,
| | 08:30 | the question mark and the colon.
| | 08:33 | It looks a little strange here but do
bear in mind that this whole operation
| | 08:38 | will result in one single value.
| | 08:41 | This will be evaluated and return some thing.
| | 08:44 | In fact, you can think of the ternary
operator is kind of like a mini if-else statement.
| | 08:49 | Let me show you an example of how this works.
| | 08:52 | Let's say I have written a little
bit of code here to set up a couple of
| | 08:55 | integers somewhere in my program:
playerOne score and a playeTwo score.
| | 09:00 | And we can imagine that these are being
changed and these are being incremented
| | 09:03 | and the values are 400, 500, or 600, who knows.
| | 09:07 | Later on, somewhere in the code I
want to create a new variable called
| | 09:11 | highScore and I want to set it
to whatever the bigger one is.
| | 09:15 | So, I might write an if statement
that says if playerOne is greater than
| | 09:19 | playerTwo, I will set highScore to player one.
Otherwise, I will set highScore to playerTwo.
| | 09:24 | Yup, fairly simple code here but we
are still using 1, 2, 3, 4, 5, 6, 7 lines,
| | 09:31 | not even counting the space,
just to set up a variable value.
| | 09:35 | So, using the ternary operator, I can
kind of compress this all down to one line.
| | 09:40 | What I'm going to do is replace this
highScore declaration and say I want to
| | 09:45 | create a high score and I'm going to use the
ternary operator to immediately set its value.
| | 09:52 | Ternary operator has three parts: the
condition, question mark, what if it's true,
| | 09:57 | colon, what if it's false.
| | 09:59 | So, I am going to grab the condition from
the if statement, so just copy that up there.
| | 10:03 | Condition is playerOne > PlayerTwo,
then I write the question mark.
| | 10:08 | Then I say what is this if it's true?
| | 10:10 | I am just going to return the value of
playerOne, add a colon, and then what will
| | 10:16 | I return if it's false?
| | 10:17 | I will return playerTwo.
| | 10:19 | We end the statement with the semicolon,
and what this actually means is I can
| | 10:24 | get rid of that if statement.
I don't need it anymore.
| | 10:27 | Simply by using that ternary
operator, we really get this mini if-else
| | 10:33 | condition going on.
| | 10:34 | We check the condition. If playerOne
is higher, we will return playerOne;
| | 10:38 | otherwise we'll return playerTwo.
| | 10:40 | Now yes, there are a few
other more esoteric operations.
| | 10:44 | We do have things like bitwise
operators in Objective-C that can work on
| | 10:49 | shifting individual bits around inside a byte.
| | 10:52 | I'm not going to cover
bitwise operators in this course.
| | 10:55 | These days many programmers go
for years without needing to do
| | 10:57 | bitwise arithmetic.
| | 10:59 | If you need them, they are there, go
look them up, but the ones we've just
| | 11:02 | explored should certainly be enough
to get us moving on and building some
| | 11:06 | useful logic in our code.
| | Collapse this transcript |
| Loops| 00:00 | Like writing if statements and
conditional code, you really don't get very far in
| | 00:04 | any programming language
without needing loops or iteration.
| | 00:08 | And the idea is simple.
| | 00:09 | We have a little bit of code, maybe
it's one or two lines, maybe it's a dozen,
| | 00:14 | maybe it's a hundred, and we want to repeat this.
| | 00:17 | Well, we could just copy and paste
it and do it again and do it again.
| | 00:22 | What would be a much better way of doing
it is to be all to take those two lines
| | 00:26 | or a dozen lines, make a block out of
them, and then just say repeat this 5
| | 00:31 | times, or 5000 times, or just keep on
repeating until something changes.
| | 00:37 | Or more generically, process all entries or
process every address in my address book or
| | 00:42 | for each photo in my photo
library perform these actions.
| | 00:47 | Setting up loops in Objective-C is easy.
| | 00:49 | In fact the main issue with any loop
is not when to loop; it's when to stop.
| | 00:53 | So how do we do that?
| | 00:54 | Well, the format is pretty much
identical to working with say an if statement.
| | 00:59 | If take a look at basic if statement
here, we're asking if, then the condition
| | 01:04 | is in the parentheses and then we have
the opening curly brace, our statements,
| | 01:09 | one or a dozen, and our closing curly brace.
| | 01:13 | To change this into a loop I simply
replace the word if with the word while.
| | 01:18 | And this one says while this condition
is true, I will just keep looping around
| | 01:23 | the statement block.
| | 01:25 | So we have a very simple loop here.
| | 01:28 | In fact, we have an infinite loop here.
| | 01:30 | If I run this right now what's going
to happen is we're just going to keep
| | 01:33 | looping around and around and around,
until somebody presses the stop button
| | 01:39 | and kills this program.
| | 01:41 | Because of course, the problem is this
condition on line 12 is always going to be true.
| | 01:47 | a will always be less than 10 unless
something changes a in the body of the loop.
| | 01:53 | That's a very common thing that you'll
see towards the end of a while loop is a
| | 01:57 | line like this, a++.
| | 02:00 | We run this one again and what's going
to happen is we're going to go around
| | 02:04 | from 1 to 9 because when a hits that last ++ and
it becomes 10, the condition is no longer true.
| | 02:13 | So we jump out of the loop and start
continuing from the closing curly brace onwards.
| | 02:19 | This is the most basic
kind of loop in Objective-C.
| | 02:23 | There is a variant of the while
loop called the do while loop.
| | 02:28 | The real difference here is simply
that we move the condition to the end.
| | 02:32 | I could convert this while loop into a
do while by selecting the while part in
| | 02:38 | the condition, cutting that out,
changing it to the word do, and then pasting in
| | 02:44 | the while at the end.
| | 02:45 | Now I do have to add a semicolon to close this.
| | 02:48 | In fact, if I run this now I would get
an identical result to the result I got
| | 02:53 | from just having while.
| | 02:55 | However, the big difference between a
while and a do while is that with a do
| | 03:00 | while this statement block will always be
executed once, even if the condition is false.
| | 03:07 | So in this case if a starts off with a
value of 1000, even though the condition
| | 03:13 | says we do this while a is less than 10,
we're still going to run through an
| | 03:18 | output that message once.
| | 03:20 | That's very different
from just a while statement.
| | 03:23 | Converting this back into while and
get rid of that closing semicolon, we can
| | 03:28 | run it and in fact it will run and
Xcode is detecting there is no output from
| | 03:33 | this program so I am not even
getting the debug area popping up.
| | 03:37 | You'll find that while loops like this one
are much more common than the do while loops.
| | 03:42 | In the code I've written over the
years, I'd guess I would write 100 or 200
| | 03:45 | whiles every do, because in most loop
it is expected to check the condition
| | 03:50 | before you enter the loop, and it's
much more readable to have the condition
| | 03:54 | at the top of the loop rather than at the
bottom, particularly if you've got a lot of code.
| | 03:58 | So while loops are very, very common
and in fact in many loops a pattern
| | 04:04 | emerges, because we start to notice that
we really need to set up this while loop
| | 04:10 | with a counter or an index going into it.
| | 04:13 | In fact, you'll find it very, very common
that an index variable will be set up called i.
| | 04:18 | And then of course, the loop itself
needs a condition that it's going to be
| | 04:22 | checked every time we go around the loop,
every time we iterate, and then within
| | 04:26 | the body of the loop itself, usually
right at the end, is the increment of the
| | 04:31 | index to make sure that we're
keeping track of the right position.
| | 04:35 | In fact, having these three pieces is
so common that there is another statement
| | 04:40 | that brings all these pieces together.
| | 04:42 | It's creating a for loop.
| | 04:44 | Again, it keeps the generic framework
of a while or an if in that it's the
| | 04:49 | word for, then an opening and closing
parentheses, and then an opening and
| | 04:54 | closing curly brace.
| | 04:55 | However, within the parentheses
things look a little different.
| | 04:59 | We actually have three pieces to it, the
same three we needed for the while loop.
| | 05:04 | We set up the index, often
referred to as the initializing phase.
| | 05:08 | In this case create an integer
called i and set it equal to 1.
| | 05:12 | Then we check the condition,
is i less than 10? Yes, it is.
| | 05:15 | We'll go through the loop.
| | 05:17 | At the end of the loop, we'll jump
back up and hit the third part of the
| | 05:22 | statement which is the incrementer.
| | 05:24 | It's very common to have the ++ here,
but you don't have to be incrementing by 1.
| | 05:28 | You could be adding 50 or a
dozen or 107 if that made sense.
| | 05:33 | The big benefit of this is it is very readable.
| | 05:36 | Everything about the loop is
right there, inside these parentheses.
| | 05:40 | We don't have to look outside the loop
for the index being set up nor do we have
| | 05:45 | to scan inside the body of the loop to
make sure the increment is happening.
| | 05:48 | So this is a very common way of
seeing loops written in Objective-C,
| | 05:53 | particularly if they're number based.
| | 05:55 | You want to do something
1000 times or 500 times.
| | 05:58 | Now to wrap this module up, there are
two words that you will occasionally run
| | 06:03 | into when working with loops. Not
all the time, but you'll see them.
| | 06:07 | That's the word break and the word continue.
| | 06:10 | Let's take break first.
| | 06:11 | In fact, we've seen break used before.
| | 06:13 | It was used in a switch statement
and it meant we're done with the switch
| | 06:17 | statement, jump out of the block.
| | 06:19 | And that's really what it means here too.
| | 06:21 | If inside the body of the loop we see
the word break and it's just break by
| | 06:26 | itself, there's nothing else needed, we
will jump right back out to the end of
| | 06:30 | the loop and continue as if
the loop had fully finished.
| | 06:33 | So in this case we're setting up a
loop that should go around 5000 times, but
| | 06:38 | inside the body of the
loop there's an if statement.
| | 06:40 | If i is equal to 101, break.
| | 06:43 | And if we ever hit that line we're
going to jump completely out and say we're
| | 06:47 | done with the loop and move on forward.
| | 06:50 | The other word that you'll see from
time to time is the word called continue.
| | 06:55 | Like the word break' it's just used by
itself, on its own line as its own statement.
| | 07:00 | The big difference between the two is
that break jumps out of the loop and says
| | 07:05 | we are done with this for statement or
this while or this do, where as continue
| | 07:11 | says no, we're just done with this
iteration and jump back up to the top and
| | 07:16 | check the condition again.
| | 07:18 | It might look a little strange here, so let
me show you what the impact of this is.
| | 07:22 | So I've got a very simple for
loop beginning on line 10 here.
| | 07:25 | We're setting up with integer i equal to 1.
| | 07:28 | The condition we're checking is i is less
than 5000, and then the increment is i++.
| | 07:33 | Inside the loop I have a simple if
statement. If i divided by 5 leaves a
| | 07:38 | remainder of 0, I am using the modulus
operator there, then we're using the word continue.
| | 07:44 | What that should mean is every time i is
a number that's cleanly divisible by 5,
| | 07:50 | we're not going to continue
on to line 16 and hit NSLog.
| | 07:53 | We're actually going to jump back to
the start of the loop and go around again.
| | 07:57 | So let's see the impact of this.
| | 07:59 | I run it, it loops around just about
5000 times, but if you scan the numbers
| | 08:05 | what you're going to see is we're going from 1,
2, 3, 4, 6, 7, 8, 9, missing 0, and going to 1.
| | 08:11 | So every time this number is cleanly
divisible by 5, either ending in 5 or 10,
| | 08:17 | we're skipping the NSLog message.
| | 08:20 | Yeah, a very simple example, but
hopefully that should get over the point of
| | 08:23 | continue. continue will
always jump back to the top.
| | 08:29 | It doesn't cause the
initializer to be executed again.
| | 08:32 | We don't reset i to 1, but we
do check the condition again.
| | 08:36 | You won't need break or continue in
most loops, but you will see them from time
| | 08:40 | to time and you need to know what they mean.
| | 08:42 | Now there are a couple of the other
loop types that we get to later in the
| | 08:46 | course when we have a bit more data to
play with, but these three are essential
| | 08:51 | for us to move forward.
| | Collapse this transcript |
| Functions| 00:01 | As we add more code, it will get more
complex to read and understand and as
| | 00:05 | with all languages, we'll break
apart larger amounts of code into smaller
| | 00:09 | modular reusable pieces.
| | 00:12 | Now there's a couple ways to do that in
Objective-C, but right here and right now,
| | 00:15 | that means we're going to create functions.
| | 00:18 | A function is simply a chunk of
related code wrapped up and given a name.
| | 00:23 | Now right now I am looking at
kind of a pseudo code example.
| | 00:26 | So let's see really how
to do this in Objective-C.
| | 00:30 | To create a function, we start off
with the code that we're interested in.
| | 00:34 | Whether that's 1 line, 10 lines, a
dozen, or a hundred, we wrap that in another
| | 00:38 | statement block, the opening and
closing curly brace, and we give it a name.
| | 00:43 | In some other languages, you might need to
actually type the word function or procedure.
| | 00:48 | You don't here. You just give it a name
like createMessage, or saveSettings,
| | 00:53 | or connectToDatabase. It's up to you.
| | 00:56 | You'll commonly see this
written in CamelCase format.
| | 00:59 | If there is multiple words, the
first one will start lowercase, every
| | 01:02 | subsequent one will start uppercase.
| | 01:05 | Objective-C doesn't really care.
| | 01:07 | It's just common practice.
| | 01:08 | So I'll call this something generic
like myFunction, but we're not done yet.
| | 01:13 | We have two more pieces of
information to add, to make this correct.
| | 01:17 | So I am going to give myself a bit more
space before the opening curly brace and
| | 01:21 | put in an opening and closing parentheses.
| | 01:24 | This is where we define any
parameters to this function.
| | 01:28 | When this function is called, do we
pass it in some information, and like what?
| | 01:33 | We'll say we want to call it passing in
an integer because we want it to perform
| | 01:37 | some operation on an integer.
| | 01:39 | Well, we put the type, which is int,
and we give that a name like x or foo or
| | 01:44 | myVariable or myParameter.
| | 01:47 | We use the same naming conventions
as we use for creating variables.
| | 01:52 | If I wanted to pass in multiple ones,
I would give a comma in between them.
| | 01:58 | In this case we're saying we
expect two parameters passed in.
| | 02:01 | We'll call one x, we'll call the other
one y, and those would be the names that
| | 02:05 | you would use to refer to those
values inside the body of the function.
| | 02:08 | Now you don't have to take any
parameters. You can just use the word void
| | 02:14 | instead to say explicitly that this
takes no parameters, or you could just leave
| | 02:20 | that empty and have the
opening and closing parentheses.
| | 02:24 | But even if it is empty you
still need to have those opening and
| | 02:26 | closing parenthesis.
| | 02:27 | I got one more piece to add here, so I
am going to create a bit of room at
| | 02:32 | the start because, before the name of the
function we're going to add the return type.
| | 02:37 | Does this function send something back?
| | 02:40 | And again, like what?
| | 02:41 | Well, let's say we want
to return an integer value.
| | 02:44 | I'll put a return type of int and all
I do here is give it the type. I don't
| | 02:50 | give it a name because that will be up
to whoever is actually taking this value back,
| | 02:54 | but I say do we return
an int or a float or a char?
| | 02:57 | Now if I say that I am going to return
an int, well I better have some code in
| | 03:02 | the body of the function
that actually does that.
| | 03:04 | And typically speaking, in the last
line you'll have something like this:
| | 03:08 | the word return and then well,
what are we returning?
| | 03:11 | I said it's an integer,
so I better return say a 0.
| | 03:14 | That's common for meaning this was successful.
| | 03:17 | If you had a lot more complex code you
might be returning error codes, which are
| | 03:21 | completely up to you.
| | 03:22 | If you wanted to return
99 you could do that too.
| | 03:25 | But as soon as you hit a return
statement, we are done with the function.
| | 03:30 | Now what if I don't want
to actually return anything?
| | 03:33 | What if I just want this function
to write out some messages or save
| | 03:36 | something to a database?
| | 03:37 | Well, I don't have to say int.
| | 03:39 | I can say void and that's how we would
explicitly say this function returns no value.
| | 03:44 | Well, then that better not be returning a 0.
| | 03:46 | So I am going to change that just to the
word return, which you can do for a void
| | 03:51 | function, but actually if it is
void, you don't even need anything.
| | 03:55 | You can allow the function just to get
to the closing curly brace and that will
| | 03:59 | count as the end of the function.
| | 04:02 | So this is the general format
of a function in Objective-C.
| | 04:06 | And we already actually have one.
| | 04:09 | Main is a function.
| | 04:11 | This is the default function
that you have in your program.
| | 04:14 | On line 3 here we're saying that
this is a function called main.
| | 04:17 | It returns an integer and it takes two
arguments here, one an integer called
| | 04:22 | argc and the other which is this
rather odd looking const char and then the little
| | 04:27 | asterisk representing a
pointer and an array here.
| | 04:30 | Now, that looks a little weird.
| | 04:31 | We haven't really gone into that
format yet so you can just ignore it, but we
| | 04:34 | can imagine that this is a main function
that takes two arguments and returns an integer,
| | 04:39 | and if you see on line 18,
that's where we have return 0.
| | 04:44 | main is the only function that
will be called automatically.
| | 04:48 | Every other function, we actually have
to add the code ourselves to call it, but
| | 04:52 | before we call it we need to create it.
| | 04:55 | So what I am going to do is I am going
to take a block of code that I have here
| | 04:58 | from line 10 to line 15 and
make a function out of that.
| | 05:03 | So up here after the #import but before
main and completely outside main, I am
| | 05:08 | going to create a void myFunction.
I'm going to say a simple one here so it returns
| | 05:14 | void and takes no parameters.
| | 05:16 | I have my opening and closing curly braces.
| | 05:19 | And I am going to come down here into
main, grab that code, cut it out, and
| | 05:23 | paste it up here into the body of the function.
| | 05:26 | Well, right now this should compile,
but I am never calling my function.
| | 05:31 | The only thing again that gets
called automatically is main.
| | 05:34 | So where I did originally have that
code I am now going to replace it with a
| | 05:38 | call to myFunction and I can even see
that I am getting the Code Sense, the code
| | 05:42 | completion popping up here.
| | 05:44 | So I'll type in my. I'll
just hit return to accept that.
| | 05:47 | Put the closing semicolon, save it, and run it.
| | 05:53 | Build Succeeded and we get our
little 5000 loops popping out.
| | 05:56 | Function is no very exciting, but
it'll do to prove what's working here.
| | 06:00 | Now what's quite common is that you
don't always want to put all these
| | 06:04 | functions up at the top.
| | 06:06 | So what would happen for example, if I
took this function and cut it from here
| | 06:10 | and then pasted it below main?
| | 06:12 | Well, in some languages it wouldn't really care.
| | 06:15 | But in this one, it does.
| | 06:17 | Build has failed because as the
compiler is moving through it's saying "Well,
| | 06:22 | I got to line 13 which is calling
myFunction" and it's complaining about this.
| | 06:27 | Implicit declaration of function
'myFunction' is invalid in C99.
| | 06:31 | Complex error message there, a
warning, but it really says "I have no idea
| | 06:35 | what myFunction is."
| | 06:37 | Now there's two ways to handle this.
| | 06:39 | one is I just take the definition of the
myFunction function and move it back up
| | 06:43 | to the top, but if I don't want to do
that, if I wanted to keep it a bit tidier,
| | 06:48 | what I could do is just
describe the function up here.
| | 06:52 | And that sounds a little weird if
you've never done that before, but all it
| | 06:55 | means is I would describe what the
signature or the description of the function is.
| | 07:00 | So I would say void myFunction,
open and closed parentheses, semicolon.
| | 07:06 | There is no body of the function here.
| | 07:08 | All I am telling the compiler is
"Hey, by the way there's going to be a
| | 07:12 | function called myFunction.
| | 07:13 | It takes no parameters and returns void.
| | 07:16 | So when you see it being
used, don't worry about it."
| | 07:19 | I still do need to define what that
function is which we have defined now in
| | 07:23 | line 19 down here, but this
would allow this program to compile.
| | 07:28 | The build has succeeded and when we
run it it's going to run just fine.
| | 07:32 | Now doing this is what's
referred to as a function prototype.
| | 07:36 | On line 4 all we have is a description
that the function exists, what it returns,
| | 07:41 | and what it exempts, but nothing in the body.
| | 07:44 | Now on this very simple example like
this it really doesn't matter all that much,
| | 07:48 | but what you'll see is this
ability to have these prototypes to describe
| | 07:53 | the functions and the capabilities that
exist can come in very handy later on.
| | 07:57 | We would use that a lot when we get into
the object oriented side of Objective-C.
| | 08:02 | Now what you'll often find very common is
that you're going to be doing functions this way.
| | 08:07 | You'll be taking code that exists
somewhere else, copying and pasting it there.
| | 08:12 | And that can a get a little tedious so there
is something that can actually help us out.
| | 08:15 | If you'll let me take this back a
little bit into the way it was a few minutes ago,
| | 08:20 | where there was no
separate function, we just had main.
| | 08:24 | Now here's a cool thing that can make it easier.
| | 08:26 | Xcode can help us make those
functions from code that we might have
| | 08:30 | written somewhere else.
| | 08:31 | I am going to select that code and then
I am going to right-click or Ctrl+click it
| | 08:36 | and what you'll find is
this a Refactor option here.
| | 08:40 | This is going to allow us to Extract
that code and create our own function.
| | 08:45 | So I hit Extract and it's going to take
a little look at it and say "Okay, let me
| | 08:49 | try and figure out what you want to do.
| | 08:51 | I presume that what you want to do here
is create a function." extracted_function
| | 08:55 | is kind of an annoying name that would
work, but I am just going to say well, I
| | 09:00 | wanted to call it myFunction.
| | 09:00 | I am going to hit Preview.
| | 09:03 | It's going to tell you exactly what
it's going to do here, that it's going to
| | 09:07 | create a new void myFunction
that takes void. Yeah, looks okay.
| | 09:11 | So I quick Save. It pops up a little message here.
| | 09:14 | The first time I've seen this.
Would I like Xcode to take automatic
| | 09:18 | snapshots before Refactoring?
| | 09:20 | Basically a snapshot is just a
point in time state of your project.
| | 09:25 | You can say Enable.
| | 09:26 | I don't want to get too much stuck with
snapshots right now so I am going to say Disable.
| | 09:30 | There's no big deal there.
| | 09:31 | I am just trying to keep my
setup as simple as possible.
| | 09:35 | And then we see here that
we've got the void myFunction.
| | 09:38 | Xcode added the word void
in this parameter section.
| | 09:42 | I don't have to have that, but
it is okay just to leave it there.
| | 09:45 | And where I had originally had the code,
you see that Xcode has replaced it with
| | 09:49 | a call to that function.
| | 09:51 | It's not indented properly, but that's fine.
| | 09:53 | In fact, I am just going to do highlight
all the code here by hitting Command+A,
| | 09:57 | and then just hit Ctrl+I to do
indentation of it automatically.
| | 10:03 | And as we get even more complex we'll
start managing our project by breaking our
| | 10:08 | code out into completely different
files instead of having them all in one file
| | 10:12 | called main.m, but for now, this will do.
| | Collapse this transcript |
|
|
4. VariablesData types| 00:00 | In all programs we need to keep track
of dozens, hundreds, thousands of pieces
| | 00:04 | of data. Email addresses, the color of
the background, the position of an object
| | 00:08 | on the screen, the amount of
time the program has been running.
| | 00:11 | So we create variables to hold that data.
| | 00:14 | A variable of course is
simply a named container.
| | 00:18 | It's a container that represents a
piece of computer memory set aside for us to
| | 00:22 | use while the program is running.
| | 00:24 | As in real life some of these
containers can be smaller and some of these
| | 00:28 | containers can be bigger.
| | 00:29 | Some containers hold one kind of
substance. Other containers hold the same
| | 00:34 | substance, but less of it or indeed more of it.
| | 00:39 | And other containers well, sometimes
it's a bit more difficult to figure out
| | 00:42 | what these ones hold.
| | 00:43 | You may have to look a little deeper to
figure out what's inside some of them.
| | 00:47 | And this is the same in our program.
| | 00:49 | We have these containers in memory.
| | 00:51 | Some of them will contain integers.
| | 00:53 | these are numbers without a decimal point.
| | 00:55 | Some will contain larger integers.
| | 00:58 | Some will contain numbers with
something after the decimal point.
| | 01:01 | Some will contain characters.
| | 01:03 | And we can create more complex variables
that contain combinations of the above.
| | 01:09 | Now if you're coming from a language
like JavaScript, you may be familiar with
| | 01:13 | creating variables like this where
you can start off by defining a variable
| | 01:17 | called foo and setting it to be a
string and then deciding to change it to a
| | 01:22 | number and then back to a string.
| | 01:24 | This is not something we do in Objective-C.
| | 01:26 | We will type our variables.
| | 01:28 | Now to recap in Objective-C
we define variables like this.
| | 01:33 | Every variable has a type,
| | 01:34 | it has a name and it has a value.
| | 01:37 | The value is the part that can change.
| | 01:39 | It can vary, hence the name variable.
| | 01:41 | So to create a variable called
highScore that can hold an integer, we use
| | 01:45 | the type int or int.
| | 01:48 | This is all lowercase.
| | 01:49 | It's part of the language.
| | 01:51 | Actually it's part of C so it's
automatically part of Objective-C.
| | 01:54 | We'll talk about the other
available types in a moment.
| | 01:57 | Now when it comes to naming our
variables well, we can start off by playing
| | 02:01 | around and creating variables called a,
b, c, or common nonsense words like foo
| | 02:07 | and bar and this is because right
now these names don't mean anything.
| | 02:11 | But in your programs they're going
to represent high scores and account
| | 02:15 | balances, names and dates,
latitude and longitude.
| | 02:19 | So we name them so they make sense later when
we or someone else reads this code in a year.
| | 02:24 | Now every programming language tends
to develop its own style guidelines
| | 02:28 | for naming variables.
| | 02:30 | And we'll talk more about style
guidelines later in the course, but for now in
| | 02:34 | Objective-C this is what we do.
| | 02:36 | We name variables with CamelCase.
| | 02:39 | We begin with a lowercase letter and
if there are any subsequent words, we'll
| | 02:43 | start each one of those with an
uppercase letter like the hump of a camel.
| | 02:48 | Variable names are of course case sensitive.
| | 02:50 | Everything is case sensitive in Objective-C.
| | 02:53 | Don't be afraid of long variable names.
| | 02:56 | Long variable names are quite common
in Objective-C and we have code sense in
| | 03:00 | Xcode that will help us
automatically complete long variable names later.
| | 03:05 | If you're coming from a language
where they use some other standard like
| | 03:09 | prefixing variables with their type
or using underscore between words, know
| | 03:14 | that there is nothing that will stop
you from doing that in Objective-C, but
| | 03:18 | it's not what Apple will do.
| | 03:20 | And that's important because you're
going to need to read Apple documentation
| | 03:24 | and view sample code and
read online discussions.
| | 03:28 | And they're pretty much all going to
do it the way the first four are here.
| | 03:32 | So do jump in, try and name your
variables the Apple way, and it will make
| | 03:36 | it easier when it comes to naming other
parts of our program like methods and classes.
| | 03:42 | So back to that integer. Well, when this program
runs this line it will allocate an area of memory.
| | 03:47 | In this case 4 bytes,
| | 03:49 | an integer is always 4 bytes,
and sets it to this value of 100.
| | 03:55 | And the maximum value of this
highScore variable the way I've written it
| | 03:59 | is about 2 billion.
| | 04:00 | That's the max value of a
regular int variable in Objective-C.
| | 04:04 | There is a bit more to integers,
but we'll see that in a moment.
| | 04:07 | So what other types of data
can we have in our variables?
| | 04:10 | Well, because Objective-C is built on
top of C we have the same primitive data
| | 04:15 | types as the C language.
| | 04:17 | We have int, we have float, we have
double, we have char. int we've seen.
| | 04:24 | float is a floating-point variable.
| | 04:26 | Either a number that's too large,
small, or inexact to be represented as an integer.
| | 04:31 | double is also
for floating-point variables.
| | 04:33 | It simply double the size of a float.
| | 04:36 | And char for single characters.
| | 04:38 | Now officially in Objective-C, we
then have all those same data types.
| | 04:44 | There is also a Boolean data type
and it's written in Objective-C all
| | 04:48 | uppercase as BOOL.
| | 04:50 | Technically it's really a char under
the hood, but we can account it as being
| | 04:54 | one of the built-in data types.
| | 04:56 | And we'll cover all of
these in the next few minutes.
| | 04:59 | But that's pretty much it for data types.
| | 05:01 | And you might think well, hang on,
what about more complex data types?
| | 05:05 | What about dates and pieces of
text longer than one character?
| | 05:08 | What about images or buttons or menu items?
| | 05:11 | Well, these, the int, float, double,
char, BOOL, are built into the C and
| | 05:17 | Objective-C language.
| | 05:18 | They are what are often called primitive types.
| | 05:21 | And many other data types could be
considered combinations of the primitive types.
| | 05:26 | For example, you could say that a date
could be represented by several integers,
| | 05:31 | one for year, one for month, one for
day or, it could be represented by one
| | 05:36 | integer that's simply the number of
seconds since the 1st of January, 1970.
| | 05:40 | You might think I am kidding here,
but this is UNIX or POSIX time.
| | 05:44 | It's a very common way to
represent a date and time on a UNIX system.
| | 05:48 | It means we can hold a date and time
internally in a single integer variable.
| | 05:54 | Now if we're working with text or strings,
well, they are at their core simply a
| | 06:00 | bunch of single characters strung together.
| | 06:03 | Even if writing them like this would be
very tedious indeed. And string is not a
| | 06:08 | built-in data type in Objective-C.
| | 06:11 | A date is not a built-in data type in
the Objective-C language, but that doesn't
| | 06:16 | mean we don't have strings and dates. We do.
| | 06:19 | Apple took the core of the Objective-C
language and they wrote code to make it
| | 06:24 | easy to work with strings and dates and
images and video and menus and buttons
| | 06:28 | and hundreds of more complex types.
| | 06:30 | But these are part of the frameworks we
can use, not part of the language itself.
| | 06:36 | So for example, there is an
NSString type that we can use.
| | 06:40 | There's an NSDate type that we can use.
| | 06:43 | These are classes that have
been written using Objective-C.
| | 06:48 | But they're not like
primitive types like ints and floats.
| | 06:51 | And the process of creating and using
variables that hold say strings and dates
| | 06:56 | is very different from
ints, floats, chars, BOOLs.
| | 06:59 | So we're going to get to these,
but we're going to get to them later.
| | 07:03 | Let's begin with the
primitive types and build on those.
| | Collapse this transcript |
| Working with numbers| 00:00 | So we've seen int, the classic
integer variable in C and Objective-C.
| | 00:05 | This holds whole numbers,
takes up 4 bytes or 32 bits.
| | 00:09 | That's important solely
because it affects the range.
| | 00:13 | 32-bit, 32 of these little 1s and 0s
turning on or off, can hold roughly 4.3
| | 00:19 | billion possible combinations.
| | 00:21 | Because ints are signed by default,
meaning they can hold both positive and
| | 00:26 | negative numbers, that gives us an effective
range of about -2.1 billion to +2.1 billion.
| | 00:33 | If I knew that a variable of mine
could even have the slightest chance of
| | 00:37 | getting smaller or larger than this,
then a regular int isn't going to cut it.
| | 00:42 | So what alternatives do I have?
| | 00:43 | Well, for start, if I knew that I
didn't need negative numbers, I could add
| | 00:48 | what's called a modifier to this variable
declaration and I could add the word unsigned.
| | 00:53 | That simply gives us the roughly 4.3
billion combinations from 0 upwards,
| | 00:59 | allowing me a larger range here.
| | 01:01 | But what if I need more?
| | 01:03 | Well I can use a different modifier.
| | 01:05 | Instead of unsigned, I'm going to add the
word long and make a long integer variable.
| | 01:11 | Now the range of this is hmmm,
-2.1 billion again to +2.1 billion.
| | 01:18 | This is the strange one.
| | 01:20 | You see, when you create a long int it
matters how you compile or build your project.
| | 01:26 | If you compile for 32-bit, a long
int is exactly the same as an int.
| | 01:31 | It takes up 4 bytes.
| | 01:33 | However, if you compile for 64-bit,
then it takes up 8 bytes and gives you a
| | 01:39 | range of-- well let's just say it's fairly large.
| | 01:42 | This is the only datatype that
matters how you're compiling your project.
| | 01:47 | So what do I do if I have say 32-
bit and I want a very long integer?
| | 01:52 | Well, what you can do is add the modifier again.
| | 01:55 | You can make what's called a long long int.
| | 01:58 | That takes up 8 bytes on
32-bit and 8 bytes on 64-bit.
| | 02:04 | So it's the same on both.
| | 02:06 | So a regular int is always 4 bytes.
| | 02:09 | A long, long int is always 8 bytes.
| | 02:12 | And a long int depends on whether you're 32-
bit or 64-bit, which is why I avoid long ints.
| | 02:18 | If I need a bigger integer value
I'll always make a long, long int.
| | 02:21 | Now you'll sometimes hear these
referred to just with the word long.
| | 02:25 | In fact, you can actually leave the
word int out when you use the word long.
| | 02:29 | You can make either a long or a long, long.
| | 02:33 | I prefer to be explicit and say int,
but just to let you know you can do that.
| | 02:37 | And you could also add the modifier
unsigned in front of these as well, giving
| | 02:43 | you all positive values.
| | 02:45 | If your concern is that you actually want to
go the other way, well, you can do that too.
| | 02:49 | You can add the word short in front
of int and make instead of a 4 byte
| | 02:54 | integer a 2 byte integer, which gives
you a much smaller range of roughly
| | 02:58 | -32,000 to +32,000.
| | 03:01 | But that's our built-in primitive
integer variables that we have to deal with.
| | 03:05 | What if we did want
something after the decimal point?
| | 03:08 | Well for working with the primitive
types, we can work with the float and double
| | 03:12 | datatypes and I simply use
the word float instead of int.
| | 03:16 | So here I'm creating a float variable
called myFloat and I'm setting it equal to
| | 03:20 | 7.2 and I am using this letter f after it.
| | 03:24 | Now it would actually work without the
f and I'll explain why in just a second.
| | 03:28 | But it's a good rule of thumb that if
you want to set a float, you use the
| | 03:32 | little f to be explicit about what you're doing.
| | 03:35 | There is also the double datatype.
| | 03:38 | It's also floating point,
but uses double the space.
| | 03:41 | A float is 4 bytes, a double is 8 bytes.
| | 03:44 | There's your double
precision versus single precision.
| | 03:47 | I'm not going to get into the
range stuff here, because we're talking
| | 03:50 | floating-point arithmetic here.
| | 03:51 | As on any computer system, you can lose
precision with floating-point operation
| | 03:55 | simply because of the way the
computer stores this information.
| | 03:59 | But that's not an issue for most
developers. We won't be doing floating-point
| | 04:02 | operations in this course.
| | 04:04 | So what I'm showing here is creating
these variables and setting their values.
| | 04:09 | When I'm setting the float, I'm using the f;
when I'm setting the double, I'm not.
| | 04:13 | That's because when you write a literal,
including the decimal point, it's always
| | 04:18 | going to take it as a double
unless you put the f after it.
| | 04:22 | Now, in both of these cases I'm just
using 7.2, which is a value that will fit in
| | 04:27 | both a float and a double just fine.
| | 04:29 | So it doesn't really matter,
but the f is good practice.
| | 04:37 | So in my code here I have a couple of
lines that are creating that float and
| | 04:41 | that double variable.
| | 04:43 | What I want to show here is the slight
difference when we have to write them out in a message.
| | 04:47 | So if I do an NSLog and say "The value
of myFloat is," well up to this point for
| | 04:56 | our placeholders we've been using %i
and then after the comma the name of the
| | 05:03 | variable we're talking about.
| | 05:04 | Now, if I run that, we're
going to get some output,
| | 05:08 | although it's going to kind of
complain about it. The value of myFloat is 1.
| | 05:13 | We're getting a bit of
weirdness there. Why is that?
| | 05:16 | Well, because we're saying we want to
write out a float variable, but we've
| | 05:20 | given an integer placeholder.
| | 05:22 | So instead of %i here I'm going to say
%f. Run that again and now we're getting
| | 05:28 | The value of myFloat is 7.20000.
| | 05:33 | By default using the %f will write
out 6 places after the decimal point.
| | 05:38 | However, we have an alternate way
of writing this out which is using
| | 05:42 | exponential notation.
| | 05:43 | Instead of %f we use %e. Run that, and
then we have the proper floating-point
| | 05:51 | notation for our information here.
| | 05:53 | Now, if I want to write out the contents
of the other variable, because right now
| | 05:57 | it's complaining that I'm not
using the myDouble variable.
| | 06:01 | So I'll copy and paste that message and
say "The value of myDouble is." Now you'd
| | 06:07 | be forgiven for thinking that if it was
%i for integers, %f for floats, that it
| | 06:13 | might be %d for double.
| | 06:14 | But no, we actually use exactly the
same placeholders for floats and doubles.
| | 06:19 | So, %f for the decimal representation,
%e for exponential and there is also %g,
| | 06:27 | which will make its own guess as to
which one will be the best to show.
| | 06:30 | I like to be explicit here.
| | 06:32 | So we'll run that one and we get
exactly the same output in our debug area.
| | 06:36 | Now, technically speaking you can use
the long modifier in front of the word
| | 06:41 | double, but it doesn't do anything in
Objective-C so don't use it. Even Apple
| | 06:46 | themselves will say that it's broken
and don't do a long double in Objective-C.
| | 06:51 | The last thing that I want to show here
is just a bit of information about how
| | 06:55 | floats, and doubles, and integers interact.
| | 06:58 | Let's say that we start off with a couple
of simple integer variables, say int a = 25.
| | 07:04 | int b = 2.
| | 07:07 | I'm now going to create a float.
| | 07:10 | I'll call it result, and I'll set it
equal to a / b. So 25 divided by 2, which would be
| | 07:20 | 12.5, and then after that I'll write
out a message, "The result is %f," result.
| | 07:32 | And I'll run this. Build succeeded
and it's showing all of the messages.
| | 07:37 | Here we can see "The
result is 12.000000" etcetera.
| | 07:40 | Well, what's going on?
| | 07:44 | Well up here on line 18 where we are
dividing a by b, that's being done as
| | 07:50 | integer arithmetic, because both
of the values in there are integers.
| | 07:54 | What that means is it will
truncate anything after the decimal point.
| | 08:00 | It won't round it up.
| | 08:00 | It won't round it down.
| | 08:01 | It will just forget about it.
| | 08:03 | That's worth bearing in mind when you're
performing operations that involve integers.
| | 08:08 | Now, what we have to do is we have to
tell Objective-C well, hang on a second,
| | 08:13 | I'd like to treat one of these, at
least one of the pieces of this operation, as
| | 08:18 | a float, so that I don't lose
anything after the decimal point.
| | 08:22 | What I can do with that is use
what's called the cast operator.
| | 08:25 | It sounds kinds of complex. It really isn't.
| | 08:27 | It just means before either the a
or b variable here, I need to open my
| | 08:32 | parenthesis and write the word float.
| | 08:35 | Basically means convert a into a
float and then divide it by b and as long
| | 08:39 | as one of these two pieces of this
operation is considered to be a float,
| | 08:44 | we run this again and we get the result
being spit out down here at the bottom as 12.5.
| | 08:49 | Just something to be aware of when you're
working with integers and floats together.
| | 08:54 | Now, to let you know, Apple
themselves have written objects to deal with
| | 08:59 | more complex numbers.
| | 09:00 | So let's say for example you're dealing
with currency a lot and a lot of large
| | 09:06 | dollars and cents, or
pounds and pennies values.
| | 09:09 | Well, floats aren't really the way
you want to do that, because that's
| | 09:13 | floating point arithmetic.
| | 09:14 | It's not exact decimal arithmetic.
| | 09:17 | So there are some objects that exist in
the frameworks that we can use to deal
| | 09:22 | with larger numbers,
something called NSDecimal number.
| | 09:25 | But that's not where we are right now,
we're working with integers, floats, and
| | 09:28 | doubles, but we will get to those
stuff a little later on in the course.
| | Collapse this transcript |
| Working with characters| 00:00 | Wrapping up the primitive data types,
we have the char data type to represent a
| | 00:05 | single character, not a word, not a
phrase, not a paragraph, but a single
| | 00:10 | character and it uses
single quotes, not double quotes.
| | 00:13 | Chars can't hold more than one
character because they're stored as one byte,
| | 00:17 | one byte that can represent any character in
the ASCII character sets. Not even Unicode.
| | 00:23 | So this could represent b or an
uppercase B. It could represent a special
| | 00:26 | character, like an
exclamation mark, or the digit 7.
| | 00:31 | This would be 7 as a
character, not 7 as a number.
| | 00:35 | Now if you wanted to spit out a char
variable in a format string like an NSLog
| | 00:40 | message, well we have %i for integer,
%f for float, we have %c for char, and
| | 00:46 | that would work just fine.
| | 00:47 | Not really much more to this one.
| | 00:49 | It's not a very interesting data type
by itself and you probably won't use an
| | 00:53 | awful lot of them, but
certainly something to be aware of.
| | 00:56 | In Objective-C we also have a Boolean data type.
| | 00:59 | We want to store a variable with a
Boolean value, something that only has two
| | 01:04 | possible states, usually
referred to as true or false.
| | 01:08 | Now unlike ints, floats, doubles and
chars, there wasn't a BOOL data type back
| | 01:16 | in C in the 80s when Objective-C
was added to the C language.
| | 01:20 | So the BOOL data type was
added in the Objective-C pond.
| | 01:24 | It's a little different from the others.
| | 01:26 | Rather than write bool lowercase, like
int and floats and char and double, we
| | 01:31 | write BOOL, all uppercase, and unlike
other languages were Boolean values are
| | 01:36 | typically represented with the words
true or false, in Objective-C we use YES
| | 01:42 | or NO, all uppercase.
| | 01:43 | No quotes around this, so no
double quotes, no single quotes.
| | 01:47 | YES, all uppercase is understood and as is NO.
| | 01:51 | So it looks a little odd.
| | 01:52 | Almost seems like you're shouting
when you're defining these variables.
| | 01:55 | But BOOLS are very simple to use,
possibly the most simple data type there is.
| | 02:00 | Two possible states, YES or NO, and
even when you're using them in say an if
| | 02:04 | statement, all we'd need to write is
if (isCompleted) and that will either be
| | 02:10 | YES or NO or true or false, the equivalent of.
| | 02:13 | I don't even have to say if
(isCompleted) = YES,. This would work just fine.
| | 02:18 | It's very simple to use.
| | 02:20 | Now just as an aside, kind of a little
trivia point, you could in Objective-C
| | 02:26 | write a BOOL variable using bool lowercase
and set it equal to the words true or false.
| | 02:35 | Now Xcode is throwing up a warning
here but it's simply because I'm not using
| | 02:39 | either of these variables.
| | 02:41 | My question is well, why is this?
| | 02:44 | Why would I use BOOL all uppercase and
YES all uppercase when I could use bool
| | 02:49 | and I could use true?
| | 02:50 | While the bool data type, bool in
lowercase, did not exist in C back in the 80s,
| | 02:56 | they ended up baking bool into the C
language about ten years ago with C 99.
| | 03:02 | And because Objective-C is based on top of C,
we kind of end up having two bool data types.
| | 03:08 | But we are going to be using the one on
line 15, BOOL all uppercase and YES and NO.
| | 03:14 | And this is not because of tradition.
| | 03:16 | It has nothing to do with that.
| | 03:18 | It's simply down to the fact that
because we have so much history with the
| | 03:23 | BOOL data type as defined in Objective-
C, there are hundreds and hundreds of
| | 03:28 | classes out there that use BOOL all uppercase
and they expect that definition of the data type.
| | 03:34 | So while you could use the lowercase
bool in your own code, it's going to make
| | 03:38 | things very inconvenient for you trying
to do interoperability with other parts
| | 03:43 | of the frameworks that are
available to you on Apple hardware.
| | 03:47 | So we'll use BOOL all
uppercase and YES or NO, all uppercase.
| | 03:52 | Now if we wanted to write that one out
in say a log message, so %i for integer,
| | 03:57 | %f for float, %c for char.
| | 04:00 | You would be forgiven for
thinking it was %b for BOOL.
| | 04:02 | But no, BOOL doesn't actually have a
format specifier. Well internally a BOOL
| | 04:07 | is actually represented with a signed
char because it's the smallest datatype
| | 04:11 | there is, only one byte.
| | 04:13 | The best way to spit out the value of a
BOOL would be %i for the integer value of it.
| | 04:19 | We are not going to get the words YES
or NO here. What we will get instead is
| | 04:24 | 0 for NO, 0 for false and 1 for true
or YES, however you want to think about it,
| | 04:29 | which is typically the way these are
represented in other programming languages as well.
| | 04:34 | That wraps up the primitive
types built in to Objective-C.
| | Collapse this transcript |
| Variable scope| 00:00 | Sooner or later everyone new to a C-based
language writes some code like I'm about to.
| | 00:06 | I've got a simple for loop on line
eight here that loops around 10 times,
| | 00:11 | creates an integer inside it,
writes out the value of that integer.
| | 00:15 | But let's say I come along and after
the loop has closed, I am going to write
| | 00:19 | another NSLog message. The last of
value all of foo was, give it the little
| | 00:25 | placeholder, and then say I want to write out
that variable that was created down on line 10.
| | 00:32 | I save it, I build it.
| | 00:33 | Build has failed. Use of undeclared
identifier 'foo'. Did you mean for?
| | 00:38 | No I didn't. I meant foo. I can see it.
| | 00:40 | It's right there. It's on line 10, but
I will not be allowed to write this out.
| | 00:45 | This is because of
something called variable scope.
| | 00:48 | Every variable has a scope, a place
where it's visible and accessible.
| | 00:53 | By default, variables only exist inside
the statement block they are defined in,
| | 00:59 | in what are called local variables.
| | 01:01 | So if a variable is created inside a
for loop either inside the braces or as
| | 01:06 | part of the initializer, say on line
eight where we are creating the integer i,
| | 01:11 | it only exists inside that for loop.
| | 01:14 | Once we get one step beyond the
closing curly brace, it has gone.
| | 01:18 | If a variable is created inside the
braces of an if statement, it only exists
| | 01:23 | inside those braces.
| | 01:24 | If it's defined in a function, the
variable is only available inside that
| | 01:29 | function and most of the time
this is the behavior you want.
| | 01:32 | So this line 14 is not going to work.
| | 01:35 | Now do be aware that this is a
restriction that only works from the inside out.
| | 01:40 | What I mean by that is if I created a
variable say here on line eight called
| | 01:45 | integer x equal to 10, that variable
exists and is accessible inside the main
| | 01:52 | function and inside any for's or if's
or while's or do-while's inside main.
| | 01:59 | It's available all the way down.
| | 02:02 | So inside this for loop, I can say x++.
| | 02:05 | That would be perfectly acceptable.
| | 02:07 | What I can't do is take foo and make it
available outside of this internal for loop.
| | 02:15 | Once again most of the time,
this is the behavior that you want.
| | 02:20 | I am going to get rid of those variables there.
| | 02:22 | Now the question might be well, but
what if I wanted to use the same variable
| | 02:27 | between different functions?
| | 02:29 | Well, that's perfectly accessible.
| | 02:30 | Let's say I create just a simple function here.
| | 02:33 | I'll call it myFunction.
| | 02:34 | It takes an integer parameter that
I'll call someValue and I'll just have a
| | 02:42 | simple NSLog message that
writes out whatever was passed in.
| | 02:47 | Now, I can certainly come into my main
function and even into the nested for
| | 02:53 | loop and here on line 14, I am going to
add a line that calls myFunction and I
| | 02:58 | am going to pass in foo, which
should be equal to 55. I run this.
| | 03:03 | This should work absolutely just fine.
| | 03:05 | We are just passing it in.
| | 03:06 | We are calling that function 10 times.
| | 03:09 | So we are getting all these different
messages popped right back out there.
| | 03:12 | However, bear in mind
what's actually happening here.
| | 03:16 | When we call the function on line 14,
we're passing foo, but strictly speaking
| | 03:23 | we're passing the value of foo.
| | 03:25 | We are copying the value.
| | 03:27 | So I declare foo on line 13, set it equal
to 55, and then I pass it into the function.
| | 03:32 | If in the function I accept it and I
give it the name someValue and then I say
| | 03:38 | someValue equals someValue plus 10.
| | 03:44 | I'm changing the copy of foo.
| | 03:47 | I'm not changing foo.
| | 03:48 | Just to prove that, we'll run it 10
times and you'll see it be 65 passed into
| | 03:54 | the function, but still 55 when
we go right back outside again.
| | 03:58 | So we are not truly sharing variables
between functions; we are just copying
| | 04:02 | them as we send them around.
| | 04:04 | Well what if I actually really needed to
share say a simple variable like an integer?
| | 04:10 | Well, what I can do is define it as a
global variable as opposed to the local
| | 04:16 | variables we've been defining.
| | 04:17 | To do this, what I simply do is I
define it outside all of the functions
| | 04:23 | available to all of them.
| | 04:25 | So right up here outside the #import,
but outside of main and outside of
| | 04:30 | myFunction, I'm going to
create a new integer variable.
| | 04:34 | I'll call it int bar and I am going
to set it equal to 10, which will be how
| | 04:39 | it gets initialized.
| | 04:40 | Now what I then find is that the bar
variable is accessible inside myFunction.
| | 04:46 | Now we can actually write it out.
| | 04:48 | I am kind of ignoring my
parameter, but that's okay.
| | 04:59 | It's also accessible inside even
multiple levels of nesting inside main.
| | 05:05 | I'll say bar++ again and because bar is
global, it can be affected by any of the
| | 05:11 | functions at any level of nesting.
| | 05:14 | I am going to save that and run that
and we'll actually see that while foo
| | 05:17 | remains the same, at 55 every time,
bar is jumping up twice every loop because
| | 05:23 | it's being added to once in the
loop and once in the function call.
| | 05:26 | So even here I can see it jump from
16 to 18 to 20 to 22 to 24 and so on.
| | 05:32 | Now you'll usually find global
variables referred to as kind of unnecessary evil.
| | 05:37 | They are something to be avoided,
simply because having a variable that
| | 05:42 | can be changed from anywhere in your
code can make them very difficult to debug,
| | 05:46 | but we'll occasionally see them.
| | 05:48 | Now the last thing I'm going to talk
about here with variable scope is something
| | 05:52 | that hopefully you won't run into too
often, but it's just worth pointing out.
| | 05:56 | So I am going to simplify this code
again, back to the way it was a few minutes ago,
| | 06:03 | where I have on line nine an
integer variable called foo being declared.
| | 06:07 | What I am going to do is outside the for
loop I am going to create an integer variable.
| | 06:13 | I am going to call it foo, set it equal
to 10, save that, build it, saying the
| | 06:21 | build has succeeded.
| | 06:23 | I have two lines that are
identical now, line 7 and line 11.
| | 06:29 | I think that's okay, but say if I'd
done it again, if I have integer foo
| | 06:33 | equals 11 and I declare it again right next to
this, it's actually going to complain about it.
| | 06:39 | It will say no, you are
redefining it. That's not allowed.
| | 06:42 | But it seems to be allowed
inside the for loop and it is.
| | 06:46 | The fact that variable scope can
change from block to block allows you to
| | 06:50 | redefine variables inside statement
blocks and you see what I could do now is
| | 06:56 | on line 15 I could uncomment the
line that was giving me a problem a few
| | 07:01 | minutes ago and this build actually succeeds.
| | 07:04 | The question is well, what
value will I be writing out?
| | 07:08 | If I'm trying to write out the valley of
foo on line 12 and I am trying to write
| | 07:12 | it out on line 15, which one am I using?
| | 07:15 | Well the rule is whatever is closest wins.
| | 07:19 | So if I run this, we are going to go
through that loop 10 times and we'll be
| | 07:23 | writing out 55, which was the
definition of foo within the loop.
| | 07:28 | Once we're back out of the loop as, this
last message, we'll write out the last
| | 07:32 | value of foo, which was 10,
how it was declared on line seven.
| | 07:37 | So when I redefine the variable foo on
line 11 that takes over and this becomes
| | 07:43 | the accessible one inside the
statement block and inside any statement blocks
| | 07:48 | that were nested inside this one.
| | 07:50 | So be careful with this one.
| | 07:51 | It's certainly not a best practice to
redefine variables, but as you see the
| | 07:55 | compiler won't complain about it if you do that.
| | 07:58 | That can easily lead to confusion
between yourself and others as to what the
| | 08:02 | right scope is for that particular variable.
| | Collapse this transcript |
| Enumerations | 00:00 | You know sometimes we
just have too many choices.
| | 00:03 | Let's say I'm creating a
variable called bobSeatPreference.
| | 00:07 | If I define it as an integer, this
could have a range of 4.3 billion different
| | 00:12 | values, but I wanted to represent a
preference of Window, Middle, or Aisle.
| | 00:17 | Well, there is nothing
that would of course stop me.
| | 00:19 | I could just say 1.
| | 00:21 | That's perfectly acceptable and just have it in
my own head that in this program 1 means Aisle.
| | 00:28 | I could even say myself a little bit
of space and put short int, but I have
| | 00:32 | still got 65,000 different values and
there is nothing that actually stops me
| | 00:36 | in the code setting it equal to 123, which
would be out there on the wing somewhere.
| | 00:41 | So wouldn't it great if there is a way
of defining some kind of data type with a
| | 00:45 | much more restricted range of possible values?
| | 00:48 | And I'm sure you're right there with me,
that yes there is indeed. It's called
| | 00:52 | an Enumerated data type or an Enum for short.
| | 00:56 | What we'll do first is
define those range of values.
| | 01:00 | We use the word enum and then describe
whatever it is we're wanting to define.
| | 01:04 | In this case, I'm saying
seatPreference just in general.
| | 01:07 | I'm not creating a variable here, so
there is no equal sign and I just use the
| | 01:12 | opening curly brace and closing curly
brace and inside those braces I list my
| | 01:17 | values that I want this to be,
and you can use your own words here.
| | 01:21 | So I can to say window, aisle, middle.
| | 01:26 | It's up to me. If I wanted to have something
else that meant no preference or what have you,
| | 01:32 | it's completely my decision. Those words
and how they are spelt they are up to me.
| | 01:36 | What that means after we're done is we
can use the phrase enum seatPreference
| | 01:41 | as a data type. Instead of creating a
short int or an int for bobSeatPreference
| | 01:46 | I type in enum seatPreference, then the
name of the variable, and instead of = 1,
| | 01:51 | I'd say = aisle.
| | 01:52 | I will create another variable of
that same type, but this one is for
| | 01:57 | fredSeatPreference and he wants window.
| | 02:01 | I'm allowed to use those words.
| | 02:03 | It will restrict me to those possible values.
| | 02:07 | If I say the Joan's one equals to front
and compile that, I'm going to get to
| | 02:12 | no, there is a problem.
| | 02:13 | I did not assign one of the
listed values for the enum.
| | 02:18 | And the benefit is that later on in
the code what I can do is ask a question,
| | 02:22 | like if bobSeatPreference ==
window, then go and do something.
| | 02:30 | Without having to remember now, did
one mean window or was it two windows
| | 02:34 | or was it zero window?
| | 02:35 | You'll find that these are used quite a
bit inside of the Foundation framework.
| | 02:38 | It's just a way of restricting
ranges of values in certain classes and
| | 02:43 | they're really good for that.
| | 02:44 | Now if we write them out in say a log
message, all we have to realize is well,
| | 02:50 | how do we describe this,
how do we write out an enum?
| | 02:53 | Well, technically you see an enum is
actually stored internally as an integer.
| | 02:59 | So we can use the %i to write one out.
| | 03:03 | The question is what's it going to do?
| | 03:05 | Well, unless you tell it otherwise, the
enum is actually going to pick the first
| | 03:09 | value as zero, the second one as 1,
the third one as 2, and so on.
| | 03:14 | If you had other numbers you wanted
them to represent, you could do so.
| | 03:20 | I'm picking numbers here that don't
really have much drastically important to them.
| | 03:24 | So when I run this program,
fredSeatPreference, which was assigned to window,
| | 03:28 | should be popping out in the message as
the number 99, because that's how it's
| | 03:31 | internally stored in the enumeration.
| | Collapse this transcript |
| Using typedef| 00:00 | When we create an enum, it almost sort
of kind of feels like we're defining our
| | 00:05 | own data type, even if it
feels little clunky to do it.
| | 00:08 | Now we can take it one step further
and actually really define our data type.
| | 00:11 | There is a word called typedef. What
that allows you to do is assign a new name
| | 00:18 | to an existing data type.
| | 00:20 | Something as simple as
this is perfectly acceptable.
| | 00:22 | I can say typedef int
and then give it a new name.
| | 00:25 | I'll call it simonsInt.
| | 00:26 | I think well, what does that do?
| | 00:28 | Well, we can now create variables of
that type, and in this case they'll behave
| | 00:36 | exactly like the underlying type of an integer.
| | 00:38 | Now there's no real point in just
redefining an integer right now but we
| | 00:42 | could do it that way.
| | 00:44 | What is quite common, however, is there
is something that's a bit more complex
| | 00:47 | to define such as the enum could be
redefined with a typedef and then it makes
| | 00:53 | it easier to create variables of
that type instead of saying enum
| | 00:56 | seatPreference all the time.
| | 00:57 | So how do we do it?
| | 00:58 | Well, what I'm going to do in this case
is use the word typedef, then what we do
| | 01:03 | is describe the type and then
what we do is say what the name is.
| | 01:07 | Well, the name that I wanted was seatPreference.
| | 01:11 | So I'm going to cut that part out of the
lower line where I declared in line and
| | 01:15 | just paste it in up here.
| | 01:17 | And then the rest of the
definition is the enum, which is the type.
| | 01:21 | So it's almost like kind of
reversing things a little bit.
| | 01:24 | So on line five, I have now defined a
new type called seatPreference that is an
| | 01:31 | enum with these three settings:
| | 01:33 | window, aisle, and middle.
| | 01:34 | And the reason why it is complaining about on
line 10 and 11 is I don't need enum anymore.
| | 01:39 | I can literally just create
variables of type seatPreference.
| | 01:44 | Now commonly, you'll find this defined
outside a block like main, because it
| | 01:52 | will need to be available not only
in the main function but also anywhere
| | 01:57 | else in the project.
| | 01:58 | That's perfectly acceptable because this
line of code does not actually do anything.
| | 02:02 | It doesn't cause anything to happen
except it describes this new type.
| | 02:07 | And you'll find it mostly used to just
shorten some code to redefined types that
| | 02:12 | like an enum would be quite
clunky to keep on writing otherwise.
| | Collapse this transcript |
| Preprocessor directives| 00:00 | In every project that you create in
Xcode, you're going to see lines that look
| | 00:04 | something like line 9 here, the
import statement that begins with the pound
| | 00:08 | symbol or hash symbol if you prefer.
| | 00:10 | This is not a line of Objective-C,
which is why it doesn't need a semicolon.
| | 00:14 | It is instead what's called a
preprocessor directive, and that simply means it
| | 00:19 | causes something simple to
happen before our code is compiled.
| | 00:24 | You see anytime you hit Command+B or
you select Build from the Product menu or
| | 00:28 | you try and run the program, all
these files are scanned, all the files in
| | 00:32 | your project, for these preprocessor
directives, these instructions that begin
| | 00:37 | with this # symbol.
| | 00:38 | And if it finds any, it causes
something very simple to happen.
| | 00:42 | In the case of the #import, it
simply means go and find this file called
| | 00:46 | Foundation.h and whatever it
includes paste it in here.
| | 00:50 | It's a way of including the
content of a separate file in this one.
| | 00:54 | If Foundation.h had its own #import
statements, it would go and find those files
| | 00:59 | too and paste all the results into our
own file. It becomes part of our own code.
| | 01:04 | But there are a couple
others worth knowing about.
| | 01:08 | #define, this allows us to
create what's called a macro.
| | 01:11 | It's really just a little shortcut,
commonly used to do something like this, to
| | 01:15 | create a value and give it a name.
| | 01:18 | It might sound like a variable,
but this is really very different.
| | 01:22 | In this case, I've defined
something called HIGHSCORE=1000000.
| | 01:24 | These are usually written in all caps.
They don't have to be but it makes
| | 01:28 | them very recognizable.
| | 01:30 | I don't use an equal sign.
I don't use a semicolon.
| | 01:33 | Now HIGHSCORE is not a variable.
| | 01:35 | It's not changeable.
| | 01:37 | But what I can do from this point on is
anywhere in my code I create say a new
| | 01:41 | integer called a and set it
equal to whatever HIGHSCORE is plus 500.
| | 01:47 | I can write out the contents.
| | 01:52 | I can change variables
that are based on that value.
| | 01:55 | What I can't do is change the value.
| | 01:58 | You'll commonly see it being used to
declare things that really need to be fixed
| | 02:02 | values like let's define PI as
3.14159265, and then we could use the word PI
| | 02:09 | anywhere in our code. In the same way
that the #import statement just does
| | 02:13 | something very simple by finding
the file and coping its contents.
| | 02:16 | And here all that the #define does
is the equivalent of a find and replace.
| | 02:21 | It's basically taking the value and
before our code is compiled saying hang on
| | 02:26 | a second, just going to go through
your code, find that word, and then replace
| | 02:30 | it with that value.
| | 02:31 | That's the end result of the #define.
| | 02:34 | The benefit of course is what we
can do is then declare a lot of these
| | 02:39 | #defines up at the top and it gives us
one place to change these values if we
| | 02:43 | need to change them.
| | 02:44 | Now what you'll find is you're probably
a bit more likely to use other built-in
| | 02:48 | macros than to define your own.
| | 02:50 | I'll give you an example.
| | 02:51 | Here I'm going to write out an NSLog
message that says the maximum value of an
| | 02:56 | int is integer placeholder and then
what? Well there is actually a built-in one.
| | 03:04 | When I'm going to start to type INT,
I've INT_MAX, INT_MIN, and I'll do INT_MAX.
| | 03:12 | This is a built-in predefined macro that's
actually in some of the underlying C Libraries.
| | 03:19 | That's just been defined with that
number, so we don't have to bother
| | 03:22 | about remembering it.
| | 03:23 | I'm going to run this and it not
surprisingly outputs a message here.
| | 03:27 | The maximum value of an
int is 2147000000 and so on.
| | 03:32 | There are a lot of these, you've got--
if I start typing FL-- you've got Float
| | 03:37 | Max, Float Max 10 Exponents.
| | 03:40 | There is a lot of stuff.
| | 03:41 | Why they're written in caps is
they make it quite easy to recognize,
| | 03:44 | although you'll see the hash mark or
the pound symbol at the start of them
| | 03:47 | when you're looking them up.
| | 03:50 | Back to INT_MAX there.
| | 03:52 | The last one that I'm going to talk
about in terms of preprocessor directives
| | 03:55 | is the if statement.
| | 03:57 | Now we have an if statement in Objective-C
and we're certainly going to get to that.
| | 04:01 | But this one is a really easy one
allows us to have conditional code and that
| | 04:07 | might sound little strange.
| | 04:08 | So let me be sure what I'm talking about here.
| | 04:11 | What I'm going to do here
is type if DEBUG, endif.
| | 04:14 | Now bearing in mind that any and all of
these preprocessor directives cause
| | 04:21 | something to happen before our code is executed.
| | 04:24 | And what this is going to
do is scan through our code.
| | 04:28 | It hits line 16, and it's going to
ask, are we compiling in Debug mode?
| | 04:34 | If we are, then that's fine.
I'll leave this line of code in.
| | 04:38 | If we're not, I'm just
going to pull this code out.
| | 04:41 | This is a very different idea from when we're
running our program is it going to ask anything.
| | 04:45 | This is happening before we compile and
our code will actually be stripped out,
| | 04:50 | as if we've never written it at all.
| | 04:52 | So how do I change this?
| | 04:53 | Well, if I go up here into my Scheme
dropdown, what can happen is I can edit
| | 04:59 | the settings of this and I can
change from a Debug configuration to a
| | 05:04 | Release configuration.
| | 05:05 | Now let me leave it at Debug and run it.
| | 05:10 | I get that little diagnostic
message about the maximum value of an int.
| | 05:14 | If I go and switch it, change to
Release, click OK, run it again, I don't get
| | 05:21 | that message at all. It was as if
it was never written in the program.
| | 05:24 | Now the way that quite a lot of
developers use this capability is to be able to
| | 05:29 | put in say quite a few diagnostic
messages that's peppered throughout the code.
| | 05:34 | Then rather than have to go and rip
all that code out when they're actually
| | 05:37 | compiling it for release, they just make
it conditional using these preprocessor
| | 05:41 | directives and it's as if that
code never existed in the first place.
| | 05:45 | Those are the three most common
preprocessor directives that you're likely to
| | 05:49 | run into either writing them yourself
in Objective-C or by reading through
| | 05:53 | the Apple sample code.
| | Collapse this transcript |
| Working with strings| 00:00 | Let's finally get around
to strings in Objective-C.
| | 00:03 | How do we work with text,
words, and phrases and sentences?
| | 00:08 | Now depending on which language you are
coming from, you might expect to be able
| | 00:11 | to write something like this,
just string message = "Hello".
| | 00:17 | But no, this is not going to work.
| | 00:19 | In fact this is not going to
work in several different ways.
| | 00:21 | There is no built-in string type in the
Objective-C language and again this goes
| | 00:27 | back to its roots in C where you
manage strings as arrays of characters,
| | 00:32 | and those are pretty tedious to deal with.
| | 00:34 | So we don't want to work with the C
style character arrays and we don't have to.
| | 00:39 | Instead, we use the NSString type to
work with strings and we do it like this.
| | 00:45 | Now looks a little different,
so let me go through this.
| | 00:48 | The first part is the type. It is NSString.
| | 00:52 | Now while NSString is not officially part of
the Objective-C language, it might as well be.
| | 00:58 | NSString is part on the Foundation
framework, a collection of different
| | 01:03 | pre-written pieces of
code that we are linking to.
| | 01:06 | That's what this #import statement
does that we have in pretty much every
| | 01:11 | project that we will ever write in Objective-C.
| | 01:14 | This import of Foundation/
Foundation.h is pointing to the
| | 01:19 | Foundation framework.
| | 01:20 | In fact, if I look at my Project files
and expand Frameworks, I'll expand the
| | 01:26 | Foundation.framework here, and I see
a whole bunch of stuff, most of which
| | 01:31 | begins with NS, NSBundle, NSCoder,
NSDate, NSDecimal, NSDistantObject, NSPort,
| | 01:39 | NSObject and NSString.
| | 01:42 | Now, I don't want to ever have to change this.
| | 01:44 | It looks fairly intimidating here.
| | 01:46 | But this is what that #import statement
does, is it links to all that extra code
| | 01:53 | so that we will have a string
data type to work with, NSString.
| | 01:57 | As I mentioned before, the NS comes
from the old Next Step days and while it
| | 02:03 | might seem a little strange to
have a 15-year-old operating system
| | 02:06 | determining your strings and your
dates and your reports and your paths that
| | 02:11 | you write in Objective-C,
| | 02:12 | well you just got to have to get
used to it because it's not going away.
| | 02:16 | It's written with an uppercase N an
uppercase S and another uppercase S. Again
| | 02:20 | case-sensitive and again, use Code Sense
code completion to help you in those
| | 02:25 | early days while you are
still getting used to it.
| | 02:28 | So the last part, the value over
here which looks a little strange.
| | 02:32 | We've got the double quotes which represent
a string but we've got the @ in front of it and
| | 02:38 | we've seen this before in all our
NSLog messages. We are using that @.
| | 02:42 | Well what's this all about?
| | 02:44 | Well the @ is a clue to the compiler.
| | 02:47 | And it's not like this is the only one we've used.
| | 02:50 | If we say create float variables,
we use that little f to say hey,
| | 02:54 | this is a float variable.
| | 02:56 | If we are using a character, we use the
quotes. We are making an indication to
| | 03:01 | the compiler, this is a float, this is a char.
| | 03:04 | Well, what we're doing with that @
is we are saying this is an NSString.
| | 03:09 | If we left the @ off, and that's a
very common error for people to make,
| | 03:12 | that will be considered a C style character
array and it's not going to work very well.
| | 03:17 | So we have got two pieces here, then
in the middle we have the name of the
| | 03:22 | variable, which in this case is message,
but what's this other piece, what's this asterisk?
| | 03:27 | Well, this asterisk means pointer and
what this means is that the variable
| | 03:33 | message that we're creating
does not directly hold an NSString.
| | 03:37 | it holds a pointer to an NSString object.
| | 03:41 | It points to a different area of memory
where the contents of the string are stored.
| | 03:46 | Well, there is a lot of reasons for this.
| | 03:48 | The reason why we're hitting this now is
that we are finally moving from classic
| | 03:52 | C in its float char into real Objective-C.
| | 03:57 | This is the first code we have written
that creates an object. But we are in an
| | 04:01 | object-oriented language and
we will make a lot of objects.
| | 04:04 | And in Objective-C, all
objects are accessed using pointers.
| | 04:09 | We will be using this asterisk every single
time that we write code to create an object.
| | 04:16 | And if you look at line 6, the
NSAutoreleasePool line that's being generated,
| | 04:21 | the asterisk here means pointer as well
because this is an object that is being created.
| | 04:28 | pool is a pointer to an NSAutoreleasePool.
| | 04:32 | You can put the asterisk anywhere.
| | 04:35 | It is very commonly written like
this where the asterisk is right by the
| | 04:39 | variable name. The asterisk is
not part of the variable name.
| | 04:43 | I am not making a variable called *message.
| | 04:47 | I am making a variable called
message and it is a pointer to an NSString.
| | 04:52 | So I could write it with the asterisk
against the word message, I could write
| | 04:56 | it with a space in between both of them,
I could actually put the pointer right by NSString.
| | 05:03 | All of this would work and you are
actually likely to see it done all different ways.
| | 05:08 | Different people have different preferences.
| | 05:09 | Now one of the questions is, do I
always need it? And yes you do, when you are
| | 05:15 | creating these objects, but
let me show you an example here.
| | 05:20 | So on line 11 here, I am going to
define a variable called message.
| | 05:25 | It is a pointer to an NSString.
| | 05:27 | If you would prefer, you
can put a space in-between.
| | 05:30 | again it is not whitespace sensitive.
| | 05:31 | You could put the multiple spaces in
between but message is a pointer to an
| | 05:35 | NSString and the contents
of message will be @"hello".
| | 05:41 | Now, it's given me a warning right now because
I am not using it, so I might as well use it.
| | 05:46 | Let's write an NSLog, "The value of
a message is... Well how are we going
| | 05:53 | to write this one out?
| | 05:54 | It is not going to be %i. it is not
an integer or %f. it is not a float.
| | 05:59 | It is not a character either.
| | 06:01 | The way we are going to write this
out is we are going to use %@ and this
| | 06:07 | is not for strings particularly.
| | 06:11 | %@ is the placeholder for objects.
| | 06:14 | A string is an object. So if the %@
is my placeholder, then I will write a
| | 06:19 | message and notice that I'm not using *message.
| | 06:22 | Again, the name of the variable is message.
| | 06:24 | I save that, I run it and we should
get the message out here that the value
| | 06:29 | of message is Hello.
| | 06:31 | No particular surprise there.
| | 06:33 | The thing that I was going to show is
where exactly is the asterisk needed?
| | 06:38 | Well, it is typically there when you
are defining what this variable is.
| | 06:42 | So let's say I wanted to
split this into two pieces.
| | 06:47 | First line, declare a variable called message.
| | 06:50 | It's a pointer to an NSString.
| | 06:52 | Next line, I want to set it.
| | 06:56 | Now, what occasionally puzzles people
is why didn't I need an asterisk at
| | 07:05 | the start of line 12?
| | 07:07 | Well, I don't, because I've already
told the compiler what message is.
| | 07:11 | It is really the same as on line 89.
| | 07:14 | If I declare an integer called foo,
then on line 9 when I am setting foo,
| | 07:18 | I don't need to tell it
again that it's an integer.
| | 07:20 | It already knows that it is an integer.
| | 07:22 | On line 12, I don't need to say
that it as a pointer to an NSString.
| | 07:25 | It already knows that.
| | 07:26 | I just used the variable name.
| | 07:29 | Now everybody gets a little puzzled by
pointers the first time they deal with them.
| | 07:33 | If they don't seem intuitive that's okay,
you're not alone. Pointers have been
| | 07:38 | confusing people for decades.
| | 07:42 | Now we are going to get much deeper
into this, but understanding that an
| | 07:45 | NSString is an object leads us into,
well, what exactly does it mean to be an object.
| | Collapse this transcript |
|
|
5. ClassesIntroduction to object orientation| 00:00 | Beyond the syntax changes the
@ signs and the square brackets, the real
| | 00:05 | difference between regular classic C
and Objective C is that regular C is a
| | 00:10 | procedural programming language and
Objective-C is an object-oriented program language.
| | 00:15 | Well, in a procedural programming language like
C, the program is written as a long procedure.
| | 00:21 | Even though it might be split up into
files and functions to make a more modular
| | 00:25 | maintainable, it's really effectively
a long piece of code combining data and
| | 00:30 | logic all mixed in together.
| | 00:32 | But in an object-oriented
programming language this program would instead
| | 00:36 | be split apart into self-contained
objects, almost like having several mini
| | 00:40 | programs each object representing a
different part of the application, each
| | 00:44 | object contains its own data and its own
logic and they communicate between themselves.
| | 00:50 | Now you can't avoid object
orientation in Objective-C.
| | 00:54 | You can'y even write the simplest
Objective-C program without using it.
| | 00:58 | And while object-oriented
programming can bring a lot of jargon to the
| | 01:02 | table, there are really only a couple of
terms we need to be comfortable with to forward.
| | 01:07 | The first and the core idea is
the idea of a class and an object.
| | 01:12 | These two things go hand in hand.
| | 01:14 | A class is a blueprint an idea,
a description, a definition.
| | 01:19 | It describes something, but
it isn't the thing itself.
| | 01:24 | Like a blueprint describes a
house, but it isn't the house.
| | 01:27 | It is a well-defined idea.
| | 01:29 | The classes will exist for
many parts of your applications.
| | 01:33 | Some classes you may write yourself,
say you are writing a restaurant review
| | 01:37 | application, you might have a class to
represent a restaurant, another one to
| | 01:40 | represent a review, a class to
represent a user of your app.
| | 01:44 | These classes would all describe them very well.
| | 01:47 | There're also classes to
represent visual parts of an application.
| | 01:51 | If you are building a desktop or an
iPhone app, there are existing classes that
| | 01:55 | represent text boxes, buttons and
windows and menus, but classes can also
| | 02:01 | represent more invisible
intangible things like dates and time zones.
| | 02:07 | So you'll not only write your own
classes, but you will also use many that
| | 02:12 | Apple have already written in fact,
everything you see here with the prefix and
| | 02:15 | it does already exist in the Apple
frameworks, but whether you're writing them
| | 02:20 | or whether Apple write them, all classes
describe two things, attributes and behavior.
| | 02:27 | What are some things
characteristics its attributes and what is its
| | 02:31 | behavior, what can it do?
| | 02:33 | So if we are describing a class to
represent a person, we might say that the
| | 02:37 | attributes of that person or a name, a
person has a height and a weight and a
| | 02:41 | gender and an age and then there's the
behavior that it describes what can they
| | 02:47 | do while a person can walk and run and
jump and speaking and sleep and defining
| | 02:53 | this is the key when you're
creating your own classes.
| | 02:57 | Now these two pieces can also
be described with other names.
| | 03:01 | When we start referring to object-oriented
programming jargon you will often
| | 03:06 | hear I am referred to as properties and methods.
| | 03:09 | Properties of a class describing
the class's characteristics, its
| | 03:12 | attributes, and method's describing
what it can do, but the class described
| | 03:17 | everything in abstract.
| | 03:18 | We say that something has a name, but
we don't say what the name is because the
| | 03:22 | class is the description
and the object is the thing.
| | 03:27 | So if the class was the
blueprint the object would be the house.
| | 03:32 | The object is created from the class.
| | 03:35 | So obviously there is a sequence here,
first the class is defined, and then the
| | 03:38 | object or objects are created based on
that class because you can take the same
| | 03:44 | class and make multiple objects from
it, in the same way you could take one
| | 03:48 | blueprint and make multiple houses from it.
| | 03:51 | In more of a programming context, we
could have a class that represents a button
| | 03:56 | and a desktop or an iPhone application
and by creating multiple objects based on
| | 04:03 | my class with different
characteristics, we can have different buttons with
| | 04:07 | different heights and widths and
colors all based on that same core idea.
| | 04:12 | Now if you've already been exposed to
object oriented programming you know that
| | 04:16 | there's quite a lot of jargon that
comes along with it and one of the most
| | 04:19 | common things you'll hear of the four
keywords that can be used with remember
| | 04:24 | about the phrase APIE, abstraction,
polymorphism, inheritance, encapsulation.
| | 04:29 | Well, right now we don't have to care
about two of them, but it's worthwhile
| | 04:33 | paying attention to the A and the E, the
abstraction and the encapsulation ideas
| | 04:39 | because that will help us build and use classes.
| | 04:42 | Abstraction, that's simply the idea of
focusing on the core pieces of something
| | 04:48 | to describe it well, of reducing
details to focus on the core concepts.
| | 04:54 | It's what allows us to take the idea
of multiple people and abstract out the
| | 04:59 | idea of a Persian class what are the
things that everything has in common.
| | 05:05 | In our code it means that we create
classes that focus only on those core pieces
| | 05:11 | of information and the core
capabilities of that class needs to have.
| | 05:14 | And not only that, but that's what we
should expect of the classes that Apple
| | 05:20 | have already written that we want to use.
| | 05:22 | Now hand in hand with this is the idea
of encapsulation that we are taking the
| | 05:26 | code that represents our properties,
we're taking the code that represents our
| | 05:29 | methods and we are wrapping it up,
we are boxing it up in this class,
| | 05:35 | encapsulated, sometimes referred to
with the concept of black boxing and what
| | 05:39 | keeping the functionality self-
contained and that we will only share with other
| | 05:43 | objects what we decide to share.
| | 05:45 | By default everything is closed off
and self-contained inside our objects.
| | 05:49 | But what does that really mean for us?
| | 05:51 | Well, an example, so, we can think
of the class in essence as a type.
| | 05:57 | We are defining say a new and a string object.
| | 06:01 | Well what's happening here is the word
and NSString is representing the class
| | 06:05 | that already has defined when the
object itself is being created on the
| | 06:09 | right-hand side of the equals sign here
and the variable message represents it
| | 06:14 | pointed to that object.
| | 06:16 | Now because we can create multiple
objects based on the same class, we could
| | 06:20 | have another line of text to create
another object based on the same class and
| | 06:25 | when objects are created, you'll often
hear this referred to as instantiation,
| | 06:29 | in fact the word instance and
object are really interchangeable.
| | 06:33 | Object is an instance of a class.
| | 06:36 | Now when we are working with the
NSString, this is a bit of a lazy way to do it
| | 06:40 | because we're having the object being
created very simply by using the at sign
| | 06:45 | and the double quotes.
| | 06:46 | In more typical environment, the
actual process of creating an object is a
| | 06:50 | little bit more complex and
you've actually seen it already.
| | 06:54 | The first line of any main method that
we have has this line NSAutoreleasepool
| | 06:58 | and what's happening here is really
we're going through the same process.
| | 07:03 | The class is NSAutoreleasepool.
| | 07:06 | We have a pointer to an object and
we'll talk about pointers in a minute and
| | 07:10 | on the right-hand side of the equals sign
we'll have the object creation process itself.
| | 07:15 | But in the very first line of this
simplest project that you have, that you
| | 07:19 | have this line of code we're using class as
we're creating objects, we're having pointers.
| | 07:25 | You can get away from this object-oriented
programming idea, but at least some of
| | 07:29 | the basic concepts allow us now to
drill down and explore what's exactly
| | 07:33 | happening on this line here.
| | Collapse this transcript |
| Using objects and pointers| 00:00 | I have said it before and
no doubt I'll say it again.
| | 00:03 | In Objective-C all objects are
accessed using pointers, all objects are
| | 00:08 | accessed using pointers.
| | 00:10 | If you want to make and use an object
even from a simple class like NSString,
| | 00:16 | you will need a pointer
to reference that object.
| | 00:19 | So, we will be using this asterisk
every single time that we write codes
| | 00:24 | to create an object.
| | 00:25 | Now, here is the key difference
between needing one and not needing one.
| | 00:29 | You see when you create an integer
variable, we are writing a line of code like
| | 00:34 | this, what's going to happen an area of memory.
| | 00:37 | in this case, 4 bytes will be
allocated for that variable and it will hold
| | 00:41 | the value directly.
| | 00:42 | Well, in this case, the binary
representation of 100, but the variable holds
| | 00:48 | the value directly.
| | 00:49 | However, if you write a line of code
to create any object, a variable is
| | 00:55 | still claimed in memory.
| | 00:57 | in this case it is called message
but it does not hold the object itself.
| | 01:01 | Instead, it holds an address, a
reference, a pointer that points to a different
| | 01:08 | area of memory where that object itself exists.
| | 01:11 | Now, I am often asked the question,
why are objects handled differently?
| | 01:15 | Well, there are few reasons but the
most basic is that objects are more complex
| | 01:19 | than primitive types.
| | 01:21 | We know how much memory to
reserve for a char, 1 byte.
| | 01:23 | We know how much memory to
reserve for an integer. 4 bytes.
| | 01:26 | But how big is an NSString?
| | 01:28 | How big is a piece of video?
| | 01:29 | How big is an image?
| | 01:30 | We don't know, and it might even
change during our program and while it is
| | 01:34 | running, we need a more flexible way to
manage objects and pointers allows us to
| | 01:39 | do that and having a pointer, just an
address allows us to pass the object
| | 01:43 | around without coughing and which
could be time-consuming and inefficient.
| | 01:46 | We just passed the address of the
object around and we passed the pointer.
| | 01:50 | Now, you may wonder, do I actually need
to know what the address is, what that
| | 01:55 | pointer value is, what
that address of memory is.
| | 01:57 | Well, no you don't.
| | 01:58 | It doesn't matter, but you do
need to know that's what's happening.
| | 02:02 | Now this is the way that most object
oriented languages work under the hood.
| | 02:06 | Even languages like Java and C# work this way.
| | 02:08 | They just hide the asterisk away.
| | 02:10 | Now, when declaring again, we
can put the asterisk anyway.
| | 02:14 | You will commonly see it written like
this, but you could have a space between
| | 02:19 | the class name, and the variable name
or you could have the asterisk right up
| | 02:23 | against the class name itself,
because the asterisk is not part of the
| | 02:28 | variable name here.
| | 02:29 | We are not trying to make
a variable called *message.
| | 02:31 | We are making a variable called message
and it's a pointer to an NSString object.
| | 02:37 | We can think of the asterisk
representing the word pointer here.
| | 02:41 | Now two common misconceptions,
I am going to go through.
| | 02:44 | Common misconception number one.
| | 02:45 | do I always need and the asterisk
with that variable? No you don't.
| | 02:49 | Let's say I wanted to define
this variable called message.
| | 02:53 | It's a pointer to an NSString
and I want to set its value.
| | 02:56 | Well, I can just use the
variable name message = @ "Hello".
| | 03:01 | I don't need to use the asterisk on
the second line here because Objective-C
| | 03:04 | already knows that message
is a pointer to an NSString.
| | 03:08 | As an equivalent, if you were declaring
say an integer called foo and then you
| | 03:12 | wanted to write a line of
code that says foo = 45.
| | 03:15 | you don't need to say
that foo is an integer again.
| | 03:18 | Objective-C already knows and
that's the equivalent with message.
| | 03:22 | Objective-C already knows
message is a pointer to an NSString.
| | 03:26 | So you use the asterisk when you are
telling Objective-C what something is.
| | 03:32 | not what its value is, but what its identity is.
| | 03:35 | In this case, on line 15, I'm saying
that message is a pointer to an NSString.
| | 03:41 | We also have the code on line 13
that is saying, pool is a pointer to an
| | 03:46 | NSAutorelease pool object.
| | 03:49 | Now both of these objects are being
created slightly differently here, but
| | 03:52 | that doesn't matter.
| | 03:53 | That's not what we are interested in right now.
| | 03:55 | So the pointer symbol is used when you
define the object and the second place is
| | 03:59 | going to be used is when
you start to pass it around.
| | 04:02 | Let's say I want to define a new
function, and I want this function to accept a
| | 04:07 | parameter in here that
will be an NSString object.
| | 04:11 | I have got to think, what am
I actually expecting in here?
| | 04:14 | Well, if I was expecting an integer, I
would give it a type which would be say
| | 04:18 | integer a. That would be fine, but if I
want to pass an NSString object, I got
| | 04:24 | to think, what am I passing?
| | 04:25 | Well, I wouldn't be passing the object itself.
| | 04:28 | All objects are pointer types.
| | 04:30 | So instead, I would say NSString
pointer, and then give it a name.
| | 04:35 | In this case, let's call it foo.
| | 04:37 | Inside the body of the function, I
could then simply use that variable.
| | 04:42 | And then in my main method, I am going
to just call that simple function passing
| | 04:47 | in the pointer to the NSString object.
| | 04:50 | It is a wholly unexciting
piece of code that we have here.
| | 04:54 | But not surprisingly, we get
that being output on our debug area.
| | 05:01 | So in this particular example, I am
using that pointer asterisk in three
| | 05:07 | places that I can see it.
| | 05:09 | One is on line 17, when the
NSAutorelease pool object is being created.
| | 05:14 | nothing to do with me.
| | 05:15 | That's part of the template. Two.
| | 05:17 | on line 19 when I define this NSString
pointer object called message and three,
| | 05:23 | when I define the signature of the
function here and say I am expecting a
| | 05:29 | pointer to an NSString as a parameter.
| | 05:31 | But the other places
that I am actually using it.
| | 05:33 | on line 12 and on line 20 I do not need the *.
| | 05:38 | The common misconception number two.
| | 05:40 | doesn't it get confusing that the
asterisk is used for pointers and also
| | 05:43 | used for multiplication.
| | 05:45 | No, it really doesn't.
| | 05:46 | They are so different and
used in very different context.
| | 05:49 | As an equivalent for example, we are
familiar with using the / for a division operator.
| | 05:54 | But if you see a URL path, you
don't suddenly think, well, this means
| | 05:58 | www.lynda.com divided by news.
| | 06:01 | It is a completely different context.
| | 06:03 | In the same way, as you become
familiar with looking at it, you will realize
| | 06:07 | that when you see an operation like
this where the asterisk is being used on
| | 06:11 | the right hand side of the assignment
operator, this is doing multiplication,
| | 06:16 | whereas if you see an operation like
this where the asterisk is being used on
| | 06:20 | the left hand side after a class name, you
will realize this is just a pointer declaration.
| | 06:26 | Now if you are new to pointers, yes
just realize they are not going to feel
| | 06:30 | comfortable until you make a bunch of
them, create them and use them and we are
| | 06:35 | going to do that a lot in this course.
| | Collapse this transcript |
| Messages and methods| 00:00 | Modular, reusable code. it's a good thing.
| | 00:03 | Now we know that we can take a block of
code, wrap it up, give it its own name
| | 00:07 | and it is considered a function.
| | 00:09 | But this is the old-school
classic C way of doing things and we are
| | 00:13 | in Objective-C now.
| | 00:14 | most of the code that we are
going to write or use will be gathered
| | 00:18 | together inside classes.
| | 00:20 | And if you took that same code, you
wrapped it up, gave it a name and put it in
| | 00:24 | a class it would be considered a method.
| | 00:27 | A method it is basically a
function that belongs to a class.
| | 00:30 | It is how you describe, what it is that that
class and any objects of that class can do.
| | 00:36 | Let me give you a couple of examples.
| | 00:38 | If I were to show you some of the
classes that exist in the Cocoa framework,
| | 00:42 | classes we can just use because Apple
have written them already that might
| | 00:46 | include say the AVAudioPlayer.
| | 00:49 | This is an existing class that has
methods like play and pause and stop and the
| | 00:54 | kind of things you can probably
guess an audio player would have.
| | 00:57 | But even NSString has plenty
of methods. It has dozens.
| | 01:01 | We have an NSString object, we have
methods like lowercase string, and
| | 01:06 | uppercase string, length and has prefix
and has suffix, we can do all sorts of
| | 01:11 | things with that string object.
| | 01:12 | When it comes time to write your own
classes let's say we wrote a bank account
| | 01:16 | class, we would be writing methods like
deposit and withdraw and open and close.
| | 01:21 | So it is how you describe what
it is that that class can do.
| | 01:25 | Now that's common object oriented stuff,
but the question is well, how do we
| | 01:29 | call methods in Objective-C because that's a
little different than most other languages.
| | 01:34 | In a lot of languages, you would call a
method by using something called dot syntax.
| | 01:40 | You would use the name of the object, dot,
the name of the method, and then any
| | 01:44 | parentheses that would say
does this take any arguments in.
| | 01:49 | This is not going to work in Objective-C.
| | 01:52 | We don't use dot syntax in
Objective-C to call methods.
| | 01:55 | We use square brackets.
| | 01:57 | Square brackets is one of those indicators
to the compiler that this is Objective-C.
| | 02:03 | So we are sending a message here, is
the term that's actually being used and in
| | 02:07 | fact the official term is that we are sending
a message someMethod to the object myObject.
| | 02:12 | It is all enclosed in the square
brackets and there's no dot between the object
| | 02:17 | name and the method name.
| | 02:19 | Now some developers get really weirded out
by the square brackets. It is just syntax.
| | 02:23 | It is just a slight change,
the concept is the same.
| | 02:26 | But let's take it, a little step further.
| | 02:28 | What happens if this method returns a value?
| | 02:31 | Well, if you are familiar with dot syntax,
you would expect to write some code like this.
| | 02:36 | You would have a receiving variable and
set it equal to whatever came back from
| | 02:40 | myObject.someMethod ().
| | 02:42 | Well it is exactly the same in Objective-C,
you just replace the dot syntax with
| | 02:46 | the square brackets and call it that
way, but if the method returns a value,
| | 02:50 | this would work just fine.
| | 02:52 | Moving on one more step, what happens,
if you want to pass an argument into
| | 02:57 | that method so the method has been defined
with parameters, we are passing arguments into it.
| | 03:01 | Well, in dot syntax you would simply
put the argument in the parentheses.
| | 03:07 | The concept is the same in Objective-C,
but instead of parentheses, we use a colon.
| | 03:11 | So it is object name method name:argument,
all within the square brackets.
| | 03:18 | But that's how we pass in
an argument to that method.
| | 03:21 | Now where it gets a little bit more
complex, is if we have multiple arguments
| | 03:25 | because that is the first thing where
it's really different and giving the
| | 03:29 | analogy again of a dot syntax way
of doing it you just pass in multiple
| | 03:34 | arguments separated by commas.
| | 03:36 | That's not going to work in Objective-C.
| | 03:38 | The big difference in Objective-C is
if you have a method name that takes
| | 03:43 | multiple arguments the method name
becomes split apart into multiple pieces.
| | 03:48 | the actual name of the method changes.
| | 03:51 | So let me show you an example.
| | 03:54 | This is a real method that's
available to you in Objective-C.
| | 03:59 | It is the method insert string at index.
| | 04:03 | More specifically it is read as,
insertString:atIndex
| | 04:06 | and the way we would write it,
is use the object name, the first part of
| | 04:11 | the method name which is insertString:
| | 04:13 | and the first parameter space the second
part of the method name which is atIndex:
| | 04:19 | and the second parameter.
| | 04:21 | So the actual method name is
different, each parameter is named.
| | 04:25 | Now if you have detected, I am using
the terms parameter and argument kind
| | 04:29 | of interchangeably.
| | 04:30 | Officially, they're described as such,
you pass an argument into a method which
| | 04:35 | is received as a parameter.
| | 04:37 | But you can kind of think
about them the same way.
| | 04:39 | Now what this leads to is something
that Objective-C is notorious for,
| | 04:43 | particularly, when people are new to it
which is method names that are really,
| | 04:47 | really, really long because if you
think about it this way any method name
| | 04:51 | that's been defined to accept
multiple arguments is going to have multiple
| | 04:56 | pieces to it and that leads us to -- I
will show you a couple of my favorites.
| | 05:00 | Let's say the NSFileManager has a method
called replaceItemAtURL: withItemAtURL:
| | 05:06 | backupItemName: options:
| | 05:08 | resultingItemURL: error:
| | 05:11 | Doesn't exactly roll off the tongue or
perhaps even better than that one, in the
| | 05:15 | built-in NSBitmapImageRep, we have --
well, I am not going to read this but you
| | 05:20 | can see it is a fairly long method name.
| | 05:22 | Now the big benefit of doing it this
way is even though it gives you a lot more
| | 05:26 | code to read and as you could you can
split it across multiple lines, it becomes
| | 05:31 | more readable in an actual program
because instead of a smaller method call,
| | 05:36 | where you are just passing multiple
parameters and you don't really know what
| | 05:40 | those parameters are, there are all meant here.
| | 05:42 | It's obvious what they are and that's why
Objective-C has the really long method names.
| | 05:47 | And most of the developers I
know that have spent some time with
| | 05:50 | Objective-C actually begin to prefer
it this way because it does make for
| | 05:54 | more readable maintainable code.
| | 05:55 | Now lastly, I am going to talk about
here is nested method calls, just as in dot
| | 06:00 | syntax that you could pass in a
argument into a method or you could actually
| | 06:06 | just nest in another call to a different
function or method, you can do the same
| | 06:10 | thing in Objective-C.
| | 06:12 | instead of the standard Objective-C
where I have been using the in the
| | 06:15 | argument, we can add another set of square
brackets and nest inside it another method call.
| | 06:21 | The interior one will be evaluated
first and the result of that will be fed
| | 06:26 | into the exterior one.
| | 06:28 | I don't tend to go any deeper than two
levels though you can, but these will be
| | 06:32 | passed just the way you
would expect them to be passed.
| | 06:35 | So that gives us the way of calling
methods in Objective-C and let's go and step
| | 06:41 | on a little further and we will
actually see what methods are available to us.
| | Collapse this transcript |
| Using existing classes in the foundation framework| 00:00 | Sure, you're going to write your own
classes, but you're likely to spend way
| | 00:04 | more time writing code that
users wants that already exist.
| | 00:08 | One of the challenges when you're new to
Xcode and to Objective-C is finding the
| | 00:12 | right ones, finding the
classes, finding the methods.
| | 00:15 | Let's take a look at how.
| | 00:16 | I am going to make a new Xcode project.
| | 00:17 | Once again, it will simply be a Mac OS X
Application and a Command Line tool.
| | 00:23 | I'll call this one ExistingClasses, and
make sure to have a type of Foundation,
| | 00:28 | not Core Foundation, but Foundation.
| | 00:31 | The whole reason for selecting
Foundation is so that our project is already
| | 00:36 | linked to the Foundation.framework.
| | 00:38 | That simply means link our code to a
whole bunch of prewritten code that
| | 00:44 | includes very basic datatypes, things
like, NSString, NSDate, NSCalendar that
| | 00:50 | I'm likely to want to use in pretty
much every single project I'll ever write.
| | 00:54 | So if I open up my ExistingClasses, I'm
going to jump into the main file here.
| | 01:00 | Now we've already worked with NSStrings,
but if I hadn't done anything with it,
| | 01:05 | how am I going to find information about this?
| | 01:08 | Well, we've already seen that we do
have the code sense, this automatic code
| | 01:13 | completion here that as I start to
type, it's going to help me do this.
| | 01:17 | This is a good thing, particularly if
you don't remember the case sensitivity,
| | 01:21 | because it doesn't matter here.
| | 01:22 | So I am going to type in NSString and
just create something super simple here.
| | 01:29 | Not really interested in the
contents, more in the NSString itself.
| | 01:33 | So if I wanted to find out what
was available to me, I have a couple
| | 01:36 | of different options.
| | 01:37 | One is, if I had the Utility section
open on the right and I can just toggle
| | 01:42 | this on and off with this button up
here on the top right, I have these two
| | 01:46 | sections on the top.
| | 01:47 | But if I select the one with
the wavy lines, that's Quick Help.
| | 01:50 | What that means is if I have my cursor
selected in NSString, Quick Help will
| | 01:55 | show me introductory paragraph, point me
to the NSString class references, point
| | 02:01 | me to the String Programming Guide, and so on.
| | 02:04 | You want to get comfortable
with looking up Class References.
| | 02:07 | So I am going to click that.
| | 02:09 | It's going to open up the other
window of Xcode, the Organizer window.
| | 02:13 | It's taking me right now to
the NSString Class Reference.
| | 02:16 | There is a lot of information when
you look in the Reference Library.
| | 02:20 | There is a lot of information about strings.
| | 02:22 | But as we come down, we'll see all
the tasks we can perform, and these are
| | 02:26 | basically telling us all the methods that exist.
| | 02:29 | So for Creating and Initializing
Strings we have a bunch of options.
| | 02:32 | Creating and Initializing a String from
a File, or URL, Getting Characters, and
| | 02:37 | Bytes, Combining Strings,
Dividing Strings, Finding Strings.
| | 02:40 | There is a whole bunch of stuff going on here.
| | 02:43 | In any of them I can take a look, say
the Changing Case section, find one like
| | 02:47 | uppercaseString, and click that to tell
me a little bit more about this method.
| | 02:52 | Now, what this one is telling me is
that it's a method called uppercaseString
| | 02:56 | and it's going to return a pointer to
an NSString object, and the dash at the
| | 03:00 | start of it shows me that
it is an instance method.
| | 03:04 | So it needs an instance of
the NSString object to work on.
| | 03:07 | Okay, so how might we use it?
| | 03:09 | Well, I jump back into this code here,
and I do have an instance to work on.
| | 03:13 | I've got an instance called message.
| | 03:15 | So while I could actually just
use my Square Brackets and say
| | 03:19 | message uppercaseString.
| | 03:21 | Well, it's going to
return a new NSString pointer.
| | 03:26 | I need somewhere to put it.
| | 03:27 | So I better create a new one.
| | 03:31 | I'll call it message2.
| | 03:33 | Sure, we're working with basic, basic
stuff here, but just to prove that this
| | 03:37 | works, let's put down NSLog, The result
is, and the placeholder that I need to
| | 03:43 | use for a string is not percent sign i,
or percent sign c, or percent sign f,
| | 03:47 | but percent sign, @ sign.
| | 03:49 | Actually that isn't specifically for a string.
| | 03:52 | That's a placeholder for an object.
| | 03:55 | So we're creating a simple
NSString object or message on Line 9.
| | 03:59 | We're then calling its uppercaseString
method to return an uppercase version of
| | 04:04 | it and store that in message2,
and then we're outputting message2.
| | 04:08 | Again, nothing particularly exciting,
just talking about the kind of rationale
| | 04:13 | for how we find what we're looking for,
and of course spitting out the results.
| | 04:17 | The result is HELLO in all uppercase. Fine.
| | 04:20 | So what else can we do?
| | 04:21 | Well, let's create a different kind of object.
| | 04:23 | What I am going to do here
is type NS and put in NSDate.
| | 04:26 | Now, you'll notice as I start to type, we
do have a bunch of different options here.
| | 04:32 | If you look at the start of them,
you'll see that there are different icons.
| | 04:35 | Ks and Ts and Cs, and you'll see
hash marks, all that kind of stuff.
| | 04:40 | The C is representing a
Class. So NSDate is fine.
| | 04:44 | NSDate, it's a class, we're
creating an object, so we need a pointer.
| | 04:47 | I'll call it myDate.
| | 04:48 | And now I am thinking, well, now what
do I do, because I can't just create a
| | 04:52 | date with say NSString object.
| | 04:54 | So how do I create a date?
| | 04:56 | Well, maybe I don't know.
| | 04:57 | So the easy way to do this is I want
to jump to the Date Class Reference.
| | 05:01 | Well, I'd close down my Quick Help,
so I could bring it back open again.
| | 05:05 | But a quicker way and one that I use
all the time and you probably will too
| | 05:09 | is you hold down the Option key, and
what will happen is your cursor changes
| | 05:14 | into this little crosshair, and
you mouse over the class that you're
| | 05:17 | interested in, and click.
| | 05:19 | What that does is pop-up a little
window here telling you about the class,
| | 05:24 | little bit of an introduction, and
then telling you where it's Declared, and
| | 05:27 | where the Reference is, even pointing me
to the Date and Time Programming Guide.
| | 05:30 | That looks pretty interesting,
but really all I need is the Class
| | 05:33 | Reference right now.
| | 05:35 | If I start looking through that,
the best place to jump to is Tasks.
| | 05:39 | What are the core tasks I want to do?
| | 05:41 | Well, I want to Create
and Initialize Date Object.
| | 05:44 | I have a whole bunch of options
here, but the first one is date.
| | 05:47 | Let's take a look at that. Jump in there.
| | 05:50 | It says that this will create and return a
new date set to the current date and time.
| | 05:54 | Yeah, it looks exactly what I'm looking for.
| | 05:56 | In fact, it says the following code
sample here that actually says how to get
| | 06:00 | the current date, even
storing it in a pointer object.
| | 06:03 | So I'm going to just Copy
that code and put that in here.
| | 06:08 | So I'll write in NSDate date, and
then I better prove that this one works.
| | 06:13 | So we'll write out an NSLog message,
The date is, and I need to put my
| | 06:18 | placeholder, which will
be percent sign, @ sign.
| | 06:22 | Again, percent sign, @ sign is
what we'll use for an NSString.
| | 06:25 | It's what we'll use for an NSDate,
because it's the generic placeholder for an
| | 06:29 | object, and the name of my object was myDate.
| | 06:33 | Save that, Run it, and we're
getting both our messages out.
| | 06:36 | the uppercase HELLO, and then
just the output of the date and time.
| | 06:41 | Again, not tremendously exciting stuff, but
it does expose a couple of questions here.
| | 06:45 | So I've written two lines that call methods.
| | 06:50 | Line 10 calls the uppercaseString method
of the message object and Line 14 calls
| | 06:56 | the date method of the NSDate.
| | 06:59 | Now, there is a big difference here,
because on Line 10 I use the name of
| | 07:04 | the object, the name of the instance,
whereas on Line 14 I use the name of the class.
| | 07:09 | So what's happening here?
| | 07:10 | Well, if you are already familiar
with object orientation, you'll know that
| | 07:14 | there can be class methods and instance methods.
| | 07:17 | That means when the classes are defined,
some of the methods are designed only
| | 07:22 | to work on an instance, whereas
other methods are defined to work on the
| | 07:26 | entire class itself.
| | 07:28 | Now, the question is, well, how do you know?
| | 07:29 | Well, it will tell you.
| | 07:31 | If I go back into my NSDate Class
Reference, again, I'll hit the Option key, and
| | 07:36 | click over NSDate, jump into Class Reference.
| | 07:39 | When I come down to see the different
things I can do, notice that my Tasks here
| | 07:44 | all begin with either a plus or a minus sign.
| | 07:48 | Now, if you're coming from something
like C# or Java, you'll be forgiven for
| | 07:51 | thinking this might mean
public or private. It doesn't.
| | 07:54 | The plus sign means these are class
methods and the minus sign means these
| | 07:59 | are instance methods.
| | 08:01 | The immediate impact of that means that
when I am using the square brackets to
| | 08:05 | call them, Objective-C will make
sure I'm doing the right thing.
| | 08:09 | If I'm calling the uppercaseString
method, Objective-C will make sure that I'm
| | 08:13 | calling it on an instance on NSString.
| | 08:16 | If however I'm calling the date method,
Objective-C will make sure that I'm
| | 08:20 | using the name of the class, which is NSDate.
| | 08:24 | Now, we'll get a little more into class
versus instance methods when we start to
| | 08:28 | design our own, but that's that plus
sign and minus sign, and you'll run into
| | 08:32 | that as you start to look through the
Class Reference documentation for your
| | 08:37 | different available classes.
| | Collapse this transcript |
|
|
6. Memory ManagementWhat's new with memory management?| 00:00 | When we make a new project in Xcode.
whether that's a Command-line tool,
| | 00:04 | or an iOS application, or a Mac desktop, or
laptop application. We now have the option
| | 00:09 | to turn on something called
Automatic Reference Counting.
| | 00:12 | This was made available with Xcode 4.2 in
late 2011, so it was not an option when I
| | 00:18 | first recorded this course and obviously for
many years before that, and this rather innocent
| | 00:22 | looking check box represents the biggest change to
learning Objective-C, and it's a welcome change.
| | 00:28 | Focus here on the word Automatic. What it
means is by checking this something can now
| | 00:33 | be done automatically that used to be done
manually. Meaning we used to have to write
| | 00:37 | code and with this checked we don't have to
write that code anymore, and that code is
| | 00:41 | all about memory management, but I can't
explain what this is doing automatically until we
| | 00:47 | see what it would do manually. So
here's how we're going to do this.
| | 00:51 | The next four movies cover conventional manual
memory management in Objective-C. Memory Management
| | 00:59 | as you had to do it prior to late 2011, so
any Objective-C project you'd run into that
| | 01:04 | was created before that, which also means a
lot of what you'll see for sample code out
| | 01:09 | there on the web, and how it is even right
now if you have that check box unchecked.
| | 01:14 | If you're going to be doing Objective-C, you
need to understand manual memory management.
| | 01:20 | Even if you don't have to actually do it
anymore, and it's only from watching the next four
| | 01:24 | movies that I can then talk about the Automatic
Reference Counting feature, and you'll understand
| | 01:29 | why it's important, how it works, and why
you'll really enjoy having it. And towards the end
| | 01:35 | of this course I'll also talk about upgrading
older projects, projects created before late
| | 01:40 | 2011, so they can use the new
Automatic Reference Counting feature.
| | 01:45 |
| | Collapse this transcript |
| Memory management in Objective-C| 00:00 | All right, next up, Memory Management,
a term that strikes fear into the hearts
| | 00:04 | of programmers everywhere,
and it really shouldn't.
| | 00:07 | See Objective-C wants you to manage
memory for every object you create, not
| | 00:13 | Ints, Floats, Chars, Bools but objects
whether those objects are coming from
| | 00:18 | your own classes or from classes
in any of the other frameworks.
| | 00:22 | Now the concept here isn't hard to understand.
| | 00:25 | You write code to say when those
objects are created, so you should write code
| | 00:29 | to say when you're done with them.
| | 00:32 | True in my languages things like Java,
C#, Ruby, Python all the scripting
| | 00:37 | languages, you don't
really have to think about this.
| | 00:40 | You just make the variables that you
need and the language takes care of
| | 00:44 | cleaning up your mess.
| | 00:46 | This is usually done by part of the
language called a Garbage Collector.
| | 00:50 | Now, Objective-C actually has a
Garbage Collector kind of, see it wasn't
| | 00:55 | originally part of the language, they
added it a couple of years ago and we are
| | 01:00 | not going to use it in this course.
| | 01:01 | and there are four main reasons why not.
| | 01:04 | One, the main one, Memory
Management is a baseline core skill for any
| | 01:12 | Objective-C developer, end of story.
| | 01:14 | Two, garbage collection can't be used
on the iPhone, it can't be used on the
| | 01:18 | iPad, and it can't be used on
Mac OS X versions prior to Leopard.
| | 01:23 | So if you are going to write apps for
any of those platforms you have to do
| | 01:26 | manual memory management.
| | 01:28 | Number three, unlike all the other
garbage collection languages that I
| | 01:32 | mentioned, garbage collection is
never the default in Objective-C.
| | 01:37 | You have to choose and change settings
in your own project and often write code
| | 01:42 | just to opt into garbage collection.
| | 01:45 | and four, to even use garbage
collection you have to understand the normal
| | 01:50 | way of doing things.
| | 01:51 | So even if your aim is to use it, step
number one is understand manual memory management.
| | 01:57 | And here's the secret.
| | 01:58 | It's really not that bad.
| | 02:00 | It may not be as easy as a
scripting language but memory management in
| | 02:04 | Objective-C is not that hard.
| | 02:06 | It's not as bad as memory
management in C and certainly not as bad as
| | 02:11 | assembler, because we don't have to
worry about manually taking care of memory
| | 02:15 | addresses and that kind of thing in
Objective-C, we use something called
| | 02:19 | Reference Counting.
| | 02:20 | So let's see how we get into that.
| | 02:23 | Here's the way Reference Counting works.
| | 02:25 | Your app start, so command line app, a
desktop app, iPhone doesn't matter which,
| | 02:30 | and an area of memory is
available for your objects to use.
| | 02:34 | You write code to create an object.
| | 02:37 | Now, right now let's not worry too
much about the code being used here.
| | 02:40 | Whatever it is, an object is created and an
area of memory is cleaned for that object.
| | 02:46 | What you have is a pointer to an area of memory.
| | 02:49 | What happens is that object gets
what's called a retainCount. It's a number.
| | 02:54 | It's a number saying who
cares about this object?
| | 02:57 | And when the object is
created, the retainCount is 1.
| | 03:01 | You then work with the object.
| | 03:03 | Use the square brackets to call methods
using the pointer and when you are done,
| | 03:08 | you issue a call to release the
object and the retainCount goes to 0.
| | 03:15 | Objective-C then says hey!
| | 03:17 | It's an object that nobody cares about
and it blows away that area of memory and
| | 03:21 | makes it available for another object to use.
| | 03:24 | You never explicitly tell Objective-C to
destroy the object, you simply release it.
| | 03:29 | So that doesn't seem so hard and it isn't
if your application is as simple as this.
| | 03:35 | The issue is what happens when you start
creating objects and passing them around?
| | 03:39 | So let's kind of recap this idea.
| | 03:42 | We issue a line of code to create the object.
| | 03:44 | It's created with the retainCount of 1.
| | 03:46 | Well instead of then just using that
pointer what happens if I call some other
| | 03:52 | method of some other
object and I pass this one in.
| | 03:55 | Can I then immediately
release it? Well possibly.
| | 03:58 | So what should happen is that in the
method that I am passing it to, they issue
| | 04:04 | what's called a Retain Message and
that would up the retainCount to 2.
| | 04:10 | They get rid of it, they
issue their own release.
| | 04:13 | It takes the retainCount down to 1, I
issue a release it takes retain to 0 and
| | 04:18 | then it blows it away.
| | 04:20 | But that's making the assumption that the
method I am calling properly issued a retainCount.
| | 04:25 | Here are the real two dangers when
you're working with manual memory management.
| | 04:29 | We create a class, we use
that class, we release it.
| | 04:36 | The memory goes away.
| | 04:37 | What we still officially have is a
variable called myObj in this case.
| | 04:43 | This is what's referred to as a
dangling pointer, and what that means is if
| | 04:48 | after I release it, sometimes later I then
try and use it, we have a problem on our hands.
| | 04:55 | We're using the pointer to access
an object that doesn't exist anymore.
| | 05:00 | Now, the flip side of this is we might
make another new object, we start to call
| | 05:05 | the methods of it and then we don't release it.
| | 05:07 | What we have here is a memory leak.
| | 05:12 | Sure, no one is going to notice a
small string or two but when you're working
| | 05:15 | with audio, video, hundreds or
thousands of complex objects, it adds up, and
| | 05:20 | on the iPhone and iPad, this will often cause
your app to be killed by the operating system.
| | 05:25 | If you've ever been using an app on
the iPhone and it suddenly just goes away
| | 05:29 | and takes you back to the Home screen,
that's usually why, and these two
| | 05:33 | issues happen when people lose track
of whether they should retain or they
| | 05:37 | should release an object.
| | 05:39 | And basically the way to be disciplined
about this is to realize there really is
| | 05:43 | one rule of memory management.
| | 05:46 | If you own an object, it is
your responsibility to release it.
| | 05:51 | That kind of begs the question,
what does that mean to own an object?
| | 05:55 | Well, you own an object, if you created
it or if you copied it or you retained it.
| | 06:01 | Now it doesn't happen accidentally,
there are specific words we will use in
| | 06:05 | Objective-C to create, or copy, or
retain an object and we haven't really
| | 06:10 | used these words yet.
| | 06:11 | But if these magic words are in your
code they should be matched up with a
| | 06:15 | release method call.
| | 06:17 | Now, the flip side of this one rule just
phrased a different way is if you don't
| | 06:23 | own the object, you must not release it.
| | 06:25 | So if you're not using these magical
words to create, copy or retain it, you
| | 06:30 | must not pair it with the release,
because what's quite common particularly for
| | 06:35 | beginning developers is they're not
sure if they're supposed to release
| | 06:38 | something, so they just release it just in case.
| | 06:40 | Well, no, if you don't own the
object, you must not release it.
| | 06:45 | But really to get more into this we
need to be specific about those words, what
| | 06:50 | are those words that we use to
manually take charge of creating objects?
| | 06:55 | So we're going to get into that next.
| | Collapse this transcript |
| Object creation| 00:00 | So we've created a few objects along the way.
| | 00:02 | We've create some NSStrings, we have
created some NSDates, but we haven't really
| | 00:07 | been doing it the right way
and here is the right way.
| | 00:12 | Let's say our program begins and we've
got some memory that we want to play with.
| | 00:16 | I am going to write a line of a
code to create an object correctly.
| | 00:19 | I am using the NSDate class though I
could use any class here, so I use the
| | 00:25 | name of the class NSDate and
then the asterisk meaning pointer.
| | 00:29 | Then I am going to name my variable,
I'll call it myDate and set it equal
| | 00:33 | to [NSDate new], I am calling the new
method of the NSDate class and I am calling
| | 00:42 | this as a class method, I don't have
an instance of this yet, I can't call
| | 00:46 | an instance method.
| | 00:48 | What this is going to do is actually
create an instance, create an object for
| | 00:53 | me and it does this in two stages, there
are two very separate parts when I use new.
| | 00:58 | The first stage is allocation.
| | 01:00 | What that means is object C is going to
out to that area of memory and carve out
| | 01:05 | a space big enough to hold this object.
| | 01:08 | The second stage is initialization.
| | 01:11 | It's going to go through the object,
figure out what it's made off and
| | 01:14 | initialize variables
internally that could be very simple.
| | 01:18 | That could be very complex.
| | 01:20 | It depends on the class definition and
the final stage here is it's going to
| | 01:24 | return the address in memory of that
object that is what the pointer variable
| | 01:29 | myDate will hold is the address of this object.
| | 01:33 | All classes in Objective-C have a new
method that will do both the allocation
| | 01:39 | and initialization stages and I like
to show this one because new is a very
| | 01:44 | common keyword for object oriented
languages for creating an object.
| | 01:49 | However, even though you can use it in
Objective-C, it's not that common.
| | 01:53 | Because there are two stages allocation
and initialization what you'll commonly
| | 01:58 | see instead is those written explicitly,
one part that just does the allocation.
| | 02:04 | So in this case I am saying
NSDate *myDate = NSDate alloc.
| | 02:09 | alloc instead of new.
| | 02:11 | That will go out to that area of
memory, carve out the space and return the
| | 02:16 | address in memory, I now have a
pointer pointing to the area of memory.
| | 02:20 | I have an instance of NSDate.
| | 02:23 | What I'm then going to do is call the
init method and it's an instance method
| | 02:28 | here so I'll call it on myDate not
on NSDate and that will go through and
| | 02:33 | initialize this object and set the
variables and do whatever the initialization
| | 02:38 | needs to do there and this is the
most common way that you'll see it in
| | 02:41 | Objective-C is the explicit
allocation and initialization done separately.
| | 02:47 | Although because this is the most
common way, you don't typically spread it
| | 02:51 | across two lines you don't have to.
| | 02:53 | You can nest one inside the other.
| | 02:56 | So instead of it being written on
two lines, you'll typically see it like
| | 02:59 | this, a nested call first to alloc which
returns the instance and then to init on the instance.
| | 03:08 | This is the most common way that you
will see object instantiation in Objective-C.
| | 03:14 | You will see it all over the place.
| | 03:16 | It will just follow this general pattern,
class name, class alloc, init, Person
| | 03:20 | alloc, init, Dog alloc, init, customer
alloc, init, or even NSAutoReleasePool =
| | 03:27 | NSAutoreleasePool alloc init, if this
looks vaguely familiar that's because this
| | 03:32 | last line here is the first line you're
going to see on pretty much any project
| | 03:36 | that you make an in X code.
| | 03:38 | It's setting up the AutoReleasePool,
with the explicit allocation and
| | 03:43 | initialization stages.
| | 03:44 | Now what's quite common depending on
what language you come from is you might
| | 03:47 | look at this and think well, why on
earth would I want to do the nested call
| | 03:52 | and the alloc init when I could just say
new and new would do exactly the same thing?
| | 03:56 | Well, there is a great reason.
| | 03:59 | You see you'd often don't just have an init
method, you often have several init methods.
| | 04:05 | So we might do an allocation and
then we have a slightly different
| | 04:09 | initializer method.
| | 04:11 | You might have init with name when
you're creating a person object and it allows
| | 04:15 | you to pass some information into that,
initializer that when you're working
| | 04:20 | with an NSString, there is actually an
init method called init with contents of
| | 04:24 | files, there is init with contents
of URL, there is init with CString.
| | 04:28 | There's a whole bunch of
different ways to initialize that object.
| | 04:33 | With the NSDate there is an init with
time interval since 1970 that just expects
| | 04:39 | some seconds to be passed in.
| | 04:41 | These are all multiple ways to control
the instantiation and the initialization
| | 04:46 | of an object and you wouldn't
help them if you just used new.
| | 04:51 | So that's the big reason for it.
| | 04:53 | But here's the thing.
| | 04:55 | alloc is one of those magic words.
| | 04:57 | If you have written some code for any
class that says alloc and init, any of the
| | 05:02 | inits, or you've written
new, then congratulations!
| | 05:06 | You, I know the proud owner of an object
and it is your responsibility to release that.
| | 05:13 | An object is not just for Christmas.
| | 05:14 | It's for life or at least the lifetime
of your program if you're not careful and
| | 05:19 | if you don't control the lifetime.
| | 05:21 | So let's revisit this and see what
would actually do here, back to our
| | 05:25 | little memory space.
| | 05:27 | We run the line of code that
creates the object with an alloc and init.
| | 05:31 | It grabs the space. It initializes it.
| | 05:34 | It returns the address
and puts it in our pointer.
| | 05:37 | We then use that pointer to access the
methods of that object and play around
| | 05:42 | with and do whatever we want with it.
| | 05:43 | When we're done, we use the pointer
and we call release on that object.
| | 05:50 | That will take our retain count down
to zero and although you can control
| | 05:55 | exactly when at some point the Objective-C
runtime will say okay, nobody's using
| | 05:59 | that object anymore, I can reclaim that
space, I can use it for something else.
| | 06:03 | Now something to be aware of:
| | 06:06 | technically at this point you still have
the pointer variable myDate which still
| | 06:13 | contains an address in memory.
| | 06:16 | Well, you had to have up to this point
because you just called release on that
| | 06:20 | pointer and you had to have the pointer
around and that's not a terrible problem
| | 06:25 | although this technically is a dangling pointer.
| | 06:27 | You don't want to use
the pointer myDate anymore.
| | 06:30 | You don't want to accidentally try and send a
message to that object that no longer exists.
| | 06:36 | What you can do it's optional, you
don't have to, is you can set myDate = nil.
| | 06:42 | not null, but nil, N-I-L is
the word that we use here.
| | 06:46 | What that will do is clear out
that address in that pointer variable.
| | 06:52 | Now an interesting point for those of
you from other object-oriented languages
| | 06:56 | technically at this point, I actually
could try and call a method on myDate.
| | 07:02 | If you try and send a message to a nil
object, it will just be ignored at one
| | 07:05 | crash your program the way some languages would.
| | 07:08 | It's not really a big deal because
after all there is no point whatsoever
| | 07:12 | in trying to do there.
| | 07:13 | So hopefully it won't happen anyway,
but technically you could do it.
| | 07:17 | Although this code is very simple,
the alloc, init is the classic way to
| | 07:22 | instantiate or create a new object and
if you're going to have that, you need to
| | 07:27 | release the object as well.
| | 07:29 | It's your responsibility.
| | Collapse this transcript |
| Using autorelease pools| 00:00 | If you use any of the magic words in
working with your objects, you use Alloc,
| | 00:05 | you use New, or you use Retain, or you use Copy.
| | 00:10 | Those are those indicators that tell
you it's your responsibility to match one
| | 00:14 | of those with a release.
| | 00:16 | Let's say we start off with something
simple, we just do a basic Alloc in init
| | 00:20 | to create that object.
| | 00:21 | The object is created with a retain kind of 1.
| | 00:24 | You then use that pointer to access
the methods of that object, but at some
| | 00:28 | point it's your responsibility to create a
release, because you used the word Alloc.
| | 00:32 | You then call release, the retainCount
goes to zero and it gets taken care of,
| | 00:36 | you've done your duty.
| | 00:38 | If you do a little more, you create the
object with Alloc in it and then you say
| | 00:43 | call retain on the object, the retain
goes up to two, you'll call it again, the
| | 00:47 | retain goes up to three, you call it
again, the retain kind of keeps going up.
| | 00:52 | You need to match each of those
calls to retain with a release.
| | 00:56 | it's always your
responsibility to take it back down to zero.
| | 01:00 | But you have one more option.
| | 01:04 | anytime you call release on an object,
you could substitute that with the word
| | 01:09 | auto-release instead.
| | 01:11 | Now this has nothing to do with garbage
collection, don't be misled by this word
| | 01:15 | auto, you're still very
involved here in memory management.
| | 01:19 | Release means release it now,
reduce the retainCount now.
| | 01:23 | auto-release means release it later.
| | 01:25 | Well, there is a vague term if ever
there was one, what does it mean later?
| | 01:30 | Well you see, when you call auto-release.
| | 01:33 | instead of immediately reducing the
retainCount, what it does is it adds an
| | 01:37 | entry to something called the Auto-release pool.
| | 01:40 | An Auto-release pool sounds complex. It isn't.
| | 01:43 | It's just a list of objects that
need to have release called on them at
| | 01:48 | some point later on.
| | 01:49 | And when you call auto-release on
your object, it adds it to that list.
| | 01:54 | Let's say along with a bunch of
other objects that might be added by
| | 01:57 | different parts of your code.
| | 01:58 | Your code continues on, and at sometime
in the future there is a call to drain
| | 02:03 | the pool, this sounds complex too, isn't it?
| | 02:07 | It just means go through the list and call
release on every single object in the list.
| | 02:14 | So when is the pool drain?
| | 02:15 | Well, in a typical command-line tool
that we've been working with, on line 19
| | 02:20 | here, the pool is drained.
| | 02:21 | it basically means all your auto-
release objects will be released right at the
| | 02:25 | end of the main function.
| | 02:26 | That's pretty simple.
| | 02:27 | That's for the command-line tool
that's designed just to blast through and
| | 02:30 | finish as quickly as possible.
| | 02:32 | And in iPhone or a Desktop app, which
could be running for a lot longer, the
| | 02:36 | default behavior is that the auto-
release pool is drained repeatedly at the end
| | 02:41 | of every event loop.
| | 02:42 | Well, what's an event loop?
| | 02:43 | Something like touching a button in
the application, the button goes and does
| | 02:48 | what it needs to do and comes
back to the normal state of the app.
| | 02:51 | That would be an event loop.
| | 02:52 | So the pool might only last for
milliseconds before it is drained.
| | 02:56 | The objects don't just hang
around for some random time.
| | 03:00 | Now my suggestion is that early on in
your Objective-C career you avoid writing
| | 03:05 | the word auto-release as much as possible.
| | 03:07 | And it's not because of
performance or memory implications.
| | 03:11 | Sure, if you're using auto-release
your objects are lasting longer than they
| | 03:15 | need to, but that's not the main issue.
| | 03:17 | What happens is that I've seen many
beginners that tend to use auto-release all
| | 03:21 | the time, because they're not quite
sure if they can call release properly.
| | 03:25 | And if that's the reason you need to
become sure and figure out how to really
| | 03:30 | release an object, they should
never be a coin toss, maybe I'll use
| | 03:35 | auto-release, maybe I'll use release,
there are very specific times that you
| | 03:39 | should use auto-release, let me show you one.
| | 03:42 | The deal is you write a method that
needs to create and return an object.
| | 03:47 | this is often referred to as a Factory Method.
| | 03:49 | You don't know who's going to
call this method. It doesn't matter.
| | 03:52 | You're creating an object, you're going
to return it, but hang on, you've used
| | 03:57 | the magic word Alloc, and you haven't
paired it with the release, but it's your
| | 04:01 | responsibility to do that.
| | 04:02 | Where you'd write the code that says release.
| | 04:03 | You can do it after the return.
| | 04:07 | you'll never hit this line.
| | 04:08 | Soon as you'd hit Return,
you'll jump out of the method.
| | 04:11 | We can't put it before the return,
because at this point where the retainCount
| | 04:15 | would drop to zero and the object could
be reclaimed, so instead what you do is
| | 04:20 | replace the call to release
with a call to auto-release.
| | 04:24 | You now know that release will be called
on this object at some point in the future.
| | 04:30 | You've done your duty.
| | 04:31 | you've taken care of your responsibilities.
| | 04:33 | The object will last long enough to
pass back to have a call this method.
| | 04:38 | Now whoever called this method should
hopefully be calling retain on the object,
| | 04:42 | if they want to keep it around, but
that's their problem and it's their
| | 04:45 | responsibility to release it later.
| | 04:47 | You've taken care of your
part of the problem here.
| | 04:51 | So that's how to manually auto-release
objects and work with auto-release pools.
| | 04:56 | Throughout those lines that we've seen
in our projects all along are all about
| | 04:59 | is auto-release pools.
| | 05:01 | However, even if you never write the
word auto-release, you may still end up
| | 05:07 | with a lot of auto-released
objects, and next up I'll show you why?
| | Collapse this transcript |
| Apple autoreleased objects| 00:01 | So we spent a lot of time focusing on
those words new, alloc, retain, and copy.
| | 00:06 | But as you've probably detected and
seen in some of the code we have written so
| | 00:09 | far, we can still end up with
objects without having used those words.
| | 00:14 | So what's the deal?
| | 00:15 | I am looking at a bit of simple code here.
| | 00:17 | I've written some code that creates six
objects, three NSStrings, and three NSDates.
| | 00:22 | And we've seen most of these, but a
couple of them are new, so I'll go
| | 00:25 | through them line by line.
| | 00:26 | Line 8 creates an NSString object,
just centered to do the word Hello.
| | 00:30 | We've seen that one before.
| | 00:32 | Line 9 and 10 is creating another
NSString using something called the
| | 00:36 | stringWithFormat method of the NSString class.
| | 00:39 | And this is a simple way of creating
a string using the same kind of format
| | 00:45 | specifiers that we've been using in
our NSLog messages where we can put
| | 00:49 | placeholders in the string and fill
the values out when the program runs.
| | 00:54 | And very similar to that, below on
line 11 and 12 I am using something
| | 00:57 | called initWithFormat.
| | 00:59 | Looks very similar but I can see that I
also have to do an NSString alloc and I
| | 01:04 | am doing that manually on line 12.
| | 01:06 | Coming down the line 14, this is the way
that we can create an NSDate object and
| | 01:11 | just set it to the date and time right now.
| | 01:14 | On line 15 we're creating another
NSDate with the dateWithTimeIntervalSince1970
| | 01:20 | passing in a certain amount of seconds.
| | 01:22 | And then on line 16 we're creating a
third NSDate object by copying the first one.
| | 01:26 | On line 18 I'll spit them out in an
NSLog message but I am trying to be a
| | 01:31 | good Objective-C coder.
| | 01:33 | So the question is, which
ones do I now need to release?
| | 01:38 | And for that it always goes back
to new, alloc, retain, and copy.
| | 01:43 | Or if you prefer we could use just
the word 'narc' to remember that.
| | 01:47 | So if I just quickly scan that code, I
don't even need to really know what those
| | 01:53 | methods do and what they are.
| | 01:55 | I am just scanning for those words
and I see them in precisely two places.
| | 01:59 | I see the word alloc on line 12
and I see the word copy on line 16.
| | 02:04 | And what that immediately tells
me is I need two release calls.
| | 02:08 | one for anotherMessage, and one for anotherDate.
| | 02:14 | The other four objects, I
don't need to call release.
| | 02:17 | So what's going on here?
| | 02:19 | May are they some kind of
special with pseudo-object.
| | 02:21 | no, they're all real objects.
| | 02:24 | They're regular objects.
| | 02:25 | But when you get hold of an object by
using say the stringWithFormat method on
| | 02:31 | line 10, you can make the assumption
that these are autoreleased objects.
| | 02:36 | What's happening is that there are a
lot of shortcut helper methods like
| | 02:40 | stringWithFormat and
dateWithTimeInterval and just the NSDate date method that
| | 02:45 | are creating and returning objects.
| | 02:47 | And you can make the assumption that
whatever is going on inside the NSString
| | 02:51 | stringWithFormat method, first allocs
and inits a string object and then calls
| | 02:57 | autorelease on it before it returns it to you.
| | 03:00 | And that means you don't call release
or autorelease on these objects, because
| | 03:05 | it's already been done.
| | 03:06 | Now I am occasionally asked, well,
should I call release or autorelease just in
| | 03:10 | case just to make sure?
| | 03:12 | And the answer is, No, absolutely not.
| | 03:14 | Because those objects have already
been added to the autorelease pool and you
| | 03:18 | can mess things up if you called
either release or autorelease on them.
| | 03:22 | It always goes back to that narc word.
| | 03:24 | If you didn't use new, alloc, retain,
or copy, you don't own that object.
| | 03:31 | And if you don't own it, not only don't
you have to call release on it, you must
| | 03:36 | not call release on it.
| | Collapse this transcript |
| Introduction to Automatic Reference Counting (ARC)| 00:00 | So that was Manual Reference Counting,
conventional memory management in
| | 00:05 | Objective-C, and still a very valuable thing
to know about. But let's talk about ARC, or
| | 00:09 | Automatic Reference Counting. Made available at the
end of 2011, and here's the great thing about it.
| | 00:14 | ARC is not something you have to be an expert
on, it's something the compiler does, although
| | 00:19 | you need to understand what it's doing, so
you can let it make your life easier.
| | 00:24 | ARC is all about simplifying that Memory Management
Code that most difficult, most tedious, the
| | 00:29 | largest cause of bugs in
any Objective-C program.
| | 00:32 | As we have seen, we use reference counting in
Objective-C. We create objects using alloc
| | 00:37 | and init, or other variance of that. We use
the object, but then we better take care of
| | 00:42 | releasing that object once we're done, so
that, that memory can be reclaimed.
| | 00:47 | Now, with one object and three lines of code, this is
not a huge problem. But when you have dozens
| | 00:51 | or hundreds or thousands of objects being
created, manipulated, passed around from method
| | 00:56 | to method or object to object, and you have
to keep track of them all, calling retain
| | 01:01 | on objects when you pass them around, so they
don't get released too soon, and then matching
| | 01:05 | that up with the release call as soon as
possible. You really have to envision every possible
| | 01:10 | path through the logic of your
application, and this can be painstaking work.
| | 01:15 | If you create an object, and then release
it too soon, you can have dangling pointers,
| | 01:21 | and dangling pointers can crash your
program if you then try and use them.
| | 01:26 | On the other hand, if you create objects and
release them too late, or don't release them
| | 01:31 | at all, and then you have memory leaks, and
the bigger your applications get, the harder
| | 01:36 | this gets to create successfully.
| | 01:39 | So Memory Management Code is the main reason
why a lot of people give up learning Objective-C,
| | 01:44 | it's the main reason that applications take
longer to develop or don't get finished at
| | 01:47 | all, and it's the main reason that finished
applications crash, which itself is the biggest
| | 01:53 | reason why certain apps are
rejected from the iOS or Mac App Store.
| | 01:58 | But with ARC, the question of when to retain
and when to release pretty much goes away.
| | 02:04 | You don't write release calls anymore, you
don't write retain calls anymore, you don't
| | 02:09 | think about that. You create your objects
the usual way, and then you just use them.
| | 02:15 | That's it! ARC, Automatic Reference
Counting takes care of cleaning things up.
| | 02:20 | Now, here's the really important thing to
understand. The idea of retain and release
| | 02:25 | calls has not disappeared, Objective-C
still uses reference counting. The language has not changed.
| | 02:31 | The only difference is you don't write the
retain and release calls anymore, the compiler does.
| | 02:39 | ARC is taking the fact that compilers have
gotten so good that anytime you build your
| | 02:44 | project, the compiler--in this case the
Compiler called LLVM, which is what Xcode uses behind
| | 02:49 | the scenes--is able to scan through your code
and determine all the possible paths through
| | 02:54 | it, figure out where your objects are being
used and where they are not, and synthesize
| | 02:58 | the retain and release calls at
the best point in your program.
| | 03:02 | The compiler is effectively generating the
same code that you would write yourself if
| | 03:07 | you were really, really good at writing
memory management code. Okay, you won't actually
| | 03:12 | see these lines being added to your code, it
doesn't physically change your source code
| | 03:16 | files, but this is effectively what it's
doing when you compile or build your project.
| | 03:22 | And with ARC turned on, and yes, you can turn
it off, but it is on for a new project by
| | 03:27 | default in Xcode, you will never have to
write a release call again, never write a retain
| | 03:32 | call again or an auto release call. And not
only don't you not write this code, with ARC
| | 03:38 | turned on, you can't write this code. If you
try and write a simple release call, the compiler
| | 03:45 | will complain, Xcode will
reject it and make you take it out.
| | 03:49 | So for the most part, learning ARC is
simply learning what it is you don't do anymore.
| | 03:53 | And in fact, you can take what I have told
you in the past few minutes and just go ahead
| | 03:57 | and make a new project and run with it.
You're good to go. That's it! Well, okay, there are
| | 04:02 | a few other pieces worth knowing. So I am
going to talk about some extra things about
| | 04:06 | ARC that might be useful to know and some
gotchas to be aware of. But you now know the
| | 04:11 | impact of day to day use of ARC, which is
pretty much, don't worry about writing retain
| | 04:16 | or release or auto release calls.
| | 04:19 | Create your objects the usual way using alloc
and init, use them, and you're done. And perhaps
| | 04:25 | the best thing about ARC is it will let you
concentrate your mental effort on your actual
| | 04:30 | problem on the interesting stuff about the
application you want to make, instead of the
| | 04:35 | headaches of memory management.
| | 04:36 | ARC is really, really good at this, and you
should be using it in every new Objective-C
| | 04:41 | project you create from now on.
| | 04:51 |
| | Collapse this transcript |
| What ARC manages| 00:00 | Automatic Reference Counting, ARC,
deals with Objective-C objects.
| | 00:04 | Nothing changes about how you use inits, or floats,
or chars, just objects. And nothing changes
| | 00:10 | about the way you create your objects. You
don't make your objects in some special new
| | 00:15 | way, you use alloc, init, or convenience
methods, the same way that you always have, and we
| | 00:20 | still use these pointers to our objects. And
it's your pointer variables that are the most
| | 00:25 | important piece of the ARC world.
| | 00:27 | It's how ARC can detect this object is still
relevant. As long as it can tell that there
| | 00:32 | is a variable that's accessible, that's in
scope, somewhere in your application, and it
| | 00:37 | points to as a reference to an object,
that object will continue to exist.
| | 00:42 | So ARC considers these normal object variables,
regular pointer like these, as being what are
| | 00:48 | called strong references. It is possible to
create what's called a weak reference, but
| | 00:53 | that's a topic for another time, and it's
a regular strong reference that keeps the
| | 00:59 | object alive, and as it goes through your
code, when ARC detects that there are no more
| | 01:04 | strong references to an object, perhaps their
variable pointing to it has gone out of scope,
| | 01:09 | or it's been set to something else, or even
been set to nil. ARC will generate the code
| | 01:14 | to release the object and the memory will
be reclaimed. That's important to understand
| | 01:20 | that ARC is not garbage collection. If you
have experience in a garbage collected language
| | 01:25 | like C#, or Java, recognize that ARC is not
the same thing at all because while it is
| | 01:31 | automatic memory management, it's being
done at compile-time, not at runtime.
| | 01:37 | Garbage collected languages need a
constantly running part of the runtime that monitors
| | 01:41 | memory usage of an application, and then it
jumps in to clean up when things get too big.
| | 01:46 | This is what's often referred to with the
wonderful term of non-deterministic finalization,
| | 01:50 | meaning, you can't determine, you don't know
exactly when it will happen, and that can lead
| | 01:56 | to slow downs in garbage collected applications when
memory is being reclaimed because it happens unpredictably.
| | 02:02 | This wasn't acceptable to Apple and garbage
collection as a technique for memory management
| | 02:07 | was never implemented in iOS, although
it did exist in Cocoa on the Mac Desktop.
| | 02:14 | But another garbage collection as a
technique in Apple development now pretty much goes
| | 02:18 | away, forget about it, and we are not going
to cover in this course. ARC is a much better
| | 02:23 | way of doing it. We don't have some big memory
management layer that's slowing our application
| | 02:28 | down at runtime. It's exactly the same
runtime model as before because it's the compiler
| | 02:34 | that's already done the work of figuring
out exactly where that memory management code
| | 02:39 | should go before the application is ever run.
| | 02:45 |
| | Collapse this transcript |
| The rules of ARC| 00:00 | Apple has a handful of formal rules
for using automatic reference counting,
| | 00:05 | it's not really a chore to have to memorize
these rules because if you break any of them
| | 00:09 | you'll get an immediate error and your
program won't even compile, it will be obvious.
| | 00:14 | Now the rules are there simply so ARC can
always figure out exactly what to do.
| | 00:20 | Only two of these rules are significant for all
developers. And you'll find a few of the others
| | 00:24 | to be edge cases that you're much more unlikely
to run into because they deal with legacy code.
| | 00:30 | So I'm going to show you the most important rules
here putting my two most important ones first.
| | 00:36 | Number one, don't call memory management methods,
you can't write retain or release or auto-release
| | 00:42 | in your code. ARC is doing the reference counting,
it's doing the retaining, it's doing the releasing
| | 00:47 | and you aren't, so don't get in the way.
| | 00:50 | A side effect of this is you can also no longer
access the retain count property of any object
| | 00:55 | that will be disallowed and there is no
reason to look at it. Now there is a less common
| | 01:00 | side effect of this, you can't
explicitly call the method called dealloc.
| | 01:05 | Now we haven't talked about dealloc yet, we
will in the next chapter, but just think of
| | 01:09 | it as the flip side of alloc. Every object is
allocated as part of its creation and deallocated
| | 01:16 | when it's destroyed, so all
objects have alloc and dealloc methods.
| | 01:21 | Interacting with dealloc was sometimes
necessary with complex objects, using manual reference
| | 01:27 | counting, but with ARC, you can't manually
call this even if you wanted to. So here is
| | 01:32 | a whole bunch of code you don't have to write
anymore, and if you try to, Xcode will immediately
| | 01:38 | complain and tell you that it's not allowed.
| | 01:41 | So here is rule number two. You don't, and
can't, use the NSAutoReleasePool object using
| | 01:47 | automatic reference counting. Now the concept
of an auto release poll that we talked about
| | 01:51 | earlier, that still exists, it's exactly the
same. But in the code, the old NSAutoReleasePool
| | 01:58 | object is replaced by the @autoreleasepool keyword.
| | 02:01 | Now I mentioned this earlier, that the old
style code that was used for years, looked
| | 02:06 | something like this. It generated the code
using NSAutoReleasePool that was followed
| | 02:11 | by a pool drain call. If you try to have this
code in a project with ARC turned on you'll
| | 02:18 | get an error message that this object is not
allowed. And this is why instead of this style
| | 02:24 | of code when you create a new project you'll see this
style of code using the at @autoreleasepool block.
| | 02:30 | And one of the great things is, as you'll see a
little later, if you want to change a project
| | 02:35 | from the older style to the newer style, so
that you can turn on ARC, it will do this
| | 02:39 | automatically for you. Now here's one more rule
worth mentioning, no object references in C structs.
| | 02:46 | Now I'm only going to mention this one in
case you come from a plane C background and
| | 02:51 | it's the second nature for you to make structs
that you're manually managing using the malloc
| | 02:56 | and free keywords. While you can still
create structs, Objective-C after all is built on
| | 03:01 | top of C, but you can't put object references
inside of them because this is just too confusing
| | 03:07 | for ARC to figure out.
| | 03:09 | ARC wants to manage Objective-C objects, and
it wants to manage all Objective-C objects.
| | 03:13 | And it can deal with complex objects,
multiple levels of objects inside other objects, just fine.
| | 03:19 | But it can't deal with objects inside
the old-school C structs that you're manually
| | 03:24 | managing the memory of yourself. So you can't
do it this way, and if you try you will get
| | 03:29 | another error message.
| | 03:31 | If you are a C programmer, you can still use
structs, but if you want object references
| | 03:36 | inside them, well, use objects as your data
structures. Now if you don't come from a C
| | 03:41 | background and you didn't even know you could
write this code, well, you don't have to worry
| | 03:45 | about this at all. Most Objective-C
developers I work with don't manually create C structs
| | 03:50 | or work with C-style memory allocation,
so this is a non-issue for most people.
| | 03:56 | There are a few other edge case rules, but
they're mostly to deal with migrating older
| | 03:59 | projects to ARC. And in the final chapter
of this course I have added a movie on how to
| | 04:04 | migrate non ARC projects to ARC. And I have
put it towards the end of this course simply
| | 04:09 | because I want to cover a few more ideas and
concepts first before we see how to do it.
| | 04:14 | But from this point on, if you're creating new
project, you should always have ARC selected.
| | Collapse this transcript |
|
|
7. Custom ClassesCreating your own classes| 00:00 | Apple provides over a hundred classes
in the Foundation framework, and there
| | 00:04 | are hundreds, if not thousands more in the
other available frameworks, but it won't be enough.
| | 00:08 | You'll need to write your own classes
and then create objects based on those classes.
| | 00:14 | In Objective-C, classes are written in two
very distinct sections, the interface and
| | 00:19 | the implementation, usually
done as two different files.
| | 00:23 | The interface done in a .h file is the simplest
part. This is the face that the class is presenting
| | 00:29 | to the world. It announces what this class
is promising to do, what methods it has, what
| | 00:35 | properties are available. It doesn't say how
any of it is done, it just says what's available.
| | 00:41 | The second part, the implementation done in
a .m file, well that's where the real work is done.
| | 00:46 | The implementation must live up to
the promises of the interface. It is the real
| | 00:52 | code of the class, and here's how we do it.
| | 00:54 | So I am jumping over to Xcode where I'm going
to create a new Xcode project, this will be
| | 00:59 | an OS X application. It is of course a Command-line
tool. I am going to just call this CustomClass.
| | 01:05 | Make sure that Automatic Reference
Counting is turned on, and it's a Type of Foundation.
| | 01:12 | I am just going to save it into my Documents
folder, again it doesn't matter where this goes.
| | 01:16 | I am using Xcode 4.3.3 here, as ever if you
have a different version, you may see slightly
| | 01:22 | different behavior. We have the standard main.m
file, but what I am going to do is come up
| | 01:27 | to my File menu in Xcode and
add a new class to this project.
| | 01:32 | If I come down to the New word, we have New
File here. And when we are adding a new file,
| | 01:38 | just like creating a new project we have a
lot of different templates, a lot of different
| | 01:41 | options we can select from. What I want to
choose is under the Cocoa section under Mac
| | 01:46 | OS X, and I want the first option here which
is an Objective-C class, and I'll click Next.
| | 01:52 | It's going to ask, what is this class called?
Well, I'm going to create a class to hold
| | 01:56 | some information about employees. Now class
names should begin with an uppercase letter,
| | 02:02 | it's one of the few things that we do in an
uppercase letter with Objective-C, and it's
| | 02:06 | not a technical requirement, it's just a
style guideline. So I'll type the word Employee.
| | 02:12 | Then Xcode is asking us, what is this new
class a subclass of? We are in an object-oriented
| | 02:17 | language, and yes we are always going to
inherit from another class. Other languages might
| | 02:22 | use the term child class, or derived class.
We say we are a subclass of something.
| | 02:27 | The default one that we are going to use,
the superclass, is going to be NSObject.
| | 02:33 | Every class you are ever going to work with in
Objective-C ends up inheriting from NSObject. It is the
| | 02:39 | base class, the parent, the superclass at
the top of the tree, and it will work just
| | 02:43 | fine for us here. We'll talk about what
NSObject gives us a little more later on.
| | 02:48 | So if I go ahead and click Next, it's
asking do I want to add these to my custom class
| | 02:54 | project. Yes, I do, so I'll click Create and
what I can see is I have two files that have
| | 02:58 | been added over here in my Project
Navigator Employee.h and Employee.m.
| | 03:04 | .h is our header file, it is our interface, and
the .m file is our implementation.
| | 03:13 | Technically, these don't actually have to be into separate
files, you could put everything together in
| | 03:17 | one file, but this is the way you'll almost
always see it done. It's the most useful way,
| | 03:22 | because your .h, your header file is that
public face of the class, it's how you say
| | 03:27 | what is it this class can do, and as you get
more comfortable with Objective-C you'll find
| | 03:31 | yourself just browsing and looking at other .h
files that Apple have created to understand
| | 03:36 | the capabilities of a particular class without
having to look at the actual implementation of it.
| | 03:42 | Now in many other object-oriented languages
we create a new class by using the keyword, class.
| | 03:45 | That's not what we do here. In Objective-C
a class is made of these two parts using the
| | 03:51 | keywords @interface, and the keywords @implementation,
and as long as we have those two parts we have our class.
| | 03:59 | So first, I'm going to go into the .h section,
the interface for this class. This is where
| | 04:03 | I describe the data and behavior that this
class promises to provide, what properties
| | 04:08 | and methods does it have. And I am going to start
off with something fairly simple and straightforward.
| | 04:13 | So inside the @interface, but before the @end,
this is where we name our properties and methods.
| | 04:20 | So I'm making an Employee class, and let's say
I want this employee to have a name property
| | 04:25 | and a birth date property and employee
number property just those three pieces of data.
| | 04:29 | Now there is a couple ways you can do this
and I will talk more about this in a moment.
| | 04:34 | We are going to start off with this Property
NSString *name. The @property is an Objective-C
| | 04:42 | keyword, then we have the type like creating
a variable, it's type NSString, and because
| | 04:47 | it's an object we need to have the pointer symbol.
So this is the way we define it.
| | 04:51 | I of course don't give it a value because
all I am trying to say here is that every
| | 04:55 | object created from this class will have its
own NSString that can hold a name, and I'll
| | 05:02 | add a couple more properties here, one will
be of type NSDate we'll call it hireDate and
| | 05:07 | another will be of type int, and we
will call that one employeeNumber.
| | 05:11 | So these are properties in Objective-C.
Properties let us define the data each instance of our
| | 05:16 | class should have, like variables they have a
type and a name. Now if you have already done
| | 05:20 | something with properties you might be thinking,
well there is something missing, I usually
| | 05:23 | see a bit more information with properties.
And that is true, we are going to get to that
| | 05:27 | in a second, I just want to show
a very simple example right now.
| | 05:31 | We're describing these properties in our
interface, and we may need to do a little work in our
| | 05:36 | implementation file to make sure that these
properties will work correctly. There is a
| | 05:40 | lot more to properties that's not visible
just from these lines of code and later in
| | 05:44 | this section we'll explore more about them.
But before that I also need to describe what
| | 05:49 | it is that every object of this class can do.
So not just the data of this class, but
| | 05:54 | its behavior as well. I need to
describe the methods of this class.
| | 05:59 | Defining methods is very similar to defining
functions, and we can actually think of a method
| | 06:03 | as a function that belongs to the class.
It's the same idea, a named block of code that
| | 06:08 | can take parameters and can return a value.
| | 06:12 | Now because we don't want to get confused
about whether something is a method or a C
| | 06:16 | style function, here's the format for
declaring a method in Objective-C, meaning we are just
| | 06:21 | trying to say that this method exists,
we are not yet saying what it does.
| | 06:25 | So I want to create a generic method called
someMethod here. Line 17 is how I might begin
| | 06:32 | with something really simple. In the same
way that when we work with functions, we are
| | 06:36 | giving this method a name, someMethod. The
word void is actually the return type of this
| | 06:42 | method, meaning it doesn't return anything.
| | 06:44 | Now when I am defining a method in the interface
in Objective-C what I do is surround the return
| | 06:49 | type with parentheses, and I do that
at the start rather than at the end.
| | 06:53 | Now if you remember when we looked some of
the class reference libraries we would see
| | 06:57 | a plus sign or a minus sign, and that's
saying whether this method is for an individual
| | 07:02 | instance of this class, or is it for the
entire class. And that's what I'm doing here, I'm
| | 07:07 | using the minus sign to say this method is
an instance method, there will be a different
| | 07:12 | copy of it for every instance of this class.
| | 07:15 | The way I am defining this method here it
doesn't take any parameters, which means I
| | 07:20 | don't put anything after the method name,
I just finish it with a semicolon.
| | 07:24 | In the next movie I'll show you how you
define other more complicated methods.
| | 07:28 | Now you might be thinking, well, where is
the opening and closing curly brace, where
| | 07:32 | is all the functionality of this method?
But again, we don't do any of that inside the
| | 07:37 | interface file. All we are
saying is that this method exists.
| | 07:41 | So other code and other programmers could
now look at this interface file and say, okay
| | 07:46 | you have a method called someMethod, it
doesn't take any parameters, and it returns void and
| | 07:51 | it's for the instance. Okay I can use it, I
can call it, I don't need to see anything else.
| | 07:56 | But if we are making these promises, we now
need to provide the implementation, the second
| | 08:00 | part of the class, the actual code that
provides the functionality that we are promising here.
| | 08:05 | So I am going to jump into the Employee.m,
our .m implementation file.
| | 08:11 | And everything we do here will be inside the @implementation
keyword, but before the @end. And I can already
| | 08:18 | see that I have got this exclamation mark
showing up here. If I click that, what it's going
| | 08:23 | to tell me is there is a few problems, and
in fact, there is seven problems right now.
| | 08:27 | Because we're not providing the implementation of
the promises that we made, so let's start doing that.
| | 08:32 | I know that my interface has three properties
that is three pieces of data and one method, one behavior.
| | 08:38 | So let's first deal with the
behavior. What I need to do is define the
| | 08:43 | method, someMethod, exactly as it was defined
in our header file. But provide the actual
| | 08:49 | implementation for it.
| | 08:50 | Now I can just copy and paste, or I can type
this out in full here, and I can even see as
| | 08:56 | I'm typing that it's helping me fill this out.
But as opposed to just finishing it with
| | 09:00 | a semicolon, in the implementation I need
to do the opening and closing curly braces
| | 09:05 | and actually have some kind of behavior here. And
let's just put in a very simple NSLog message.
| | 09:13 | I don't need a return statement here because
this method returns void, meaning it doesn't
| | 09:16 | return anything, but it's still complaining.
And that's because in Xcode 4.3 and earlier,
| | 09:23 | you need to match any property declaration in
the header file with a corresponding synthesize
| | 09:29 | statement in the implementation.
| | 09:32 | That needs to be put inside the @implementation
before the @end, so put it right after this.
| | 09:38 | It is an @synthesize, and you notice
as I'm typing this is popping up here.
| | 09:43 | In Xcode 4.4 and above, this synthesize
statement can happen automatically, otherwise we'd need
| | 09:48 | to write it ourselves. What we're synthesizing
are the properties we defined on the previous page.
| | 09:53 | So we had the property called name. I could
add another statement @synthesize for hireDate.
| | 10:02 | I could add another synthesize statement for
the employee number, or we could actually combine these.
| | 10:08 | In fact, we can have one @synthesize
line which is synthesize name, hireDate, and
| | 10:16 | you see as I'm typing it's giving me the code sense
employeeNumber. I finish that line with a semicolon.
| | 10:23 | In short, what this synthesize statement is
doing is to generate two methods for each property.
| | 10:28 | One to set its value and one to
retrieve or get its value, often referred
| | 10:33 | to--not just in Objective-C, but in many other
languages--as the property's getters and setter methods.
| | 10:39 | Again, we'll talk
more about that in just a moment.
| | 10:42 | I could hit Command+B here to build this
and we can see there are no issues.
| | 10:46 | Build has succeeded, there is no warning signs up here,
it looks good. Yes this is about as simple
| | 10:52 | a class as you could possibly
write, so let's prove that it works.
| | 10:56 | I have my interface, I have my implementation,
I'm going to jump across into a main.m where
| | 11:01 | I am going to actually instantiate this class
and use it. So I don't need the NSLog Hello
| | 11:06 | World statement, but I do put my own code in the
insert code here part inside the autoreleasepool block.
| | 11:13 | I want to create a new instance of that
employee class. Now if I start typing employee, it
| | 11:18 | doesn't know what I am talking about. This file,
this main.m, doesn't know about our Employee.h
| | 11:25 | and Employee.m. The way that we tell
it is we need a new import statement.
| | 11:29 | The same way that right now on line 9 we are
linking to the Foundation header file, I need
| | 11:34 | to link to the employee header file. So I
do that with another #import statement.
| | 11:41 | When you're linking to Apple's header files,
you typically use the less than and greater than signs.
| | 11:45 | If you're linking to header files
in your own project, you use the quotes.
| | 11:50 | So inside the quotes here I am going to start
typing Employee, and we can actually see that
| | 11:54 | it's already bringing up the .h and .m. I need .h,
so I'll hit the Return key to bring that in there.
| | 12:01 | Now this main.m file knows about the Employee
object, so I can actually create one.
| | 12:07 | I'll create a new Employee, this is an object so
it will be a pointer type. I'll call it fred
| | 12:11 | and fred =, we'll do a standard
object alloc and init creation.
| | 12:18 | You might wonder, well where did alloc and
init come from. Well, those methods are already
| | 12:22 | defined as part of NSObject, and because we're
inheriting from NSObject we will always have
| | 12:28 | them, which is a good thing. We don't want to
have to write our own code for every single
| | 12:33 | object just to make sure
that it can be instantiated.
| | 12:36 | That line is giving us a warning, but this
warning is actually just because we haven't
| | 12:40 | used that variable. Well, that's okay, we are
about to. I have got this pointer variable called
| | 12:45 | fred, so that means in square brackets
I can type the word fred, and then if I type
| | 12:50 | S I am actually getting the pop up for someMethod, it
recognizes that this object has this method inside it.
| | 12:57 | If I save that and run it, what we should
get is the actual popup and the little bit
| | 13:03 | of text here that's saying we are in the
method, which of course is the implementation that
| | 13:07 | I provided in our implementation for that
employee class. Very, very simple, but this
| | 13:13 | is the way that we start to go about things.
| | 13:15 | Now what we'll also find is that from the
synthesize statement that we had in our implementation,
| | 13:21 | that Objective-C and Xcode has actually
generated two methods for each of these properties,
| | 13:26 | one to set its value and one to get its value.
| | 13:29 | Now what that means is I can actually then
use this fred keyword, and I would find that
| | 13:34 | if I typed the set word we'd actually have
three methods here, setName, setHireDate,
| | 13:39 | setEmployeeNumber as well as a whole
bunch of other internally created methods.
| | 13:45 | However, I'm going to avoid these right now.
So obviously we are not doing much with this
| | 13:49 | class, with this object, but this is the
basic approach. But to get a better understanding
| | 13:54 | and to start to use more pieces about it, we need to
take a closer look at both methods and properties.
| | 14:05 |
| | Collapse this transcript |
| Defining methods| 00:00 | To declare a method in Objective-C, to
add this in our interfacing--say that this
| | 00:04 | method exists--you need atleast three pieces.
The first thing is going to be the indicator
| | 00:09 | that says is this a class or an instance
method? If it's a class method, we'd use a
| | 00:14 | Plus sign, and the method has to be
called using the name of the class itself.
| | 00:18 | But if it's an instance method, which is
much more typical, we would use the Minus sign.
| | 00:23 | Another method has to be called using a
particular instance of that class. And the method needs
| | 00:28 | a return type, and this is in parentheses. In
this case, it's void, meaning where explicitly
| | 00:33 | saying, this method doesn't return anything
but it could return an int or float or bool
| | 00:37 | or a pointer to an NSString object or anything else.
And after that, not surprisingly, the name.
| | 00:43 | What are we calling this method?
| | 00:45 | And if the method doesn't take any parameters,
you just then finish off with the semicolon,
| | 00:50 | and we are now ready to go and duplicate
this method signature in our implementation,
| | 00:55 | where we'd actually provide the code to say
what it does. But how about a few more examples?
| | 01:00 | What if we wanted a method that
accepted a parameter or even more than one?
| | 01:04 | So I am going to start here with a method
that's been defined without any parameters.
| | 01:10 | And I'll show you how we change it. So
we'll give ourselves a bit more room before the
| | 01:13 | semicolon, and if you remember the one
we call a method and pass in an argument,
| | 01:19 | we use the colon to separate the name of the
method from the argument, and that's what we do here.
| | 01:24 | We add a colon, and then we add two pieces of information.
First, what is the type of the parameter?
| | 01:31 | And second, what do we want to call that?
So in this case we are saying
| | 01:36 | that the timesTen method takes one integer as a
parameter called param, and it also returns an integer.
| | 01:43 | Do bear in mind that if you are accepting or
returning object types, then you will typically
| | 01:48 | need the asterisk to say that these are pointers.
In this case, I am defining a createMessage
| | 01:53 | method that accepts a pointer to an
NSString called input, and returns a pointer to an
| | 02:00 | NSString, which is why we're
using the asterisks in both places.
| | 02:03 | Now, what if we want to accept multiple parameters?
Well, if you remember, when we're talking about
| | 02:09 | calling methods with multiple parameters,
that the actual method name itself splits
| | 02:14 | into different sections divided by colons, it's one of the
big differences between Objective-C and other languages.
| | 02:20 | And that means that if you're defining your
own methods, you need to do the same thing.
| | 02:24 | So let's begin with a simple method that takes
no parameters called addNumber. This returns
| | 02:30 | an integer, and I can see by the Minus
sign it's an instance level method, so we'll give
| | 02:35 | ourselves a bit more room here, and we'll
first turn this into a method that takes one
| | 02:39 | parameter, by adding the colon, then the parameter type,
which is integer, and then the parameter name of a.
| | 02:45 | So this would right now stand-alone
as a defined method. It's got a method name,
| | 02:50 | then the colon, then the
parameter type, and the name.
| | 02:54 | Now what we need to do is add the second
section to this. We are going to duplicate this whole
| | 02:58 | piece, the part with the method name, the parameter
type, and name. So I add a second section here.
| | 03:03 | Now there is nothing in between these
two pieces of the method name just
| | 03:06 | spaces, and it's insignificant white space. I am
just trying to make this a bit more readable.
| | 03:11 | So again, it's a second part of the method
name, then the colon, and then the parameter
| | 03:16 | type, and the parameter name, and this is how
we define a method with multiple parameters.
| | 03:21 | This method would be
considered addNumber: toNumber.
| | 03:25 | So let's see an example of this in Xcode. I am going
to create a new Xcode project here in Xcode 4.3.
| | 03:31 | It will, of course, be a Command Line tool.
I'll call it MethodsDemo.
| | 03:36 | It's of Type Foundation, and I'll say that we
are using Automatic Reference Counting, and
| | 03:41 | I'll just save that in my Documents folder.
Before I do anything else, I am going to go
| | 03:45 | and add a new class to this project. So coming up
to the File menu, we will select to add a new file.
| | 03:49 | This will be an Objective-C class
from the Cocoa section, click Next.
| | 03:55 | I just want something simple, so I will call it MyClass,
and it will be a Subclass of NSObject.
| | 04:00 | I will click Next and choose to add this to my project and
click Create, and we get the MyClass.h and MyClass.m.
| | 04:07 | As you might imagine, it's actually very
common to need to flip between the .h and .m files,
| | 04:13 | and in fact, in Xcode 4 there is a very nice
little helper that you can do to help you do this.
| | 04:17 | I am going to select the .h file, and
because I don't have a lot of screen real
| | 04:22 | estate, I am just going to close the right-hand
section because we really don't need it here.
| | 04:27 | Now in the Editor section on the Toolbar
where the three buttons are, I am going to find
| | 04:31 | the middle button that looks like someone
wearing a bow-tie and a dinner jacket, this
| | 04:34 | is called the Assistant Editor.
| | 04:36 | If I click that, what we are going to do is
switch into a dual-pained Editor section.
| | 04:41 | And what it should try and do by default is
figure out that if I'm looking at the .h file,
| | 04:46 | and the second section is going to show me
the counterpart to that, which will be the
| | 04:49 | .m, the implementation file.
| | 04:52 | You can change what it's showing in the
second section by using the Jump bar up at the top
| | 04:56 | here, but this looks fine for me. Now
because I don't have a lot of screen real estate,
| | 05:00 | I'm going to close the Navigator section,
too, to make this a bit more obvious here.
| | 05:05 | So, interface on the left-hand side, implementation
on the right. So first, in my interface I am
| | 05:10 | going to define a method that's about as simple as
you can possibly get. I will call it performAction,
| | 05:16 | it takes no parameters, and returns void. If I
was going to change this to accept one parameter
| | 05:22 | before the semicolon, I put a colon after
the performAction name, and then the type of
| | 05:27 | the parameter I wanted to expect, in this case
an integer, and then give that parameter a name.
| | 05:31 | I will call it param.
| | 05:33 | Next, I'll add another method. In this one
I'm going to say returns an integer.
| | 05:37 | I am going to make it take two parameters called
a and b. It will be an instance method so
| | 05:42 | we use the Minus sign. I'll say it returns
an integer. I don't care what that's called.
| | 05:46 | We call it addNumber:, now we define the first
parameter which I'll say is an integer, called a,
| | 05:54 | then a space, and then we define the second
part of the method name. I will call it toNumber.
| | 06:01 | Again, we commonly used camel
case for our method names.
| | 06:05 | And this second part also takes a parameter,
so I'll put the colon and the parameter type
| | 06:10 | which will also be an integer and the
parameter name that will be b, and then the semicolon.
| | 06:15 | Yes, Objective-C's way of doing this, does
look a little unusual depending on the language
| | 06:20 | that you are coming from, but after creating a few
of these you will find them quite straightforward.
| | 06:24 | So if I look over here in my implementation,
I already have the warning sign that says
| | 06:29 | this is an Incomplete Implementation. Because
this implementation about this .m file needs
| | 06:35 | to support the promises that the header file has
made. So inside the body of the implementation
| | 06:40 | but before the @ sign end, I
need to support those promises.
| | 06:44 | Now I could copy and paste from the header
file, but there is a couple of ways to make
| | 06:47 | this little quicker. If I put in the leading
dash, now I know that there is a method
| | 06:50 | called performAction that I have declared in my
header files, so I am just going to type in p.
| | 06:54 | And what I will instantly see is it will
pop up. I have nicely typed the word
| | 06:58 | void here, that's okay. This is a shortcut
to the method names. If I select the one I
| | 07:03 | want--we're actually on the one that we want
right now, but I could move up and down with the
| | 07:07 | cursor keys, then I am just going to hit
Return, and it copies across that whole signature
| | 07:12 | that yes it's performAction, it returns void, and it
takes one parameter of type integer called param.
| | 07:19 | Now I do have to do my opening and closing
curly braces. I really just need to have the
| | 07:23 | opening brace and then hit Return. Xcode
jumps us into the body of this method, and I'll
| | 07:28 | just put something simple in here like an
NSLog message, you passed in the value, we
| | 07:37 | have a Placeholder, and then we'll spit out
the words param. This returns void, so I don't
| | 07:42 | need an actual return statement from it.
| | 07:44 | But we are still showing up as incomplete
because I don't have the other implementation
| | 07:49 | of the other method. So again, type the Minus
sign, and I will type the first letter of the
| | 07:54 | method I know I need to support which is a, and I have
got it popping up already, addNumber: toNumber.
| | 07:59 | Hit Return, we get the signature of it.
Do my opening curly brace and hit
| | 08:04 | Return again, it jumps
us into the body of this.
| | 08:07 | Now this one does need to return at least an
integer, which is why we are seeing the warning
| | 08:12 | sign popping up already, and this one will
actually be simple. I'll just say return a+b.
| | 08:18 | The two parameters that were passing in, and
that will do it. I may not actually be using
| | 08:23 | these methods yet, but that doesn't matter. If
I save this and then hit Command+B to build,
| | 08:28 | we should get Build Succeeded, because I have
completed the implementation of what I have
| | 08:33 | promised this class would
provide in my interface.
| | Collapse this transcript |
| Defining properties| 00:00 | The heart of all classes are your
properties and your methods, meaning
| | 00:03 | your data and the behavior that acts on that data.
We just saw methods. Let's talk a bit more about properties.
| | 00:09 | Now, to do this, I need to do just a small
amount of history because we didn't always
| | 00:13 | have properties in Objective-C. For a long
time, to define the data for your classes,
| | 00:19 | you would define an instance variable
inside your interface, your header file.
| | 00:24 | Instance variables, often referred to as ivars,
are just defined as regular variables.
| | 00:28 | There is no particular special keyword. And
you'd put these in your .h file and all your
| | 00:33 | instance variables whether 1 or 100 would
group together inside a set of curly braces.
| | 00:39 | Now, you can still do this, and you will still see
code like this from time to time. In Objective-C,
| | 00:45 | other common thing is to name instance
variables with a leading underscore.
| | 00:49 | I haven't done that here. It makes no technical difference.
it was just a common style habit to make it
| | 00:54 | obvious when reading code.
| | 00:55 | But here's the problem. In Objective-C, instance
variables by default can't be accessed directly
| | 01:01 | from outside the class they're defined in.
What that means is that I can write code inside
| | 01:05 | this class to manipulate, in this case this
score variable, but it couldn't be directly
| | 01:10 | accessed or changed from say a different class.
| | 01:13 | Now, this is very common in object-oriented
languages and not a bad thing. But if I wanted
| | 01:18 | to allow another part of my program to get
access to this variable, I had to create methods
| | 01:24 | to allow it to be accessed, what are
typically referred to as Accessor Methods.
| | 01:29 | So it add two method definitions, one to get
this value and one to set it. What I am defining
| | 01:36 | here is what's often referred to
as your getter and setter methods.
| | 01:39 | Now, in other languages, it will be quite
common to call these methods getScore and
| | 01:43 | setScore, but in Objective-C, it's been the
standard for many years to have the getter
| | 01:48 | have the same name as the instance variable,
although if the instance variable had a leading
| | 01:53 | underscore, we would not include that.
| | 01:55 | So, in this example, I declare a score method
that would return an integer, and the other
| | 02:01 | method would return void, and it would be called
setScore, and it will take one parameter which
| | 02:06 | is also an integer, and then what I'd have
to do is in the implementation file, we'd
| | 02:11 | actually have to provide the
implementation for these methods.
| | 02:15 | This is not too bad for one or two instance
variables, but it makes for a lot of tedious
| | 02:20 | code to continually have to write accessor
methods. So, a few years ago, Objective-C
| | 02:25 | added the idea of properties with a new
keyword @property. A, @property is really a way of
| | 02:31 | automatically generating or
synthesizing these accessor methods.
| | 02:36 | So back into the implementation example, instead
of the two method declarations in the interface
| | 02:42 | file, we add an @property keyword with a
type and with a name. And over in the matching
| | 02:47 | @implementation file, this is where we really
save work. Instead of providing these accessor
| | 02:53 | methods in full, we just add the @synthesize
statement that matches the @property statement
| | 03:00 | in the interface, and that will generate
the getter and setter accessor methods.
| | 03:04 | Now, after properties were introduced in
Objective-C, it was very common for a long time to see
| | 03:10 | this format. You would still have your
instance variables defined inside the set of curly
| | 03:14 | braces at the top of your interface, and you
would have a matching property with the same
| | 03:19 | name and the same type, and this property would
automatically be wrapping this instance variable.
| | 03:25 | But if you think about it, if we're defining
the property and giving it a name and a type,
| | 03:30 | we really don't need the instance variable
anymore. And these days, that section has gone away.
| | 03:34 | Apple's best practice as of mid-2012
is not to have any instance variables
| | 03:40 | in your interface, so you don't need those
curly braces, and you just create all your
| | 03:45 | publicly accessible data purely with @property
statements. And these are matched with the
| | 03:50 | @synthesize statements
in Xcode 4.3 and earlier.
| | 03:54 | But here's the other thing. As these @synthesize
statements really correspond directly to @property
| | 04:00 | statements, we don't really need these either,
and as I have mentioned in Xcode 4.4 and above,
| | 04:04 | you don't even need the @synthesize statement
anymore because it's something else the compiler
| | 04:09 | can figure out from the fact
that you wrote the property.
| | 04:12 | It's another example that as time goes by,
things get slowly simpler in Objective-C,
| | 04:17 | but often these simple things hide
quite a lot of behavior under the hood.
| | 04:21 | Now, you might be thinking, well, if I don't
have to do these instance variables anymore,
| | 04:26 | why point it out? Well, as with ARC, I point
it out because you will still see this format
| | 04:31 | when reading sample code and reading books
and presentations. It's still very common
| | 04:35 | to see because it was around for
many, many years of Objective-C.
| | 04:39 | But now, while a simple property is just
that keyword @property followed by the type and
| | 04:45 | the name, like int and score, there is something
else. Properties also have optional attributes
| | 04:51 | which are written in
parentheses after the @property keyword.
| | 04:54 | Now, when your properties are primitive types
like ints and floats, you don't need anything
| | 04:59 | here, but with objects, you'll almost always
need something. This is the most common one
| | 05:05 | you will see with objects, the word strong, in
parentheses before the type. Strong has to do with ARC.
| | 05:12 | We're saying that this property should be
considered a strong reference to this NSString
| | 05:16 | object, meaning that we're saying we own it
and as long as we keep our pointer to it,
| | 05:21 | ARC will keep this object alive, and we don't have
to worry about either retaining or releasing it.
| | 05:27 | Now, you can also use the word weak here to
define a property as a weak reference.
| | 05:32 | And that means the object will only live while
some other object holds a strong reference to it.
| | 05:37 | A weak reference by itself would not be
enough for ARC to keep this object in existence.
| | 05:43 | But weak references are much less common
than strong references, and they're not something
| | 05:47 | we'll really need in this course.
| | 05:49 | There are a few other words that can be put here,
and some of these can be mixed and matched.
| | 05:54 | If for example, you wanted to make a read-only
property, you can add the keyword readonly
| | 05:58 | in these parentheses, and that tells Objective-C to just
synthesize a getter accessor method and not a setter.
| | 06:06 | The default is read/write, so you don't need to
write that. If you're developing iOS applications,
| | 06:12 | you will also see words like nonatomic and
atomic. But right now, we don't need those,
| | 06:17 | we just need a basic awareness of properties.
| | 06:20 | Now, one question you might have is what if
we actually want an instance variable that's
| | 06:25 | not a property, if it doesn't need to be
accessed from outside the class, we just want it to
| | 06:30 | find some variables to use inside the class?
| | 06:33 | That's a very common name. The current best
practice is that you can still use instance
| | 06:38 | variables but don't define them in the interface, not
in the .h file, but actually in the .m@implementation,
| | 06:45 | because after all, the interface
is the public face of the class.
| | 06:49 | So instead, if we have instance variables,
now the best practice is to put them in the
| | 06:53 | implementation, or .m file. By convention,
these go right at the top inside a pair of
| | 06:59 | curly braces right after the @implementation line,
and then it will be followed by your method implementation.
| | 07:05 | So, while you will still see instance variables
being put in the .h interface file, it will
| | 07:11 | be much more common over coming years to see
them only in the implementation and to see
| | 07:16 | all of your data actually defined
by properties in your interface.
| | Collapse this transcript |
| Defining initializers| 00:00 | Every single class you will use an
Objective-C has an instance method called init.
| | 00:03 | We know this, we have used it already.
Typically, we see init used alongside alloc,
| | 00:10 | and init is there to initialize a new object.
Make sure that it's created in a valid state,
| | 00:16 | but if necessary, all its internal values
are set to some meaningful amount.
| | 00:21 | And all classes have this method because init is
defined in NSObject, and because we were inheriting from that.
| | 00:26 | Either directly or indirectly,
we will have an init method.
| | 00:31 | But it's our choice whether to write a
custom version of init, specifically for our new
| | 00:36 | custom class, so that we can say exactly how all
our new objects or new instances are initialized
| | 00:42 | as soon as they are created, and here's how.
| | 00:46 | I'll create another Command Line tool application here.
I'll call it InitializerDemo, Type of Foundation,
| | 00:54 | and I'll check the box to say we
want to Use Automatic Reference Counting,
| | 01:00 | and I'll just save this to my Documents
folder. You can put it wherever you like.
| | 01:04 | Before I do anything else, I'm going to add
a new class to this project. Up to the File
| | 01:10 | menu, I'll select New > File. It will be a
Cocoa Objective-C class, and I'm going to call it
| | 01:17 | Player and make sure that we're inheriting from, we are
a Subclass of NSObject. Click Next, and click Create.
| | 01:27 | We have our Player.h and our Player.m files.
Now I can write an init method in this class myself.
| | 01:34 | I'll go into my Player.m file, and it
would be in the body of the implementation,
| | 01:39 | but there's an easier way than writing it.
I'm going to make sure that my right-hand
| | 01:43 | Utilities panel is turned on. If it's off,
you can get it from the three buttons in the
| | 01:48 | Toolbar, and what I'm interested in is the
Code Snippet Library, which is the second
| | 01:53 | button in the lower section, the one
that looks like a pair of curly braces.
| | 01:56 | There are a lot of different Code Snippets
in here, the one that I'm interested in is
| | 02:01 | the template for an init method. Now I can go
down here, you'll find it under Objective-C
| | 02:06 | Init method, although another quick way is
you could filter using the textbox at the
| | 02:11 | bottom and just type in init, and there we
have Objective-C Init method. I'm going to
| | 02:16 | click that and drag it directly into my implementation
file, we are dragging it into Player.m, and let go.
| | 02:24 | This is Apple's suggested code for a custom
init method. It's the correct signature which
| | 02:29 | is returning a type of ID. ID in Objective-C
basically means any object, and that's the
| | 02:35 | correct return type for any initializer method.
| | 02:38 | So what else is happening here? Well, inside the
body of init, we have a call to self = super init.
| | 02:44 | Self is a keyword in Objective-C, which means
the current object, here meaning, the
| | 02:49 | object that has just been allocated and has
caused this init method to be called. Other
| | 02:54 | object-oriented languages might use the word
this, or me, instead of self. It allows us
| | 02:59 | to write code to refer to the current object
without knowing the name of the variable that
| | 03:04 | that object might have been called.
| | 03:06 | Now super on the other hand is a keyword that
refers to our super class, which in this case is NSObject.
| | 03:10 | So here we're calling the init method
that's already defined in NSObject,
| | 03:16 | letting our super class do whatever it
wants to do to hand back the current object.
| | 03:21 | Now in the next line after this we ask if
(self), we're just checking to see that this object exists.
| | 03:26 | Now we would always expect this to work,
but this is a best practice
| | 03:30 | to detect some internal failure. Was there a
problem calling the init method of the super class?
| | 03:35 | But if we exist, then we're going to
go ahead and run whatever initializations
| | 03:40 | that we want to run.
| | 03:42 | So here is where I'd write any code to do
anything specific for my custom class.
| | 03:46 | So let's make it do some initialization. I'm
going to jump across to my header file because
| | 03:50 | we don't have anything to initialize yet.
I'm going to add a new property.
| | 03:56 | The simple property of type init, and I'll call it score.
Because I'm working with Xcode 4.3, I need
| | 04:02 | to match that with a synthesize statement
in the body of my implementation just to
| | 04:07 | make sure that my access
or method has generated.
| | 04:09 | And then what I'm going to do is in this
custom init method, I want to say that this score
| | 04:15 | is going to be initialized as 5000. Now it's
just an arbitrary value, but we need to initialize
| | 04:20 | it to something, and that's how we guarantee
that all objects instantiated from this class--
| | 04:25 | whether that's 1 or 100 or 10,000--they will
all be created with an initial score of 5000.
| | 04:32 | So let's prove that. I'm going to jump across
to main.m and instantiate an object of this class.
| | 04:37 | So after the insert code comment,
I'll create a new instance of Player.
| | 04:42 | I'm going to find that it doesn't know what Player
is right now because main.m doesn't have an
| | 04:47 | import statement to our Player class. I'm going to
add that after the import statement to Foundation.h.
| | 04:52 | I'll add an import to Player.h.
| | 04:56 | And again, if you're linking to header
files in your own project, you'd use the double
| | 05:00 | quotes as opposed to the angle brackets if
you're linking to header files in Apple's APIs.
| | 05:07 | Once we have linked to Player.h, I can now
create a new instance of Player. It is, of course,
| | 05:12 | an object, so it's a pointer type. I'll call it p,
and we'll say that equal to the standard Player alloc init.
| | 05:21 | We are allocating some memory
and then we're going to call our custom
| | 05:26 | initializer method to set up
this object in the right way.
| | 05:29 | Well, let's prove it. Right now it's given me a
warning, because I'm not using that p reference yet.
| | 05:34 | So I'll change the NSLog message to output
an integer, and then we'll grab the
| | 05:42 | contents of that by calling p score. I could
use the square brackets here of p space score
| | 05:49 | inside square brackets, or I could to use the dot syntax,
which would be p.score, both would work. Save it. Run it.
| | 05:57 | Build Succeeded, and down here when I run
it, the score is 5000. So that object has
| | 06:03 | been created in the initial
state that we want it to be in.
| | 06:08 | So this is a very easy way to do things. If
you have some very straightforward and simple
| | 06:13 | initialization tasks, just create your own init
method and put in some simple initialization code.
| | 06:18 | But what's more common is that you'll
actually want a variety of initialization
| | 06:23 | options, a variety of init methods.
Well, what do I mean by that?
| | 06:27 | Let's take a look at the Help file for some
built-in classes that Objective-C gives us
| | 06:31 | in the Foundation framework, such as say, NSDate.
I actually have the NSDate Class Reference
| | 06:37 | showing up here. If I hadn't got it, I could
have searched from it over on the left-hand side.
| | 06:41 | But if I look at this, I can actually
see that NSDate gives me all these different
| | 06:46 | tasks I can do. I can see that in the documentation I have
an init method, but I also have initWithTimeIntervalSinceNow,
| | 06:54 | initWithTimeInterval:sinceDate,
initWithTimeIntervalSinceReferenceDate.
| | 06:59 | There's a whole bunch of different methods
that begin with the word init, and this is
| | 07:04 | the convention in Objective-C, if what you
want to do is have a variety of options for
| | 07:10 | initialization, some that you don't need values
or some that have values, a variety of custom
| | 07:14 | ways to create an object.
| | 07:17 | And again, as I like to make a lot of comparisons
to other languages you might know, this is
| | 07:21 | how we do the equivalent of the constructor
idea in languages like Java or C#.
| | 07:27 | In Objective-C we actually create totally different methods
for the initialization process of our objects.
| | 07:32 | We will always the alloc, and we'll have the regular
init, but we might also have more custom init methods.
| | 07:40 | So let's say that in my particular example
here, the standard init method will always
| | 07:45 | create this Player object with the score of
5000, but what if I want the option to create
| | 07:49 | a Player object and maybe pass in 10,000 or
100 or -500 or 0? I want the choice when I
| | 07:57 | make a new instance of Player.
| | 07:59 | So I'll create another initializer method. So
I'm just going to first start off by copying
| | 08:05 | this first init and pasting it in, and I'll
change one of them, and just change the name here.
| | 08:11 | I'll change the first one, it doesn't matter
which one I change, and I'll call this initWithInt.
| | 08:16 | I know that there is nothing magical about
the method name. Initializer methods are just
| | 08:22 | regular methods. It's simply that by convention
in Objective-C. If you want to write a custom
| | 08:28 | initializer method, it should begin with the
word init, and it's usually init with something,
| | 08:33 | because you're describing what this expects. In
my case initWithInt, it could be initWithString.
| | 08:38 | I could have said initWithScore. But if I'm
going to say this accepts a parameter, I'd
| | 08:43 | better define that in the method. So we'll
add the colon, and then say that the type
| | 08:48 | I'm passing in will be an integer, and I'll call it s.
Of course, I can call it whatever I want.
| | 08:54 | So the idea is this method is called that
passes in an int, and when I get that argument
| | 08:59 | instead of setting it to 5000, I'll just say
score = s, and that's my initialization code here.
| | 09:05 | Now we have still got a bit of duplication
going on between these two initializer methods,
| | 09:09 | I'll tidy it up in a moment.
| | 09:11 | The one extra thing before I start to use
this, while we always have a plain init method
| | 09:16 | because that's defined in NSObject, that's why
we don't need to add an entry in the interface for init.
| | 09:21 | But if I'm creating a more custom
named init method that in this case takes
| | 09:26 | an integer, well, I do have to declare
that in my interface, in my header file.
| | 09:31 | So I'm actually just going to copy the method
signature of that custom initializer and jump into Player.h.
| | 09:37 | I'm going to paste it in there
and just end it with a semicolon because
| | 09:43 | I need to do this to make sure that this
initWithInt method is visible from outside this class.
| | 09:50 | So now if I jump over to main.m and decide
to create a new Player object, we alloc as
| | 10:00 | usual, but as I start typing init, I can see
we have got both the regular init method and
| | 10:05 | we have initWithInt, that takes an integer.
Well, let's try that one. I'll pass in 7500,
| | 10:11 | that's just an integer, and just add a
simple NSLog message. Save that. Run it.
| | 10:19 | And what we can see here is that we are
creating two different objects, the first one using
| | 10:25 | the init method, which will write up its value as
5000, the second one using the custom initWithInt
| | 10:31 | method, which will be created with 7500.
| | 10:35 | So jumping back into the Implementation file,
I have now got these two initializer methods,
| | 10:41 | the typical init and the custom initWithInt,
but we have a little bit of duplication still.
| | 10:46 | Let's tidy that up. See, when you have multiple
initializers in a class, you can usually contain
| | 10:51 | the real behavior, the real work in just one of
them and make the other initializer methods call int.
| | 10:57 | Now typically the one that needs to do all the
work is whatever one has the most parameters.
| | 11:02 | In this case, it's initWithInt, because that
has one parameter and the regular init has none.
| | 11:08 | So in my regular init method, instead of
having all these calls to super init and checking
| | 11:14 | if self exists, what I'm just going to do
instead is get rid of some of that code and
| | 11:19 | say self =, and I'll call the other initWithInt
method. In this case we wanted init to always
| | 11:26 | start with 5000. So I'll pass that
to that other method of this class.
| | 11:31 | And again, we're using the word self here to
refer to the current instance of this class.
| | 11:37 | So now if from outside somebody calls the
regular init, all we're going to do is call
| | 11:42 | up to our new custom one passing in the
value of 5000. In fact, I can shorten this even
| | 11:47 | a little more and put that entire one on
one line. Just a return statement and whatever
| | 11:57 | comes back from calling initWithInt. Save that,
run it again, and we get exactly the same value.
| | 12:04 | I know that you don't always have to have
a custom init method in your classes, but
| | 12:09 | hopefully this makes it a bit more clear,
not only how you do custom initialization
| | 12:13 | when you need it, but also that when you have
been creating things like NSStrings and NSDates
| | 12:18 | and other objects. But when you type alloc
and then type init, it's why you often get
| | 12:23 | a whole bunch of different init options,
because those are the custom initializers defined
| | 12:28 | for those particular classes.
| | Collapse this transcript |
| Using dealloc| 00:00 | As we have talked about the Initialization
side of objects when they first
| | 00:03 | get created, we should probably about the other,
end too. What happens when an object is destroyed?
| | 00:08 | Can we write code to interact with that
part of the process? Well, of course,
| | 00:13 | we can; however, it's often
unnecessary, particularly with ARC.
| | 00:17 | As we have seen, all classes inherit from NSObject,
either directly or indirectly through another
| | 00:24 | class, and that's why they all have an init
method and an alloc method and more besides.
| | 00:29 | But NSObject also defines a method called
dealloc, which is automatically called at the
| | 00:34 | end of an object's lifetime. So we have that
one, too, and we can provide our own dealloc
| | 00:40 | method in our CustomClasses just as
we can provide our own init method.
| | 00:44 | And again, making analogies to other
languages, if you're familiar with things like finalizers
| | 00:49 | or destructors, dealloc is the same idea in
Objective-C. It's how we would write some code
| | 00:55 | that would be run at the end of an
object's lifetime. So let's see how to do it.
| | 01:00 | I'll create a new Xcode project here, it will
of course be a Command Line tool, I'll call
| | 01:07 | it DeallocDemo, Type of Foundation, and I'll
select to Use Automatic Reference Counting.
| | 01:12 | I'll just save that in my documents folder.
Once again, add a new class to this so that
| | 01:19 | we have a CustomClass we can work with. So Cocoa >
Objective-C Class. I will call this one Player again, and
| | 01:26 | it's a Subclass of NSObject, very
straightforward stuff going on here.
| | 01:31 | Now jumping into the implementation into Player.m,
we already saw that in the Code Snippet Library,
| | 01:38 | we had a Code Snippet for an Objective-C init
method. And this is useful because it saves
| | 01:45 | us a little typing. All we really need to put
in here is some code for our initialization,
| | 01:50 | and we also have a Code
Snippet for a dealloc method.
| | 01:55 | This however, is less than useful, for two
reasons, one: dealloc is a very, very simple
| | 02:02 | method, it's simply called dealloc, all
lowercase, returns void, takes no parameters.
| | 02:08 | Now the second reason is that the default Code
Snippet includes this line here, which is a call to
| | 02:13 | super dealloc, the dealloc method of our SuperClass,
and that won't even work if you have ARC turned
| | 02:19 | on for your project.
| | 02:21 | And that's because with Automatic Reference
Counting turned on, you aren't allowed to
| | 02:24 | call dealloc method of any Object yourself.
You might occasionally still need to actually
| | 02:29 | write this dealloc method, but you wouldn't ever
call it yourself. You would let the Objective-C
| | 02:35 | runtime call the dealloc method when it
sees fit. If you try and write code that calls
| | 02:40 | this method, the Compiler will choke.
But why? That's the question.
| | 02:44 | Well, dealloc exists purely for clean up.
| | 02:48 | Prior to ARC, the main reason you'd write a
dealloc method in your class, the main reason
| | 02:53 | you'd need one is that your class contained
other Objects or being instantiated possibly
| | 02:58 | in your initializer, but could have been
anywhere else in your code. And what you needed to
| | 03:03 | do is make sure that those objects were
released, and if there wasn't a natural place to put
| | 03:07 | any release code, you'd write your dealloc method
and in that release all those internal objects.
| | 03:14 | And then, again, this is prior to ARC, the
standard technique was that after you'd run
| | 03:19 | dealloc in your Object, you'd call the dealloc
on the super class to let it do whatever it needed to.
| | 03:24 | Well, the thing is if you have ARC turned
on, you don't need to release anymore.
| | 03:29 | In fact, you can't release anymore, you are
not allowed to write that code, and if all
| | 03:34 | that you're dealloc method was doing was
calling super dealloc, well, that happens anyway.
| | 03:38 | We don't need the method at all. So a lot of
dealloc Methods that we would have written
| | 03:43 | prior to ARC just don't get written
using Automatic Reference Counting.
| | 03:48 | But make no mistake, dealloc still exists for every class.
We can write a dealloc method, but you let
| | 03:56 | the Objective-C runtime take care of calling you,
you don't call it yourself. So the question
| | 04:01 | is why would we still need dealloc at all?
Well, it is much less required if you use ARC.
| | 04:07 | And for this level--of course--that we're doing
here some basic Command Line Tools, we really
| | 04:11 | don't need dealloc Methods. The main requirement
for using a dealloc is in more complex applications
| | 04:17 | if your Object is holding onto some kind of
resource. Here is an example of this idea.
| | 04:23 | Let's say in my initializer what we have done
is open a connection to a database or file,
| | 04:29 | so I am just going to add a comment that represents
that. Well, we might then need a dealloc method
| | 04:35 | added to this class to make sure that the
connection is properly closed before this
| | 04:41 | object is destroyed.
| | 04:45 | So this kind of thing can often be required
for connections to Databases or holding open
| | 04:50 | file connections on the local machine. But
if you're using ARC, it's not necessary just
| | 04:54 | to clean up your own objects, because those
should be released automatically.
| | 04:59 | So that's the kind of reason you'd write a dealloc method,
for cleanup code that needs to happen.
| | 05:04 | But you just let this dealloc method be called
when Objective-C reclaims the Object.
| | 05:09 | And as I mentioned, prior to ARC, you'd see a
lot of this kind of call, that in your dealloc
| | 05:14 | method, you'd make a call to super dealloc.
| | 05:17 | But you'll only now see that in the non-ARC
code, and with ARC turned on, all actual calls
| | 05:22 | to dealloc up and down the object hierarchy
will be done automatically. You can write
| | 05:27 | a dealloc method, and it will be called at the
right time, but you can't explicitly call it yourself.
| | Collapse this transcript |
|
|
8. CollectionsWorking with C-style arrays| 00:00 | One thing we haven't talked about up
to this point are arrays, the ability to
| | 00:04 | have a variable that holds
multiple values at the same time.
| | 00:08 | Now in Objective-C we have the old
regular C style way of doing arrays and we
| | 00:13 | will also have some new classes to work with.
| | 00:16 | Let's start off with these C style ones first.
| | 00:18 | Now as we've seen creating a variable
that holds say a single integer very easy,
| | 00:24 | give it the type, give it the name.
| | 00:25 | that carves out the area of space that
can hold an integer and then we just use
| | 00:29 | that name to access that integer and
change it and do whatever we want with it.
| | 00:34 | Now to create an array of integers
meaning we've got one variable that holds
| | 00:40 | multiple values I start off by doing
exactly the same thing, use the type and
| | 00:44 | then the name but before the semi-colon,
I'm in the use of square brackets to
| | 00:50 | say how many should this hold.
| | 00:52 | In this case I'm saying five.
| | 00:54 | so what it will go through is carve
out five integers for me and because I'll
| | 00:59 | need a way to get to each one it's
going to give them each and index.
| | 01:04 | Now in C and Objective-C
our arrays are zero-based.
| | 01:08 | So if we have five elements that
will be element 0, 1, 2, 3 and 4.
| | 01:13 | now this use of the square brackets is
nothing to do with Objective-C it's not
| | 01:18 | about doing the messages the method
calls it's just the array accessor.
| | 01:24 | It's what I used to create the
array and it's what I use to access
| | 01:28 | each individual part.
| | 01:29 | So I'd say multiple values square
bracket zero to access element zero square
| | 01:33 | brackets one want to
access elements one and so on.
| | 01:38 | Switching over to x code where I have
exactly that same code here you imagine it
| | 01:42 | can get a little tedious to start
typing all the individual pieces out.
| | 01:46 | There is a lot of repetition going on.
| | 01:48 | So while we could do that way there is
also a shortcut if I want to create this
| | 01:54 | array and initialize all the elements
in it I can use curly braces and inside
| | 02:00 | those curly braces give it all the
different values separated by commas let's
| | 02:05 | say 50, 60, 70, 80, 90.
| | 02:11 | These are integers so they don't need to
be in double quotes or anything like that.
| | 02:15 | Just to prove that this works we will
write out an NSLog message and I'll say
| | 02:20 | the Value at the third element is and
we use the same accessor to just grab
| | 02:28 | then take a look at it. multipleValues 2.
| | 02:30 | Two would be the third element, 0, 1, 2.
| | 02:38 | Say that, run it and we would expect
to see 17 being output as our message.
| | 02:43 | nothing particularly remarkable going on.
| | 02:46 | In fact if I am providing all the
initializers here using these curly braces I
| | 02:52 | technically don't need this number and
you could actually leave it and it would
| | 02:56 | work exactly the same way creating an
array of integers that has five elements.
| | 03:02 | If I conflicted with myself that I said
the array should have five elements and
| | 03:06 | then I tried to provide six, I'm likely
to get a warning here that says you got
| | 03:10 | Excess elements in your array initializer.
| | 03:12 | So let's get that one back.
| | 03:15 | Moving on little bit, you can do this
also not just with instant floats and
| | 03:19 | charts, but you can do it with objects as well.
| | 03:22 | We are using Objective-C object but
we're making a C style array of them.
| | 03:27 | So here I am going to go do NSString and
we start off by creating something very
| | 03:31 | similar to an individual element.
| | 03:33 | I will just call it myStringArray.
| | 03:36 | It's a pointer of course but again I
just used the square brackets and say that
| | 03:40 | with this one I want five or 10 or 15
or 5000 and now I have an array called
| | 03:46 | myStringArray that can hold five
NSString object not technically of course what
| | 03:52 | it's holding is five
pointers to NSString objects.
| | 03:56 | The NSStrings don't exist so it used
the same way instead of going through it,
| | 04:01 | myStringArray position zero and then I
would create that string object because
| | 04:07 | it doesn't exist yet.
| | 04:12 | So I could use one of the formal ways
creating a string object using alloc and
| | 04:18 | say a initWithCString or initWithFormat,
but of course if I am doing an alloc
| | 04:24 | for this element, I would need to
pair it with a release somewhere and that
| | 04:28 | could be done just quite simply by
again using what evers of that element.
| | 04:34 | release, that would work just fine.
| | 04:39 | Though that's a pretty tedious way of
doing it, so there is the shorthand with
| | 04:43 | strings as well which say if you're
just creating an array at the start of your
| | 04:48 | program to hold some messages you
don't mind if it hangs around for the
| | 04:51 | lifetime of your program.
| | 04:53 | So use the opening and closing curly
braces and in here I'll use the Helper
| | 04:58 | method and just type in some values.
| | 05:05 | Compiling, and it succeeded it is
complaining that I'm not using that array
| | 05:09 | which it's technically true.
| | 05:10 | So we are about to use one of them in.
| | 05:17 | No particular surprise here writing
out the word third, and bearing in mind
| | 05:23 | that on line 12 we are creating five
NSString objects but we're using the
| | 05:30 | shortcut helpful way of doing it.
| | 05:31 | so these would be
considered auto released objects.
| | 05:33 | I wouldn't need to match them with a
manual release or auto release call.
| | 05:37 | Now these are the basic
ways of doing C style arrays.
| | 05:41 | There are three things to
be aware of when them one.
| | 05:45 | One, there is no bounds
checking, what does that mean?
| | 05:48 | Let's say up here where I defined an
integer array called multipleValues and I
| | 05:54 | said equal to five elements.
| | 05:55 | I could type the code
multipleValues 99 equals whatever.
| | 06:02 | I am trying to access an
element that doesn't exist.
| | 06:06 | Now if I compile this build is
actually going to succeed and in fact I could
| | 06:11 | even run it and it would run
through and finish and exit successfully.
| | 06:15 | But this is an astoundingly bad idea
because we're reaching into an area of
| | 06:19 | memory that we didn't claim properly, so not
a good thing so no bounds checking on these.
| | 06:25 | Second limit fixed size.
| | 06:28 | we're creating these arrays at a
particular side both of these cases were five.
| | 06:34 | I cannot come to say to my string
array and then say oh I want to add another
| | 06:38 | element or remove another element.
| | 06:41 | Once it's created, it's fixed
and third, can't make types.
| | 06:48 | I'm creating an array of integers,
an array of NSString pointers.
| | 06:52 | I am not creating an array that can
hold an integer and a float and an NSString
| | 06:58 | and a date and a piece of video.
| | 07:00 | So while they are simple to create
in their awesome limitations and those
| | 07:03 | limitations are fixed by the classes
that have been provided for us in the extra
| | 07:08 | frameworks like the foundation
framework and will see that next.
| | Collapse this transcript |
| Working with Objective-C array objects| 00:00 | So let's see what Objective-C
brings to the table as regards arrays.
| | 00:05 | Well, if we know there when we were
working with strings, we look for NSString
| | 00:09 | and when we are working with dates, we
look for NSDate, even I might make the
| | 00:12 | assumption to look for an
NSArray class and indeed I have one.
| | 00:16 | It's a regular class in Objective-C
which means we need an object pointer for
| | 00:20 | it, so I am going to create one
called myArray and set it equal to.
| | 00:24 | Now how do I make this?
| | 00:25 | There is a couple of different ways.
| | 00:27 | One thing you could do is we could
go along the road of using the usual
| | 00:31 | class name alloc init.
| | 00:33 | We are very unlikely just to say init
because NSArrays want to be creative
| | 00:38 | with their contents.
| | 00:40 | So the most common
initializer is init with objects.
| | 00:44 | I am just going to give it the
simplest way of giving in a couple of objects
| | 00:49 | here, which is two in-line created
NSStrings and then there's a comma and then
| | 00:55 | the word nil, what's that all about?
| | 00:57 | Well, we didn't say how long the
array was explicitly, there are no little
| | 01:02 | square brackets with the number two in them.
| | 01:04 | So what it's going to do is just
keep on adding new objects to this array
| | 01:08 | till it hits the word nil, nil needs to be
the last thing whenever we're creating this.
| | 01:13 | This will give me an array.
| | 01:15 | I have used the magic word alloc so I
would need to pair this with a release
| | 01:20 | statement, although if I wanted to
there is a shortcut method to create an auto
| | 01:25 | released array which would be instead
of using the word alloc, I just make a
| | 01:29 | direct call to NSArray,
arrayWithObjects instead of initWithObjects.
| | 01:36 | I didn't use any of the knock words here,
no new, no alloc, no copy, no retain.
| | 01:41 | So I wouldn't need to call release on this.
| | 01:43 | You'll begin to see this kind of
example used all over the place, arrays,
| | 01:48 | strings, dates all use it.
| | 01:50 | Then to improve it's actually working,
I am going to change my log message here
| | 01:55 | to spit out something.
| | 01:58 | The second element is.
| | 01:59 | What we are expecting back?
| | 02:03 | We're expecting an object, so my
placeholder will be percent sign at sign.
| | 02:07 | Then how do I get to that element?
| | 02:09 | Well, you might think that we could use
something like myArray1, but that would
| | 02:15 | be the C style way of doing it.
| | 02:17 | That's not going to work here.
| | 02:19 | We're in Objective-C.
| | 02:20 | We're calling methods for everything.
| | 02:22 | So what I do is I am doing the
myArray and probably the single most common
| | 02:29 | method for working with
arrays which is objectAtIndex.
| | 02:34 | This method will take an argument of an
integer, in this case I'll put in one to
| | 02:38 | get that second element, and
it will return that object.
| | 02:43 | Save it, run it and not surprisingly we
should get out the second element is two.
| | 02:49 | You might not see an awful lot of
improvement here, but there is quite a big
| | 02:54 | difference with working with NSArrays,
one thing is I can load it with pretty
| | 02:59 | much whatever I want.
| | 03:00 | Let's say I create an NSDate object here.
| | 03:03 | I'll call it myDate, and I'll just
create it with the full on alloc and init.
| | 03:07 | Well what I can do, is when I'm
creating this array, I can just pass that in
| | 03:13 | as one of the objects.
| | 03:15 | We can have strings, we can have dates,
we can have videos, we can have anything
| | 03:20 | added to an NSArray.
| | 03:22 | All it cares about is that there are
objects in it, doesn't care what kind of objects.
| | 03:27 | Now this leads us to an interesting thing here.
| | 03:31 | I've created this NSDate called myDate on
line nine and I am using alloc and init.
| | 03:37 | So I need to pair that with a release.
| | 03:40 | Well interestingly what I could
actually do here is immediately call release on
| | 03:48 | myDate once I've added it to the array.
| | 03:50 | Now you might think, well hang on a
second, what happens if the date object
| | 03:55 | goes away and then I try and access
that element of the array, well, we're okay
| | 03:59 | because what actually happens when we
add it to the NSArray is the NSArray
| | 04:04 | gives it a retain call.
| | 04:06 | It will take care of keeping hold of that.
| | 04:09 | What I'm allowed to now say is that I'm
done in myCode with it, I'm releasing it.
| | 04:13 | While you can of course use your Option+click
to jump in and see that there are
| | 04:18 | a whole bunch of other methods,
you'll find that arrayWithObjects or
| | 04:22 | initWithObjects and the objectInIndex
very much the common terms to work with
| | 04:27 | your array and the array elements.
| | 04:29 | So browse through the documentation at some
point and see what else seems useful for you.
| | 04:34 | However, here is the biggest
issue you're likely to run into.
| | 04:38 | An NSArray object is immutable,
immutable meaning unchangeable.
| | 04:45 | Once it's created you cannot add new
objects to it, you cannot remove objects from it.
| | 04:51 | It's a fixed size.
| | 04:53 | Now I'd already said that was a
limitation of the regular C style arrays and I
| | 04:57 | thought we were going to fix this. Well we can.
| | 05:00 | See a lot of the time an
immutable array is just fine.
| | 05:04 | You know how big it needs to be, you
create it with the data that it needs, but
| | 05:07 | sometimes you need something a bit
more flexible and we can do that too.
| | 05:11 | What I can do is change this declaration
from NSArray to NSMutableArray and over
| | 05:21 | here change my initialization to
NSMutableArray, array with objects.
| | 05:28 | NSMutableArray is a subclass of
NSArray which means it can do all the things
| | 05:34 | NSArray can, but it's got a
little bit extra functionality too.
| | 05:39 | So what I can do after this thing has
been created is I can call a method of
| | 05:44 | myArray called addObject.
| | 05:48 | Now this doesn't exist if myArray was an
NSArray, but it exists when it's a mutable array.
| | 05:56 | So if you need that
flexibility, this is how you get it.
| | 05:59 | Not only that, but you have
the ability to remove object.
| | 06:05 | Now there is a few different ways of doing it.
| | 06:07 | One of the most common ones
would be removeObjectAtIndex.
| | 06:10 | I am going to pass in the number one.
| | 06:12 | Now what that should do is remove
the NSString two from the array.
| | 06:19 | That will collapse that element and
the myDate object should now move into
| | 06:24 | that second position.
| | 06:26 | Well down on line 19 I have an NSLog
that's going to write up whatever is at
| | 06:29 | that second position and I'll add one
more piece to it that just says the array
| | 06:34 | count is, so we can find out the length of it.
| | 06:37 | This is going to be an integer which
does mean that the first thing after
| | 06:43 | the comma needs to be myArray and there is
a count method comma myArray objectAtIndex.
| | 06:49 | If I quickly run that it's telling me
that the array count is three which is
| | 07:00 | what I'd expect now.
| | 07:01 | It was three then I added one, then I
removed one and the second element is and
| | 07:06 | we are getting the output of the date.
| | 07:08 | Now it is giving me a complaint here,
Conversion specifies type int, but the
| | 07:17 | argument has type NSUInteger also known
as unsigned long and if you notice here
| | 07:24 | what it's doing is it's giving me a
fix it to say that it suggests that I
| | 07:28 | replace that placeholder %i with %lu
which is for an unsigned long integer.
| | 07:34 | That's simply because that is how
the count method is defined in the
| | 07:38 | NSMutabeArray object and in the NSArray object.
| | 07:42 | I'll accept that, fix it.
| | 07:43 | As we saw it works without it, but
this will now no longer give me warnings.
| | 07:47 | While we can get a bit more complex
with other more specialized classes when we
| | 07:52 | are working with collections of
objects, you are likely to see NSArray and
| | 07:56 | NSMutableArray used all over the place.
| | Collapse this transcript |
| Using dictionaries| 00:01 | Time-and-time again we'll work with C
style arrays, we'll work with NSArrays
| | 00:05 | and NSMutable arrays and they are great
for working with collections of objects
| | 00:10 | as long as you're happy by
accessing each of those elements using that
| | 00:13 | zero-based array index.
| | 00:15 | Well, what if you're not?
| | 00:17 | Well, we also have another object.
| | 00:19 | We can use this called a dictionary.
| | 00:21 | And the idea of a dictionary in Objective-C is
like the idea of a dictionary on your bookshelf.
| | 00:26 | The whole point of a dictionary is
that you have a word and a description.
| | 00:30 | The words are the key to the right place
in the dictionary, but you're using the
| | 00:35 | words to look up the description.
| | 00:36 | That doesn't mean we are
actually writing a dictionary.
| | 00:40 | a set of descriptions in terms
in our program, although we could.
| | 00:44 | What you'll find is that a dictionary
object could be commonly used for things
| | 00:47 | like State or Country LookUp tables
where we have common abbreviations, and we
| | 00:53 | can use those as the key to the actual
entry, in this case AZ goes to Arizona,
| | 00:59 | CA to California and so on.
| | 01:01 | You could use them as simple lookups
for product lists, because it's up to
| | 01:06 | you what that key is.
| | 01:09 | Now usually it's a string but it
could be just say a number, and while it's
| | 01:14 | easy to think of the dictionary entry itself
being another string, or it could be any object.
| | 01:20 | So we could have the word
startdate look up in NSDate for example.
| | 01:24 | But we are imposing our own structure on
how these individual entries are looked up.
| | 01:31 | So let me show you how to write one.
| | 01:33 | In another simple project here, just a
command-line foundation tool, I am going
| | 01:41 | to type-in NSD, I have got NSDictionary.
| | 01:43 | If you occasionally try to do some
of the code sense and you don't see
| | 01:46 | anything appear, do make sure that
you've done a recent build, because
| | 01:50 | sometimes Xcode likes to have a build
being done before it'll present you with
| | 01:54 | all the code sense.
| | 01:55 | So I will make an NSDictionary.
| | 01:57 | It is of course a pointer type, I will
call it states, and what I am going to do
| | 02:01 | is I am going to use the
method of NSDictionary called
| | 02:06 | DictionaryWithObjectsAndKeys.
| | 02:09 | This will give me an Autoreleased NSDictionary.
| | 02:12 | If I want a more manual control, I'd
say NSDictionary alloc init with objects
| | 02:18 | and keys, but this one will do just fine.
| | 02:20 | Now notice the phrasing here.
| | 02:22 | DictionaryWithObjectsAndKeys, unlike an
array we do have to provide two pieces
| | 02:28 | of information for each slot.
| | 02:31 | It's also telling us what order they
need to be in, which is object then key,
| | 02:35 | not key then object.
| | 02:37 | The object would be Arizona in
NSString, the key would be AZ. Let me do a
| | 02:44 | couple more of these.
| | 02:45 | I am going to split it on another the line
just to make it a little bit more readable.
| | 02:51 | I'll just add a few right now, and then
like working with an array, we indicate
| | 02:56 | that we are done by the word nil,
close the square brackets and we are done.
| | 03:00 | Now the whole reason for creating a
dictionary is that we are going to access it
| | 03:05 | at some point in the future.
| | 03:06 | So let's imagine that a little
later on in our program we have a State
| | 03:11 | abbreviation and we need to use it to
lookup the right slot in the dictionary.
| | 03:15 | So I will just create an
NSString object and hold the State.
| | 03:19 | I don't have to do it this way.
| | 03:20 | I could have just used a literal
but this would be fine, I will call it
| | 03:23 | someState and set it equal to AZ.
| | 03:26 | And then we will do an NSLog message.
| | 03:30 | I will have two placeholders, percent
sign at sign, is for %@, first placeholder
| | 03:39 | will be filled by the someState
abbreviation, and the second one what we are
| | 03:43 | going to do is use the State's
dictionary and use the method called
| | 03:49 | objectForKey, and here is where I
pass it the key, which I have someState.
| | 03:54 | It's in NSString and
that's fine. Save that, run it.
| | 04:01 | As we see here AZ is for Arizona, and
no particular surprise here feed in CA,
| | 04:08 | CA is for California.
| | 04:11 | The thing is, we don't have to know what
position these are in, in the dictionary.
| | 04:16 | Now even though the few entries that I
put in, I did in alphabetical order you
| | 04:21 | don't have to do that.
| | 04:23 | Dictionary is quite capable of
looking up these different values.
| | 04:26 | You don't have to impose your
own thought structure on that.
| | 04:30 | It's fine if it was the other
way around or even all mixed up.
| | 04:33 | Now just like working with NSArray, the
NSDictionary is immutable. It's unchangeable.
| | 04:40 | After it has been created you cannot
add a new entry to it, but also just
| | 04:46 | like the NSArray, and you might know
where I'm going with this, there is
| | 04:49 | another version of it, called the
NSMutableDictionary and we just add the
| | 04:53 | word Mutable in here,
NSMutableDictionary inherits from NSDictionary which
| | 04:59 | means it has all the same methods.
| | 05:01 | It just has a few more.
| | 05:04 | As the example, the few more
includes a method called setObject: forKey.
| | 05:13 | This is how we add a new
object into the NSMutableDictionary.
| | 05:19 | So in this case, I'll just say
this one as Florida forkey FL.
| | 05:22 | And not surprisingly, if I just feed an FL for
it, and run that, we will get FL as for Florida.
| | 05:32 | Now when you stop working with
dictionaries, you'll find it quite common to end
| | 05:39 | up with quite large ones, and sometimes
it can be useful to automatically to be
| | 05:44 | able to loop through all of them
without knowing exactly how many there are.
| | 05:47 | Luckily, we can do that, the something
called fast enumeration that's supported
| | 05:52 | in Objective-C and we will go through that next.
| | Collapse this transcript |
| Fast enumeration| 00:00 | Back when we were talking about loops,
I mentioned there was a kind of looping
| | 00:04 | called Fast Enumeration that
we would see a little later on.
| | 00:07 | And now is the time.
| | 00:08 | So we're familiar with the idea of the for loop.
| | 00:12 | Setting up a block of code to execute and
then having those three different pieces.
| | 00:16 | the initializer, the condition,
and the incrementer on the top.
| | 00:20 | And they're great but they don't
really help you, say, go automatically
| | 00:24 | through a collection.
| | 00:25 | Well, what we're going to use
instead is a variant of the for loop.
| | 00:30 | Except we're going to say, and this is
a little bit pseudo-coding, just going
| | 00:33 | to have a little phrase here that
says for each element in my collection I
| | 00:38 | would like to repeat this loop whether that
collection has 5 elements in it or 500 or 5000.
| | 00:43 | So we have to figure out how do we say this.
| | 00:48 | So let's imagine that I've got an
NSArray object and it's just got strings in it.
| | 00:53 | Could be 5 things and it
could be 500, I don't know.
| | 00:56 | What I want to do is just say I want
to loop through every string in myArray,
| | 01:03 | and I'll say it this way.
| | 01:04 | First, I'll name the type of the individual
element and then I'll give it a temporary name.
| | 01:08 | in this case x. Then the word, in,
and that's really the only other keyword
| | 01:13 | here, and then the name of my NSArray.
| | 01:15 | It works with the Objective-C
collections like NSArray, MutableArray,
| | 01:20 | NSDictionary, and so on.
| | 01:21 | What that means is that it'll
automatically loop through every element
| | 01:25 | temporarily for each part of the loop
giving it the name, in this case, x.
| | 01:30 | So the first time through x will be carpenteria.
| | 01:32 | Second time through x will be camarillo.
| | 01:35 | third time through, it will be ventura.
| | 01:37 | fourth time, Oxnard.
| | 01:38 | fifth time, santa barbara.
| | 01:41 | So let's see it at work in a real example.
| | 01:43 | This was the MutableDictionary
that I created in the last movie.
| | 01:47 | It's just got a bunch of states loaded into it.
| | 01:50 | And while I had written a couple of
lines to directly access one part of it,
| | 01:54 | what I would like to do here is just write
out a message with every element in that array.
| | 02:00 | So what I am going to do is get rid of that.
| | 02:03 | I am just going to type the word, for.
| | 02:05 | And when we do on a Mutable
Dictionary or just a Dictionary, what we're
| | 02:10 | interested in is the keys, and that's
what Fast Enumeration will give us here.
| | 02:14 | It'll give us all the keys.
| | 02:16 | So I have to say well, what are my keys?
| | 02:18 | My keys are NSStrings.
| | 02:19 | So I am going to say it NSString, and
then I have to give it a temporary name
| | 02:25 | for each iteration of the loop.
| | 02:26 | I could call it key or
stateAbbreviation. it doesn't matter.
| | 02:34 | Then the word, in, and then the name of the
collection which, in this case, is states.
| | 02:41 | That term stateAbbrev is
just something I made up.
| | 02:44 | It's only going to exist
for the lifetime of the loop.
| | 02:47 | I am going to then copy in my NSLog
message that I had written earlier.
| | 02:53 | But instead of having some state that
doesn't exist anymore, I'll just say well,
| | 02:56 | what I am interested in is that stateAbbrev.
| | 03:00 | And now it'll also be used as
the key to access the object there.
| | 03:05 | This is Fast Enumeration.
| | 03:08 | The for loop doesn't know how big it is.
| | 03:10 | It's not looking up the
count of this MutableDictionary.
| | 03:13 | It doesn't matter whether there
were 50 things or 5000 things.
| | 03:16 | it's going to go through all of them.
| | 03:18 | We save it, we run it and not
surprisingly, it goes through all the entries in
| | 03:24 | that dictionary and writes them out.
| | Collapse this transcript |
|
|
9. File ManagementIntroduction to file management in Objective-C| 00:00 | No language will be complete without
some discussion of reading and writing
| | 00:03 | files to the file system.
| | 00:05 | And although we do have the very low
level C way of doing things, I'm not going
| | 00:09 | to be touching that at all because in
Objective-C we have these great classes
| | 00:15 | that help us save files, read files,
copy them, read through directories.
| | 00:20 | And although there are quite a few of
them, the heart of everything is a class
| | 00:25 | called NSFileManager.
| | 00:32 | We can get this file just by
simply doing an alloc init on it.
| | 00:40 | Then what we instantly have are methods for
say copying, copying item a path or to URL.
| | 00:48 | If I type Move I can see I can move files.
| | 00:52 | There is a fileExistsAtPath that
returns a Boolean, does this file
| | 00:59 | actually exist or not?
| | 01:03 | Typing att I can let the Code Sense
show me that there are ways of getting
| | 01:07 | attributes of the item at a particular path.
| | 01:11 | We can remove items as well.
| | 01:13 | So it really does allow us
to do quite a lot with it.
| | 01:16 | But before we do any of that, what I'm
going to start off with is a path to something.
| | 01:21 | If I jump over to Finder I am just going
to show you that I've got a simple text
| | 01:26 | file sitting in my own home directory here.
| | 01:29 | There is nothing remarkable about this one.
| | 01:31 | If I look at Get Info, I
can see it's just text.txt.
| | 01:35 | I'm hiding the extension
right now, but that's fine.
| | 01:37 | So I'm going to create an
NSString just to hold that path.
| | 01:47 | Now although I'm not a big fan of
having paths hard-coded into your programs,
| | 01:52 | for our sakes here this is a useful
enough way of doing it and then I am going
| | 01:57 | to do some operations with that.
| | 01:58 | Well, first off, I better call and find
out does this actual file exist or at
| | 02:03 | least does the File Manager think it exists?
| | 02:05 | So I am going to write the body of
my if statement here and inside the
| | 02:10 | parentheses I will call File Manager
and I am going to ask fileExistsAtPath.
| | 02:17 | There's a separate option that allows
me to ask if this is a directory, but I
| | 02:24 | just need the first one here.
| | 02:26 | Just hit Return, and I'll be passing-in
that NSString I called, called Path.
| | 02:31 | Now, this is a method that returns a Boolean.
| | 02:35 | So while I could put == YES, I don't
really need to because the method itself is
| | 02:40 | going to return yes or no.
| | 02:41 | Well, we'll start off with
something simple just an NSLog message.
| | 02:45 | yes, it exists or no, it doesn't.
| | 02:49 | Save that, run, and we're getting no.
| | 02:55 | It doesn't mainly because
I spelled it incorrectly.
| | 03:02 | It's text.txt, so just make that
change, run it again, and then we're
| | 03:07 | getting yes, it exists.
| | 03:08 | So I've got a nice little proof
that to both my yes and my no work.
| | 03:11 | Well, that's not really very exciting,
so let's do a little more with it.
| | 03:16 | What I can do is grab the
attributes of that file.
| | 03:21 | As you might imagine there's
quite a few different attributes.
| | 03:24 | So the question is how do I get them?
| | 03:26 | Well, what's going to happen is
getting the attributes is actually going to
| | 03:29 | return an NSDictionary, and luckily
we've already done a little bit of work
| | 03:34 | through with the NSDictionary.
| | 03:35 | So I am going to call it
fileAttributes and set that equal to and use my File
| | 03:43 | Manager again, and the method that
I want is attributesOfItemAtPath.
| | 03:50 | The path is again my path and then I
have a second parameter here called Error.
| | 03:56 | Let me split that on another
line so it's a bit more readable.
| | 03:59 | So this method takes a second parameter
which is basically handing over an error
| | 04:04 | object, so if there's an error, it
can fill it and then pass it back.
| | 04:07 | I am just going to set that to Nil,
because we really don't need it right now.
| | 04:11 | So that should come back with an
NSDictionary full of attributes about that file
| | 04:16 | and we want to prove it.
| | 04:18 | So I'm going to do some fast enumeration
through that dictionary and print them all out.
| | 04:25 | What I've done here is very
similar to the code we had in our fast
| | 04:28 | enumeration section which is simply
looping through all the keys, and then
| | 04:34 | I'm writing out what each key is and
what the object for that key is in that
| | 04:38 | Attributes dictionary.
| | 04:40 | So let's run this, re-run that, I
am going to drag this debug window a
| | 04:44 | little wider and we can start to see
that we're getting a whole bunch of
| | 04:47 | different attributes.
| | 04:48 | I am going to hide my Navigator just to
give us a bit more room, make it a bit
| | 04:52 | more readable here, file owner account
IDs, file size, file system number, file
| | 04:58 | type, extended attributes, still there is
a bunch of stuff there that we can get to.
| | 05:03 | Again, I am not going to do anything
with it, but as you can see, you really can
| | 05:06 | start to drill down into very
particular pieces of that information.
| | 05:11 | So after getting the attributes I am
going to do one more thing to it which is
| | 05:14 | basically change its name.
| | 05:16 | The way that we do that is using again
the File Manager, File Manager is pretty
| | 05:21 | much the way we do just
about every file operation.
| | 05:24 | We're going to say moveItemAtPath.
| | 05:29 | We'll give the first path that we've
been using all along, hit Tab, jump across.
| | 05:35 | Now, the next part of the method which is
toPath, I can just give it a path literal here.
| | 05:40 | Again wouldn't typically do this in real
code, but for our purposes it's just fine.
| | 05:45 | Call it newname.txt, and then I'm
going to pass-in Nil for the error again,
| | 05:52 | save that and run it.
| | 05:55 | We spit out all the attributes but I
should hope if I jump over to my Finder
| | 06:00 | that yes, I now have newname.txt.
| | 06:03 | And of course if I click back into my
program, cleared the debug area and just
| | 06:08 | ran it again, all that it would expect
to see was the message no, it doesn't
| | 06:13 | because that file doesn't
have this original path anymore.
| | 06:19 | The last thing that I should do of
course being a good Objective-C programmer
| | 06:22 | is find anything that I manually alloced and
inited which was the NSFileManager and release it.
| | 06:29 | So as you can see it's just that
one class really does drive a lot of
| | 06:34 | behavior about working with files and you can
also work with the directories the same way.
| | 06:39 | What we haven't yet done
is start reading or writing.
| | 06:42 | So we'll get to that next.
| | Collapse this transcript |
| Working with paths and URLs| 00:00 | The first few times we think about
reading or writing files in Objective-C we
| | 00:04 | tend to think in terms of file paths.
| | 00:06 | a simple string of text, something like this.
| | 00:09 | Now this is okay to get us started but
I'm about to tell you that we're going
| | 00:12 | to stop doing it this way, yes we
will still see file paths as good old
| | 00:18 | NSStrings but from now on we're going to add
one more step to every path that we work with.
| | 00:23 | We are going to turn this
NSString object into an NSURL object.
| | 00:29 | Now for a lot of people when they think
about URLs they just think the address
| | 00:33 | of a website but for us
it's much more than that.
| | 00:36 | A URL after all is the location all of a
resource and it's a great way to work with files.
| | 00:43 | Even if we look at a simple web address
like this, there is quite a lot going on
| | 00:47 | in the URL there is this
scheme right at the front.
| | 00:51 | There is the domain, the location of
this, and those two separated by the colon
| | 00:56 | forward slash, forward slash.
| | 00:57 | There is the path that could also
be a query string or fragment ID.
| | 01:03 | Now the scheme could be a HTTP could be
HTTPS, could be FTP or it could be file
| | 01:08 | which is what we're interested in here.
| | 01:11 | We still need be :// then we
have the equivalent on the domain.
| | 01:17 | Now we could be using the address of
another machine or we could be using a
| | 01:20 | local host to represent our own
machine and after that we would have the
| | 01:25 | equivalent of what we think
a normal file path would be.
| | 01:28 | Forwards slash up to the top, down into
users into the Simon folder into file.txt.
| | 01:35 | now we could actually leave the domain
out by default that would assume that
| | 01:39 | we're on the local machine.
| | 01:41 | Now if we do that we're just pulling
the name of the domain out and we would
| | 01:45 | collapse the URL down which can look a
little odd because it has a three forward
| | 01:50 | slashes but this would be
considered a valid file URL.
| | 01:56 | And if your app needs to work with
paths to anything for files resources web
| | 02:00 | services, websites, you should be using
object of the NSURL class not just using
| | 02:05 | a string with that path in it.
| | 02:07 | Now the question is why?
| | 02:10 | Well it could just say because Apple
said so and they do, Apple are on record of
| | 02:14 | saying URLs are preferred over paths
it is a best practice but more than that
| | 02:19 | NSURL objects are faster and Apple
wrote a lot of code in Snow Leopard to
| | 02:24 | optimize URL-based operations and they
are typically more efficient than their
| | 02:28 | path-based equivalents.
| | 02:29 | Sure you're not going to notice this in
a small program but as your programs get
| | 02:33 | more complex it can add up.
| | 02:35 | two, they are better for catching errors.
| | 02:38 | It's easy to make a mistake when you're
writing a path as a string but an NSURL
| | 02:43 | won't allow itself to be created
unless the URL is well formed meaning it has
| | 02:49 | all the pieces it needs, nothing is missing.
| | 02:52 | Three they are more powerful and what
I mean by that is there are more and
| | 02:56 | more classes in Cocoa particular the newer
ones that only want to work with an NSURL object.
| | 03:03 | Now sure there are still a bunch of
classes in Cocoa that can work with a file
| | 03:08 | path as a string and I will
be the case for a long time.
| | 03:11 | Even the NSString object has string with
contents of file that can just take a file path.
| | 03:17 | There is an NSImage class that has
init with contents of file that will
| | 03:21 | just take a file path.
| | 03:23 | But these classes also work with URLs
where we had string with contents of
| | 03:30 | file we have the string with contents of
URL where we have init with contents of file.
| | 03:35 | We have init with contents of URL.
| | 03:38 | This is very commonly what you'll find
but more importantly there are some very
| | 03:42 | powerful classes things like NSDocument
that won't accept file paths of strings
| | 03:46 | they only accept URLs.
| | 03:49 | So the document, the audio-video
player item, the NSURLRequest these expect
| | 03:55 | and want these NSURL.
| | 03:58 | So we need to get comfortable creating
and working with these NSURL objects and
| | 04:02 | luckily they're pretty easy to make.
| | 04:05 | So I am looking here at the code that I
created in the last section the one that
| | 04:11 | just opened up a file at a file path
and looked at some of the attributes and
| | 04:15 | then moved it around.
| | 04:16 | So on line 10, I do have a typical
string-based path and what I am going to do
| | 04:22 | is convert this into an NSURL object.
| | 04:25 | NSURL is a class in the foundation
framework so we don't need to worry about
| | 04:30 | linking to some other framework it's
going to be there in any project, we make
| | 04:34 | along with all the other super common classes.
| | 04:37 | It's written all caps which might look
a little unusual but after all URL is
| | 04:41 | an abbreviation and we don't want to have to
write NS Uniform Resource Locator all the time.
| | 04:46 | So are going to say NSURL
and I'll call it my myURL.
| | 04:51 | So how do you create it, well typically
you won't do an alloc in the init call,
| | 04:55 | you going to use a different method
because like strings you want to create a
| | 04:59 | URL with some value.
| | 05:02 | Now if I start typing in the name of
the class and see what class methods are
| | 05:07 | available I might start looking at
some and I see that I've got a URL with
| | 05:11 | string and that looks likely
but it's not going to work.
| | 05:15 | You see if I use the URL with string
method and just pass in what I can think of
| | 05:20 | is a string-based path it's going to fail.
| | 05:23 | So what it's expecting here is a well
formed URL which means it would expect to
| | 05:29 | have the scheme of file:///.
| | 05:34 | And if I just passed in for example that
string called path this is going to fail.
| | 05:41 | It's not well formed.
| | 05:42 | However what there is is an alternative
which if I do have a normal file path I
| | 05:47 | can call NSURL fileURLWithPath
and that should do the trick.
| | 05:55 | Now I don't see an alloc or an init
here so I can assume that this object
| | 06:00 | will be auto released.
| | 06:01 | But again if you're starting to
explore them you really want to do one of the
| | 06:05 | good old Option+clicks and jump to the
class reference and just get familiar
| | 06:09 | with the different ways
that an NSURL can be created.
| | 06:13 | Once I've got one, then what?
| | 06:15 | Well this is actually a pretty good
example because if I start to come down to
| | 06:19 | where the file manager is interacting
with things I'll see that there are quite
| | 06:26 | a few path-based methods.
| | 06:26 | fileExistsPath attributesOfItemAtPath
and because the NS file manager is an
| | 06:31 | older class there are a lot of path-based
method still there but I could come
| | 06:35 | down for example here where we are
doing the moveItemAtPath and if I type in
| | 06:40 | moveItemAtPath I can see that I have
the exact equivalent as moveItemAtURL
| | 06:46 | and this would be the preferred way of doing it.
| | 06:51 | In here I will put in my URL again I
have got two URL so I would need to create
| | 06:55 | another I am not actually going to do
that right now but you get the picture.
| | 06:59 | The whole point of creating these
NSURLs is because you are going to use
| | 07:04 | them somewhere else.
| | 07:05 | they are a means to an end.
| | 07:06 | You will be using them to
read in contents of files.
| | 07:10 | You will be using them to create other
objects, but as you see they are pretty
| | 07:14 | easy to create and this is
the best practice going forward.
| | Collapse this transcript |
| Reading and writing strings| 00:00 | Although, NSFileManager will be the
class you use if you are wanting to work
| | 00:04 | with files and directories in any
significant way, we don't actually even have
| | 00:08 | to go that deep, if all we're wanting
to do is say reading the contents of a
| | 00:12 | file into a string or even go the other way
and save the contents of a string as a file.
| | 00:17 | So I've got another simple project here,
on line 9 I've just, to save us some
| | 00:22 | time written the file URL here
that's pointing to an existing file.
| | 00:26 | And what I'm going to do is create a
new NSString object, and instead of giving
| | 00:32 | it an explicit value, I'm going to
call the method of NSString, called
| | 00:37 | StringWithContentsOfURL.
| | 00:38 | There are a couple of different
choices, the difference here is one has a
| | 00:43 | second parameter called encoding and
the other one has a second parameter
| | 00:47 | called usedEncoding.
| | 00:49 | I'm picking the first one because I'm
going to tell it that as far as I'm aware
| | 00:54 | it was encoded standard ASCII UTF-8 equivalent.
| | 00:58 | The first thing I have to give it is
the fileURL that I created on the previous
| | 01:02 | line, then hit Tab, and the encoding
here is actually a built-in enumeration.
| | 01:08 | We haven't used this one yet, but what
I'm going to type is NS and as I start
| | 01:13 | typing, I'll start type UTF and it
gives me a variety of different Unicode Text
| | 01:19 | Format encoding options.
| | 01:21 | I'm picking the
UTF8StringEncoding, the most basic one here.
| | 01:26 | And then we've got another error
parameter here, I'm just going to send it Nil.
| | 01:32 | So in line 11 we should go out, find
the contents of that file and read that
| | 01:37 | into that string called Text.
| | 01:39 | To prove it let's write out a message.
| | 01:42 | Oops! Got my % sign and @ sign around
the wrong way there, and run it.
| | 02:00 | Nothing shocking, but apparently the contents
of that file say This is a simple text file.
| | 02:05 | What I'm going to do in the next
step is change it and save it back.
| | 02:10 | Now I can't actually change the NSString
because that is an immutable string, so
| | 02:15 | what I'll do on line 11 is just
change it to an NSMutableString.
| | 02:21 | Leaving everything else the same
except the name of the class, Mutable String
| | 02:26 | inherits from NSString, so
we have all the same options.
| | 02:29 | But what that allows me to do is say
I've got this Mutable String called text
| | 02:33 | which now has a nice method called appendString.
| | 02:41 | So we're changing the contents of that
Mutable String in memory and on the next
| | 02:45 | line I'm going to save it back
to that original file address.
| | 02:50 | Again, it's just a
method of the NSString object.
| | 02:53 | I type in wr and it's giving me the
writeToURL, I'm going to use the same one
| | 02:59 | that we read in with.
| | 03:00 | Well the next parameter, the Boolean
for atomically means, is if you say Yes,
| | 03:07 | it will save the file first to a
temporary file name to make sure that it can
| | 03:12 | save all the contents to the hard drive and then
when that successfully works, it will rename it.
| | 03:18 | This is designed to protect you if there are
any issues when actually saving to the disk drive.
| | 03:23 | So I'm going to say YES, why not.
| | 03:26 | Encoding, I'll do exactly the same
encoding as we did before, which was the
| | 03:30 | NSUTF8StringEncoding and I'll leave
the error as nil, Save that and run it.
| | 03:39 | We get the message coming
out saying, The contents were:
| | 03:41 | This is a simple text file.
| | 03:43 | But if I jump over to Finder and go
and find that text file right now here,
| | 03:48 | it's just been modified right now and I
should expect to see a couple of options in here.
| | 03:55 | It's added the words, here's some more
text and even more text, and that's been
| | 03:59 | successfully saved back from our code.
| | 04:03 | Now while this is obviously something
that you'd use for fairly small files, the
| | 04:09 | ability for a lot of these Objective-C
classes to be able to read and write
| | 04:13 | their own data can be very, very useful.
| | 04:16 | It's not just strings but image files,
NSDocument files, there is a lot of stuff
| | 04:21 | that has these possibilities.
| | 04:23 | If your desire is to actually go
deeper into the reading and writing without
| | 04:28 | actually loading them into a particular
object, then looking at the NSData class
| | 04:34 | and the NSFileHandle is
probably what you're after.
| | Collapse this transcript |
| Archiving objects| 00:00 | So as we've seen it's pretty simple to
use some of these built-in methods to
| | 00:04 | save data from say an NSString
or read data into an NSString.
| | 00:08 | But what happens when we're
working say with our own objects?
| | 00:12 | What happens if, for example, I've
defined an Employee class that holds a few
| | 00:16 | different pieces of data and what I'd
like to be able to do is save objects of
| | 00:21 | that class to the file system?
| | 00:23 | Well, I could write a whole bunch of
code that breaks apart different things and
| | 00:27 | saves them all as NSStrings to
different files, but that's fairly inconvenient.
| | 00:32 | So if I want to have this process of
taking it to a file, there are a couple of
| | 00:36 | classes in the Foundation.
framework that can help us.
| | 00:40 | The first class is called NSKeyedArchiver.
| | 00:44 | What it lets us do is break apart the
different pieces of our objects, give them
| | 00:51 | a key, and then store them in that file.
| | 00:54 | This process is called encoding.
| | 00:56 | But if you're going to encode,
you almost certainly want to decode.
| | 01:00 | You want to be able to break it out
of a file and reconstitute that object,
| | 01:04 | and of course you can.
| | 01:06 | The flipside is the NSKeyedUnarchiver,
which can read that file and then break
| | 01:11 | it apart and reconstitute, rebuild
the Employee object, and that is the
| | 01:15 | process of decoding.
| | 01:17 | So let's see how we do it.
| | 01:19 | Jumping over into Xcode, I've got
a very simple project set up here.
| | 01:24 | I've created a very
straightforward class called Employee.
| | 01:28 | It's about as simple as it gets.
| | 01:30 | It has two instance variables.
| | 01:32 | an NSString pointer for
name and an integer for grade.
| | 01:36 | I've added the two lines to
create the properties for that.
| | 01:40 | Then over here in the implementation
I've got the synthesize statement for that.
| | 01:44 | The only other thing that I have in
here is a simple description method that
| | 01:49 | creates a string with information about
that object, and that's not important.
| | 01:54 | Jumping over to main.m, all I have
here is on Line 9 I am instantiating a new
| | 02:00 | instance of that Employee class called
bob, and then I am calling two of the
| | 02:04 | accessor methods to set
his name and set the grade.
| | 02:07 | On Line 13 I write out the Details.
| | 02:10 | So there is nothing happening
right now as regards archiving this.
| | 02:15 | We're going to add all of it.
| | 02:16 | What I want to do is somewhere after
that message I want to be able to save that
| | 02:21 | Employee and save it to the file system.
| | 02:24 | So what do I need to do?
| | 02:25 | Well, to support this whole archiving
process what I need to do is add two
| | 02:31 | methods into my implementation.
| | 02:33 | We'll take it one by one right now.
| | 02:35 | I am going to support the process of
encoding and I need to add a method.
| | 02:40 | It's going to be an instance method
because it works on the individual objects,
| | 02:43 | and it's called encodeWithCoder.
| | 02:47 | Now, this is not my own made up name.
| | 02:50 | It's very important that you use
exactly this name, because this is the method
| | 02:55 | that the KeyedArchiver is
going to be looking for.
| | 02:59 | This encodeWithCoder method takes one parameter.
| | 03:03 | It's an NSCoder pointer and I'll call it coder.
| | 03:08 | It's the only part that's
not really important here.
| | 03:11 | When we choose to archive this
object, encodeWithCoder will be called.
| | 03:17 | So we have to add a line of code that
says yes, I want to encode the name,
| | 03:20 | and, yes, I want to encode the grade, or
whatever other instance variables or properties we had.
| | 03:26 | I am going to call a method on the
coder parameter that was passed in
| | 03:31 | called encodeObject.
| | 03:33 | In this case I am encoding name,
which is an NSString. That's the object.
| | 03:37 | There is a second part called forKey.
| | 03:41 | Now really what you just do here is kind of give
it your own name, give it your own id here.
| | 03:48 | I'll call it EMPname for employee name.
| | 03:51 | The only reason that we're doing this
is that on the other side of this I'm
| | 03:56 | going to be given a succession of
values and I need to have a key for each one
| | 04:01 | to make sure that I get them out the right way.
| | 04:04 | So it's completely up to
you what you want to call it.
| | 04:06 | Now, next up what we do, and I've
only got two variables here, so I call
| | 04:12 | encodeObject and I'm passing in grade and
I'll say forKey, let's called it EMPgrade.
| | 04:21 | Unfortunately, there is going to be a
little bit of a problem with this one.
| | 04:27 | The issue is that grade is an
integer and this is expecting an object.
| | 04:33 | Although it's a warning,
I want to take care of it.
| | 04:35 | What I am first going to do is I have to
wrap grade up in an object, I have to box it.
| | 04:41 | And there is a suitable one to do this with.
| | 04:43 | It's called the NSNumber class.
| | 04:46 | I'll call it gradeBox and just create
it by calling the numberWithInt method.
| | 04:53 | This wraps up grade in an object,
and then I pass that object into the
| | 05:00 | encodeObject method. That will do it.
| | 05:03 | I click Save. I click Build.
| | 05:06 | Build has succeeded. Okay, so now what?
| | 05:10 | Well, back over in main.m, I got a little
place where I said I wanted to save this object.
| | 05:15 | So I'm going to write the
code to actually save it.
| | 05:17 | What we're using is that
NSKeyedArchiver, not Unarchiver, but Archiver.
| | 05:24 | We're going to archive that object.
| | 05:26 | The way we say it is there is a
method called archiveRootObject.
| | 05:30 | We refer to as the RootObject because
of course we could be having an entire
| | 05:34 | object graph, it could be multiple ones
involved, and if you think about it, the
| | 05:37 | way they kind of are, my Employee object
itself contains an NSString object. That's okay.
| | 05:44 | So the object I want to archive
was instantiated up on Line 9.
| | 05:48 | It's called bob, and then it says toFile.
| | 05:51 | And here it's actually
expecting just a string path.
| | 05:56 | I'll Save it to Users, under my home
directory, and I am going to call this
| | 06:02 | bob.plist, because by default it
will save as a Property List file.
| | 06:07 | We'll take a look at that in just
a moment to see what that means.
| | 06:10 | I am going to Save that,
click Build, and then Run it.
| | 06:18 | It spits out the log message.
| | 06:19 | There is no message coming back from the
archive, but let's go and find out if it worked.
| | 06:22 | I am going to jump over to my Finder,
and I do see that at my home folder here I
| | 06:27 | do have bob.plist that just got created.
| | 06:30 | This is a Property List file.
| | 06:34 | I can actually open it up
with Xcode and take a look.
| | 06:38 | What it's doing and this is what the
KeyedArchiver does in conjunction with the
| | 06:42 | coder is break this down
into the tiniest little pieces.
| | 06:46 | It's a very controlled, very
structured, way of doing this.
| | 06:50 | So it includes not just the data itself
such as the Number and the String of Bob
| | 06:55 | Jones, but what is this object?
| | 06:57 | Well, it's an Employee.
| | 06:58 | What does it inherit from?
| | 06:59 | It inherits from NSObject,
all of that kind of stuff.
| | 07:02 | So it is rather deep.
| | 07:06 | However, the flipside is, no real
point archiving something if you're not
| | 07:10 | going to unarchive it.
| | 07:12 | No, that doesn't happen automatically,
what I'm going to have to do is jump back
| | 07:16 | over into my implementation and I am
going to add the ability to decode this.
| | 07:24 | This is a method that returns an
id because it's returning an object.
| | 07:28 | It's basically an initialization method,
which makes sense if you think about it.
| | 07:31 | So it's not decodeWithCoder.
| | 07:33 | Its initWithCoder, because if this
ever happens it will happen on that
| | 07:39 | first initialization.
| | 07:42 | Like the previous method it's using the
NSCoder object to reconstitute this, and
| | 07:48 | what I'm doing is the flipside of this.
| | 07:50 | So I need to set my name instance
variable equal to on the way out I called
| | 07:56 | coder encodeObjectForKey.
| | 07:59 | This time I'm calling coder decodeObjectForKey.
| | 08:05 | The keys that I'm passing are just the
ones that I defined on previous lines,
| | 08:09 | say in this case on Line 8.
| | 08:11 | So it will say EMPname.
| | 08:12 | Next, I want to get grade back out,
although that is going to be an NSNumber, so
| | 08:18 | I have that in between stage that I need
to do to get it out and then decode it.
| | 08:26 | I'll call it gradeBox again.
| | 08:29 | coder decodeObjectForKey.
| | 08:33 | In this case it was EMPgrade.
| | 08:37 | Then I'll actually set that integer
variable by casting out of that NSNumber object.
| | 08:50 | The NSNumber object actually has a
method called integerValue, but that's
| | 08:54 | returning an NSInteger object.
| | 08:57 | So this is the only way that I am going
to do it that won't give me any warnings.
| | 09:01 | The last thing I need, because this does need
to return an id is I am going to return myself.
| | 09:08 | Build, Build succeeded.
| | 09:10 | I am going to jump back over to
main, and well, let's prove it.
| | 09:14 | I think the best way to do this would
be after we've archived it off, I'm going
| | 09:19 | to now create a new Employee.
| | 09:22 | This one can be called fred, and
I'm going to reconstitute fred from
| | 09:27 | the bob.plist file.
| | 09:29 | The way that I do is I just call
NSKeyedUnarchiver, and the method is
| | 09:40 | unarchiveObjectWithFile.
| | 09:45 | Obviously in this case it has to
be the same path that I saved it to.
| | 09:49 | Just going to give myself a bit more room here.
| | 09:53 | And just to prove that worked I really
need to write out an NSLog message that
| | 09:58 | says The new object is %@, fred description.
| | 10:09 | If you remember I had written a
description method in my implementation.
| | 10:12 | I'm going to talk about that in just a second.
| | 10:14 | I'm going to Save that and Run it.
| | 10:16 | What we see is we're outputting the
first message just before we save it and
| | 10:20 | then we're reading it back in, we're
reconstituting that new object, and it has
| | 10:25 | got all the same data as the previous one.
| | 10:28 | Again, a very simple example here, but
the process is exactly the same even if
| | 10:32 | you have many more instance variables.
| | 10:35 | Now, the last thing I was going to
point out was, I am calling the description
| | 10:39 | method of these objects here
and I really don't need to.
| | 10:42 | In fact, I just need to pass in
that object name. Why is that?
| | 10:48 | Well, because by default when you use
the percent sign, at sign in an NSLog
| | 10:56 | message or anything, what it's
actually doing is looking for the description
| | 11:01 | method of that object.
| | 11:03 | That's the default behavior.
| | 11:04 | So we're using the NSKeyedArchiver
here, we're using the NSKeyedUnarchiver.
| | 11:10 | Simply by adding those two methods.
| | 11:13 | the encodeWithCoder and initWithCoder,
we can start to support the idea of
| | 11:18 | breaking this apart into a plist file.
| | 11:20 | Now, the last thing to point out is,
if you take a look in your Code Snippet
| | 11:24 | Library, you'll actually find one
of the examples here, which is the
| | 11:29 | initWithCoder is there.
| | 11:31 | For some reason they have the
initWithCoder as a code snippet but they don't
| | 11:34 | have the encodeWithCoder as a code snippet.
| | 11:36 | It's not a particularly complex one
anyway but just to let you know if you're
| | 11:40 | looking for a bit of a
helper, there is one there.
| | 11:42 | Now, there is one more thing I need to
do before I'm done here, which is that in
| | 11:47 | our initWithCoder, Line 14 is extracting
this new object and assigning it to the
| | 11:53 | instance variable of name.
| | 11:55 | Well, that certainly means the coder
is just providing me an auto-released
| | 11:59 | object here, and because it is an
object I need to make sure that we are
| | 12:02 | retaining it so that it doesn't disappear.
| | 12:05 | So I am going to call name retain.
| | 12:10 | Now, what you'll see is that you'll
often see that quite commonly just written
| | 12:14 | this way, as a nested call.
| | 12:20 | But either way we're going to retain it here.
| | 12:23 | The best idea would be if I need to
release it I'll come down here to my dealloc
| | 12:28 | method to make sure that
name has a release call.
| | 12:33 | I don't need to do that for grade,
because grade is just an integer and we don't
| | 12:37 | bother with any of those
things with normal primitive types.
| | Collapse this transcript |
|
|
10. More Complex ClassesInheritance and NSObject| 00:01 | A key idea in object-oriented
programming is the idea of inheritance and that is
| | 00:06 | simply meaning a new class can
base itself off another class.
| | 00:10 | It's another form of code reuse.
| | 00:13 | We've been using it all along, every
time I add a new class in Xcode what
| | 00:17 | it's going to do when I select this Objective-C
class is ask, do I inherit from something?
| | 00:24 | The question is being phrased here
as am I the subclass of another class?
| | 00:28 | In this case I'm selecting NSObject
which is one I'll do most of the time.
| | 00:31 | There are a few other choices in the
dropdown, but the rest of them are to do
| | 00:34 | with more complicated user
interfaces, I don't need that.
| | 00:37 | So NSObject is just fine.
| | 00:40 | Click Save, I am now inheriting from NSObject.
| | 00:45 | Well I'm not alone, virtually
everything does inherit from NSObject, NSString,
| | 00:49 | NSArray, NSDate, they all inherit from NSObject.
| | 00:53 | Even some of the more complex
classes we've been dealing with such as
| | 00:56 | NSMutableString and mutableArray, well
they themselves inherit from NSString and
| | 01:01 | NSArray which in turn inherit from NSObject.
| | 01:05 | So inheritance can work up multiple levels.
| | 01:08 | In fact when you get into more
complicated user interfaces and say you're
| | 01:13 | working with views and buttons you'll
find that the NSButton inherits some
| | 01:18 | NSControl which inherits some NSView,
which inherits some NSResponder, which in
| | 01:22 | turn inherits from NSObject.
| | 01:23 | Now you are unlikely to create
inheritance hierarchies of this complicated,
| | 01:30 | something that's not really needed
in Objective-C by most developers.
| | 01:35 | So we're primarily concerned with
what is our direct superclass and that's
| | 01:40 | the term that we use.
| | 01:42 | When we create a new interface for a
class, in this case call MyClass, after the
| | 01:46 | name of the class is the colon
and then the name of the superclass.
| | 01:52 | Just because other object-oriented
languages use different terms for the same
| | 01:56 | concept, you might hear this is also refer
to as your base class or your parent class.
| | 02:01 | We are inheriting from NSObject and
because so many things inherit from NSObject
| | 02:07 | you might often hear this
refer to as the root class.
| | 02:10 | It really is at the base of everything.
| | 02:13 | Now that inheritance means that your
class immediately has every piece of
| | 02:17 | functionality that NSObject has, plus
whatever you decided to add, your new
| | 02:23 | methods, your new instance
variables, your new properties.
| | 02:26 | It is why immediately after creating a
new class without writing any extra code
| | 02:31 | from it, I could come into my main
function, add a line to import the class
| | 02:37 | header files just so main knows what
I'm talking about and then write some code
| | 02:42 | here to create a new instance of that class.
| | 02:45 | It's why we immediately have an alloc
method, because alloc is defined in NSObject.
| | 02:51 | It's why we have an init method,
because init is in NSObject.
| | 02:56 | It's why you could call the
description method on any object anywhere because
| | 03:00 | NSObject has a description method.
| | 03:03 | Now of course there's not much point
to creating a new class if you are not
| | 03:07 | going to add anything to it.
| | 03:09 | While you can add your own methods in
your own properties your own instance
| | 03:13 | variables to your new class, what you can't
do is remove methods you get in a superclass.
| | 03:19 | So I can decide not to have an init method,
though I could choose to make my own version of it.
| | 03:26 | Now what you might find useful is
occasionally doing an Option+click on
| | 03:30 | NSObject, taking a look at the class
reference and actually finding out what are
| | 03:35 | available methods in this NSObject class,
what things might I'd be interested in
| | 03:41 | providing my own version of?
| | 03:44 | Well to be honest, there is not that
many, I mean you are very unlikely to
| | 03:48 | create your own version of alloc for example.
| | 03:51 | The one that's there is perfectly good enough.
| | 03:53 | In fact the methods that you're most
likely to provide your own version of are
| | 03:58 | the init method and the dealloc method.
| | 04:02 | In fact those are the ones that
conveniently are provided for you as boilerplate
| | 04:08 | code to provide your own version of
them in your own class implementation.
| | 04:12 | This is what's called overriding, you
can override a method in the superclass by
| | 04:18 | providing your own version of it.
| | 04:20 | Now it needs two examples here both for
the init method beginning on line 14 and
| | 04:25 | the dealloc method, we can see we have
a little bit of code in here and we've
| | 04:29 | seen this one before, but what's
quite common is this call to super.
| | 04:34 | We have a call to super init on line 16
and then in our dealloc method we have a
| | 04:39 | line to super dealloc.
| | 04:41 | This is great for us because what it
allows us to do is both provide our own
| | 04:45 | implementation of init and dealloc and
still use the one that's defined in the
| | 04:51 | superclass in NSObject.
| | 04:53 | So in the init method on line 16 we
first say pass this backup, let NSObject
| | 04:58 | do whatever it needs to do internally,
I don't even need to think about that
| | 05:02 | and then on line 17 making sure that I
exist as an object I'm going to then do
| | 05:07 | my own extra stuff.
| | 05:08 | In the dealloc method well before the
call to super dealloc, I could then tidy
| | 05:14 | up anything that I did myself.
| | 05:16 | Very common patterns to see, you don't
need to provide your own version of them,
| | 05:20 | but this would be the way that you could.
| | 05:22 | Now to override a method, all you need
to do is write a method in your new class
| | 05:29 | implementation with the same
signature as the one in the superclass.
| | 05:34 | Don't change the parameters,
don't change the return type.
| | 05:37 | The description method is one
for example that exists in the
| | 05:41 | NSObject superclass.
| | 05:42 | Now you don't need to list any of
these overridden methods in your header
| | 05:46 | file, because your header file
already points to NSObject so that compiler
| | 05:51 | knows that method exists.
| | 05:53 | Now I am overriding description here.
| | 05:56 | Description is the method that is
called when you use a placeholder in a format
| | 06:01 | string to write out your object
and this just returns an NSString.
| | 06:06 | This would not be a method where I would
need to call the superclass version, so
| | 06:10 | there is no call to super
description, because there is no point.
| | 06:13 | Now what happens if I don't override it?
| | 06:16 | Well, let me show you.
| | 06:18 | So in this current brand-new
class I don't have an overridden
| | 06:20 | description method.
| | 06:21 | I am going to jump over to my main.m
and after the line that instantiates that
| | 06:27 | object I am just going to output a
message that says "The description is %@" as
| | 06:34 | a placeholder and then say newObject.
| | 06:39 | This will call the
description method of this newObject.
| | 06:43 | It will see that newObject
is an instance of myClass.
| | 06:48 | It will jump into myClass and look for
that implementation say do you have a
| | 06:52 | description method, in this case I don't.
| | 06:54 | So what it will then do is kick it up
to the superclass which it will see is
| | 06:59 | NSObject and look for the
description method there.
| | 07:03 | We run this and what we are going to
get and this is the default description
| | 07:07 | method in NSObject that will say the
name of the class, not the name of the
| | 07:11 | object and then the address in memory
of this particular object, might be what
| | 07:16 | you want, but really not very useful.
| | 07:19 | To provide my own version, I simply
jump into my implementation file and in the
| | 07:25 | body of implementation I am going to write this.
| | 07:27 | It is an instance method
that returns an NSString.
| | 07:33 | Description, now I don't actually have
any instance variables to piece together
| | 07:39 | which is what I'd usually do here so I
will just return interesting message.
| | 07:44 | You can tell from this that
obviously in NSString there is an overridden
| | 07:49 | description method that
returns the contents of the string.
| | 07:52 | In NSDates there is an overridden
description method that returns the date
| | 07:56 | formatted out as date and time and time zone.
| | 07:59 | We run this again and now it says okay,
you do have an overridden version of
| | 08:03 | that description so I'll
output that one instead.
| | 08:06 | That's pretty much it.
| | 08:07 | Once you've overridden the method,
it will be used in preference to
| | 08:11 | the superclass version.
| | Collapse this transcript |
| Extending classes with categories| 00:01 | So we use inheritance in every class we
deal with, and that might make what I'm
| | 00:06 | about to say sound a little weird, but
in Objective-C inheritance is just not as
| | 00:11 | big a deal as it is in other languages.
| | 00:13 | Let me explain what I mean.
| | 00:15 | See, in most Object-Oriented languages
you're concerned about inheritance in at
| | 00:20 | least two different ways.
| | 00:21 | One, when you are defining your own
unique classes for your app, you inherit
| | 00:26 | from a typical base class, fine.
| | 00:28 | We do that too, and it's usually NSObject.
| | 00:30 | But two, the other way.
| | 00:31 | See, it's very common in other Object-Oriented
languages to need to inherit from
| | 00:37 | existing specialized classes.
| | 00:39 | You might have to create your own
version of a string class or a subclass, a
| | 00:44 | collection class, or subclass a built-in
UI class, so that you can create your
| | 00:50 | own extended version of those classes, because
the built-in ones don't quite do what you want.
| | 00:55 | Now, this is the thing we
don't need to do in Objective-C.
| | 01:00 | Sure, we can do it, but we don't need to
because of something called categories.
| | 01:04 | And categories simply allow us to add
our own methods to an existing class
| | 01:09 | without subclassing it.
| | 01:11 | So simple example, let's say you like
the NSString class but you just wish it
| | 01:16 | had a built-in method to reverse a
string or convert a string to Pig Latin or
| | 01:20 | convertWhiteSpace to underscores.
| | 01:21 | Well, you could subclass it.
| | 01:25 | You could create a new class called
MyConvertingString that inherits from
| | 01:28 | NSString and then start to
add your new methods to it.
| | 01:32 | Or you could do it the Objective-C way,
which is, you don't bother subclassing
| | 01:38 | it, you simply use a category that
adds those methods to NSString and then in
| | 01:44 | your application it's as if
NSString had had those methods all along.
| | 01:48 | You don't need to go through your code
converting all your NSStrings to your new
| | 01:52 | converting string object,
you just use the new methods.
| | 01:55 | To create a category, it's a little
similar to creating a custom class.
| | 02:00 | If this is the code to add a new
class, we would have the @ sign
| | 02:03 | interface, MyClass:
| | 02:05 | NSObject, meaning I inherit from NSObject.
| | 02:09 | To create a category we do have an
interface and an implementation but it
| | 02:14 | looks more like this.
| | 02:16 | Our @ sign interface then has the
name of the class we want to add to.
| | 02:20 | in this case NSString.
| | 02:22 | And then instead of having a colon
and the name of our superclass, we use
| | 02:26 | parenthesis and a category name.
| | 02:28 | Something descriptive that describes
what we're doing this category for.
| | 02:32 | Now, one big difference is you don't
have the opening and closing curly braces,
| | 02:36 | because using categories you
don't add new instance variables.
| | 02:39 | It's just add new functionality.
| | 02:41 | So I am going to go ahead and do this.
| | 02:43 | So I have a good old command line
foundation tool here and I have added
| | 02:46 | precisely two lines to it.
| | 02:48 | on Line 8 I create a normal
NSString and on Line 10 I spit it out.
| | 02:53 | Let's add a category.
| | 02:53 | I come up to the File menu and say New File.
| | 02:57 | Now, we have seen these Objective-C
class before, but we also have a built in
| | 03:01 | template for an Objective-C category that's
under the Cocoa section of Mac OS X, click Next.
| | 03:08 | And instead of asking what is this a
subclass of, it's asking what is this a category on?
| | 03:14 | So what class am I extending?
| | 03:15 | Well, I want to extend NSString. Click Next.
| | 03:19 | And then it asks for the name of the category.
| | 03:21 | Now, you can call it anything you
want, but there is a suggested standard
| | 03:26 | from Apple, just to make your code
readable when we're scanning lots of
| | 03:31 | filenames, the suggestion for
categories is you first have the name of the
| | 03:35 | class that you are extending NSString,
then a plus sign, and then whatever is
| | 03:41 | descriptive for your category name.
| | 03:43 | Let's say I am creating a category
to convert whitespace to underscore.
| | 03:46 | So I am going to say this is ConvertWhitespace.
| | 03:48 | And there is nothing magical
about this name, you don't have to.
| | 03:53 | I could name it anything I wanted.
| | 03:55 | But this is the suggested format.
| | 03:57 | So I click Save and it creates it
with those files for the .h and the .m.
| | 04:03 | If I look at the interface notice that
we don't have the opening and closing
| | 04:08 | curly brace, we're just saying @interface
NSString and then in parentheses our category name.
| | 04:13 | Well, all I am going to say in here is
give it the signature of a method, this
| | 04:18 | is our interface after all, and my
method is going to return, I'll point it to
| | 04:23 | an NSString, and I will
call it convertWhitespace.
| | 04:27 | Nothing special about this, I
just make up my own method name.
| | 04:31 | Well, of course my implementation
does need to fulfill the promises of my
| | 04:36 | interface, so I jump across to my
implementation file, and in here I am going to
| | 04:40 | provide exactly the same
thing and provide the code for it.
| | 04:47 | Now, obviously here this one really is a
very simple example, but whether we had
| | 04:52 | one line of code or 20,
they all work the same way.
| | 04:55 | So all I am going to do is return a new auto-
released object, string my current identity.
| | 05:00 | I will say self
stringByReplacingOccurrencesOfString:@", there we go.
| | 05:09 | I will say find any spaces
and replace with an underscore.
| | 05:15 | And yes, of course if it was truly a
piece of functionality this simple, I
| | 05:18 | probably wouldn't bother with a
category, but you get the idea. I Save that.
| | 05:24 | I Build it. I am now done.
| | 05:25 | I have added this new
method to the NSString class.
| | 05:29 | I am going to jump over to my main.m and use it.
| | 05:32 | Now, bearing in mind that, that new
method is not defined in the foundation
| | 05:37 | Header files, I will need to put an @ sign
import just to link to that category file.
| | 05:43 | That will do the trick, but from that
point on I should be able to use it.
| | 05:48 | In fact, what I will do is here in
my NSLog message instead of just using
| | 05:52 | sentence, which would call the
description method, I am actually going to say
| | 05:55 | sentence and we should have, there
we go, a convertWhitespace method.
| | 06:00 | This object, sentence, is still
considered a NSString, we just have a new method
| | 06:06 | added to that class.
| | 06:08 | Save it, Run it, and then we
should have our string being output with
| | 06:14 | underscores instead of spaces.
| | 06:16 | Now, do be aware, this is not
just subclassing with another name.
| | 06:20 | It's not inheritance. It is different.
| | 06:23 | For example, you cannot add new
instance variables using categories, only
| | 06:27 | methods, but for that feature alone it's great.
| | Collapse this transcript |
| Defining protocols| 00:01 | A protocol in Objective-C is a great
way to standardize interaction between
| | 00:05 | objects without worrying about
inheritance or any formal relationship and that
| | 00:10 | sounds all kinds of vague,
so let me give you an analogy.
| | 00:14 | Let's say you want to hire a cleaner
for your office, so you might put together
| | 00:18 | a quick job description on the back of a napkin.
| | 00:21 | This person must clean floors, must
vacuum, must empty trash cans, and
| | 00:24 | optionally clean windows.
| | 00:25 | You don't really care who does this or how
they do it, you just want someone to do it.
| | 00:31 | Could be the same person every time, a
different person every day. It doesn't matter.
| | 00:35 | It just matters that someone agrees to
do these things and if they agree they
| | 00:39 | actually do them or at
least all the required pieces.
| | 00:42 | Now in Objective-C this would be a protocol.
| | 00:46 | A protocol is simply a list of
methods you want an object to perform.
| | 00:51 | It doesn't say how they're done, doesn't
say who does them, doesn't matter what class.
| | 00:55 | It has nothing to do with inheritance.
| | 00:57 | It's simply a formal list that any
class can volunteer to support, and the term
| | 01:01 | we use is to conform to the protocol.
| | 01:04 | And if a class says it confirms
to the protocol then it better have
| | 01:08 | implementation of these exact methods, or
at least any of them not marked as optional.
| | 01:14 | However, you won't always be the person
writing the list, sometimes you need to
| | 01:19 | be the person who writes the
class that conforms to the protocol.
| | 01:23 | And in fact, as an Objective-C developer,
you'll typically start by conforming
| | 01:26 | to existing protocols rather than writing one.
| | 01:29 | And in fact, we've already done that, in
an earlier movie we did conform to one.
| | 01:34 | In the archiving example, we took a
custom object, now we were able to have
| | 01:39 | this object broken apart and saved to a
file, and then reconstituted, read from
| | 01:44 | the file and rebuilt, and we used two built-in
classes to do this, the NSKeyedArchiver.
| | 01:49 | And what that did was take the
object and encode it to a file, and the
| | 01:54 | NSKeyedUnarchiver that read it from the
file and decoded it into an object in memory.
| | 02:01 | And those two objects did pretty much
all of the heavy lifting, although we did
| | 02:06 | have to write two simple
methods in our own custom class.
| | 02:10 | Those methods were called
initWithCoder and encodeWithCoder.
| | 02:14 | And at the time, well, I said was
these have to be the names that you use.
| | 02:18 | Well, the reason those have to be the
names that you use is that those are the
| | 02:22 | two methods listed in a protocol
called NSCoding, and that's all that the
| | 02:28 | NSCoding protocol is, a
list of two method names.
| | 02:33 | And if you go to Xcode Help, and if I
were to search on the NSCoding phrase,
| | 02:39 | I'll find a very formally
sounding NSCoding protocol reference.
| | 02:43 | Well, this has a bit of an overview.
| | 02:46 | If I come down to it, all it says is
that this must provide two methods, one is
| | 02:52 | called initWithCoder, the
other is called encodeWithCoder.
| | 02:55 | That's all it means to be a protocol.
| | 02:57 | But what's the benefit?
| | 03:00 | The benefit is if that we agree to
provide those exact methods, we can pass our
| | 03:06 | custom object into the
KeyedArchiver or the NSKeyedUnarchiver.
| | 03:10 | Because really it doesn't care
that we are an employee object.
| | 03:14 | All it cares about is that we're
something that conforms to NSCoding.
| | 03:18 | That's all it wants to know.
| | 03:20 | It could be anyone of a thousand
different objects, but as long as it conforms
| | 03:24 | to NSCoding it will have the
initWithCoder and the encodeWithCoder methods,
| | 03:29 | and that's all that these two objects care
about, and that's the benefit of protocols.
| | 03:35 | You can really standardize
interaction between objects and there is no
| | 03:38 | inheritance going on here,
there is no formal relationship.
| | 03:42 | And you'll find as you get more and more
into Objective-C programming that there
| | 03:46 | is quite a lot of protocols that exist.
| | 03:48 | It will allow you to tap
into some great functionality.
| | 03:52 | So formally how do we deal with them?
| | 03:53 | Well, to write them, although you
may not do this very early on in your
| | 03:58 | Objective-C career, it is
very simple. It's just a list.
| | 04:02 | In fact, there is a template in
Xcode for creating a protocol.
| | 04:05 | you just list the method names.
| | 04:07 | No instance variables nothing like
that, simply a list of method names
| | 04:12 | could even just be one.
| | 04:14 | On the other end is how do
you conform to a protocol?
| | 04:18 | Well, to create a class that
conforms to your protocol, you go into your
| | 04:21 | interface and after the name of your
super class, in this case NSObject.
| | 04:27 | you put the name of the
protocol in angle brackets.
| | 04:31 | Now if you promise that you are going
to support or conform to that protocol,
| | 04:35 | then you better list at least the
required methods of that protocol and then
| | 04:40 | in your implementation simply provide
the code for these methods, and they
| | 04:45 | must match exactly.
| | 04:46 | And that's pretty much in, now there
is not a great deal that you do with
| | 04:50 | protocols in a command-line tool, in
fact, the NSCoding example we've just gone
| | 04:55 | through would probably be the most common one.
| | 04:57 | But when you get building iPhone Apps
and Desktop apps, you actually run across
| | 05:02 | more and more of them, because
when you're working with those kind of
| | 05:05 | multi-class, multilevel applications,
you'll find that protocols can help with
| | 05:10 | everything from dealing with
spellchecking to handling pop-up alerts.
| | Collapse this transcript |
| Dynamic typing| 00:01 | There is a word we've seen a couple of times
but haven't yet explored, and that word is ID.
| | 00:06 | It is a type in Objective-C and it is
very common return type in methods in
| | 00:10 | the Apple frameworks.
| | 00:12 | Alloc returns an id, init returns an id,
and it's common because it's really flexible.
| | 00:18 | ID can represent any object and it
allows us to have both the benefits and the
| | 00:24 | downsides to something called Dynamic Typing.
| | 00:27 | So far we've been pretty
strict about creating our objects.
| | 00:30 | We create them with static typing.
| | 00:32 | We describe that they are NSStrings
or NSDates or NSArrays or dictionaries.
| | 00:37 | Now in this simple project that I
have here, I have created three very
| | 00:41 | straightforward classes called First,
Second, and Third, and in fact all of them
| | 00:46 | are based on NSObject and only
one of them has had anything added.
| | 00:50 | The Second class has one method defined
called secondOnly that returns void and
| | 00:55 | just outputs an NSLog message.
| | 00:58 | We're going to use these classes
just to show some examples of static
| | 01:01 | versus dynamic typing.
| | 01:02 | Well, we start off with static typing.
| | 01:04 | On line 10, 11, and 12, I am
creating statically typed objects based on
| | 01:10 | those three classes.
| | 01:11 | The good thing about that is it
allows me after they've been created to say
| | 01:15 | use the object called s, which is an
instance of Second to call the secondOnly method.
| | 01:23 | Again, the phrase we use is
we're sending it a message here.
| | 01:25 | If I Build that, it says Build Succeeded.
| | 01:28 | It's quite happy with it, and I run
it, and we get the message coming out
| | 01:31 | that This only works in the second class,
and that makes sense that's what I'd expect.
| | 01:35 | If however, I change that to represent
an instance of the class called First
| | 01:39 | which doesn't have that method, or when
I Build it, it will give me a warning.
| | 01:44 | First may not respond to secondOnly,
but it doesn't stop me running it.
| | 01:48 | But if I do, here is the problem,
Program received signal SIGABRT.
| | 01:53 | We have a whole problem here.
| | 01:54 | The actual error message that
you're going to get is the unrecognized
| | 01:57 | selector sent to instance.
| | 02:00 | Meaning, we sent the message secondOnly
to that instance called f and it doesn't
| | 02:05 | know what to do with it. All right!
| | 02:06 | Fair enough.
| | 02:07 | I am going to hit Stop and come out of that.
| | 02:10 | Just a good example of I
shouldn't have ignored that warning.
| | 02:14 | However, there is another
way of defining these objects.
| | 02:19 | Instead of typing the name of the
class, for a second or third NSString,
| | 02:24 | NSArray, NSDictionary, what I
can do is type id. That is a type.
| | 02:31 | I can then create a variable with a name.
| | 02:34 | I'll call it whoKnows, because
this could represent any object.
| | 02:38 | Then at some point, could have done on the
same line, but I'll do it on a different one.
| | 02:43 | I can say whoKnows is equal to, and I
am going to create an object for it.
| | 02:47 | In this case, I will create an instance
of the Third class just using alloc init.
| | 02:53 | This is perfectly acceptable way of doing it.
| | 02:56 | Build has Succeeded.
| | 02:57 | It has no problems whatsoever doing that.
| | 03:01 | whoKnows is a dynamically typed variable.
| | 03:05 | It could represent anything and we're only
really going to know for sure at runtime.
| | 03:10 | What that means is that if I try and
use it to call say the secondOnly method,
| | 03:17 | which we know from looking
at it, it shouldn't work.
| | 03:19 | But if I compile, its not even going to
give me a warning about that, because it
| | 03:23 | has no idea what this object is
really going to represent come runtime.
| | 03:26 | Now that sounds a little vague, because
you'd think well, why would I do that here?
| | 03:31 | Well, the answer is I wouldn't.
| | 03:33 | But sometimes you don't
know this well in advance.
| | 03:38 | Let me set up a bit more
of an explanation there.
| | 03:40 | I am going to delete that code and I
am going to create 100 objects now.
| | 03:49 | First, I am going to create an
NSMutableArray that can hold a lotsOfObjects.
| | 03:54 | We can just keep adding
new objects to this array.
| | 04:04 | So I am creating a for loop that's
just going to go around 100 times.
| | 04:10 | On the first line of it, I am going to
create an integer that's just going to
| | 04:13 | represent a random number using the
arc4random function, which is a part of
| | 04:19 | the standard C library.
| | 04:21 | The first part of it's going to give me
a number between a 0 and 2, so I am just
| | 04:25 | going to add 1 to it to
make it a little clearer.
| | 04:28 | Then I define an id called
temp, that can hold any object.
| | 04:33 | And then what I am going to do is
check that random number every time I
| | 04:37 | go around the loop.
| | 04:38 | If it's 1, I'll create an instance of
First, if it's 2, I'll create an instance
| | 04:42 | of Second, otherwise, I'll
create an instance of Third.
| | 04:45 | I will then take that randomly
created object and store it in the array.
| | 04:53 | Now I have put that temp object in the array.
| | 04:55 | I don't need it anymore,
so I can call release on it.
| | 04:59 | The array itself will have done the retain.
| | 05:02 | So that's my duty over.
| | 05:05 | What I am trying to replicate here is
the idea that you don't always know the
| | 05:10 | objects that you're going to have.
| | 05:11 | You might be reading in information from
an external file or from a web service.
| | 05:16 | You might be being given a list of bank
account or a product information and you
| | 05:20 | have no idea what these
objects are actually going to be.
| | 05:24 | You just know you're going to end up
with a lotOfObjects. So then what?
| | 05:30 | Well, what I want to do, because that's
not really the main part of this example.
| | 05:33 | What I am really interested in is
showing you how we work with them.
| | 05:37 | How do we work with a bunch of objects
when we are not sure exactly what they are?
| | 05:43 | Well, we'll start off simply.
| | 05:44 | I am going to do another for
loop that's going to go back through
| | 05:48 | that NSMutableArray.
| | 05:50 | Now because it is in NSMutableArray, I
can use fast enumeration and I can use
| | 05:55 | the for with an in rather than
the int i=0, i<100, and so on.
| | 06:01 | I could do either way, but this will be easier.
| | 06:03 | Well, I don't know what each
individual objects going to be.
| | 06:07 | So to loop around them, I am just
going to say well, give me back an id.
| | 06:11 | I will call it eachObject for every
iteration, and then say in the name of the
| | 06:17 | MutableArray, which is lotsOfObjects.
| | 06:21 | So let's start off simply.
| | 06:22 | I am going to do NSLog and then say
The object is, give it a placeholder, and
| | 06:32 | then give it the name of the object.
| | 06:34 | nothing particularly remarkable here.
| | 06:36 | But bear in mind within this loop,
we don't know what that object is.
| | 06:40 | I can use the generic
placeholder Percent sign, At sign.
| | 06:44 | What that's going to do is called
the description method on every object.
| | 06:48 | Every object will have one because
it's a method that exists in NSObject.
| | 06:52 | So we'll run it and see what happens.
| | 06:54 | Run and we do appear to be
having kind of a random selection of
| | 06:58 | different objects here.
| | 07:00 | The default description method is
actually writing out the name of the class and
| | 07:04 | then the address in memory.
| | 07:06 | Now why I quite like looking at this
default output is it's obvious that even
| | 07:11 | though we're just splitting out an id,
the object itself knows what it is,
| | 07:17 | and that can be useful.
| | 07:18 | Now taking this a little bit
further, I am going to leave that as is.
| | 07:24 | Jump over into one of my classes here,
let's say on the Third class, and jump
| | 07:31 | into the implementation, and I'll
quickly just override the description method
| | 07:42 | returning a custom string here.
| | 07:44 | The reason that I am doing this is just
jumping back into main.m. We'll run this again.
| | 07:49 | The more we can see is that when the
object is of type Second or First, it's
| | 07:56 | using the default description method.
| | 07:58 | When it's of type Third, it's actually
using the overridden one in the Third class.
| | 08:04 | While the actual output of any
of these isn't very exciting?
| | 08:07 | The point is what we're doing here is
what's called the Polymorphic Method Call.
| | 08:12 | Even though within the body of that loop,
the type of these objects are id, it's
| | 08:17 | calling the right thing at the right time.
| | 08:20 | Let's take it a step further.
| | 08:23 | What happens if for example,
I say each object secondOnly?
| | 08:28 | Well, it will let me write this code.
| | 08:31 | It will even succeed with no issues whatsoever.
| | 08:34 | But again, what's going to happen is I
will be sending the secondOnly message
| | 08:39 | to the wrong kind of class and very
quickly we're going to get another
| | 08:43 | exception, no surprises there.
| | 08:45 | But what I might often want to do is
say well, I know I could have 100 objects
| | 08:50 | here, but sometimes they
will be of that Second class.
| | 08:53 | So surely, it should work in those cases.
| | 08:55 | Well, we can check it.
| | 08:57 | What I can do here is put in an if statement.
| | 09:00 | See every object will have a
method called isKindOfClass.
| | 09:05 | What we can do there is put in the
name of the class space the word class.
| | 09:13 | They all have this method too. Close this off.
| | 09:16 | That returns a Boolean value.
| | 09:19 | I don't explicitly actually need the
opening and closing curly braces for one
| | 09:23 | line, but I prefer to have it.
| | 09:24 | So I am asking if with every iteration
of the loop, this particular object is of
| | 09:30 | the type Second, then I can call
that method, so let's run that.
| | 09:33 | Now what we can see as we're going
through this is that I am getting different
| | 09:39 | ones being written out, but if the
object is of the type Second, I am then going
| | 09:45 | on to call that method.
| | 09:49 | Alternatively, rather than asking
whether the object is a particular kind of
| | 09:55 | class, another if statement that I
can ask for will be if eachObject
| | 10:01 | respondsToSelector and that will be
very useful in the case that I might have
| | 10:06 | multiple objects with the same named method.
| | 10:10 | Selector again is the
equivalent of our method name.
| | 10:14 | Basically saying if we send this
particular message to the object, will
| | 10:19 | it respond, yes or no?
| | 10:21 | The way that we do this is actually by
using the word At sign selector and then
| | 10:26 | just giving it the name of the method.
| | 10:30 | Use the Square Bracket just to
finish that off and calling it again.
| | 10:40 | So what we should be able to do is
have two occurrences of that method.
| | 10:44 | Call one right after the other as
long as the class is of type Second.
| | 10:50 | Save that, run it, and yes it does
appear to be the case when we're getting
| | 10:54 | the one message output.
| | 10:55 | We're getting it both responding to
the isKindOfClass and responding to
| | 11:00 | the respondsToSelector.
| | 11:01 | Now as you can imagine, dynamic typing
is kind of a difficult thing to explain
| | 11:08 | in a short and somewhat
contrived scenario like this.
| | 11:12 | The point is you don't always know
what these objects are in advance.
| | 11:15 | Now I am a fan of statically typing as
much as possible, because that does put
| | 11:20 | as much as checking as I
can to the compile time.
| | 11:23 | But Objective-C as you can see is
perfectly capable of determining the identity
| | 11:28 | of objects at runtime and you will
need to do this from time to time.
| | Collapse this transcript |
|
|
11. DebuggingCommon compile errors| 00:00 | We write a bunch of code, we hit Command+B
and we get build failed along with a whole bunch of
| | 00:06 | cryptic error messages.
| | 00:09 | When this happens to you don't start cherry
picking the ones you think that you recognize.
| | 00:14 | The rule is start at the top and
work your way down, because the first
| | 00:18 | mistake can have a domino effect and cause
multiple issues down the line that aren't problems.
| | 00:23 | In fact the main problems might
not even be in the file that you are
| | 00:26 | currently looking at.
| | 00:27 | So do make sure that you have your
issue navigator opened that's the middle
| | 00:31 | button in the navigator, the one
that looks like an exclamation mark.
| | 00:34 | If you have multiple files, pick the first
file, pick the first issue and fix that one.
| | 00:40 | In this case, it says missing
terminating double quote character.
| | 00:44 | Now that's fairly straightforward, so
in line 3 yes indeed I do have that, hit
| | 00:49 | the double quote, and hit Save, hit Build again.
| | 00:51 | Now we have just fixed every single
problem, well I wish I could say it was
| | 00:54 | always going to be that easy.
| | 00:56 | you are going to run into a few
more errors and warnings than that one.
| | 00:59 | So let me take you through a
few of the most common ones.
| | 01:02 | I am going to jump over to a project here,
where I have written a whole bunch of bad code.
| | 01:08 | These first ones are going to
cause errors, the red stop sign, the
| | 01:12 | exclamation mark of doom here.
| | 01:14 | Again if you get that error and you
are perhaps on a different area, what you
| | 01:18 | want to do is click that issues
navigator and it's telling me that I have one
| | 01:23 | error which is the semantic issue
that the interface type can not be
| | 01:26 | statistically allocated.
| | 01:28 | Well this is X-code's friendly way
of telling you forgot the pointer.
| | 01:32 | That is what this error means that you
tried to create an object and all objects
| | 01:37 | are pointed types, but there was no
asterisk but simply by adding the asterisk
| | 01:41 | we get build succeeded.
| | 01:43 | Moving on to error number two, also
very common, save and build something and
| | 01:48 | you get a few messages popping up.
| | 01:50 | I have got three over here in my issue
navigator and one that I can see here,
| | 01:54 | expected semi-colon after expression.
| | 01:57 | That one is pretty straightforward.
| | 01:58 | I can look at that statement on
line 17, yeah, forgot to terminate and
| | 02:02 | didn't add semi-colon.
| | 02:04 | To bear in mind sometimes we will get
the fix it, the suggestions, they can pop
| | 02:08 | up if you click on the gutter, although
I find a more reliable way is to click
| | 02:13 | the actual issue in the issue navigator
and we will get to fix it down here, to
| | 02:17 | suggest to insert a semi-colon.
| | 02:18 | Yes, looks good, I hit Save, and I hit
Command+B to build again, build is still failing.
| | 02:24 | Now what we are getting
here, is a parsing issue.
| | 02:27 | expected closing curly brace.
| | 02:29 | Now you can see a lot of messages that
include that word expected and they all
| | 02:34 | tend to mean that you missed a curly
brace or a square bracket or parenthesis.
| | 02:36 | When I click it it's taking me down
to the bottom of the file, saying it's
| | 02:41 | expecting a closing curly brace.
| | 02:43 | Now it wouldn't be a good idea for me to
add it, I know I didn't change the code
| | 02:47 | down here, but it's because I braces
can last for quite a while, the issue is
| | 02:52 | really back up here.
| | 02:54 | On line 15 I am opening a curly brace,
then I am immediately opening one
| | 02:58 | again and I am only closing it once, so
something is not pairing up and that's the one.
| | 03:03 | I will hit that save it,
there we go build succeeded.
| | 03:06 | moving on to the next one, a very
common error, use of undeclared identifier.
| | 03:11 | Now this is actually four errors in
two lines, which is pretty impressive.
| | 03:17 | As you will see there is actually
nothing wrong with these lines of code, almost
| | 03:20 | we are most interested in the one at
the very top, we can ignore the rest.
| | 03:26 | So selecting in the issues
navigator says it's an undeclared
| | 03:29 | identifier, myNewClass.
| | 03:31 | Well let's say that I had just written
this and I know I did, if I click over
| | 03:35 | here, just to verify, in my code I have
got something called myNewClass, yes I
| | 03:39 | am using the right spelling
and the right case sensitivity.
| | 03:42 | It looks fine, there is my implementation.
| | 03:44 | So what's the problem?
| | 03:46 | Well undeclared identifier always
means I don't know what this is, and reason
| | 03:51 | for the problem is I am
not importing a header file.
| | 03:53 | Now it's a very common reason for use of
undeclared identifier whether it's your
| | 03:59 | classes or something else.
| | 04:01 | that's a very common reason
for undeclared identifier.
| | 04:04 | Whether you are trying to create a new
class that you wrote or trying to link to
| | 04:08 | say something else in one
of the Apple frameworks.
| | 04:10 | So I import the header file, Save and
Build and again my build succeeds without
| | 04:14 | me having to change either of those two
lines of code and just as an addition to
| | 04:20 | that one, we have got the use of
undeclared identifier and a string and just as
| | 04:26 | it related addition to their error, if
you get the same message the undeclared
| | 04:29 | identifier on an object that you think
exists well again it's probably down to
| | 04:33 | the whole case sensitivity thing.
| | 04:35 | Objective-C is of course very concerned
about knowing what everything is and in
| | 04:39 | fact error four, which
technically isn't an error.
| | 04:42 | It's a warning it's
related to those two as well.
| | 04:44 | Now what I am getting here it the
implicit declaration of function NSLog is
| | 04:49 | invalid in C99, a very long winded
phrase to say I don't know what NSLog is.
| | 04:54 | now looking at that what I can see is,
it's meant to have an uppercase L, and
| | 05:01 | that should do the trick.
| | 05:03 | Error number five, still something
that I run into or I see people run into
| | 05:07 | from time to time, particularly based
on the language background build failed
| | 05:12 | here, unexpected @ sign in program
and whenever I see this, I think some one
| | 05:17 | coming from a language where it doesn't
matter if you use double quotes or single quotes.
| | 05:20 | Well it matters here, the only
thing that uses single quotes are chars,
| | 05:24 | NSStrings which is what we are
doing here, need to have double quotes.
| | 05:30 | Next up, let's talk about some common warnings.
| | Collapse this transcript |
| Common compile warnings| 00:01 | So let's talk about some common warnings that
you'll run into when building your projects.
| | 00:06 | Now there is one warning in
Objective-C that I absolutely hate.
| | 00:09 | I consider this one to be a vile
deceptive gateway drug of a message that snares
| | 00:14 | new developers into its
evil web, and it's this one.
| | 00:18 | the unused variable warning.
| | 00:21 | Now you might think, okay,
Simon has finally lost it.
| | 00:24 | Why would he hate this message?
| | 00:25 | I mean finally we have a
message that a, isn't cryptic.
| | 00:29 | It's very straightforward.
| | 00:31 | It's telling us you declared a variable,
and as far as it can tell you don't use
| | 00:34 | it, and b, that's true.
| | 00:36 | That's no big deal, no real problem
with the unused integer, unused float,
| | 00:42 | even an unused string, and that's precisely
why I don't like it because it's easy to ignore.
| | 00:48 | This unused variable warning is the
most common warning you're going to get in
| | 00:52 | development and it can lead people to have a
blind spot with these little yellow triangles.
| | 00:57 | But the thing is most warnings are not
like this, most warnings are significant
| | 01:02 | logic errors that will make your program crash.
| | 01:05 | They'll make it give wrong data,
they'll make it leak memory.
| | 01:08 | You should never ignore a warning.
| | 01:11 | One of the issues too is depending on
your settings, it won't always throw open
| | 01:14 | the Issues Navigator.
| | 01:16 | So you should keep an eye on the
little iTunes style display up at the top
| | 01:20 | here to see if there is any little yellow
triangles and again use the Issues Navigator too.
| | 01:26 | So I don't even like to keep these ones
hanging around, so I will comment them
| | 01:29 | out just so it doesn't
keep complaining about them.
| | 01:32 | Let's go through a few of the
other more significant warnings.
| | 01:36 | Here's a pretty common one and the
warning is incompatible pointer types
| | 01:42 | something, something, something.
| | 01:44 | I am showing two different
versions of this because you'll find them
| | 01:47 | phrased different ways.
| | 01:48 | While most say incompatible pointer
types something, something NSString,
| | 01:52 | something, something char array, and
the other one will do the opposite and
| | 01:56 | incompatible pointer type something
char array, something, something, NSString.
| | 02:00 | Both are the same problem.
| | 02:02 | We've missed the @ sign in
front of the NSString object.
| | 02:07 | So here for example we are making an
NSString object, we need an @ sign in front
| | 02:11 | of the double quotes as
we do in the NSLog message.
| | 02:14 | This is something that all developers new to
Objective-C are going to hit once in a while.
| | 02:19 | So many languages just use the double
quotes that it's easy to get into the
| | 02:22 | habit of doing that.
| | 02:23 | So just keep an eye out for it
until you're used to that whole
| | 02:27 | NSString double-quote thing.
| | 02:29 | Moving on, another very common warning.
| | 02:34 | The message here is, Using the result
of an assignment as a condition without
| | 02:38 | parentheses which is Xcode's way of
telling you you're using a single equals
| | 02:43 | sign in an if statement,
shouldn't that be a double equals sign?
| | 02:46 | If I am asking if C=D, it needs to
be double equals, otherwise this is
| | 02:51 | assignment I would be setting C=D, and
the if statement would always be true.
| | 02:58 | This is one of these warnings that
will typically give you a fixit if you
| | 03:01 | highlight the issue in the Navigator here.
| | 03:05 | It will throw up the little fixit here,
Use '==' to turn this assignment into an
| | 03:08 | equality comparison, but be careful
because there is another option here in the
| | 03:12 | fixit, which is, Place parentheses
around the assignment to silence this warning
| | 03:16 | which is certainly not what I want.
| | 03:18 | I want to use the double
equals sign and there we go.
| | 03:21 | Moving on, warning number four, a
very common one but a really significant
| | 03:26 | one if you let it go.
| | 03:27 | Now this warning I actually need to make a
little tweak in a separate class file here.
| | 03:32 | What this warning is all about is
the idea of having a method that has
| | 03:37 | been defined here on line 6 to return an
NSString that somehow doesn't return something.
| | 03:43 | Now, this is very, very common too.
| | 03:45 | Again, if I am back in Main,
I am saving, I am building.
| | 03:48 | Build has succeeded, the only
indicator that there is a problem is up here.
| | 03:54 | I've got the little yellow triangle.
| | 03:56 | Again, jumping across to the Issue
Navigator and the issue here is Control may
| | 04:02 | reach end of non-void function telling you, hey!
| | 04:06 | This method is defined to return an
NSString and I've detected that there is
| | 04:10 | a way that you may not get that
NSString back, and in this case whether it's
| | 04:15 | intentional or not.
| | 04:17 | That's because I've got a
little if statement on line 10.
| | 04:19 | There is no curly braces after it,
which means, that's the same as having
| | 04:24 | this enclosed in braces.
| | 04:26 | So there is a possibility that it's
detecting that I might not always hit
| | 04:31 | a return statement.
| | 04:32 | Yes, I might get it, I might not.
| | 04:34 | I really want to make sure that
whatever happens whether I use an else
| | 04:38 | statement or whatever that I do have some kind
of return statement that sends back an NSString.
| | 04:45 | Obviously it's the same if it's
an int, if it's a float, anything.
| | 04:48 | You always need to be able to return
something because even if you don't think
| | 04:53 | that's important, back in Main.
| | 04:56 | bear in mind what's happening as I am
calling that method, I am expecting a
| | 05:01 | result back out of it.
| | 05:02 | I am going to do something with that
result, so it could have significant knock
| | 05:06 | on effects, and that was the
Control reaches end of non-void function.
| | 05:12 | And the last one that I am going to
point out here, again a very common one, I
| | 05:15 | am going to save it, I am going to build it.
| | 05:18 | The warning is, NSString may
not respond to groovyMethod.
| | 05:22 | Now, the bit that should be jumping out
of you is not the front and the end of
| | 05:26 | this, it's the middle bar, may not respond to.
| | 05:30 | This is Xcode telling you, hey!
| | 05:32 | I don't think this object does what
you think it does, and the reason you'll
| | 05:37 | often get this is calling
the method on the wrong object.
| | 05:42 | Let's say I was copying and pasting some code.
| | 05:44 | I wanted on line 34 to create a new
instance of my new class and then I was
| | 05:49 | going to call the groovyMethod on it,
but maybe I copied and pasted from another
| | 05:54 | few lines and I am accidentally using
the wrong object, I am using an object of
| | 05:59 | NSString rather than object of my new class.
| | 06:03 | Objective-C won't make this an error
because of things like dynamic typing.
| | 06:07 | All it's ever going to do is make its best
guess at what objects respond to what messages.
| | 06:12 | So it's just telling you.
| | 06:14 | may not respond here.
| | 06:15 | Again, the issue with this kind
of warning is it won't stop you.
| | 06:20 | It will allow you to build, Build will succeed,
problem is when I hit this line. Well, let's do it.
| | 06:27 | Let's run this application.
| | 06:28 | What it's immediately
going to do is basically crash.
| | 06:33 | We're in debug mode, so we could go
through and start seeing things but
| | 06:36 | terminating the application due to
the uncaught exception, unrecognized
| | 06:41 | selector, all going back to that idea.
| | 06:44 | I don't think that this
object does what you think it does.
| | 06:47 | Now because I don't like the idea of
warnings like this allowing me to just
| | 06:54 | plough on and run the application,
what I often do with my projects on a
| | 06:58 | project-by-project basis is I change
the settings so that warnings are treated
| | 07:03 | as errors and they won't actually let
me run the program till I fix those.
| | 07:08 | The way that you do this is by
jumping to your Project Navigator and just
| | 07:12 | selecting the very top icon
that represents the project itself.
| | 07:16 | This is where you find an enormous
amount of different settings and things you
| | 07:20 | can change, most of which you'll never
have to touch, but if, and the way that I
| | 07:26 | typically go about this is I select
the PROJECT, I go to Build Settings, make
| | 07:30 | sure I am looking at all the options,
and then just about right down the bottom
| | 07:35 | here, one of the options that I have
is this guy, Treat Warnings as Errors.
| | 07:42 | What I can do is change that to Yes.
| | 07:45 | This is not a general Xcode
setting. It's per project.
| | 07:48 | But what this will do is when I now
try and build, the Build will fail.
| | 07:54 | It will not let me go on and run this
application until I fix this problem and
| | 07:59 | suddenly realize, oh!
| | 08:01 | That's right, I don't want to call it
on result, I wanted to call it on that my
| | 08:05 | third object that I just
created on the previous line.
| | 08:07 | We build that, Build succeeded,
now we can go ahead and run it.
| | 08:11 | I scan up at the top, no warnings.
| | 08:13 | Now, having a successfully built
project doesn't mean that it won't crash the
| | 08:18 | moment you run it but we can deal with
those issues, the runtime issues next.
| | Collapse this transcript |
| Common run-time errors| 00:00 | This is programming.
| | 00:02 | There are a million ways your program
can go wrong once it starts to run, but
| | 00:06 | there are a few common ways that things
do go wrong in Objective-C and just as
| | 00:10 | importantly a few ways that they don't.
You see Objective-C is a very forgiving
| | 00:15 | language, and because of dynamic typing,
if you do something that doesn't make
| | 00:19 | sense, it may just ignore
you instead of crashing.
| | 00:22 | So let me give you an example.
| | 00:29 | I am going to create a
pointer to an NSString object here.
| | 00:33 | I'm going to forget to instantiate it.
| | 00:35 | It doesn't created, and then on line 9,
I am going to send it a message to the
| | 00:40 | method uppercase string, and on line
10 I am going to send another message,
| | 00:43 | telling it to write to file.
| | 00:45 | I am passing it a whole bunch of
parameters, but I am never creating the object.
| | 00:49 | There is no alloc init, and there is
no shortcut convenience constructor.
| | 00:55 | So let's run this and see what happens.
| | 00:58 | Well it builds, Build succeeds and it
spits out a message here saying, got to
| | 01:02 | the end of the program, which is just
a simple NSLog I have right at the end.
| | 01:06 | Now if you're coming from C# or Java,
you are likely to find this fairly
| | 01:11 | surprising, because this
wouldn't be allowed in those languages.
| | 01:14 | You try and call a method on a null
object and you are likely to crash.
| | 01:18 | But in Objective-C, you can send messages
to a nil pointer, which is what we have here.
| | 01:24 | See the variable called emptyPointer
does not point to an area of memory yet, no
| | 01:29 | object was ever instantiated.
| | 01:31 | It was never given an address.
| | 01:33 | Those messages will just be ignored.
| | 01:36 | However, that doesn't mean you can
just send any message to any object.
| | 01:40 | That won't work and it's
one easy way to go wrong.
| | 01:43 | Let's say I create a new NSDate object,
and then I decide to send it the message
| | 01:52 | uppercase string which is a method
that exists in NSString not in NSDate.
| | 01:58 | Now the compiler is giving me a
warning here, and the warning is actually
| | 02:02 | saying that NSDate may not respond to
uppercase string, but I could still go ahead and run it.
| | 02:07 | We are going to get instantly
this Program received signal:
| | 02:11 | "SIGABRT", and if I look down here in
the output, it's terminating application
| | 02:17 | due to uncaught exception.
| | 02:19 | The important thing here is this one.
| | 02:21 | unrecognized selector sent to Instance.
| | 02:24 | Now you might say, well that's okay, we
got the warning, if we weren't ignoring
| | 02:27 | the warning, there wouldn't be a
problem here, but not necessarily.
| | 02:31 | For example, I could have defined this
as an ID and if you remember that, an ID
| | 02:36 | can represent any object.
| | 02:38 | In this case, I wouldn't have got
any warnings whatsoever, because of the
| | 02:42 | dynamic typing or maybe this object was an
NSDate maybe later on it will be something else.
| | 02:48 | But of course when we run it, we will
still get exactly the same problem we are
| | 02:52 | instantly going to crash.
| | 02:54 | So just because you can send
messages to an object that's never been
| | 02:58 | instantiated, and you can send it
anything, that's quite a different matter
| | 03:02 | after that object has been instantiated,
and it really does represent something.
| | 03:06 | Now the classic other way to go wrong,
and I am going to comment out this code
| | 03:12 | here, is that we create a new
object, I'll just make an NSString.
| | 03:19 | Next, I release it.
| | 03:25 | Then on line 19, I am going to try and
create a new string based on that old one.
| | 03:30 | I am going to call the method
uppercaseString send in that message and then on
| | 03:34 | line 20 send it out, let's run this one.
| | 03:38 | The Build has succeeded, and we are
starting to run, but here is the problem,
| | 03:42 | and you might have to scroll down
if you don't immediately see it.
| | 03:45 | Program received signal: "EXC_BAD_ACCESS".
| | 03:51 | Now there are occasionally
circumstances where in a super, simple program like
| | 03:56 | this you might have it work, even
though it's been released, because there just
| | 04:00 | hasn't been time for the runtime to
actually clear that object out of memory.
| | 04:06 | But of course, what's happening here is
that we've created this object, we then
| | 04:10 | release it, then we try to use it, and
the EXC_BAD_ACCESS is the classic example
| | 04:17 | of trying to use an object that's been released.
| | 04:20 | Now the thing that often confuses
people when they are new to this is, what's
| | 04:24 | the difference between this nil
pointer up here like emptyPointer that
| | 04:28 | doesn't point to anything?
| | 04:30 | And this will release down
here which has been released.
| | 04:34 | What's the difference between the two?
| | 04:35 | Well, on line 17, we are releasing
the object, but the pointer still has
| | 04:42 | the address in memory.
| | 04:44 | It is not a nil pointer.
| | 04:46 | It's pointing to a space that's been reclaimed.
| | 04:50 | If I wanted to be doubly sure that this
program would work, what I could do is
| | 04:54 | set willRelease = nil.
| | 04:59 | This doesn't do anything in
terms of releasing memory.
| | 05:03 | That's all being taken care of by the runtime.
| | 05:06 | It's all being taken care
of by reference counting.
| | 05:09 | What it does is blank out the pointer,
and then if we try to use it on line 20,
| | 05:15 | well it's actually going to run.
| | 05:16 | It's going to run all the way through.
| | 05:18 | The new string that I try and write
out from line 21 is going to be null,
| | 05:23 | because nothing was ever there, but
we are going to actually continue.
| | 05:26 | So you will see that Objective-C is
very forgiving in some circumstances, and
| | 05:31 | very unforgiving in others.
| | 05:34 | But these are perhaps the classic
two runtime errors when it comes to
| | 05:37 | working with objects.
| | 05:39 | either trying to send messages to
objects that don't support them, or trying to
| | 05:43 | use objects that have been reclaimed.
| | Collapse this transcript |
| Exception handling with try/catch| 00:01 | If you've used structured exception
handling in other languages, you will
| | 00:04 | be glad to know that it exists in
Objective-C as well, and if you haven't,
| | 00:08 | well you're about to.
| | 00:09 | The idea here is pretty straightforward.
| | 00:11 | Sometimes we have code in our
programs that we know might cause an error.
| | 00:16 | And if we can't do anything above that
it's going to cause our program to crash.
| | 00:20 | I have two lines that
actually will cause an error here.
| | 00:22 | On line 9, I'm creating a new
object of type NSDate and on line 10.
| | 00:28 | I'm sending it the message to
uppercaseString, and unfortunately uppercaseString
| | 00:32 | is a method that's defined
in NSString not in NSDate.
| | 00:35 | Now the compiler isn't going to catch
this because I've typed it as type ID,
| | 00:40 | which could be appointed to any object.
| | 00:42 | But if we run this we're going to have
a problem. Pretty much immediately this
| | 00:47 | one's going to crash with this board
unrecognized selectors send to instance,
| | 00:52 | and the program is
terminated. So what can we do?
| | 00:55 | Well we're using what's called
Structured Exception Handling.
| | 00:59 | It's a piece of code that's made up of
three points, Try, Catch, and Finally,
| | 01:04 | and in fact the easiest way to get use to it is
to just grab it from the Code Snippets Library.
| | 01:09 | If I open up my right-hand side my
Utilities panel, make sure I'm on Code
| | 01:13 | Snippets Library with the braces, and
then it's in there somewhere I might as
| | 01:16 | well just search for it, type in the
word Try, and here I've got two, the
| | 01:21 | C++Try/Catch Block, certainly not what
I want, and the Objective-C Try/Catch
| | 01:25 | Block that looks good.
| | 01:26 | Let me make sure that I've stopped this
application and there we go and I'll drag it over.
| | 01:32 | So three parts to it, all beginning
with the beginning with the @try, @catch,
| | 01:36 | @finally, each having their own
statement block with the curly braces.
| | 01:40 | The Try is the code that we're worried about.
| | 01:43 | The code that might cause an exception.
| | 01:46 | might cause this error to happen, so
what I'm going to do is take the code I'm
| | 01:50 | worried about, cut it from up there,
and then just paste it in down.
| | 01:55 | It's getting a little ugly formatting
wise, but I'll tidy up in just a moment.
| | 01:59 | The next block is the Catch block.
| | 02:01 | What happens is, whatever code is in
Try, whether it's two lines or 20 lines,
| | 02:06 | we're going to go through line by line,
and if anything causes that error, we're
| | 02:10 | going to jump into the Catch block,
we're going to wrap that error up and pass
| | 02:14 | it in as an object called an
NSException, and here it says.
| | 02:18 | well, this is going to be
passed in as a parameter here.
| | 02:21 | So what do you want to do to do with it?
| | 02:22 | Well, here I might output a message,
I might log something, I might save a
| | 02:27 | problem to a file, I might pop up a
message box if this was on a Desktop or an
| | 02:32 | iPhone, but here all I'm actually going
to do, to prove the point is we're going
| | 02:36 | to log out a message.
| | 02:38 | There was an error, and because I'm
being passed an object that's going to be
| | 02:44 | called Exception, I might as well
write it out and see what it's made of.
| | 02:48 | It is an object, so I'll do the
percent sign, at sign, and say Exception.
| | 02:54 | There is nothing magical about that
name, if I wanted to change it to just e
| | 02:58 | here, I could change it to e here.
| | 03:00 | It's just what is this going to
be called, but Exception is good.
| | 03:03 | And then we hit the Finally block,
whatever code I put in the Finally block will
| | 03:09 | be executed regardless if everything in
the Try block work correctly or if the
| | 03:14 | first line or third line, or seventh
line and Try through this exception and we
| | 03:18 | had to jump to the Catch block.
| | 03:20 | Now I don't actually need to put
anything here, I'll just put this message out.
| | 03:27 | The reason that the Finally block exist,
is let's say what I put in the Try was
| | 03:32 | saving information to a database.
| | 03:34 | It might work, it might not, but
regardless what I want to make sure that I do
| | 03:39 | is in the Finally block I'm going to
close my connections to my database.
| | 03:42 | So there is nothing particularly
important here, I'm going to garb this code and
| | 03:46 | just hit Ctrl+I to format it a
little bit better, and then let's run it.
| | 03:51 | So I'm just going to shrink this down
to show just the Target Output, make it a
| | 03:54 | bit more obvious here.
| | 03:55 | So what we're getting is the message
unrecognized selector, and you can see
| | 04:00 | where I'm writing out myself whether
there was an error, but see that I'm also
| | 04:04 | jumping to that Finally block.
| | 04:06 | It is not causing the program to crash,
in fact, if I look at the logs here,
| | 04:12 | I've got the fact that this one ran,
there was a Debug and there were no issues,
| | 04:15 | we ran it, not a problem.
| | 04:17 | As far as this is concerned,
we finished successfully.
| | 04:22 | We can run it again, we can run
it again, and we can run it again.
| | 04:25 | Of course, what you want to be doing
with your code is writing in such a fashion
| | 04:32 | that this doesn't happen anyway, that
as much as possible, exemptions never
| | 04:37 | occur, that you're always checking
beforehand, so that you don't have to worry
| | 04:41 | about Try and Catches and Finals.
| | 04:43 | But in those rare circumstances
where you're aware that a combination of
| | 04:47 | conditions might make things a little
bit tentative, this is a great asset to have.
| | Collapse this transcript |
| Breakpoints and debugging| 00:00 | When it comes to really understanding
what is going on in your code there is no
| | 00:03 | substitute for a proper debugging
session on using and using X-code we can step
| | 00:08 | through our code line by line as its executing.
| | 00:11 | The simplest way to do that is to
pick a line that we want to stop on.
| | 00:15 | I am going to pick line 15.
| | 00:17 | there is an NSLog message here.
| | 00:19 | What I am going to do is come over into
the gutter and just single click here.
| | 00:23 | This creates the breakpoint.
| | 00:25 | That's what this blue icon represents,
saying that when this program runs,
| | 00:31 | stop here and allow me to browse through
the code and continue to execute line by line.
| | 00:36 | Now the shape of the breakpoint matches
a shape up here on the navigator and if
| | 00:40 | I in fact click that it will keep a
list of any breakpoints that I click on in
| | 00:45 | the gutter or turn off.
| | 00:46 | Now you notice that if I single click
and then single click off again, what
| | 00:51 | happens as the breakpoint
doesn't go away it becomes deactivated.
| | 00:55 | Now that I can be useful but
maybe I just created it by accident.
| | 00:59 | Well to delete a breakpoint I can
actually deleted from the navigator or I can
| | 01:05 | drag and drop it off the gutter and
it disappears in a puff of smoke here.
| | 01:09 | But let's say what does.
| | 01:11 | So with this breakpoint activated I'm going
to click the Run button, build succeeded.
| | 01:16 | It runs it executes the first few lines of main.
| | 01:19 | it hits that breakpoint and stops.
| | 01:21 | We are now in a running program.
| | 01:24 | It's waiting for input.
| | 01:25 | Now what you can see is up here on
line 910 I have created some variables and
| | 01:29 | done a little bit of interaction with
them and then down here on the left-hand
| | 01:33 | side of the debug area we have the
variable section and this is actually showing
| | 01:38 | me the local variables that are
currently in scope A=300 I could actually double
| | 01:44 | click that and change that value if I wanted.
| | 01:46 | I can see the variable B, I can see
there is a string called simpleString
| | 01:50 | here that must have been initialized and yes
indeed it was on line 14 with a value test string.
| | 01:57 | You not only have this list down here
in the variable section but you can mouse
| | 02:02 | over a variable itself to see what's inside it.
| | 02:05 | mousing over here integers I can
also mouse over a string or even
| | 02:09 | an NSAutoReleasePool.
| | 02:10 | Now that there is an awful lot of data,
some of them you can expand by clicking
| | 02:16 | the disclosure triangle, to see some of
the internationals of what's going on.
| | 02:20 | So with the little green indicator here
our question is now what do we want to do?
| | 02:25 | We stopped before the line NSLog.
| | 02:28 | So this line has not actually executed
right now and I want to execute it and move on.
| | 02:32 | Well I have a couple of choices and
everything is driven from these buttons down
| | 02:36 | here at the top of the debug area.
| | 02:39 | This first one looks
like a Play button on a VCR.
| | 02:43 | Continue program execution, just keep
going either till the end of the program
| | 02:46 | or till you hit next breakpoint.
| | 02:48 | This one is called a step over and the
next one is called step into and we will
| | 02:53 | see what those do right now.
| | 02:55 | What I'm going to do here is click this
button it executes the line in the NSLog
| | 03:01 | and I actually can see you can see
over here in the output its output of the
| | 03:04 | string is a test string.
| | 03:06 | Now were paused right before
the call to simple function.
| | 03:10 | Now if I click this button, the third
one this is the step into button which
| | 03:14 | means execute this but as it's a
function called we're going to jump into the
| | 03:19 | function which is actually down
at the lower part of the screen.
| | 03:23 | Now if you notice that the local
variables change because we're in a
| | 03:26 | different scope it might have some odd
values depending on whether they have
| | 03:30 | been initialized or not.
| | 03:31 | I'm going to keep stepping into a
setting those values and I can see them change
| | 03:37 | in the variable screen below.
| | 03:39 | We hit the NSLog message, I come to the
end of the function and what's going to
| | 03:44 | happen when I'd step into it again we
are just going to continue executing
| | 03:47 | jumping back into the main function,
we are finished what our call to simple
| | 03:51 | function we're on to the next NSLog.
| | 03:54 | We output a message.
| | 03:55 | we are creating a custom class.
| | 03:56 | Now these next lines 20 21 and 22
these are using a class that I've created
| | 04:02 | myself a custom class because I have
the code in my project what that means is
| | 04:09 | it's going to jump into the init method here.
| | 04:13 | So if I hit this step into I'm
jumping actually into a completely different
| | 04:18 | file into a simple class.m where I have
got a custom init method I can start to
| | 04:23 | jump into that and keep going return we
jump back in and back in main now it's
| | 04:30 | call to simple method we jump over we output
another message I keep on stepping through.
| | 04:37 | Now let's say for example that I
realized that we're jumping into a lot of code.
| | 04:41 | I am having to step through quite a few things.
| | 04:43 | One of my other choices because I can
see there is another call coming up to
| | 04:46 | simple function or maybe I don't want
to jump into it, I do want to execute it.
| | 04:50 | So what I will do instead is I will
click this option which is a step over.
| | 04:55 | Now step over doesn't mean bypass.
| | 04:57 | It means execute this function but I don't
need to go into and see every single line.
| | 05:03 | Just executed and move on.
| | 05:05 | So if I click that we move on to the
next line, we did execute that function and
| | 05:10 | it wrote out the message in the
simple function writing out 199.
| | 05:14 | I can come down a little bit here,
give myself some room and now I am
| | 05:18 | jumping into a loop here.
| | 05:20 | It begins initializing on line 29
we're creating a new instance of my custom
| | 05:25 | class that means when I hit that
line we are going to jump into the init.
| | 05:29 | Again I might be thinking I didn't want
to do this but what I am going to do is
| | 05:34 | continue executing this init method, but just
say I want to continue on and then jump out.
| | 05:40 | that doesn't change anything about how
the program executes it just allows me to
| | 05:44 | skip past a few lines and come back to
where I was before I called it.i now jump
| | 05:50 | on and we keep going.
| | 05:52 | Now I could make this a little quicker
by using the step over which means I can
| | 05:57 | at least start to rotate around that
loop but it would certainly get a little
| | 06:01 | tedious to have to do this a hundred
times particularly as I can see that the
| | 06:09 | integer counter is only equaled 11 right.
| | 06:11 | So what would be a good idea well what
I am going to do is come down and click
| | 06:15 | in the gutter and create a breakpoint
just before this NSLog message come down
| | 06:20 | to the bar here and just click
the Play button, keep going bang!
| | 06:25 | We've gone through that loop a hundred times.
| | 06:28 | In fact if I look at my variables here,
it's a little difficult to see it's gray
| | 06:31 | there but there are hundred objects in it now.
| | 06:33 | We are now out of the loop I could
choose either the step into or the step over,
| | 06:38 | they both work the same way here.
| | 06:41 | We drain I click Play and we finish.
| | 06:45 | Technically X-code is using the
GNU debugger GDB in the background.
| | 06:50 | So if you are familiar with that you can
even start typing in, in the debug area
| | 06:54 | over here if you wanted to.
| | 06:58 | But as you can see a very simple way
to start jumping through your code.
| | 07:02 | very easy to start creating and
manipulating breakpoints choosing to jump in or
| | 07:06 | jump out of different pieces,
choosing when to stop one to look at things.
| | 07:11 | You can also set watches and
expressions, I am not going to get into this
| | 07:14 | in this particular movie but do have
an experiment with that and see what you think.
| | Collapse this transcript |
| Upgrading code to utilize ARC| 00:00 | If you have Xcode projects created
prior to ARC, including many of the
| | 00:04 | exercise projects for this course, they will
continue to work correctly. You can open them
| | 00:09 | up in Xcode, and they'll work just fine.
Xcode will not force you to migrate anything to
| | 00:14 | ARC, but it might be a good idea to.
| | 00:16 | So I'm opening an older project here that
was created prior to ARC's existence.
| | 00:22 | It's from the Archiving Chapter earlier in the course.
Even from just taking a quick look at that
| | 00:27 | I can see there are some things that need
changing. We're working with the NSAutoreleasePool
| | 00:31 | Object, that shouldn't be used with ARC,
we have got calls to release, pool drain, and so on.
| | 00:37 | If I looked further into the actual objects
here, I have got the dealloc method with a call
| | 00:44 | to super dealloc. I know that kind of thing
is not allowed in ARC. But even so, I can
| | 00:49 | actually go ahead and build this. It should
build successfully, because we don't have
| | 00:54 | to use ARC, so projects opened beforehand
will work just fine, and when I open an older
| | 00:59 | project, it's worthwhile looking on the Toolbar here.
I can see that I have got one warning popping up here.
| | 01:04 | That right now says validate project
settings, and we should work with these first.
| | 01:10 | So if you are getting any complaints, deal with
those first. It's suggesting that I upgrade
| | 01:14 | the debugger from GDB--the older one--to LLBD. That's fine.
I am going to go ahead and perform those changes.
| | 01:19 | It's asking if I want to take snapshots
before cleaning up this project,
| | 01:24 | for my purposes, no, I don't.
| | 01:26 | So I have dealt with that. We have no issues.
I have done nothing yet about converting to ARC.
| | 01:30 | Now we have seen earlier that ARC is something
the compiler does. So one question might
| | 01:35 | be, how do I know? How do I know if ARC is
on or off for a particular project?
| | 01:40 | Oh, one clue might be just looking at your code and
seeing if you have things like NSAutoreleasePool
| | 01:45 | being used, that's not ARC compatible. So
this is telling me that this project isn't ARC.
| | 01:51 | But what if I want to formally look, what I
need to do is look at the Project Settings
| | 01:55 | for this project. How I do that is by
clicking the very top icon in the Project navigator
| | 02:01 | here, the one with the project name. In this
case, Archiving. So selecting that icon, we have
| | 02:06 | settings that we can read over here. We have
got settings for both the project and want
| | 02:10 | called the target. If I select the Project
Settings we find a section called Build Settings.
| | 02:15 | Now there's an awful lot of stuff that goes on
here, most of which you'll never need to touch.
| | 02:22 | But the setting or whether Automatic Reference
Counting is turned off or on is actually buried in here.
| | 02:26 | The easy way to find it is using this box,
I can search on Automatic, there we go.
| | 02:33 | As I'm starting to type it, I'll see there is
an Option under the Apple LLVM compiler,
| | 02:38 | what Xcode is using behind-the-scenes to compile our project,
and it says Objective-C Automatic Reference Counting: No.
| | 02:46 | Now you might be tempted to just change this
to Yes. That would be the wrong way to go about
| | 02:49 | it, because it'd be incompatible. Xcode can
help us migrate this project to Automatic
| | 02:55 | Reference Counting. I don't want to just flick
this option to Yes, because there's all sorts
| | 03:00 | of things going on that are incompatible with
ARC. So to probably convert a project to ARC,
| | 03:05 | I'm going to go to the menu Option under Edit
in Xcode, come down to the Refactor section,
| | 03:11 | where I'll find Convert to Objective-C ARC,
click that, it's going to ask what Target
| | 03:17 | you want to Convert. I only have one here, a
typical project with a single target, meaning
| | 03:21 | what we will actually compile
this into, it's just one program.
| | 03:26 | I'll click check, it'll step us through a
couple of different screens about converting
| | 03:30 | to Automatic Reference Counting, click Next
on this panel, and what it's going to do is
| | 03:36 | now give us a Preview, give us a comparison
of the things that it's changed between our
| | 03:42 | project as it was before, and what it's
doing afterwards. What we're actually seeing is
| | 03:46 | the before is on the right-hand side
and the after is on the left-hand side.
| | 03:52 | So by scanning it I can see that in the
Employee Header file it's changing the retain property
| | 03:58 | to a strong property. If I jump into the
implementation file, I can see that there are a couple of
| | 04:05 | calls to retain that are being removed, because
those aren't necessary anymore, ARC will take
| | 04:09 | care of figuring out when an object needs
to be retained. Not only that, but I can see
| | 04:14 | the dealloc method in the original one has
been completely removed in the converted one,
| | 04:20 | because it's just not needed anymore.
| | 04:22 | If I jump into main.m and take a look at the
changes there, I can see that the NSAutoreleasePool
| | 04:27 | on line 6 has been changed to an at sign,
@autoreleasepool block. If I come down a little
| | 04:32 | further to see what else is going on, we have
got a call to release, doesn't need to be
| | 04:35 | done anymore, and the drain of the pool has
been replaced just with the closing brace
| | 04:40 | of the at sign @auto release.
That all looks good, I'll click Save.
| | 04:46 | I jump over into my main, where I can see
that I have got some simpler code going on now,
| | 04:51 | but if I go ahead and click Build, Build Succeeded.
We have now successfully converted this project into ARC.
| | 04:57 | Now for additional information, take a look
at the developer.apple.com web site,
| | 05:05 | and what you'll find is in the Mac OS X Developer
Library, there is a document on transitioning to ARC.
| | 05:11 | Sometimes it's a little difficult to find,
but you'll find it in the Release
| | 05:15 | Notes Section, or you can search for it.
Transitioning to ARC Release Notes will actually go into
| | 05:20 | Detail about some of the things you should
be aware of when converting older more legacy
| | 05:25 | style projects with a lot of code.
| | 05:27 | So this contains more information on the
Technical Details if you need it on the common issue
| | 05:32 | when migrating projects. Most of these
things we have actually talked about, there are a
| | 05:35 | few more unusual things that ARC will choke on.
Like if you have defined your own Custom
| | 05:40 | retain and release methods,
these aren't allowed.
| | 05:43 | So there are suggestions in that document for
you might do instead, and it's certainly a
| | 05:47 | worthwhile document to have on hand the first
couple of times you migrate a larger project to ARC.
| | Collapse this transcript |
|
|
ConclusionExploring and using other frameworks| 00:00 | From this point on, most of what
you'll do is less to do with the language
| | 00:03 | itself, and more about the frameworks
that you will choose to link to and use.
| | 00:08 | Of course, in this course we have
concentrated on the language by creating
| | 00:11 | simple Command Line tools that
use the Foundation framework.
| | 00:15 | little over hundred classes that
we can use in any code we write.
| | 00:18 | If you move into building Desktop apps,
you will be using Cocoa, and if you're
| | 00:22 | building iPhone or iPad it's
often referred to as Cocoa Touch.
| | 00:25 | Now these things sound like there
must be some massive pieces of software
| | 00:29 | architecture, but they're really not.
In fact they are quite deceptive.
| | 00:33 | Cocoa itself is kind of a hand-wavy
vague term that's often used just I mean
| | 00:38 | general all aspects of Apple development.
| | 00:42 | And there is a good reason for this, let's
go and take a look at what Cocoa actually is?
| | 00:47 | So I find them in Xcode and I create a Cocoa
application instead of a Command Line tool.
| | 00:51 | I'll give it a name. Let's
just call this FirstCocoaApp.
| | 00:54 | Now it does want me to give a Company
Identifier, which is often your Company in reverse DNS.
| | 01:00 | So I am just saying com.lynda here.
| | 01:02 | I'll leave all the rest blank and click Next.
| | 01:05 | It will go and create this application
for me, and instead of linking to the
| | 01:10 | Foundation framework, we are now
linking to the Cocoa.framework which sounds
| | 01:14 | very impressive, and isn't.We know that
we could break the Foundation framework
| | 01:19 | into loads of different header files.
| | 01:22 | Well if I expand the Cocoa.
framework, I see precisely one.
| | 01:26 | You see Cocoa itself contains nothing.
| | 01:30 | There are no classes, there's no
functionality, there's no code at all.
| | 01:34 | All Cocoa technically means is
linked to these three other frameworks.
| | 01:41 | Foundation, AppKit and CoreData.
| | 01:44 | Foundation is the one we
have been using all along.
| | 01:47 | AppKit contains classes
for developing desktop apps.
| | 01:50 | They represent Windows, menus, buttons,
fonts, images though it's not just
| | 01:54 | visual, there are also classes in
AppKit for background functionality,
| | 01:58 | spellcheckers, event handling and the
application itself, and then CoreData.
| | 02:03 | This is a framework to help you persist
your objects to save them into storage
| | 02:08 | and read them back from storage.
| | 02:09 | It's recently become the recommended way
to store your data, but technically you
| | 02:13 | don't even need this for Cocoa, because
while this is the technical meaning of
| | 02:18 | the Cocoa header file, in general
discussion with other Apple developers, Cocoa
| | 02:22 | really just means Foundation and AppKit
on the desktop or Foundation and UIKit.
| | 02:28 | which is the iPhone equivalent and iPad
equivalent on the iOS platform, and in
| | 02:33 | fact that's even what Apple quote.
| | 02:35 | If I bring up some Apple
documentation from the Cocoa Fundamentals Guide,
| | 02:40 | Apple themselves will say that
foundation, AppKit and UIKit frameworks are
| | 02:45 | essential to Cocoa application development,
all other frameworks are secondary and elective.
| | 02:51 | So Cocoa really does just become
this generic term for using the Apple
| | 02:55 | frameworks for building desktop applications
and tangentially iPhone and iPad applications.
| | 03:02 | Cocoa Touch doesn't even
have a technical meaning.
| | 03:05 | There isn't actually a
header file for Cocoa Touch.
| | 03:08 | But the benefit here is we
don't have to worry about it.
| | 03:11 | If I make a Cocoa App in Xcode, if I
make an iPhone or iPad App in Xcode it will
| | 03:16 | link to the things that I actually need.
| | 03:19 | What I can then choose to do
is link to other frameworks.
| | 03:23 | Well how do I do that?
| | 03:24 | Well, even in a basic Command Line tool
like this, I can link to other frameworks.
| | 03:29 | If I click on the Settings of my
project, I make sure that I have the target
| | 03:34 | selected and I jump over to Build Phases.
| | 03:37 | What I will find here is this
wonderfully phrased Link Binary With Libraries,
| | 03:42 | meaning when it comes time to
compile and build this application, are we
| | 03:47 | reaching out to another framework?
| | 03:49 | And in this case, yes we are
Foundation.framework is the default here.
| | 03:53 | If I click the plus button, it gives
me a link of a whole bunch of other
| | 03:57 | frameworks I can add.
| | 03:58 | Now what you'll find is some of them
end in the dot framework, they look like
| | 04:02 | the little tool chest, others end
in dylib which are Dynamic Libraries.
| | 04:07 | You're more likely to be interested in
the frameworks themselves, which really
| | 04:10 | bundle up libraries with a
bunch of other resources.
| | 04:13 | Just browsing through them, I can also
make a pretty good guess, as I'm sure you
| | 04:18 | could about what they represent.
| | 04:20 | We've got things like CoreVideo,
CoreAudio, CoreMIDI, though some of them are a
| | 04:25 | bit more vague, ApplicationServices for
example, you might take a guess of what
| | 04:30 | it represents, but I don't
think anyone would bet money on it.
| | 04:33 | It's all going to be driven by what you
want your app to do. The thing is this.
| | 04:39 | Your first step should never
be just going out of framework.
| | 04:43 | It should be go look in the documentation.
| | 04:46 | So I cancel out of that, I jump
into Help, and I jump to Xcode Help.
| | 04:51 | Now we've used this primarily as a class
references so far, and that's great for
| | 04:56 | that but it's way more useful than that.
| | 04:59 | The thing is when you start to search
on terms that you don't know how to do,
| | 05:02 | you want to do more with dates or
strings, you want to work with audio or
| | 05:06 | video or timers or something, you just start
off by trying to figure out what's available.
| | 05:11 | We type-in String and the first thing
we're going to get is the Reference for
| | 05:16 | things like NSString and Mutable string.
| | 05:18 | Down in the System Guides is the
really, really important stuff.
| | 05:22 | You'll get things like the
String Programming Guide.
| | 05:25 | You will find a lot of different, very
focused programming guides here available
| | 05:29 | through the Xcode Help.
| | 05:30 | We have got the String Programming Guide for
Cocoa and now using Cocoa is a generic term.
| | 05:36 | We could quite happily use this
programming guide in just a regular Command
| | 05:40 | Line foundation tool.
| | 05:41 | If I search on date and time, we will
find the Date and Time Programming Guide
| | 05:46 | way more than just trading date
objects but being able to work with calendars
| | 05:51 | and formatting and so on.
| | 05:53 | File management, be aware that sometimes
the System Guides have a lot of results
| | 06:00 | and here we've got over a hundred,
but you'll find things like the File
| | 06:03 | Management Programming topics.
| | 06:06 | As you start to find some of these,
what you can do is highlight one and then
| | 06:09 | from the Editor menu, you
can add a bookmark to it.
| | 06:18 | That then gives you the bookmarks
icon which will allow you to jump to your
| | 06:21 | favorite documents, and if you can't
find one of the programming guides or
| | 06:27 | programming topics documents, this should
be considered your first source of authority.
| | 06:32 | Now when you're looking up information
on something in particular, let's say I
| | 06:36 | want to work with a timer.
| | 06:37 | I want to figure out how
to delay certain actions.
| | 06:41 | I find that there is a class called NSTimer.
| | 06:43 | I find that there is a System Guide for
Timer Programming topics. It looks terrific.
| | 06:47 | What you'll also often find is this
section down at the bottom that says Sample Code.
| | 06:52 | Unfortunately this is the one area I'm
not such a big fan of, simply because
| | 06:57 | there's a lot of old pointless
stuff here in the Sample Code.
| | 07:00 | If I look at all the results here,
there is a whole bunch of things that look
| | 07:04 | quite interesting, but clicking some
of them, you're going to find let's say
| | 07:08 | SonOfSillyBalls here, created back in 2003.
| | 07:11 | I can assure you that this one is
not going to be very useful to you.
| | 07:16 | However more recent ones,
particularly from say 2008-2009 onwards and
| | 07:21 | particularly the iPhone-based ones
can be very useful and good sources of
| | 07:25 | information, but generally speaking,
any programming guides that you can pick
| | 07:30 | up, and even as a first three I'm
very fond of those String Programming
| | 07:34 | Guide, Number and Value and the Low-
Level File Management, these are great
| | 07:38 | sources of information.
| | 07:40 | Let's say we did find something.
| | 07:42 | I know that I want to work with say
CoreAudio, playing back some music files.
| | 07:47 | So I look at the Programming Guide.
| | 07:50 | I find out the useful information here,
and then I go back into my Project and
| | 07:54 | say yes, I want to link to that framework.
| | 07:57 | So I find in this case CoreAudio I click Add.
| | 08:01 | Our project is now linking to that.
| | 08:03 | However I can't do anything in my
code until I do the Import statement,
| | 08:10 | but until you use to what you're linking to,
you want to take a look at your frameworks.
| | 08:13 | I actually added this, let me just
drag that into the Frameworks folder.
| | 08:18 | just to keep it together.
| | 08:19 | It doesn't really matter here.
| | 08:20 | I will expand the CoreAudio headers,
and I will see that there are several
| | 08:24 | different ones AudioDriverPlugin,
AudioHardware, CoreAudioTypes.
| | 08:28 | If you find the header file with the
same name as the framework, that's almost
| | 08:32 | certainly the one you need.
| | 08:33 | That will just import all the others.
| | 08:35 | So I would come in here, #import>
CoreAudio/CoreAudio.h. I'm using here the angle
| | 08:46 | brackets not the quotes
because this is not my code.
| | 08:50 | It's system code, and of course once
you've imported it, then the real work is going to begin.
| | Collapse this transcript |
| Goodbye| 00:00 | Thanks for joining us for
Objective-C Essential Training.
| | 00:03 | You should now have a firm grasp on the
core language features and feel pretty
| | 00:06 | comfortable about taking those into more
device-specific frameworks, things like
| | 00:10 | iOS or desktop development.
| | 00:13 | Take a look at the other courses of
lynda.com that dive deeper into some of
| | 00:16 | those areas of Apple development, and let us
know if there's anything you would like to see.
| | 00:19 | Good luck with your Objective-C programming.
| | Collapse this transcript |
|
|