navigate site menu

Start learning with our library of video tutorials taught by experts. Get started

iOS SDK Essential Training (2012)
John Hersey

iOS SDK Essential Training (2012)

with Simon Allardice

 


In this course, author Simon Allardice shows how to develop, debug, and deploy applications for the Apple iPhone, iPad, and iPod touch using iOS 5 SDK and Xcode 4. The course reviews Objective-C basics, covers key concepts such as the Model-View-Controller pattern and delegation, and explores new features of the SDK, including Automatic Reference Counting (ARC) and Storyboards. The course also shows how to create and customize user interfaces and table views and develop apps with multiple view controllers, and explores the differences between iPhone and iPad development.
Topics include:
  • Using Xcode and the iOS Simulator
  • Reviewing Objective-C basics and structure
  • Creating objects, variables, properties, and custom classes
  • Connecting UI elements to code
  • Using Delegation
  • Troubleshooting an application
  • Using the Xcode debuggers
  • Creating and customizing table views
  • Introducing blocks
  • Saving and loading data
  • Understanding iPad development
  • Creating iPad apps with popovers and split views
  • Creating application icons and launch images

show more

author
Simon Allardice
subject
Developer, Mobile Apps
software
iOS 5, Xcode 4
level
Beginner
duration
6h 26m
released
Mar 01, 2012

Share this course

Ready to join? get started


Keep up with news, tips, and latest courses.

submit Course details submit clicked more info

Please wait...

Search the closed captioning text for this course by entering the keyword you’d like to search, or browse the closed captioning text by selecting the chapter name below and choosing the video title you’d like to review.



Introduction
Welcome
00:04Hi! This Simon Allardice, and welcome to iOS SDK Essential Training.
00:09Here you'll see how to build applications that run on the iPhone and the iPad,
00:13using Apple's free iOS SDK, or software development kit.
00:17In this course we'll work with Xcode 4, the main application for creating,
00:22testing, debugging, and managing our apps.
00:24You see a lot of Objective-C, the programming language we use to create iOS applications.
00:30But apart from the tools and the language, we're going to explore the
00:33conventions and guidelines of programming iOS devices,
00:36essential concepts like model ViewController, target action, and delegation.
00:42And we'll see how to build an iOS user interface using the most recent
00:47features of the iOS 5 SDK, like ARC and Storyboards.
00:51We'll work with the most important controls and controllers in iOS.
00:56We'll talk about testing and debugging and even see what's different when
00:59developing for the iPad.
01:01So let's get started.
Collapse this transcript
What you should know
00:01So what should you know to make the most of this course?
00:03Well, it is an introduction to programming on the iPhone and the iPad, but it's
00:07not an introduction to programming in general,
00:10so I do expect that you can program.
00:12You can write code in some other language.
00:14You're comfortable with the core skills of programming: functions, conditions,
00:18variables, loops, and so on.
00:20Now if this is all brand-new to you, this is not the best course to begin.
00:25So take a look at our Foundations of Programming Fundamentals course.
00:29Next, you should know a little Objective-C, and the more you know the better.
00:33If you've only dabbled in, or if it's been a while, I am going to have a short
00:38refresher/introduction to the language here, but it is just the basics, because
00:43we have a full Objective-C Essential Training Course in the lynda.com library,
00:48and I am not going to just duplicate that course inside this one.
00:51And that let's us focus here on the iOS side of things,
00:55what's specific about iPhone an iPad development, instead of things like how do
00:59you make an integer?
01:00So if that's the case, what should you expect with this course?
01:04Well, I had three rules for myself when I was putting this course together.
01:08Number 1, I was going to focus on the most important 20%.
01:11There are thousands of pages, dozens of documents on Apple's developer site alone.
01:17There is a lot of iOS information for you to try and cram into your brain, but
01:21only about 20% of that is immediately worthwhile, and we're going to focus on that 20.
01:27It's iOS SDK Essential Training here, the fundamentals, the things you will need
01:32in every iOS app you make.
01:35Number 2, the rules, not the exceptions.
01:38This is programming, so yes, there are always multiple ways to accomplish the
01:42same result and the geekier you are, the more you can find.
01:46So if it makes you happy, assume that yes, there are other ways to do
01:50everything I am going to show.
01:52But also assume that I am going to show you the simplest one.
01:55Number 3, this is not an exam.
01:57I'm not interested in you doing a memory test of long method names and
02:01obscure parameters,
02:02so focus on the concepts, on the approach here, rather than memorizing
02:07the tiniest pieces.
02:08Because we are also going to get familiar with the help systems and the
02:11documentation, so that when you do forget something--and you will--you can just
02:16find it when you need it.
02:17So those are my three items for how I am putting together this course. What about you?
02:22Well, I do have three suggestions for you too.
02:25One, realize that you're in another world now.
02:29You may have a ton of experience in Java or .NET or PHP or Ruby On Rails, but
02:35leave that at the door.
02:36Objective-C and iOS development is different, often very different, and this is
02:41more than just a few syntax changes.
02:44Apple development has a substantial history, and it has its own customs and
02:48ways of doing things.
02:49If you try to force everything here into an exact equivalent of something you
02:53do in Java or C++ or JavaScript, you're likely to find this journey very painful indeed.
02:59So number two, embrace confusion, at lease for a while.
03:04There are a thousand things to learn with the iOS SDK, and you can't learn them all at once.
03:10In a few minutes we are going to create your first iOS project and some code
03:14will appear, and you'll have no idea what it means.
03:17And your personality may be such that you think, well, I need to have that
03:19explained before I move forward, and I will say, no, you don't, we are going to
03:23move on and come back to that later.
03:25So there will be things that won't make sense for a little while.
03:29So number three, experiment and have fun.
03:32If you don't already have an app in mind, come up with something,
03:36anything to help you use the examples here in your own way, and it will help you
03:40make all the connections.
03:41So realize you're in another world, embrace a little confusion, and experiment
03:45and have fun with it.
03:46If you keep this in mind throughout the course, you'll have a much better
03:49time learning it all.
Collapse this transcript
What's new in this version of the course
00:00In 2009, we released our first course on iPhone development called iPhone
00:06SDK Essential Training.
00:08Now back then, the operating system on the device was still so-called iPhone OS,
00:12not iOS, because there was no iPad yet.
00:15It was iPhone OS Version 3 and we used the iPhone SDK Version 3 to program our apps.
00:21A lot has changed since then.
00:23New hardware of course; we have the iPad, the iPad 2, the iPhone 4 and 4S.
00:28But more importantly for developers, we have much that has been added and improved.
00:32So since then, we've released many iOS courses at lynda.com, covering features in
00:37Version 4 of the SDK and iPad development, the release of Xcode 4, even iOS 5
00:43SDK, game development and so on, but the original course was falling behind.
00:47So this is a completely new version of the Essential Training course to bring it up to date.
00:53This course has been recorded from scratch using the latest version of the iOS
00:57SDK and Xcode, but more importantly, the newest features and the current best
01:02practices for iOS development.
01:04Because we now have technologies like multitasking, Grand Central Dispatch,
01:08blocks, storyboards, Automatic Reference Counting, none of which were available
01:13when I wrote the first course, all of which I'll cover in this one, and while
01:17they might sound a little intimidating, all of them make creating an iOS app
01:21better and easier than it ever was before.
01:24So what does up to date mean?
01:26I'm recording this course in early 2012, and right now the version of the iPhone
01:31and iPad operating system is iOS 5, released in October 2011. And in this course,
01:36we'll be using the iOS SDK Version 5.
01:40And our main application is Xcode 4, specifically Xcode 4.3, although any
01:46version from Xcode 4.2 upwards will work.
01:49Now if you don't yet have the SDK, or if you're not quite sure which version you
01:53have, we'll get to that in a moment.
Collapse this transcript
Using the exercise files
00:00If you're a Premium member of lynda.com or if you're watching this tutorial on a
00:04DVD, you have access to some exercise files used in this title.
00:08I have them here on my desktop, and they are in a folder just called exercise files.
00:12Inside that, any of the relevant chapters will have its own folder, and there are
00:17some simple files that you'll find inside some of these folders that will help
00:20you build the exercises.
00:22And we will point out any of these files at the relevant time, just by showing
00:25your path to the file location.
00:27And there are also some finished examples if you want to compare and contrast
00:31what you've done. But these are all just for convenience.
00:34If you don't have access to the exercise files, you can follow along from
00:37scratch or create your own assets.
Collapse this transcript
1. Getting Started
Requirements: installing the SDK
00:00So let's say you've got a great idea for an iPhone or iPad application. What do you need?
00:05Well, first things first: you are going to need a Mac. The development tools
00:08are not cross-platform.
00:10You need an Intel-based Mac, which really means any Mac released after late 2006.
00:14And it should be running Lion, Mac OS 10.7 or later.
00:20Now let's say you just borrowed a Macintosh and you don't know for sure what it is running.
00:23If you click your Apple menu at the top-left and select About This Mac, this
00:27will give us the version of the operating system that were using.
00:31In my case it's 10.7.2, which is fine.
00:34You can install the tools on Snow Leopard, which is Mac OS 10.6, but being on
00:40the latest operating system is highly recommended if you're going to be
00:43developing on any Apple platform.
00:46So I'll be using Lion as my operating system here.
00:49Now I can also see the word Intel here in my Processor section, which means
00:54we're fine. As far as our hardware requirements go,
00:57we are completely ready.
00:59Because technically, you don't actually need an iPhone or iPad to write iOS
01:05applications, as there is a Simulator in the SDK that you are going to download.
01:11But realistically, I expect that you do have either an iPhone or an iPad or
01:16both, so that you can test your apps on a real device.
01:19But to get this simulator and all the other tools that we need, we need to go
01:23ahead and get Xcode and the iOS SDK.
01:26You can't do any development without installing the SDK first.
01:30If you have Lion as your operating system, you can just get Xcode directly
01:34from the Mac App Store.
01:35If you go to the Developer Tools category, you'll find it there.
01:41This one Xcode download is about 1.4 GB currently.
01:46Now the reason it's so big, that it's not just Xcode.
01:50That's a bit of a lie.
01:51It's Xcode plus a whole bunch of other programs and tools and supporting files,
01:55the iPhone and iPad Simulator, the SDKs, or software development kits,
02:00all bundled together.
02:01Everything you need for creating iOS apps and Mac desktop apps is all here.
02:07Now I've gone ahead and installed it already, which is why I see the Install button.
02:12And I'm looking currently at Version 4.3, released mid-February 2012.
02:16Now Xcode is a free download from the app store, but as of today, that's only if
02:22you have Lion or a later operating system.
02:24If you have Snow Leopard as your OS, right now you have to get Xcode from the
02:28developer.apple.com web site.
02:31Up until February 2012, if you downloaded Xcode from the App Store or from the
02:36Developer site, what you actually got was an installer application and you
02:40would run that. It would install Xcode and all the other SDK files under a
02:44folder called Developer, at the root of your hard drive.
02:48Now with the release of Xcode 4.3, in February 2012, Xcode is now installed like
02:54other applications directly in your normal Applications folder.
02:58And the real test of course is, can you open it?
03:01And once it's open, either from the Welcome screen or you go to the Xcode About
03:06menu, you need to see at least Version 4.2.
03:10This course will work with any version of Xcode from 4.2 upwards.
03:14Now Apple releases updates to their developer tools frequently, usually every few months.
03:19So you could well have a later version than I have, and that's fine.
03:23I am a big believer in always having the latest version of Xcode.
03:26Though if you do, you may have some small changes, and part of being an Apple
03:30developer is rolling with these frequent incremental changes.
Collapse this transcript
Becoming a registered Apple Developer
00:00If you haven't already, you should sign up with Apple to become a registered
00:04Apple Developer before you go much further, and this will give you access to
00:09documentation and sample code and videos and other good stuff, and it's free.
00:13To do this, point a web browser at developer.apple.com.
00:20From this page, you can get to the three different main Developer Centers that Apple has.
00:24It's the iOS Dev Center.
00:26That's the one we're obviously interested in. And there's two more links for the
00:30Mac Dev Center and Safari Dev Center.
00:32So click that link.
00:33That takes us here, the iOS Dev Center.
00:36This is a useful link to have, so bookmark it.
00:39You're going to use it a lot.
00:40But you need to register with Apple in order to log in.
00:43Now, there's multiple ways that you can sign up as an Apple Developer.
00:47Some of them cost money; some of them are free.
00:49The most basic is free.
00:51You can just click that Register link, if you haven't already signed up, and you
00:54get all this information about what you get. But I can just go ahead and click
00:58the Get Started button, and it will step me through creating an Apple ID if I
01:02don't already have one, or using an existing one.
01:05And once you've filled all this information out, you can go back and log in
01:09to the iOS Dev Center.
01:11And for now this is the place that you need that has the most
01:13current documentation.
01:14It has sample code, and it will be very useful.
01:17And not only that, we'll often access it using Xcode, to make sure that we have
01:22all the most up-to-date help information.
01:24But signing up as a registered Apple Developer isn't the only thing that we're
01:28likely to do, and in a moment I'll talk about the other developer programs
01:32that Apple has.
Collapse this transcript
Joining the iOS Developer Program
00:00So Apple gives us Xcode and the iOS SDK for free, and it is the full complete version.
00:06It's everything you need to write and test your iOS applications using your Mac
00:11and using the iPhone and iPad Simulator.
00:14But there are a couple of restrictions to know about.
00:17If all you've done so far is sign up with Apple as a registered Apple Developer,
00:23what you won't yet be able to do is plug in your own iPhone or iPad and copy
00:28your applications from Xcode to that device. And you also can't yet publish your
00:33apps to the App Store.
00:35If you want to do either of these things-- and hopefully you will want to--you'll
00:38need to join the iOS Developer Program.
00:41That's one step up from just being a registered Apple developer, and it does cost money.
00:46On the same page that you can get information about being a registered
00:49developer, down towards the bottom is another link for more information about
00:54the Developer Programs.
00:55Well, there's an iOS Developer Program that lets us release apps in the iOS
01:00App Store, and a separate Mac Developer Program to release apps in the Mac Desktop App Store.
01:06Now, there are a couple of different ways to join, depending on if you're trying
01:09to sign up as an Enterprise Program or with the university, but the classic
01:14individual developer would be $99 a year.
01:17It's 60 pounds in the UK, and so on.
01:20Now, you don't get new software.
01:22It's the same Xcode. It's the same SDK.
01:24There is nothing changing about the tools. But after joining what you will get
01:29is the ability to do what's called provisioning your devices, and that allows
01:34you to copy your programs directly from Xcode to your devices to test them,
01:38which is much better than only having a simulator.
01:41And you'll be able to take your finished applications and sell them on the App
01:46Store, and there really is no other way of getting your applications sold.
01:49You can't do it privately.
01:51You need to do it through the App Store.
01:53You do not need to be in the iOS Developer Program for this course, but you
01:57certainly should know about it.
01:59Do be aware that if you haven't joined and you're just holding off until you
02:03absolutely need to, the process of doing this is not immediate.
02:07You can't just pay your $99 and than instantly copy across to your devices or
02:11submit to the App Store.
02:13Some information needs to be verified, and you may have to wait a couple of days
02:18after starting the sign-up process before everything gets turned on.
Collapse this transcript
Creating a simple iOS application
00:00So of course we want to dive right in and start building iOS applications.
00:04I am going to open up Xcode.
00:06It's the icon that looks like the blueprint with a hammer on top.
00:10Now when you learn a new computer language there is of course the tradition of
00:13creating the simple "hello world" application.
00:16Now the idea usually is that by writing this really simple program, you'll
00:20actually learn a lot about how the new language or system works and how it
00:24all hangs together.
00:25Now with iOS development, you might have a few more questions than answers after
00:30you do this, but still we need to see why.
00:33So I have the welcome screen for Xcode here.
00:36If I'd had any recent projects, I'd see them on the right-hand side.
00:40On this left-hand side, I have a few clickable areas for creating a new Xcode
00:44project or connecting to a source control repository.
00:48I am going to go ahead and create a new Xcode project.
00:50We could also get to this through the File menu.
00:53And right now just think project equals application.
00:57Whenever you want to make an app in Xcode, you're going to make a project.
01:00It's a way of keeping all the relevant files together.
01:03So I have this New Project window open.
01:06And we actually have a lot of choices if we start clicking around, because of
01:11course Xcode isn't just used for iOS development; it's also used for developing
01:15programs on the Mac desktop.
01:17So we actually have two main sections for projects:
01:19the Mac OS X section and the iOS section.
01:23And the place we want to live is here, clicking the Application beneath iOS, and
01:29with that selected, we will see several templates for creating different kinds
01:34of iPhone and iPad applications.
01:36We're going to come back to these, but the one I'm interested in is this
01:39Single View Application.
01:41So again, under iOS on the left, we have Application selected and then
01:46Single View Application.
01:48We click Next and now we have to provide some names for our application.
01:52The first one, the main one, is this Product Name.
01:55You can call it anything you want.
01:57We're just making casual projects here.
01:59So Demo is fine; Example is fine, or in our case, HelloWorld.
02:05Here, don't use spaces, or if you have multiple words, just capitalize
02:10the subsequent ones.
02:11Now for Company Identifier, you need a name here, because the Product Name won't
02:16be enough to guarantee this was unique if you were to sell it on the App Store.
02:20There's over half a million applications up there.
02:23But by combining it with the Company Identifier that's unique to your
02:27organization, even if that organization is just you as a solo developer, we can
02:32be pretty sure that it's unique.
02:33Now, by convention, this is usually your domain name in reverse, so for me,
02:38it might be com.lynda.
02:40This address isn't actually followed, so I could type whatever I wanted here.
02:44It's just a way of making a unique name, because as you see, what it's doing is
02:49combining the Product Name and the Company Identifier into what's called a
02:53Bundle Identifier, which should make this unique.
02:56Don't worry too much about the Bundle Identifier right now.
02:59Now there's also this section that says Class Prefix.
03:01Now whatever you type here will be inserted by Xcode at the start of any class
03:07or class files it makes for you. Don't worry too much about this.
03:10We're making casual projects.
03:12Now, however, we do have to look at this section, the Device Family.
03:16What's this iOS application for?
03:19Mostly we'll use iPhone in this course because it's the simplest.
03:22You can also make an iPad-specific application or a universal application.
03:27And universal simply means one iOS app that can change its appearance based on
03:33what device it's running on.
03:34Now that adds some complexity to the situation, so we won't do that here.
03:38I'm going to choose iPhone.
03:41And below, we have check boxes for three extra features.
03:44Now all of these features are great, but two of them would add some complexity
03:49to our simple little Hello World project and one of them removes complexity from it.
03:54So I want to have Storyboard unchecked and Include Unit Tests unchecked.
04:00But this is the one option I am going to have checked, Use Automatic
04:04Reference Counting.
04:06Automatic Reference Counting, or ARC, is a new feature in version 5 of the iOS SDK.
04:11We'll talk more about this later, but in short, it makes memory management easier.
04:16It makes you write less code, and we are going to have ARC checked for every
04:21single project in this course. So, click Next.
04:25Now we have to say where to save the project files.
04:29Now you can put this stuff anywhere you want.
04:31There is no magic location for storing your projects from Xcode.
04:35You can put them in your Documents folder, on your Desktop, however you'd
04:39like to manage them.
04:40I am going to just save them on my Desktop.
04:42Now Xcode understands both git and subversion for source control, if you work with those.
04:47But this course is not about source control, so I am going to leave this option
04:52at the bottom unchecked and hit Create.
04:54Now when you create this project, Xcode is going to make several files for you.
04:59On the left, we have a section called the Project Navigator.
05:03We'll get into this in a moment, but it's basically a view of the different
05:06files in the project.
05:07If I single-click the individual files, I'll see them open up in the editor here.
05:13So we have some code files, some of which might look pretty complex if you've
05:17never seen this before.
05:18If I like this one, ViewController.xib, that's actually a user interface file.
05:23So I'll get a user interface editor with a blank canvas that seems to represent
05:29an iPhone, which is what it does, even with the battery bar up at the top.
05:33Now like many other programming IDEs, Xcode let's me write code, test code,
05:38design interfaces all in the same app. And like many IDEs, it lets me drag and
05:44drop user interface elements.
05:46Now in Xcode, the place to find your user interface elements is what's
05:49called the Object Library.
05:51Now mine is open right here, but if it wasn't, I could get to it from the View
05:55menu, down to Utilities, and say Show Object Library.
05:59I am going to go through this and just find the label, drag it across to the interface.
06:06I should see the Plus button here.
06:08I can position it anywhere that I want, and then I'm going to double-click it
06:12and just type the words "Hello World."
06:15We will see more about how to change this later.
06:18I could roughly click it to select and position it.
06:21If you see as I am dragging it around, you can see little guideline markers on
06:25the left, in the middle, on the right; in the middle will do just fine.
06:29I am going to leave it at that and then just take my mouse up to the Run button
06:33up here on the toolbar and click it.
06:37What it's going to do is compile and run our iOS application.
06:42It's going to automatically open up the iPhone Simulator, which is this little
06:45cut-down version of an iPhone.
06:47It's going to load our program into it and run it.
06:50So we get the remarkable words here, Hello World showing up here.
06:54I can actually hit the Home button on the Simulator, jump back out onto this
06:58simple menu, go back into my Hello World program, and see it again.
07:02A simple app to be sure, but it is running in our iPhone Simulator.
07:07So I'm going to quit out of the Simulator and return back into Xcode.
07:11Okay, that was easy enough, and it was simple enough.
07:15But you're probably starting to form a whole bunch of questions.
07:18We haven't even touched any code yet but still, what do all these code files
07:23represent? Some of them seem to have a lot of content inside them.
07:27Why do we have this many code files? What do they mean?
07:29What are the different parts of this user interface view? What do these icons
07:33over here represent, like File's Owner and First Responder?
07:37How would I hook a button up?
07:39How is the Simulator different from a real device?
07:42In short, what's immediately important, and what's not?
07:45And we're going to get to all of this.
07:47But what we're first going to do is take our perspective up a level about the
07:52best way to approach this all.
Collapse this transcript
The four pillars of iOS application development
00:00A lot of people get introduced to the world of iOS development and become
00:04immediately overwhelmed by this massive amount of terminology, all these tools
00:08and technologies to learn.
00:10You first come across Xcode and Objective-C, but then hear terms like Cocoa
00:14Touch, frameworks, memory management, view controllers, delegation, MVC,
00:19categories, versioning, push notifications, and it's tough to figure out
00:23what's important here, what's the right order, what should I do first, and how
00:27do they support each other,
00:28and why you can't learn it by just throwing yourself into the deep end.
00:32What I find is a bit more useful is to approach your application development
00:37on the iPhone as being supported by four pillars, four areas of content that
00:42you need to have all together in order to build the applications that you want to make.
00:48The first pillar is the tools we use to build these apps.
00:52You're going to start off with Xcode and the iPhone and iPad Simulator.
00:56Now later, you will see another program called Instruments.
00:59You already have it.
01:01It is part of the SDK and the instruments will let you view and analyze diagnostics
01:05about how well your app is performing.
01:07The second pillar is the language.
01:09You need to know Objective-C, and you need to know the coding patterns, the
01:14design patterns we use inside it, like MVC and delegation and the supporting
01:19frameworks that Apple provide.
01:20The third one is the Design.
01:23Not just making your application look good, but how to flow through streams
01:27correctly, how to choose the right kind of user interface elements to create for
01:32the right kind of application.
01:33Because using the wrong elements the wrong way can actually cause your app to be
01:37rejected from the App Store.
01:39Apple have what are called the Human Interface Guidelines that you need to be aware of.
01:44And just as important as all of this is the overall process.
01:49You're in a very formalized process now, working with Apple's rules.
01:53So when you're testing your app, when you're provisioning your devices, signing
01:57and submitting to the application store, you need to know the process to follow.
02:01When you keep in mind that these pillars all need to be there to support your
02:06application development, you can avoid getting buried in one specific area
02:10or neglecting another.
02:12You can stay conscious of the whole process, that it's not just about Objective-C
02:16and it's not just about Xcode.
02:18And as you learn more and more, understand where the different pieces fit
02:22into this picture.
Collapse this transcript
2. The Tools
Using Xcode
00:00So let's get to the tools that we use and our main one, Xcode.
00:04We'll spend most of our time here.
00:06Xcode is an IDE, an integrated development environment, like Visual Studio
00:11or Eclipse or Aptana.
00:12And this just means it does more than one thing.
00:15You organize your application in Xcode.
00:17You write your code here.
00:18You design your interfaces in Xcode.
00:20You compile your applications there.
00:22You use it to test and debug. You use it to browse documentation and to find help.
00:27But at its core, it's there to organize all the files in your applications.
00:32And it groups them together into what it calls projects.
00:35Projects are just a way of taking a bunch of files together and giving them a name.
00:39Now when you create a new project in Xcode--again you can do it from the welcome
00:43screen or from the File menu--be make sure to select New Project, not New File.
00:48We can start that process.
00:50Once again, we want to have the Application section selected under iOS,
00:55and the one we're interested in right now is the Single View Application.
00:59Now this won't always be the one you want.
01:01But while we're learning Xcode and building straight forward iOS applications,
01:05this is the Goldilocks project type: it's not too complex;
01:09it's not too simple; it's just light.
01:11With that selected, I click Next.
01:14Again, it asks me for the naming information.
01:16I am going to call this one DemoXcode.
01:18I am going to leave my Company Identifier as com.lynda, make sure my Device
01:24Family is iPhone, and have everything unchecked except to Use Automatic
01:29Reference Counting.
01:31Click Next. It asks us where we're going to save it.
01:33I'm going to just select to save to my desktop.
01:37You can put them wherever you want. And Xcode opens properly with our
01:41project loaded inside it.
01:44But before we go exploring, I'm going to go and take a look at what was just
01:47created when we did that.
01:48I am just going to minimize this down.
01:50I am going to notice that here on my Desktop, which is where I saved it, I have a
01:53folder called DemoXcode, and this was just created by Xcode.
01:58If I go into this folder--and I am going to change it, just so I can see this a little better--
02:04I can see that I have quite a few different files that have been created.
02:08Opening Xcode back up, just to compare them, I can see that some of the files
02:14that I have in Finder match the ones in Xcode.
02:17I have an AppDelegate.h file in Finder. I have AppDelegate.h in Xcode.
02:23But where I have a supporting files folder in Xcode, I don't have one here in
02:28the Finder. Nor do I have one that says frameworks or products.
02:32And that's because the folders you see in Xcode won't exactly match the
02:36folder on the hard drive.
02:38Don't worry about that.
02:39What's happening is that Xcode is giving us more ways of grouping our files
02:43together than just the physical folders on the hard drive.
02:47However, in Finder there is one important file worth talking about, which is this
02:51one, the one that ends in .xcodeproj.
02:55It's the Xcode project file.
02:57Now this is a file that contains all the settings for this particular project.
03:01In fact, if Xcode was closed, double- clicking this Xcode project file would be
03:05the quickest way to open up Xcode with this project loaded inside it.
03:10We're going to let Xcode manage these files.
03:13We're not going to use Finder to do it.
03:15But to do that, we really need to know our way around.
03:18So let's talk about the best way around the Xcode for interface.
03:21We are of course in a programming environment,
03:24so everything is oriented around this middle section, the editor.
03:28Whether that's letting us edit code, if I select a code file or whether
03:32that's letting us edit a user interface, if I select a file that represents a user interface.
03:37Now, the text here is a little small.
03:41I am going to change that in just a minute.
03:42Up at the top of Xcode we have this toolbar which will let me run the
03:46application by clicking this Play button here and select how to run it.
03:50So I can choose to run it on the iPhone Simulator or the iPad or an iOS device
03:55if I have one connected.
03:56Now this center section of the toolbar looks a little bit like an LED display,
04:01and it will actually show messages about anything that Xcode is doing as we
04:04work with our project.
04:06It's kind of like how iTunes displays messages when you're copying or syncing.
04:10And over here at the top-right of the toolbar you have two sections of three buttons:
04:15Editor and View.
04:17Right now the first button of Editor is pressed in, and that means we're looking
04:21at the standard editor.
04:23There are different ways to edit, but we will see them later.
04:26Now in the second section, we have three buttons: one with a dark left section,
04:31one with a dark bottom section, and one with a dark right section.
04:34All these buttons do is toggle sections of Xcode on and off. That's it.
04:41Unlike some other applications, in Xcode you don't rearrange or detach and drag
04:46and drop different panels from one area to another.
04:49The layout of Xcode is the layout of Xcode.
04:52The section that's on the left here stays on the left. You can choose to make it
04:56visible or not, but it stays on the left.
05:00And this left-hand section is called the navigator.
05:03The navigator is our way to navigate, to get around everything in and everything
05:08about the project, all the files, the settings, the configuration options.
05:12I can expand folders that I am looking at.
05:15And if I single-click on a file that can be edited, it will open up in that
05:20middle editor section.
05:21If I double-click one of these files, it will actually open up in a
05:25separate editor window.
05:27I typically use single-clicking all the time.
05:29Now this left section actually contains seven different navigators.
05:34You can move between them by clicking the buttons at the top here.
05:38Now there's not much to see yet now in the other navigators, but you'll be able
05:42to view things like issues or log messages using these different sections.
05:46And sometimes Xcode will switch you to a different navigator if useful.
05:51But you don't need to memorize all of them.
05:53You can hover over them to find out what they are.
05:56And note that the most important one of the seven navigators is the Project
06:00navigator, the first button, the one that looks like a folder.
06:04And a useful shortcut for this is Command+1.
06:07That will open the Project Navigator even if, for example, that left section is closed.
06:12I hit Command+1, we open right back up to this view. And it is a view not just of
06:18all the files in your project, but also of the project settings itself.
06:23Clicking the top icon underneath our different navigators will actually let me
06:28view the top-level settings of the project, not just one file in the project.
06:32And having that selected, we can say things like, what are the supported
06:36orientations for this application, what are my icons for the application?
06:41And this will come in very useful later.
06:43Now just as the left side can be turned on or off--and I might do that because
06:48I don't have a lot of screen real estate--the right-hand side can be turned on or off as well.
06:54I am going to just select a code file to make it a bit more obvious where the
06:57right-hand side is. Now this side contains two different sections, what are
07:03called Inspectors at the top and Libraries at the bottom.
07:08Now the arrangement of these things is not random.
07:11There is a point to how everything is grouped together.
07:14If we can think of the Navigator section as showing everything in the project
07:19and the Editor is showing the one thing that I'm working on, while the inspectors
07:23at the top of the right-hand section are context sensitive.
07:27Like many applications, they change based on the file I am working on or what I have selected.
07:32So as I select different files, you can see the Inspectors on the right-hand
07:37side actually change.
07:39If I'm working on a user interface file, they change even more significantly.
07:44Like the navigators on the left, you will find that the inspectors on the
07:48right-hand side have different options.
07:51There are several inspectors.
07:53You can mouse over the individual ones to find out what the inspectors are, and
07:57again, we'll come back to these.
07:59Now, sometimes you'll see six inspectors, such as when editing a user interface.
08:04Whereas if I have a code file selected, I might only see two.
08:08Again, don't worry about memorizing that.
08:11It will become familiar as you start to move through it.
08:14And last for right now, we've got the Libraries down at the bottom section, and
08:17we can actually move this up a little bit.
08:20The libraries are the simplest section, and these do not change based on what you
08:24have selected. So it doesn't matter what I'm clicking on, whether it's a code
08:28file or a user interface, we have the same four libraries available:
08:32File Template Library, Code Snippet Library, Object Library, and Media Library.
08:38These just contain collections of things you might want to add to your project,
08:42like having the library of user interface element so I could drag and drop, or
08:48a library of code snippets that I can drag and drop into my code files.
08:52That's the basic breakdown of the layout.
08:54We'll get more into it as we go through and start to create some code.
08:58Now Xcode, like any other application, has preferences, things you can customize
09:02about this app to make it work better for you.
09:04I am going to leave it pretty much as is, straight out of the box,
09:07but I will make two small changes.
09:09Now you don't have to do this, but you'll see why I'm going to.
09:11So from the Xcode menu I select Preferences, and I am going to do two things here:
09:17first jump to Fonts & Colors and then I'm going to change the theme to Presentation.
09:24You have a whole bunch of different options you can select from.
09:27I am selecting presentation to make our code a bit easier to read.
09:32And then in my Preferences panel over here on Text Editing, I'm also going to
09:37select Line Numbers so that we get the line numbers show in the Gutter here, and
09:42that will make it easier for me to explain which line of code I'm talking about.
09:46Closing this down and going into one of these code files, I can immediately see
09:50the like most modern IDEs, we get automatic indentation. We get color coding of
09:55the different pieces of syntax, showing the difference between comments and
09:59keywords and variables.
10:02We also get Code Sense, which is Xcode's auto-completion feature.
10:07If I start typing, for example, I will start typing the letters NSR, we will see
10:12this window starts to pop up and filter down and as I type more information, it's
10:18going to actually start to bring it even closer to what I want.
10:21I can move up and down with my cursor keys and select a different option and
10:25then hit Return to select it.
10:28That helps us a lot because Objective-C in general has a lot of very long names
10:33for its functions and its methods.
10:34Now, I don't actually need to use this piece of code at the moment so I am
10:39going to delete it.
10:39But I'll notice already that I have this exclamation mark popping up here on
10:43the left-hand side.
10:44That's because Xcode 4 will try to highlight issues with your code as you're
10:48typing it, and that's often a little bit quick, and you haven't even finished a
10:52line before it starts complaining about that line.
10:54But you will see that a lot.
10:56Now, of course, there's much more to this application.
10:58Xcode has options to connect to source control repositories and help you with
11:03debugging, and it has code snippets and ways to help you manage your projects.
11:06But this basic layout is enough to help us get going, because some of these other
11:10options really aren't worth bothering with until we've got a bit more code.
Collapse this transcript
Using the iOS Simulator
00:00The iOS Simulator can work as either an iPhone or an iPad, and is just a way to
00:06test our applications without having to copy all the files to a physical device.
00:10Now, there are some things that can only be tested with a real iPhone or iPad,
00:15so it doesn't remove the need for one during the process, but it's a very
00:19convenient thing to have, and we'll mostly be using the Simulator in this course.
00:23You can start up the iOS Simulator by itself, but usually you just let Xcode
00:28launch it when you need it. And Xcode will take care of copying over your
00:32application to the Simulator and starting it up.
00:35But there are a few things to know about this Simulator.
00:39Number one, it doesn't have a camera, and it doesn't just use, say, a camera on a
00:44laptop or a display.
00:45Now, this might not be a problem, but if your application needs to access the
00:49camera, well, it's something to be aware of.
00:51Now, remember, it is perfectly legitimate for an iOS device to not have a camera.
00:56For example, the third-generation iPod touch will run iOS 5 but does not have a camera.
01:01The first iPad does not have a camera.
01:04The next thing is we don't have a real accelerometer.
01:07That's the part of the iPhone that detects the position that it's being held in,
01:11and can even detect G force, whether it's being swung around or shaken.
01:15Again, that might not be important for your application, but if you have an
01:18app that needs to be controlled by tilting, you're going to need to use a real device.
01:22However, built into the iOS Simulator is the ability to change orientation.
01:28There is a Hardware menu where you can rotate the phone left and right and see
01:33if your application correctly shifts from one perspective to another.
01:37And you can even kick off a shake gesture. Though you don't see that being animated,
01:42you can respond to it.
01:43The Hardware menu is also where I can change this to an iPad or iPhone with a Retina display.
01:50And you can also do a couple of other things from this, such as toggle the
01:56in-call status bar, if you want to see how your application is going to look, if
02:01somebody phones while the app is in use. Just dismiss that.
02:05And you can also trigger simulated memory warnings.
02:08Other than that, it behaves quite like an iPhone or iPad, except for the fact
02:11that, as you can see, there are not a lot of applications installed.
02:15If I switch screens here, I've got my simple Hello World application, which will
02:20start up, but back on the main screen there is no mail application, no music
02:24app, no calendar, no camera.
02:26What's quite common is you'll end up with a lot of testing applications.
02:31If you want to delete them, you can do it the same way you would on a normal
02:34iPhone, which is, you hold down until the machine goes into the shaky mode, and
02:40you can just delete that application.
02:42Or alternatively, if you have quite a lot of them, what you can also do is go to
02:48the iOS Simulator menu and say Reset Content and Settings, to take it back to
02:54the original way that it was, just the basic applications.
02:57So while there are a few limitations and features, one thing to be aware of is
03:01this is not a substitute for real performance. checking on a real device. Because
03:06we are running the Simulator that's on the CPU on our laptop or our desktop and
03:10you're going to have different capabilities on the iPhone itself.
03:13It's very convenient.
03:15It's often quicker to boot up the Simulator to test an app rather than copy it
03:19to a device, and you'll be using it a lot as you write your iOS applications.
Collapse this transcript
3. Objective-C Refresher
Objective-C basics
00:00As I mentioned, this course does expect at least basic familiarity with reading
00:04and writing Objective-C, even if it's been a while.
00:07If you are coming from expert-level Java or C++ or C#, and you are thinking, how
00:12different can it be?
00:13Well, it is very different.
00:15If you have not seen Objective-C before, I highly suggest doing at least
00:19the first few chapters of the Objective-C Essential Training course, here at lynda.com.
00:24These next few movies are not intended to be enough if you are brand-new to the
00:28language. But here is a recap of the basics.
00:31Objective-C is a language that is not influenced by C, or inspired by C; it is
00:37the C programming language with extra pieces added to it, to make it an
00:41object-oriented language.
00:42So the core flow of the language, if statements, for and while loops, switch,
00:48case, break, return, int, float, basic operators, that's all straight C. I could
00:54copy and paste a bunch of C code from the 70s into an Objective-C program and
00:59expect it to compile without any changes.
01:02That's very different from languages like Java or JavaScript or C# that are just
01:07influenced by C. But why is that important? Well because it is the reason why
01:12Objective-C can look a little strange.
01:14You have this newer language that's built on top of an older language, and we
01:18need some way to indicate which parts are C and which are the newer Objective-C
01:22pieces. And we have clues by marking these new pieces.
01:26So you'll have a lot of @ signs and square brackets that you wouldn't find in
01:30regular, C because these are the added Objective-C pieces.
01:34A specific example might be exception handling.
01:37A lot of languages have keywords like "try" and "catch" and "finally," but straight C
01:42does not have these keywords.
01:44Objective-C does, but instead, you write @catch, @try, @finally.
01:51These Objective-C keywords are mixed in with the straight C keywords like "if"
01:55and "while" and "for," and there are other Objective-C keywords which we will see
02:00like @synthesize, @interface, @property to tell the compiler we want to do
02:05things that aren't allowed in regular C. And in the square brackets will see a lot of these.
02:10This use of square brackets is how we call methods in Objective-C.
02:14So almost all of these additions are to do with the object-orientation features
02:18of Objective-C, the ability to have classes and objects that straight C does not have.
02:24Let's take a look at a real Objective-C program.
Collapse this transcript
Objective-C structure
00:00I'm going to open up Xcode and create a very simple project.
00:04This time instead of selecting one that's an iOS application, I'm going to come
00:08down to the Mac OS X selection, select Application there, and choose Command Line tool.
00:13I'm going to make the simplest Objective-C program possible, an old-school
00:17command-line or console application with no user interface.
00:21So selecting Command Line tool, I'll click Next. I'll call this one BasicCode.
00:25And I want to make sure that my type is Foundation, not Core Foundation or C,
00:31but just Foundation. We'll talk about what that means in a minute.
00:35I'm going to leave Use Automatic Reference Counting checked, as we're going to
00:39do with every project in this course.
00:41Click Next and then we'll choose where to save it. I'm just going to save it
00:44out to my Desktop again. And we have a simple Objective-C command-line project.
00:50I've got several files over here in my Project Navigator, but only one that's
00:55important. We're looking for Objective-C, and we'll find it in .m files.
01:00We've got one here called main.m, and let's take a look at it.
01:04Well, from line 1 through 7 we have comments. They are of course C style. Two
01:08forward slashes makes the line of comment and Xcode makes it show up in green.
01:12On line 9 we have this #import, and that's pointing to the foundation
01:17framework header file.
01:18Now that doesn't cause anything to happen in our program, but it's telling the
01:22compiler that yes, this code that I'm about to write can use the foundation
01:27framework and anything inside it.
01:29Now frameworks are simply collections of prewritten code that have been bundled
01:32up and given a name, and the foundation framework is the most common Objective-C
01:37framework, and we always use it.
01:39Now next, to line 11. As in C, Java, C#, C++, to run an Objective-C program that
01:46might be thousands of lines across dozens or hundreds of files of Objective-C,
01:50it needs to know where to start.
01:52Objective-C expects somewhere in your code that there is a function called main, and
01:56that's where all Objective-C programs begin.
01:58Now if you're curious, yes, that is still the case with iOS projects, and
02:03there is a main.m file in all your iOS projects, although you typically won't
02:09ever need to touch it.
02:10It's considered a supporting file, not one you need to edit, because it
02:14already contains the code to stop the lifecycle of an iOS program, but yes,
02:18it always will be there.
02:20main of course is written lowercase. Objective-C is a case-sensitive language.
02:25Very important to remember if you're coming from a case-insensitive language.
02:29Now this first line on line 14 inside main, is @autoreleasepool,
02:35and that's an Objective-C keyword to do with memory management.
02:38We'll explore this more later on. For now, we can just let it pass.
02:41So, on line 17, we pretty much have the one line that actually does anything here.
02:46This is an output message using the function NSLog, which is part of that
02:51foundation framework we're linking to on line 9.
02:54The letters NS stand for next step and this is part of the next computer's
02:59legacy that's hugely impactful in Apple development.
03:02NS is one of the most common things you'll type in Objective-C, and it's always
03:07written in uppercase, as is the following letter.
03:10So we're going to write a Hello, World!
03:12string out to the console.
03:14In Objective-C, we don't just use double quotes, because that would make a C-
03:18style character array.
03:20Instead, we put an at sign before this, which turns this into an Objective-C-
03:25style NS string object. It's a true object with methods and properties we could
03:30access, instead of just an array of characters.
03:33Now Objective-C is not whitespace sensitive, so it doesn't really matter what
03:38kind of white space or tabs you put here, whatever makes it readable.
03:42The only place it does matter are of course spaces inside a string, which are impactful.
03:48I could go ahead and just run this directly. If you wanted to be a bit
03:52more specific about this, we could go to the Product menu and come down and say Build.
03:57Build is the term we use here that other languages might say compile. We are of
04:01course compiling and linking and creating an application here.
04:04I saw the message Build Succeeded.
04:06I can also see that in the little LED- style display up on the top of the toolbar
04:11here, and I could just go ahead and run this.
04:15We don't get an amazing amount of information; what I do get here is the third
04:19section that we can turn on or off an Xcode, which is this Debug area.
04:24I can toggle that on or off by this button on the toolbar.
04:27This itself, as we'll see, is useful for debugging information that's split into
04:32two main panes, and you can use the similar buttons here to decide which parts
04:36of it you want to actually show.
04:38So, just outputting the messages here, I can see that I've got my Hello, World!
04:43from the NSLog message. And this is the basic structure on an
04:47Objective-C program.
04:49Now that's as simple as it possibly gets, but we're not doing much with objects
04:54in this example, and we're in an object-oriented language, so that's up next.
Collapse this transcript
Creating variables
00:00Let's just recap basic variable creation.
00:03In Objective-C we create simple primitive variables as in many other languages.
00:08We use the data type--in this case I'll have int--and a space, then the name of the
00:14variable--I'll call it minutes--and then you can just use a semicolon to finish
00:17this off, or of course use the equals sign to actually give it a value while
00:22you're declaring it.
00:23I'll create a couple more integer variables here.
00:29Now as I'm typing, what you're probably seeing is over in the gutter section
00:33here, I've got these little pop-up warning messages and if I click any of them,
00:38it'll tell me what is the detecting, which in this case is its unused variable.
00:42Well, that is correct. I haven't actually had a chance to use it yet, so I'm
00:46going to ignore that warning for now, but it's always good practice to get into
00:50to figure out exactly what it's complaining about.
00:52Now we have the usual suspects: ints, floats, unsigned and signed. We have charge.
00:58We also have a Boolean variable type,
01:00although that's a little unusual. It's uppercase for BOOL. When we name it
01:06we typically use the Pascal casing or Camel casing in Objective-C, but the value
01:11of a Boolean variable is not true or false as it is in many other languages, but
01:16instead yes or no, and these must be written as all uppercase.
01:26We can of course create variables based on calculations of other variables and
01:31so on. And if we want to take some of these variables and output them in our log
01:36messages, we can use C-style format strings.
01:40What that means is we can construct a message, such as this one, where we have a
01:48placeholder format that represents a value that will be filled in at runtime.
01:52We can have percent sign I for an integer, percent sign f for a floating-point
01:56variable, percent sign c for single characters, percent sign at sign for objects, and so on.
02:02What I need to do is follow the closing quote of that string with a comma and
02:06then the variable that I want to fill in here, which in my case is minutes in a year.
02:11As I start typing, I get code sense come up. I select what I want hit Return.
02:16I'm just going to tuck the right- hand side out of the way here, so I can
02:19view this more easily.
02:21And the only thing it's now complaining about is line 20, that I'm declaring a
02:25Boolean variable, which I'm not using. That's what it's complaining about.
02:29So I could just comment that out.
02:31Warnings won't stop my program from compiling, it won't stop it from running,
02:35but it's always good practice to be aware of exactly any issue that's happening in your code.
02:40If I wanted to build this before I ran it, I can do this from the Product menu,
02:45or I can just select Command+B. I get Build Succeeded, no issues and then no
02:50surprise, I could run it either by pressing the button up here or hitting
02:53Command+R. Now I had manually hidden at the lower section all Xcode, so I'm going
02:59to manually turn it back on. And it saying here that yes, there are 52,560 minutes
03:05in a year, which sounds about right.
03:07Again very basic stuff; we're creating and using simple primitive variables. But
03:13objects are going to be a little different.
Collapse this transcript
Using pointers
00:00So there is a key difference when creating simple primitive variables as to when
00:04we're creating objects.
00:06In Objective-C, all objects are accessed using pointer types, using the asterisk
00:11when we're declaring the variables.
00:13If you want to explicitly make a variable that represents an object, even from
00:17a simple class like NSString, that variable is a pointer type. So we use that
00:22asterisk every single time that we make a variable that represents a pointer to an object.
00:27Now here is the key difference between needing one and not needing one.
00:31When you create a simple integer variable using, say, int highscore=100, the
00:37variable is holding that value directly.
00:40It holds 4 bytes, and it holds the value of that integer.
00:43However, when you create an object variable, the variable does not hold the object itself.
00:49It does not hold the contents of the object, in this case the word Hello;
00:52instead it holds an address, a reference, a pointer. That variable points to a
00:59different area of memory where that object exists.
01:02Now you don't need to know exactly what that address is--with Objective-C it
01:06doesn't matter--but you do need to know that that's what happening.
01:10So when declaring pointer variables, you can put the asterisk anywhere.
01:14It's most common to see it right before the name of the variable.
01:19But it's not part of the variable name.
01:21You could put it in between with spaces or even right by the class name itself.
01:26The asterisk is not part of the variable name.
01:28We're not making a variable called asterisk message. The variable is called
01:32message and it is a pointer to an NSString object.
01:36Now this is the way that most object- oriented languages work with pointers. Even
01:41languages like Java and C# work this way;
01:44they just hide the asterisk away.
01:46In Objective-C it's explicit.
01:48All objects are accessed using explicit pointer types.
01:52Now can this get a bit more involved?
01:54Well, like everything else in programming, of course.
01:56We can have pointers to pointers. We can de-reference pointer.
01:59We can arrays of pointers.
02:01We could find out the actual memory addressm though that's rarely necessary in Objective-C.
02:05If you new to explicitly working with pointers, do realize they're not likely to
02:10feel comfortable until you've made a bunch of them, created themm and used them.
Collapse this transcript
Sending messages and calling methods
00:00So we are in Objective-C, an object- oriented language, and most of the code that
00:04we are going to write or use will be contained inside classes. We will create
00:09objects based on those classes, and we will tell those objects to do things.
00:13We will call methods of those objects.
00:15If I were to show you a few of the classes that we have available to us, because
00:19Apple has written them already, that might include something like the
00:23AVAudioPlayer class.
00:25This is an existing class that has methods like play and pause and stop and the
00:30kind of things you can probably guess an audio player would have, and we can
00:33create an object of this class and call those methods.
00:36But even NSString, our basic string object in Objective-C, has plenty of methods.
00:42It has dozens, and if we have an NSString object, we have methods like
00:46lowercaseString and uppercaseString and hasPrefix and hasSuffix.
00:51We can do all sorts of things with that string object.
00:54And when it comes time to creating your own classes, we can write things, say,
00:57like a BankAccount class, and we could have methods like deposit and withdraw
01:01and open and close.
01:02So it's how we are describing what it is these classes can do.
01:06Now this of course is common object- oriented stuff, but the question is, well,
01:10how do we call these methods in Objective-C? Because that is a little different
01:15than most other languages.
01:16In most languages, you would call a method by using something called dot syntax.
01:21You'd use the name of the object, dot, then the name of the method, and then any
01:26parentheses that would say, does this method take any arguments in?
01:31This is not going to work in Objective-C.
01:34We don't use dot syntax in Objective-C to call methods;
01:37we use square brackets.
01:39Square brackets is one of those indicators to the compiler that this is
01:43Objective-C, not regular straight C.
01:46So in this case, we are sending a message here.
01:48We are sending the message some method to the object, myObject.
01:53It's all enclosed in square brackets, and there is no dot between the object name
01:57and the method name.
01:58Now some developers get really weirded out by the square brackets, but it is
02:02just a syntax change.
02:04It's a slight change. The concept is the same, but let's take it a little step
02:08further: What happens if this method returns a value?
02:12Well, if you are familiar with dot syntax, you'd expect to write something like this.
02:16You would have a receiving variable called result and set it equal to whatever
02:20comes back from myObject.someMethod.
02:22It's exactly the same in Objective-C.
02:25You just replace the dot syntax with the square brackets and call it that way.
02:30But if that method returned a value, this would work just fine.
02:34Now moving on one more step, what happens if you want to pass an argument into that method?
02:39So the method has been defined with parameters. We are passing arguments into it.
02:44While in dot syntax, you would typically put the argument inside the parentheses,
02:49Object.method and in parentheses the arguments. And the concept is the same in
02:55Objective-C, but instead of the parentheses we use a colon.
02:59So it's object name, space, method name, colon, argument, all within the square
03:05brackets, and that's how we pass an argument into that method.
03:08Now next up is where it gets a little bit more complex,
03:11if we have multiple arguments--because that is the first-place where it is quite
03:16different. And giving me analogy again of the dot syntax way, you'd pass in
03:21multiple arguments separated by commas inside the parentheses.
03:26Well, that's not going to work in Objective-C.
03:28The big difference in Objective-C is that if you have a method that takes
03:32multiple arguments, the method name becomes split apart into multiple pieces;
03:37the actual name of the method changes.
03:40So let me show you an example.
03:42This is a real method that's available in Objective-C.
03:45It is the method insertString atIndex.
03:49More properly, it's read as insertString:
03:52atIndex. And the way we would write it is we'd use the object name--in this case
03:57myObject--then the first part of the method name, which is insertString:,
04:01and the first parameter, then a space, then the second part of the method
04:05name, which is atIndex: and the second parameter.
04:09So the actual method name is different.
04:12Each argument represents a different piece of the method name.
04:15And what this leads to is something that Objective-C is notorious for,
04:19particularly when people are new to it, which is method names that are
04:22really, really long.
04:25Because what this means is any method name that takes multiple parameters has to
04:29be defined to have multiple parts to the name of it. And that leads us to, for
04:33example, a real method called replaceItemAtURL: withItemAtURL:
04:39backupItemName: options: resultingItemURL:
04:44error. And yes, that doesn't exactly roll off the tongue, and you will find in
04:48Objective-C and in some of the classes that Apple provide, there's ones they are
04:53even bigger than that.
04:54Now I am not going to even attempt to read this one.
04:56And the big benefit of this is even though it can give you a lot more code to
05:01read--and you can of course split the single method call across multiple lines to
05:06become more readable--well your code becomes more understandable in an actual
05:10program, because instead of a smaller method call where you are passing multiple
05:15parameters, all squeezed into one set of parentheses, but you don't really know
05:20what those parameters are, they are all named here in your code.
05:23It's obvious what they are, and that's one of the benefits of having a really
05:26long method names in Objective-C.
05:28And most of the developers I know that have spent some time with Objective-C,
05:32including myself, actually begin to prefer it this way, because while it makes
05:36for a longer writing of code and figuring out what those methods are, it makes
05:40for much more readable and maintainable code after the fact.
05:43Now the final piece here.
05:45Yes, we can have nested method calls, just as in dot syntax, where you could
05:50instead of passing in an argument directly, you could just put in a call to
05:55another function or method.
05:56Well, you can do the same thing in Objective-C. Instead of the standard
06:00Objective-C way where I have been using the argument after the colon, we can add
06:06another set of square brackets and nest one call inside another.
06:11The interior one will be evaluated first, in this case calling another method of
06:16another object, and the result of that will be fed into the exterior one, the
06:21myObject someMethod call.
06:23So while the syntax is different and can take a little bit of getting used to,
06:27the concepts are exactly the same as in other object-oriented languages.
Collapse this transcript
Creating objects
00:00NSString is an easy class to use when we are talking about the left-hand side of
00:05the equals sign. We are talking about creating the variable, the pointer that
00:08points to an object, but we haven't really talked about the other half.
00:12What actually happens when we create an object?
00:15Now here, I'm just using the Objective-C that means I want an NSString object
00:19with the world Hello in it, using that at sign in front of a double quotes, but
00:24usually there is a bit more to object creation than this.
00:27I am going to show the more typical way of doing it by creating an NSDate object.
00:32NSDate is another class defined in the foundation framework, and we use it a lot.
00:37Now to create an object in Objective-C, we have two explicit stages.
00:43The first stage is allocation, and what this means is Objective-C is going to go
00:48out to an area of memory and carve out a space big enough to hold this object.
00:53It does that when we call the alloc method of the NSDate class.
00:58And then it's returning the address in memory of that object, which is what
01:02this pointer variable myDate will hold.
01:05So I now have a myDate that represents a pointer to an NSDate object.
01:10And I can use that pointer to do the second part of creating an object, which is
01:15initialization, where it's going to go through the object, figure out what it's
01:20made of, and initialize variables internally.
01:22Now initialization could be really, really simple.
01:25It could be really complex.
01:27It depends on how complex the class definition is itself.
01:30But these are the two stages of actually having an object allocated and initialized.
01:35And because this is such a common thing to do, you typically don't see it spread
01:39across two lines because you don't have to.
01:42You can nest one inside the other.
01:45We have the internal call to the alloc method of the NSDate class, and that will
01:50return an instance of NSDate, and then we call init on that.
01:54And you'll see this all over the place,
01:56this general pattern of allocation and initialization: Class alloc init, Person
02:02alloc init, Dog alloc init, Customer alloc init.
02:05However, as with other languages, you don't always want to just create and
02:09initialize an object the same way; sometimes it's nice to pass in some
02:13information when it's being created.
02:15And that's what init is really for, because you can have custom initializers.
02:20Instead of just the straight init method, we often have a bunch of methods
02:24that start with init.
02:26So we might have a method called initWithName that we can pass in a name and
02:31make sure that when our class is allocated and initialized it's initialized with some data.
02:35An example of this for NSSting is that NSString has an init with contents of
02:41file, an init with contents of URL.
02:44We can just give it some contents to start initializing that string.
02:48The NSDate object has an init with the time interval since 1970 that just expects
02:53some seconds to be passed into it.
02:55There are often multiple ways to control the allocation and initialization of an
02:59object apart from just alloc init.
03:02Now, before iOS 5 came along in late 2011, creating your object was only half of the picture.
03:10You had your alloc and init, and then you would use that object, call methods on
03:16it, use it, pass it in and out of other objects,
03:19but you also had to be explicit about when you were finished with that object,
03:24so that the memory could be reused.
03:26You had to issue retain and release calls to say when you were done with that object.
03:32But with the arrival of Automatic Reference Counting in iOS 5, we don't have
03:38to worry about that.
03:39We'll talk about that next.
Collapse this transcript
Understanding Automatic Reference Counting (ARC)
00:00Automatic Reference Counting, or ARC, is a developer feature that was added with
00:05iOS 5 and Xcode 4.2 in the late 2011.
00:08And I'm going to talk about it here because in my original Objective-C course
00:12ARC did not yet exist, but here's the great thing about it:
00:16ARC is not yet another thing to think about, something else you have to learn;
00:21it's actually something less to think about,
00:23something less to worry about, because Automatic Reference Counting is not
00:27something you do as a developer.
00:29It's something the compiler does.
00:31You don't have to become an expert on ARC; you just need to know what it is so
00:36that you can let it make your life easier.
00:38ARC means you will write less code and the code that you won't have to write
00:43anymore is the tedious code you didn't want to write anyway.
00:46So Automatic Reference Counting is all about simplifying memory-management code.
00:51This is the most difficult, the most tedious, the largest cause of bugs in any
00:55Objective-C program.
00:56And if you learned Objective-C prior to ARC, you know we use reference
01:00counting in this language.
01:01We create objects using alloc and init or other variants of that.
01:06Those objects have a retain count on them.
01:09We use the object, and then we better take care of releasing that object once
01:14we're done so that memory can actually be reclaimed.
01:17Now with one object in three lines of code this is not a huge problem.
01:22But when you have dozens, hundreds, thousands of objects being created,
01:26manipulated, and passed around, you have to keep track of them all.
01:30You'd have to call retain on an object when you pass it around so they don't get
01:34released too soon and match that with a release call as soon as possible.
01:39You really have to envision every possible path through the logic of your app,
01:43so that the lifetime of your objects can be managed correctly.
01:46And this is very difficult to do.
01:48There is multiple ways it can go wrong, the two classics being that you create
01:53an object, you use it, and then you release it too soon.
01:57You have something referred to as a dangling pointer.
02:00Try and use that after you've released it and you can crash your program.
02:04On the other hand, if you create an object and you release too late, or you
02:09don't release at all,
02:10you are then leaking memory.
02:13And the bigger your apps get, the harder this gets.
02:16The memory-management code is the main reason why a lot of people give up
02:20learning Objective-C.
02:21It's the main reason apps take longer to develop or don't get finished at all.
02:25It's the main reason that finished apps crash, which itself is the main reason
02:28why apps are rejected from the App store.
02:30But with ARC, the question of when to retain and when to release pretty much goes away.
02:37You don't write release calls anymore.
02:40You don't write retain calls anymore.
02:42You don't think about it.
02:43You create your objects as usual with alloc and init, and you just use them. That's it.
02:49ARC takes care of cleaning things up. Because here's the thing:
02:53it's not that the idea of retain and release calls have disappeared--it hasn't--
02:58Objective-C still uses reference counting.
03:02The difference is you don't write the retain and release calls anymore, the compiler does.
03:08ARC takes the fact that compilers have gotten so good that anytime you build
03:12your project, the compiler--in this case LLVM 3.0, which is what Xcode uses
03:17behind the scenes--is able to scan through your code, determine all the
03:21possible pass through it, figure out where your objects are being used and
03:24where they're not, and synthesize the retain and release calls at the best
03:28point in the program.
03:29The compiler is effectively generating the same code you would write yourself if
03:34you were really, really good at writing memory-management code.
03:37Okay, you won't actually see these lines, so
03:39it doesn't physically change your source code files, but this is effectively
03:43what it's doing when you compile a project.
03:45So with ARC turned on--and yes, you can turn it off, but it is on for new
03:49projects by default in Xcode 4.2--
03:52you never need to write a release call again, never write a retain call again, or
03:56an auto-release call.
03:58You'll never have to create a dealloc method that's simply full of code to release
04:01all the instance variables in an object.
04:03That just goes away.
04:05Well, not only do you not write this code, with ARC turned on, you can't write this code.
04:11You try and write a simple release call and the compiler will reject it and
04:16make you take it out.
04:18So for most existing iOS developers, learning ARC is simply learning what
04:23you don't do anymore.
04:25And in fact you could take what I've told you in the past few minutes and just
04:26make a new project and run with it; you're good to go. That's it.
04:31Okay, there are a few other pieces worth knowing.
04:35Later in the course, I'm going to talk about some extra things about ARC that
04:36might be useful and some gotchas to know about, but you now know the impact
04:42of day-to-day use of ARC, which is pretty much, don't worry about these retain and release calls.
04:45Create your objects, use them, you're done.
04:48And I find the best thing about ARC is that it lets you concentrate your mental
04:52effort on your actual problem, on the interesting stuff about your app, instead of
04:56the headaches of my memory management.
04:58ARC is really good at this, and you should be using it in every Xcode project
05:03you ever create from now on.
Collapse this transcript
Using existing classes
00:00One of the challenges when you're still fairly new to Xcode and to Objective-C
00:04is finding out what's available, finding the right classes, finding the methods.
00:09Let's take a look at how.
00:11I'm going to go ahead and just create another simple Xcode project.
00:14This will be a Mac OS X application, and again a command-line tool.
00:18I'll call it ExampleClasses, and I'll make sure that it's a type of foundation,
00:23and that yes, we Use Automatic Reference Counting.
00:26Clicking Next I'll just save it to my Desktop and create it.
00:30Now we've only got one Objective-C file over here, main.m, so I'll select that
00:35because here's where we can write some code.
00:37Now we've already worked with things like NSStrings and NSDates, and hopefully
00:41quite a few more, but if I hadn't done anything with them, how would I find
00:45information about this?
00:46Well, we've already seen that as we start to type,
00:48we've got CodeSense,
00:49this automatic code completion that helps me find classes and it helps me
00:54find the different names.
00:56And it is a good thing, particularly if you don't remember the case sensitivity
01:00as CodeSense doesn't care.
01:01I can start typing another S and an S, now I'm actually typing lowercase, but
01:06it's showing me whatever matches. And it will correct it if, for example, I then
01:10type a T and an R and an I, and yes, NSString is what I want.
01:15I hit Return and I have the correct casing for that.
01:17I'm going to create something very simple here.
01:23Because I'm not actually interested in the contents of the string object. I'm
01:28just interested in the fact I have a string object at all, and I want to find
01:32out what it is and what it can do.
01:35So if I want to find out what's available to me I have two options.
01:38One is if I have the Utility section on the right-hand side open--and I can
01:43just toggle that on and off over here-- that if I click anywhere in the class
01:46name NSString and I have the wavy lines selected up here, this is the Quick Help section.
01:52And it will show me an introductory paragraph where it's declared, point me
01:56to the NSString Class Reference.
01:58I've got point just to the String Programming Guide and so on.
02:02I mean you want to get comfortable with looking up class references, so I'm
02:05going to click NSString Class Reference.
02:08It's going to open up this other window of Xcode, the Organizer window, which
02:12is actually taking me to the Documentation section and to the NSString Class
02:17Reference, and there is a lot of information when you look in the Reference library.
02:21But what we can do is start to come down here, start to read about the
02:25string object, understanding characters, and sub-classing notes, and all sorts of stuff.
02:30But what we're really probably mostly interested in are the different tasks we can do.
02:34In Creating and Initializing Strings, I can see that I have options for Creating
02:39and Initializing a String from a File, Creating and Initializing a String from a
02:43URL, Getting the Length of a String, Writing to a File or a URL. There is whole
02:48bunch of stuff going on here.
02:50In any one of them I can take a look, say, in the Changing Case section and find
02:55something like this Lowercase String and click that to find a bit more about
02:59that particular method.
03:00It tells me it's a method called lowercaseString that will return a pointer
03:06to an NSString object, and the dash at the start of it is telling me that
03:10this is an instance method.
03:11It needs an instance of the NSString object to work on, which is what I have.
03:16So what else could we do?
03:17Well, let's say we are working with a different kind of object, maybe one we're
03:20not so familiar with like, NSDate.
03:23Also notice as I'm typing here that I have a bunch of different options
03:27in different letters in the CodeSense we have Ks and Ts and Vs and a C,
03:32which represents a class.
03:34So NSDate, this is fine.
03:36It represents a class.
03:37We're making an object, so I need a pointer.
03:39I'll just call it myDate.
03:41Now I'm thinking well, now maybe I don't know what to do, because I can't just
03:45create a date and use say that @ sign and the string. Maybe I don't know how to create a date.
03:50So again I could select this by selecting NSDate and over here in Quick Help,
03:56I can see some more information. But let's say Quick Help isn't open.
03:59Another option I can do, and I'm very fond of this one is holding down my Option
04:04key on the keyboard.
04:05I can hover over different class names, and you'll see it turned into a hand
04:09symbol with a question mark.
04:11I can click that and get this little pop- up of a NSDate, introductory paragraph,
04:16where it's declared, Class Reference, Date and Time Programming Guide. Again the
04:21Class Reference is what I immediately need.
04:24Coming down, there's a lot of information about it.
04:26What I'm really most interesting in is the tasks, Creating and Initializing Date Objects.
04:31I have several options here, but the first one is just Date, so I'll click
04:35that and take a look.
04:36It says this Creates and returns a new date set to the current date and time.
04:41That looks about right, and in fact it even gives me a little code sample here
04:45that I could highlight and copy.
04:47By going back up a little bit, notice that all of these methods begin with
04:51either a Plus sign or a Minus sign.
04:54Now if you coming from something like C# or Java, you'll be forgiven for
04:58thinking that this might mean public or private, but it doesn't.
05:01And the Minus sign, which is much more common with most classes, means these
05:06are instance methods.
05:08You will call these methods using an instance of a class, an object which
05:12already needs to have been created.
05:13Whereas the Plus sign means that these are class methods, so I use the name of
05:19the class, like NSDate to call this.
05:22So, for example, in this case, pasting any code that I've just copied, we're
05:26calling the date method of the NSDate class.
05:30This is a class-level method.
05:33But as I've just created an instance, I could now use the instance to call any
05:38of the instance-level methods, such as dateWithCalendarFormat. And CodeSense of
05:43course will help me fill this out with the different parameters that this method needs.
05:48Now I don't actually need to do that right now, so I'm just going to go
05:50ahead and delete it.
05:52But of course there are other ways to go through documentation and get help.
05:56These are very too quick, very easy ways to find the methods and the tasks and
06:01the classes that are available to you using Objective-C.
Collapse this transcript
Creating custom classes and methods
00:00In Objective-C, classes are written in two separate sections, an interface
00:06and an implementation.
00:07The interface is the simplest part.
00:09This is the public face that the class is presenting to the world, or at least to
00:14other parts of your application.
00:16It's announcing what this class is promising to do, what methods, what
00:20properties are available.
00:22It doesn't say how any of them are done;
00:24it just says what's available.
00:26Now the second part, the implementation, that's where the work is done.
00:30The implementation must live up to the promises of the interface.
00:34The implementation is the main code of the class.
00:37So here is how we do it.
00:39I am just going to jump over to Xcode, where I'm going to make another very basic
00:43Command Line tool application, just call this CustomClasses, and make sure to
00:49select a foundation type and then Automatic Reference Counting is on.
00:53I will save this again to my desktop.
00:56So I want to create a new class, and there is a couple of different ways to
01:01do this, but the most basic is going up to the File menu in Xcode and saying New File.
01:06Just as we have templates for projects, we have templates for files as well, all
01:12sorts of different ones, but what I'm interested in here is Objective-C class,
01:17and I'm selecting that in the Cocoa section under Mac OS X.
01:21I will click Next, and it's going to ask, what do you want to call this?
01:25Now classes should begin as a rule with an uppercase letter.
01:28It's one of the few things that does begin with an uppercase letter in Objective-C.
01:32So I am going to create a new class called Player.
01:34Now this dropdown is asking, what is this class a subclass of.
01:39Depending on which object-oriented language you are used to, you might be
01:43thinking of this as your parent class or your base class.
01:46But what we are asking is is there an existing class out there that this new
01:50one should be based on?
01:52And we have a few choices, but yes, we are always going to inherit from at
01:56least one other class, and the default one that we are going to inherit from is NSObject.
02:00In fact, every class you are ever going to work with within Objective-C ends up
02:05inheriting from NSObject.
02:07It's the base class, the super class, the parent at the top of the tree, the
02:12very top class, and it will work just fine for us.
02:15So I click Next, and it's going to ask, do I get added to this project folder? Yes, that's fine.
02:21So I will just Create, and it creates two classes for me that I can see over
02:27here in the Project Navigator, a .h and a .m file.
02:31Now classes don't actually have to be done in separate .h and .m files.
02:35They can be combined, but this is typical.
02:38The .h, or header file, is your interface. The .m is your implementation.
02:44And in fact, if I switch between the two, you can see that the .h is using the
02:48Objective-C keyword interface and the .m file is using implementation.
02:54As in other object-oriented languages, every class we make is really defining
02:58two pieces: behavior and data, methods and properties.
03:02So I need to describe, say, what it is that this class is going to do, describing
03:07the methods of this class.
03:09And I will do this in the interface here.
03:11Let's say I just want to create a method with the name of simpleMethod.
03:16I then have to say, does this method take any parameters and does it return a value?
03:21Well, to say that this method returns void, meaning returns nothing, I'm going
03:26to use parentheses in front of it and just say void.
03:29And I do that at the start of the method name.
03:32If I wanted this method to be defined with parameters, I'd put a colon in here
03:37and start to describe them. I don't.
03:39I am going to say this method takes no parameters and returns nothing,
03:42so I am just going to put a semicolon here.
03:45Now if you remember when we looked at some of the class reference libraries, we
03:48would see either a Plus sign or a Minus sign that says
03:51this method is for the instance, or it's a method for the entire class, and
03:55we do this here too.
03:57So I am going to add the Minus sign here.
03:59Now it's not whitespace-sensitive.
04:01I could put spaces in between there, but this is the default way you will see this written.
04:06So I am going to say here, this is an instance method called simpleMethod that
04:11returns void and takes no parameters, which is why I am just finishing the line
04:16off with a semicolon.
04:17A little bit later on we'll see how to define more complicated methods.
04:21Now you might be thinking, where is the opening and closing curly brace?
04:24Where is all the functionality?
04:26But again, we don't do any of that inside the interface part of this class.
04:31All we are saying is this method should exist.
04:35Other code can now look at this interface and say, okay, you have a Player
04:40class and it has a method called simpleMethod that takes no parameters and
04:45returns void, okay.
04:46Now what will happen here is if I save this and then hit Command+B to build
04:51this application, it's going to succeed technically, but it'll point out there
04:56is an issue with it.
04:57I am using the Issues section of the Navigator, which is the middle section with
05:00the exclamation mark.
05:01There is that semantic issue, an incomplete implementation, basically letting me
05:07know that my interface said I had a method called simpleMethod, but my
05:12implementation doesn't actually do it, so I need to.
05:16Now there are multiple ways to be in this file. Of course, we can get to it just
05:19by single clicking in the Project Navigator.
05:22Another option that we could use, if I had enough screen real estate, is with
05:26either of them selected, I could come up to the toolbar and click the button to
05:30say Show the Assistant editor.
05:33Selecting that, I am just going to turn off the Utilities panel to get a bit
05:38more screen real estate.
05:39This editor gives us two views of complementary classes.
05:43So if I have the .h file selected, it will also show me the .m. We can actually
05:47switch them the other way around as well.
05:49But if you have a large monitor, it's a good way to get both the interface and
05:53the implementation onscreen at the same time.
05:56So I just want to prove that this works.
05:57I am going to go ahead and provide the implementation for this, so I am going to
06:02match the signature that was in my interface, although this time around I do
06:07have to have the opening and closing curly braces because I have to provide an
06:11implementation for this method.
06:13I am just going to put in a very straightforward NSLog message here.
06:21Now if I were to save and build this, we would see Build Succeeded, no issues,
06:25no semantic problems.
06:27Well, let's prove that this works.
06:29I have created a new class called Player. I now want to use it.
06:32I jump over to main.m and I am going to write some code to create it here.
06:37Well, I know how to make an NSString, so let's try and see if it's the same
06:41thing for the Player object.
06:43And it's actually going to have a problem here.
06:45It doesn't know where the Player class is defined.
06:48We get access to things like NSStrings and NSDates because we are importing the
06:52foundation framework header files.
06:55I also need to have an import statement here for that new Player class that I did.
07:02Now if my class is in my own project, as opposed to one of the system ones, I
07:06don't use the Less Than sign.
07:08I just use the double quotes.
07:10So here I am going to start to type Player and even as you can see, it's pulling
07:13it up for me. I will just hit Return and we are importing the header file of the Player Class.
07:19Now I should be able to create an instance here.
07:22I will create a Player called bob = and we are just going to use this standard
07:27way of doing it, which is Player alloc,init.
07:29Now although I have the Assistant editor opened here, there is no actual
07:34assistant counterpart file, so I will just switch back to the standard
07:37editor and see this.
07:39And you might be wondering, where do I have the Player alloc and
07:42init functionality from?
07:43Well, that's all coming because of NSObject.
07:45I am inheriting from that superclass, so I automatically have that information.
07:50The only thing it's complaining about right now is that I am instantiating a new
07:54object and I am never using it. So I better use it.
07:57Use the name of the object and then as I start typing, I should see my defined
08:03methods appear. In this case, there is only one, simpleMethod.
08:07Hit Return, close the square bracket, semicolon to end the line, save and build,
08:12and let's run this and check that it works.
08:18Zoom out so I can see my full output, and I get my CustomClasses, Yes, this method works!
08:23So it seems to be working just fine.
08:25So this is a super-simple class being defined here, but most classes don't just
08:31contain behavior; they are going to contain data.
08:34So let's see next how to do that.
Collapse this transcript
Creating properties
00:00So what if we want to add a couple of pieces of information to our Player class,
00:04so that every instance we create of this class has its own set of data?
00:08I am going just switch to the interface by itself and just put on the standard
00:13editor so I have a bit more space here.
00:15Now in previous years the way we would describe the data in Objective-C classes
00:20is to define instance variables or ivars, and these are just variable
00:24definitions that are wrapped in a pair of braces inside the interface but
00:30outside where you have declared the methods.
00:32And you just write pretty normal variable declarations.
00:35Let's say we have an integer called age, or I could have objects to. I will have
00:40an NSString pointer called name and you just start to fill out your instance
00:45variables like this.
00:46But in Objective-C, these aren't accessible from outside the class.
00:50So if you wanted another part of your program to be able to reach in and either
00:55read a value or change a value. You would have to start wrapping these up in
00:59Accessor methods, writing one getter method and a separate setter method for
01:03every single instance variable.
01:04Now this is kind of tedious and it's pretty prone to errors.
01:07So a few years ago the concept of properties was introduced with Objective-C 2.0.
01:13Properties can generate, or synthesize is the term we use, these getter and setter
01:18methods, and allows access to these ivars from outside of this class.
01:23So instead of writing separate getter and setter method declarations here, I
01:28would say @ sign and I'd use the word property.
01:31I would say what kind of property this is, what is the type.
01:34In this case, it's an int and call it age. That's it.
01:39And there is one important piece, which I need to match this @property in my
01:44interface with an equivalent synthesize statement in my implementation.
01:49So let me quickly just open up the Assistant Editor, so I've got my interface on
01:53the left and my implementation on the right, and in here I am going to add,
01:58inside implementation--
01:59I usually put them at the top-- synthesize and give it a name.
02:03Well, what's the name of it? It was age.
02:05Save that, Build, Build Succeeded, no issues.
02:10So the property statement in my interface matches the synthesize statement in my implementation.
02:16Now here's the thing.
02:18While properties started off being used together with instance variables because
02:22everybody was used to writing these ivars,
02:24it's actually kind of redundant to have both, because the information that I
02:29provide here to define a property is enough to allow it not just to synthesize
02:34the getter and setter methods, but it's enough to allow it to synthesize the
02:38instance variable as well.
02:39So in the last couple of years the shift has actually been to move away from
02:43bothering with explicitly defined instance variables and just use properties,
02:47and in fact, that's what we are using in this course.
02:50So I'm going to add another property that represents the name, so we have the word property.
02:55This will be an NSString *name. Bery similar to the declaration here, but I
03:02don't need to do this anymore.
03:04I'm going to remove my instance variables and because of that, I'm also going
03:08to remove the braces.
03:10I don't need that, and it becomes a much more straightforward interface.
03:13We have got two properties and one method right now.
03:17There is one extra thing I am going to add. When we are working with objects for
03:21properties you typically add some attributes, and that's after the word property
03:26surrounded in parentheses. And I'm going to add these two: nonatomic, strong.
03:34So what is this?
03:35Well, when defining properties that are objects, there is usually a bit more to it.
03:40And nonatomic here means that I'm not worried about multiple threads trying to
03:44access this object at the same time, and it means that Objective-C doesn't have
03:49to synthesize thread-safe code for my getters and setters.
03:52Now if I'd said atomic or just actually left this out because atomic is
03:57actually the default, it would generate that thread-safe code.
04:01So nonatomic is actually a little faster, and it's much more common to see in
04:06iOS, and pretty much this is a habit for me to write nonatomic unless I know other ones.
04:11Strong, on the other hand, is one of the few changes that comes along with
04:15Automatic Reference Counting.
04:17And what strong is doing here is telling the compiler that I want this Player
04:22class to hold a strong reference to this name property. We are saying yes.
04:27We own it. It's ours.
04:29As long as a Player object exists, the string object inside it that holds the
04:34name of the Player object should also exist.
04:36That's pretty typical for this kind of data, for this kind of property.
04:40Now before ARC, it was quite common to see the word retain being used here.
04:45But strong is more usual now that we have ARC, and in some circumstances you can
04:49use the word weak, but that comes later.
04:52Now the final step here, what it's still complaining about, is I am not
04:57synthesizing this property in my implementation.
05:00I can do that on another line, but you can also just synthesize multiple
05:05properties by separating them with a comma.
05:08So synthesize age, name.
05:11Save that. Command+B to build it.
05:13Build Succeeded, no issues.
05:15So these are my classes. Let's go ahead and use them.
05:18I am going to jump across to main.m and open up the regular Standard Editor.
05:23Here is where I had earlier created an instance of this class and called a
05:27method on it, but what I should now have is new synthesize methods for getting and
05:33setting the age and name of that object.
05:36Now I mentioned that Properties will generate two methods, a getter and a
05:40setter, and these methods are generated with different names, which may strike
05:43you as unusual, depending on the language you are coming from.
05:46The getter method by default has the same name as the property.
05:51So I should be able to use something like name.
05:53We can actually see here there is a name that returns a string.
05:57However, the setter method is different.
05:59It has the word set in front of it.
06:02And notice here with CodeSense, I actually have two ones here, setAge and
06:07setName, and these both are the synthesized setters for my properties in my custom class.
06:13So I am going to bob setAge:
06:1554, bob setName, and this takes an NSString.
06:24We can just pass in an NSString literal object using @", and we are using
06:33those synthesized setter methods.
06:35And if I wanted to prove at least one of them was working, we could write on an NSLog message
06:41that Bob's age is--we use a placeholder for where we are going to put the age
06:49and that is an integer, so I will use the %i placeholder comma, and I need to use
06:53now the getter method to go and grab that age. It's a method.
06:57We are going to use the square brackets.
07:00The object we are working with was bob and the method just has the same name as
07:05the property, which is age.
07:07So it's not getAge and setAge.
07:09It's age and setAge.
07:11Don't need that second NSLog, so I will just comment that out.
07:15Save this and build it and go ahead and run this.
07:19Drag that up a little bit and we can see, yes, Bob's age is 54, so we're successfully
07:26both setting and getting information using synthesize properties.
07:31A one last note here: along with the @property keyword, Objective-C 2.0 added
07:37something called dot syntax.
07:39Now this is a really common way to access this kind of information in other languages.
07:44What it means is instead of saying bob age inside the square brackets, I could
07:50say bob.age, and it also works for the setter.
07:55Instead of using this format where we have bob setAge: 54,
08:02I could instead say, bob.age = 54.
08:06And with dot syntax we don't use the word set.
08:11Save that, run it again, and we can see that it still works.
08:15If you are coming from a language like C# or Java, this may look great to you.
08:19This is a much more familiar way for most people.
08:22However, while I find dot syntax to be a nice little addition, in the rest of
08:27the course I am going to be going back to using the standard Objective-C square-
08:33bracket ways of accessing things, whether that's a setter or a getter.
08:38There are a couple reasons for this, and it's not that I dislike dot syntax.
08:43I am perfectly fond of it in other languages, but in Objective-C, I like to use
08:48square brackets because then I don't have to stop and think about whether I
08:52can use dot syntax in a particular place, because it does only work for
08:58synthesize properties.
08:59You can't use this dot syntax for method calls, but square brackets works for everything.
09:05So it keeps me conscious that I am in Objective-C and I stay with that one.
09:09It's completely up to you of course.
09:11There is no impact performance-wise on whether or not you use dot syntax
09:15for synthesize properties or square brackets, but I rarely use dot syntax in Objective-C.
09:21Okay, crash course over.
09:23We are going to of course see a lot more Objective-C, but we were going to
09:27see that along the way.
09:28Let's get back to some iOS.
Collapse this transcript
4. Core iOS Project Skills
Using the different iOS project types
00:00So let's get back to actually creating some iOS applications.
00:04As we've seen when I make a new project in Xcode, I have several iOS choices, as
00:09long as I have the correct area selected on the left-hand side.
00:12Because I have iOS Application, I do also have Framework & Library, which would let
00:18us create shared libraries of code, which we're not doing in this course, and
00:21another section, which lets us make a completely empty project.
00:25But I don't want that either.
00:27I don't want the raw simplicity of a command-line tool anymore.
00:31Now we want some provided code. We want a structure.
00:35So we're going to work with these iOS application project types.
00:39There are seven options available for us here.
00:41I'm going to talk just briefly about what each of them mean.
00:44Now this first one here, if you've used your iPhone or iPad for more than about
00:48a day you will have used a master-detail application.
00:52It's a classic iOS application style.
00:55Many built-in apps on the iPhone or iPad use this, like the Settings application
01:01and the Mail application.
01:02They all use this master-detail structure.
01:05It's the ones where screens will scroll from the left to the right as you drill
01:09down into different parts.
01:10Sometimes it's one level, sometimes it's multiple levels.
01:13And use the bar at the top to navigate back up the stack.
01:17Now with the master-detail application on the iPhone we switch between multiple
01:22screens, whereas on the iPad you often have what's called a split view where we
01:26can keep two sections on screen at the same time.
01:28Now this project template will actually for both.
01:33Next, we have the OpenGL Game template.
01:36This is the one that has the icon that looks like the icon for the Game Center
01:40on an iPhone, and we're not going to touch this one in this course.
01:43This is using OpenGL, a graphical library, which really is its own skill set for
01:48developing games and anything that's really heavy on graphics.
01:51So we'll leave this one alone and move on to the next one.
01:54This is the page-based application. We'll see this later.
01:58But as you might guess from the icon, what this allows us to do is switch between
02:02multiple screens but instead of the scrolling left to right with a master-detail
02:07we're using this animated page flip, and it takes care of doing that for us.
02:15The fourth template type is the Single View Application.
02:18This is a very common one to use.
02:20I've hold it the Goldilocks of iPhone project types.
02:22It's not too complex, not too simple.
02:25It doesn't enforce something like a master-detail structure or a page flip, but
02:29it's enough structure to be considered a complete app.
02:32It's a single view, which means it gives us a screen of our user interface.
02:36One blank canvas. We can come along and add our stuff to it.
02:40Next we have the Tabbed Application.
02:42This is another classic iOS model.
02:46It's the one that has the tab bar down at the bottom that allows us to switch
02:51between different sections of the application.
02:53This can be divided into two, sometimes three, four, or even five options.
02:57You shouldn't go beyond the five on an iPhone because it's tough to use if you do.
03:01Many applications actually combine both this tab bar idea and the
03:05master-detail view.
03:07Things like the iTunes app and the music app will do this.
03:12Next to last is the Utility Application template.
03:15This really just has two views: a main view and a flipside view.
03:20Things like the built-in Stocks application and the Weather app used this model.
03:26The main view is the main screen of your application, whatever that may be.
03:30And then you usually have a little information icon button towards the
03:34bottom-right with a little dotted i, and when you click it, it will handle
03:38flipping the screen to another view, very often used for the settings of the
03:42application. And you just flip back and forth and the flip is animated between
03:46the two for you, and that's the Utility Application.
03:49And the final one is the Empty Application.
03:51Now this isn't completely empty.
03:54This template still provides the necessary code to launch an iPhone app, but
03:58nothing more than that essential code, not even a single screen for basic user
04:02interface, and you'd have to provide all that before this app would work.
04:06Now this Empty template can be useful later on, after you're familiar with
04:11everything that's needed in the iOS application.
04:13But when you're first learning it, it's the other project types that give us
04:17more of a structure we can immediately use.
04:20We're going to see the Utility Application, the Tabbed Application, and the
04:23Master-Detail Application a little later.
04:25But the issue with these right now is that until you've done a couple of simpler
04:29projects, what Apple will immediately provide for you with these project types is
04:33a bit too complex, and it's not going to make a whole lot of sense until we've
04:37done some simple application types.
04:39So we're going to concentrate, just for a little while, on the single-view
04:42application and talk about this one before we go back to the other ones.
Collapse this transcript
Using the Model-View-Controller (MVC) design pattern
00:00MVC, or Model/View/Controller is a fundamental part of iOS development.
00:05Now this isn't just for iOS.
00:07MVC is a software design patent, meaning it's an idea, and it has been around for
00:12a long time, since the late 70s.
00:13You can do MVC with Java, you can do it with C#, you can do it for the web,
00:17and you can do it for desktop applications,
00:20but the core of MVC, it needs the objects that represent your data and the
00:24objects that represent your user interface are kept apart.
00:27You should be able to change one without affecting the other.
00:31So the word model in MVC represents your data, your information, the stuff your
00:36app needs to store and manipulate objects that represent contacts in the
00:41contacts app or emails in the mail application.
00:44But model objects do not define a user interface.
00:48They don't say whether they should show up with a text field or a button or what
00:51font they use. That doesn't matter, because on the other side of things you have
00:55View objects. These are your user interface, what the user actually sees.
01:00Buttons and sliders and text fields, these are all view objects, and they can
01:05be generic and reused.
01:07A text field should know how to draw itself onscreen.
01:10It should know if it's been tapped on or edited, but it wouldn't do the job of
01:14retrieving or storing or processing any data; that would be the model's job.
01:20So these two things are very separate, and between them we have the controller.
01:24The controller is the glue that hooks one side to the other.
01:27The controller talks to view, the controller talks to the model, but the model
01:32and the view don't talk directly to each other.
01:35And the idea with pure MVC is that every object in your program would fall into
01:40one of three roles, either model, view, or controller.
01:43That doesn't mean you only have three objects, you could have hundreds, but each
01:47one is clearly model or view or controller.
01:51And in practice, you don't always create perfectly clean and independent objects.
01:56In iOS the view and controller are more tightly connected and the core building
02:01block in iOS is creating something called a ViewController class, which as it
02:05might sound, wants to claim a little bit of both view and controller. But as
02:10you'll see, even if you create these together, there is still a separation between them.
02:15The Controller side of things is an Objective-C header and implementation
02:19files are .h and .m file.
02:21And the user interface view objects are in a .xib file, and that's the one that
02:26gives us the visual user interface builder.
02:29But one of the things you do have to define very well is the
02:32relationship between them.
02:34It's not automatic.
02:35Let me show you what I mean.
02:37Let's say we've built a simple user interface in Xcode, and we've dragged on a
02:43text field and a button and a label.
02:47Now these are all considered view objects, and we have to define very
02:51specifically the connections between these view objects in our interface file,
02:56and the controller code, which will be in a .h and .m file.
03:01You can't do what you might be able to do in other environments, which is drag on
03:05a button, double-click it, and write your code.
03:08It doesn't work that way here.
03:10We have to look at each view object and think about what kind of connection it
03:14needs to our controller code.
03:16So, for example, if we have a button here, we want this button to cause a method
03:21to be run in the controller code.
03:23Well, we need to define that button as causing an action in the controller.
03:28On the flip side of that, we have to define our text field as being what's called an outlet.
03:33We want to reach from our controller code into the text field and grab
03:39the contents of it.
03:40We also want to be able to reach from our controller code into, say, a label, so
03:45that would also be considered an outlet.
03:47So when you're building your applications, you're defining very
03:50specifically actions where a view object triggers a method in the
03:55controller, and then defining outlets where something in the controller needs
04:00to affect the view and reach into that.
04:02Now some elements can be both actions and outlets, but
04:06you'll need to build a lot of these connections in your iOS code, so let's
04:10see an example of this in practice.
Collapse this transcript
Creating basic interaction
00:00Let's get some real interaction happening between our user interface and our code.
00:05I am going to create a new project in Xcode.
00:07It will be an iOS single-view application.
00:10I will just call this BasicInteraction, make sure its Device Family of iPhone,
00:17and it's only using Automatic Reference Counting.
00:19Click Next and I will save it on my desktop.
00:23What I am really interested in here are three files that Xcode has created for
00:27me that represent one complete ViewController, both parts of it: the view that
00:33we'll see when the application loads and the controller code behind it.
00:38Now it's made of one Objective-C class called ViewController.h and
00:42ViewController.m for the interface and implementation, and one user
00:47interface file, the .xib file.
00:50Now you will hear these referred to as ZIP files, which kind of makes sense for
00:54.xib, but also sometimes as a NIB files, which might not.
00:59And that's because until a few years ago the file extension for these UI files
01:03was .nib, which stood for the Next Step Interface Builder.
01:08We used to have to use a separate program called Interface Builder to work with
01:12these files, and that was to up actually until Xcode 4 when Interface Builder was
01:17integrated into Xcode.
01:19Now they have been called .xib files for a few years, but some developers
01:24will still talk about the nib and adding things to the nib and customizing the NIB file.
01:29And that's what I'm going to do right now.
01:31So with that selected, we should see it in our editor.
01:34And I'm going to make sure that I have my Object Library open, which I can get
01:39from the View Utilities menu.
01:41I know it is open, but we have got it there.
01:43I am going to drag three very simple user interface elements over.
01:47This is a Label and a Text Field and a Round Rect Button.
01:52I am going to put the Text Field up at the top.
01:55You notice as I drag these around, we get the little helper guidelines.
01:59When any of them are selected, I also have the grab handles I can use to
02:03drag this a little wider.
02:04I will do the same with the Label, position it to the left and drag it to full width.
02:11And I will use the button and use the guideline to put it somewhere in the middle.
02:16I don't like the default value of Label, so I can just double-click that and hit
02:20Delete to clear it out.
02:22And also, I can double-click the button to put in, say, a simple word like
02:27touch. So a text field, a label, and a button.
02:32Not the most remarkably impressive user interface, but it's something that will
02:37support some interaction.
02:39People can tap the text field.
02:41They can type something in.
02:42They can touch the button.
02:43I can take that value and change the contents of the label.
02:48But how do I do that?
02:50Well, we have to now be very explicit about how exactly these user interface
02:54elements connect to our code files.
02:57We have to say what do we want the relationship to be between the text field and
03:01our code, and the label and our code, and the button and our code?
03:05Well, with the button, for example, we want to touch this and have a method occur.
03:10The phrase we use is we want an action to happen.
03:14We are driving some behavior in the code from our user interface.
03:19On the flipside, at some point, I want to write some code that actually can
03:23change the value of a label or look at the value of a text field.
03:28In that case, that's being driven from the code, and those would be referred to as outlets.
03:32So the way we describe the connection between our views and our code is by
03:37defining these different elements as actions and outlets wherever necessary.
03:41I am going to show you two ways of doing this,
03:43first the older slow way and then the new quick way.
03:46And I am showing you the slow way first so that you understand what the
03:49quick way is doing.
03:51So I am going to give myself a bit more real estate here. And understand that
03:55every connection is a handshake.
03:58There are two parts to this.
04:00Something needs to be done in the code file and something needs to be done in
04:04the user interface file to hook the two up.
04:07So code first. I am going to jump across into my ViewController.h file.
04:12I can see this is a normal Objective-C class.
04:15I have got the @interface keyword here and the name of the class, which is ViewController,
04:21is inheriting from UIViewController rather than NSObject.
04:25UIViewController is a class part of the UI kit framework, and it provides all
04:31the base functionality for behaving in this role as a ViewController and what that means in iOS.
04:37We don't have to worry about that too much right now.
04:40We just have to know how to extend it.
04:42Well, here is where I would usually put the declaration of some simple
04:46methods or some properties.
04:48I might define a method like myMethod, takes no parameters, returns void.
04:55It's perfectly legitimate, but if I want this method to be directly connectable
05:01to a user interface element, I have to do something slightly different.
05:04Instead of defining it as void, I will define a new method and I will use this
05:09keyword, IBAction, as the return type.
05:14Selector is just the name of the method, which for me can be changeLabel.
05:18Let's call it that. It can be whatever you want.
05:21And the one parameter I will accept when it's presented to me here, which is
05:24(id)sender, meaning an object that will call sender.
05:28But what does IBAction means?
05:30Well, the IB here is from the old Interface Builder program.
05:34And it's how we're telling Interface Builder, or now that part of Xcode that
05:39used to be Interface Builder, that this method can be hooked up directly to a
05:44user interface element.
05:45IBAction is not actually a genuine return type.
05:49It's actually the same as void. But it's a way of marking this method so that we
05:54can allow that connection to happen.
05:56But of course if I have defined a method in my interface, I also need to have a
06:01matching code in my implementation, or we will get it complaining about this.
06:06Once again, it just needs to match that signature.
06:09So (IBAction)changeLabel, and I would put my implementation code in here.
06:17Now this would be considered just one side of this connection.
06:22I have got a method defined and it's defined as IBAction.
06:24It can be connected to a user interface element, but it isn't yet.
06:29So I am just going to save this and to do the other side, I am going to jump
06:32back into my interface file.
06:36I will click to the standard editor just because I don't have a lot of room and
06:38here's how I connected from this end.
06:41And it's all to do with this icon on the left-hand side called File's Owner.
06:46That's a little bit cryptic.
06:47What does File's Owner actually mean?
06:50This icon represents the connection between the purely visual file here of our
06:55.xib and the code files that are behind it.
07:00So File's Owner here, we could almost imagine a dotted line going from this icon
07:06to the code files of ViewController.h and ViewController.m. It's the visual
07:11representation of that class in our user interface file.
07:15Okay, so what's the point?
07:17Well, I want this button to connect to that code.
07:21I can't drag the button over to the Project Navigator, but what I can do is
07:26make a connection between the button here and this File's Owner icon, which
07:31represent those code files. How do I do that?
07:33I am going to right-click or Ctrl+click-- both work--the button, and Xcode offers
07:39me a selection of events, different things that can happen to this button, and
07:43offers me the choice of which one am I interested in.
07:46Well, the classic event with buttons in iOS, because we don't have a Click
07:49event, but we do have Touch Up Inside, not Touch Drag Inside or Outside, Touch
07:55Up Inside, meaning someone has touched the button and they have let go with the
07:59finger still inside the button.
08:01As I mouse over these little circle icons, they change to a Plus sign.
08:06So I mouse over Touch Up Inside, I click it, and I drag it over here to File's Owner.
08:13And what's going to happen is when I let go, Xcode will scan the File's Owner
08:19classes, which is ViewController.h and .m let me know if any methods there have
08:24been defined with IBAction.
08:26I let go and yes, one of them is there, changeLabel. I select that
08:31and this is how we define a connection between our user interface elements and our code file.
08:37And I can see now that there is even a representation of that in the menu that I get.
08:42I could bring that up again by right- clicking the button. Touch Up Inside points
08:47to File's Owner and to the changeLabel method.
08:50You can actually drive this two ways.
08:52I could have done it by right- clicking File's Owner and I will see there is
08:56another view of that. changeLabel points to the button Touch Up Inside event.
09:02And the third way of getting to it is using the Inspector.
09:07The last section here, with, say, the button selected, is the Connections
09:11Inspector that shows me Touch Up Inside on the button is connected to
09:15changeLabel and File's Owner.
09:17All of them can be used.
09:19They all stay in sync with each other, so it's whatever one you're
09:22more comfortable with.
09:23Well, how about we prove this works?
09:26Well, at the moment, the implementation all of that changeLabel method
09:29doesn't really do anything.
09:30Let's just do a simple little NSLog message, because we haven't yet set up the
09:37other two pieces of it.
09:39So I am going to save that.
09:41I am going to hit Run.
09:43It will build it all together, copy it across to the Simulator.
09:47And when I click the touch button, I am not changing the contents of the
09:51label yet, but if I drag over here, I can see that I'm getting my message come out that yes,
09:56it works. And in fact I should be able to do that multiple times.
10:00I am going to quit out of the Simulator and back into Xcode.
10:05The missing pieces now are that we haven't got connections between our code and the
10:11text field or the label.
10:12So I am going to add that next, but I'm going to use the quicker way of doing it.
Collapse this transcript
Creating quick connections
00:00Let's see how to quickly make connections between our user interface and our code.
00:05I am going to make another iOS Single View Application.
00:07I will call this one QuickConnections and just save it to my Desktop.
00:13Jumping over into the .xib file, I am going to lay out a very straightforward and
00:18simple interface, having a text field up at the top.
00:22I'll just used the grab handle and resize it.
00:24Then I'm going to have a label underneath it. I'll both stretch that a little
00:29wider and reset its contents to blank, and drag on a Round Rect Button, put it in
00:35the middle, and give it the word touch.
00:37Now we've seen that we have to be very specific, very explicit about how these
00:42connect to the code files that are associated with this user interface, but with
00:46Xcode 4, we can be a little quicker about it.
00:49I am going to give myself a bit more room by turning off my Navigators and
00:52Utilities. You don't have to.
00:54I just don't have a lot of screen real estate. And making sure that I'm in the
00:59.xib file--that part is important here--
01:01I am going to turn on the Assistant Editor.
01:04Now the Assistant Editor shows two files: an original file and its counterpart.
01:09So if I've been looking at the .h file, I would see the .m file
01:13that's the counterpart to the interface.
01:15But here if I am in the .xib, it's showing me my counterpart as a
01:20ViewController.h, the connected code file.
01:23And this is the way we can quickly make connections now.
01:26What I can do is connect from this button in the user interface by either
01:30right-clicking or holding down the Ctrl key, click, and holding down the mouse,
01:36drag over into the Code view.
01:38I can see that I have this pop-up saying Insert Outlet, Action, or Outlet Collection.
01:43It knows I want to make a connection.
01:45It's not quite sure whether I want an Outlet for an Action.
01:48Now notice that if I'm above or below, it won't let me do it.
01:51I have to be inside the @interface, @end block.
01:55So I am going to let go, and it's going to ask, what is this?
01:58Is this meant to be an Outlet or an Action or even an Outlook Collection which
02:02we are not dealing with.
02:04Well, I could say an Action here and give it a name, changeLabel, and this will
02:08actually create the method signature we have to manually write ourselves.
02:14I can see that it's picked the typical event, which is Touch Up Inside, which
02:17looks correct. Everything else is fine, Connect.
02:20And I get the method signature in the interface, the same one that I had to
02:24write manually in the last example. But that's not all.
02:28If I actually change up here on the jump bar and I can switch to the
02:31ViewController.m, my implementation file, I can see that not only do I have the
02:37entry in my .h, but down here at the bottom, I also have the implementation
02:43ready to go, ready for me to just put my code in.
02:46So just by dragging from the interface into the code, I get three pieces.
02:51I get the interface part,
02:52I get the implementation part, and over here
02:55I've got my connection defined as well.
02:57Well, next up I am going to create a few spare lines her,e and I'm going to make
03:02the connections for the text field and the label.
03:05Once again, I do it the same way.
03:06I am going to hold down Ctrl and drag over in here.
03:09It's going to say okay, I am going to say insert an Outlet or an Action. Which one is it?
03:14Well, in this case it will be an Outlet.
03:16I want to have a way of getting from the code to the visual interface.
03:22So it's asking for a name.
03:23This is going to be the name of a Text Field object.
03:25I will just call it myTextField.
03:28I can confirm that it's a type of UITextField. Yes, that looks correct, and click Connect.
03:34And in this case it's generating a property declaration.
03:38I will do another one from the label. Making sure the Label is selected, hold
03:42down Ctrl, drag over in here.
03:45I want to insert an Outlet.
03:46I will just call it myLabel, hit Connect.
03:49Now you may notice that just as we had to use IBAction to mark a method that can
03:54be connected to our user interface,
03:56we are using IBOutlet to mark a property that can be connected to our user interface.
04:01So it's automatically done that.
04:02Now when you're defining your own properties inside your classes, you would
04:07usually use the word strong, but here bear in mind, these objects the
04:12UITextField and the UILabel, they really belong over here in the view. The view
04:17is what owns those objects, not this class file.
04:21So we are using the word weak.
04:23We are just letting Xcode do that for us.
04:25But remember, these are generated properties,
04:28so we need to make sure that they are synthesized.
04:30Well, let's go ahead and check that.
04:32Over in the implementation file, we will actually find that it's also added the
04:37two lines of code to synthesize both myTextField and myLabel and it's done
04:42everything to hook them up in the interface as well.
04:45So in fact just by doing that dragging and dropping, we are pretty much ready to go.
04:49About the only thing that's missing is to actually provide some behavior in
04:53the changeLabel method.
04:55What I am going to do is just switch back to the Standard Editor view and then
04:58I want to edit my implementation file.
05:01I will use the jump bar to get there. I could use the Project Navigator.
05:05Come down to the very bottom.
05:07I'll just give myself a few spaces, so we can see this better.
05:11And in this changeLabel method, I want to do two things.
05:14I want to create a new message by combining the words "hello: with whatever is
05:19being typed into the Text Field, and then I am going to output that and
05:24change the value of the Label.
05:25So first, I will construct a string.
05:27I am going to create this NSString object by using not just init, but
05:36initWithForma,t which allows me to make a format string with a placeholder in it
05:41and combine multiple things together.
05:43I am just going to do something very simple here.
05:47So I'll have Hello, and then I am going to put in a placeholder for an object,
05:51which is %@. Close the quote, comma and I have to name what's going to be
05:56placed where the placeholder is, and what I want to do is grab the value of the Text Field.
06:01Now I created a property called myTextField. I could use dot syntax to get to
06:07myTextField.text. Or my preferred way of course is using the Objective-C format
06:13so it'd be myTextField text.
06:17This being the name of the method that retrieves the text property.
06:20Now I'm still in a larger method call right now, so I'd better finish that one
06:25off. Do a semicolon and we're good there.
06:28And then I'm going to use the property myLabel and its setText method to pass in
06:36that new string that I just created on the previous line.
06:39We are using Automatic Reference Counting, so even though I used alloc and init,
06:44I don't have to care about releasing anything.
06:46I can just save this, hit Command+B to build, and see if it's built correctly.
06:51Yeah, Build Succeeded, and we can go ahead and run it.
06:56Now even using the Simulator, what I can just do is tap into the text field here
07:00and it will automatically bring up the default keyboard.
07:04I can actually use the standard keyboard for typing into here, or I could hover
07:09over and use my mouse, but this is fine. And then the moment of truth, works just fine.
07:15So not the most exciting thing, but we are able to do full interaction. We have outlets.
07:20We have actions. We have a lot of code being generated to hook up our user interface to our code
07:26files so that we can just come along and put in the code that we want to work.
07:29Now there is a couple of things still missing.
07:32For example, this keyboard has popped up, but it's not going anywhere.
07:36So we could obviously spruce up this user interface, but that comes a little later.
Collapse this transcript
Dismissing the keyboard
00:00I have this simple application.
00:02It's just a text field, a button, and a label.
00:05And we've seen that if we touch into the text field, the keyboard will
00:09automatically appear.
00:10I don't have to write any code to make this happen.
00:13It'll just happen automatically.
00:15And the behavior that drives this is built into this UI text field object.
00:21It understands that the only way that it makes sense for the user to interact with
00:25it is if it pops up the keyboard.
00:27But one of the problems that we have here is even though an application is
00:30working the typical behavior would expect is that the keyboard goes away
00:34after we're done with it.
00:36It either goes away: one, if we click the button; or two, if we tap on a blank
00:40area of the interface; or three if we hit the Return key on the keyboard--and
00:45none of those three things are happening.
00:46So we don't have to do anything to make the keyboard appear, but we will have to
00:51do something to make it disappear.
00:52So I'm going to go back into my code and quit out of this application, and do
00:57the simplest one first.
00:58What happens when the user touches the button?
01:01Well, we already have a method in our implementation file called changeLabel in
01:06my case, where we are actually grabbing the contents of the text field and changing
01:10the value of the label, and it's here that I can make that keyboard go away. And
01:14the way that I do this is by talking to the text field, not the keyboard.
01:18I don't have a way of addressing the keyboard directly.
01:21Now when the keyboard was touched, it became egotistical.
01:25It realized that it was at that moment the most important user interface element,
01:31the one that user was actually interacting with.
01:33In an iOS we have a name for UI element actively in that position.
01:38It's called being the first responder. And what I've got to do is tell the text
01:44field to give up the status of first responder.
01:46And the way that I do this is by calling the text field.
01:49It's myTextField, and I'm just going to call the method called
01:53resignFirstResponder and send it that message.
01:57I don't need any parameters.
01:59It's just those two words inside the square brackets with the semicolon at the end.
02:03I save that, I run this again, we can tap into the text field, the keyboard pops up.
02:10It's become a first responder, and we can do some basic interaction.
02:15Touch the button, resignFirstResponder, the keyboard goes away.
02:19Tap into the text field again,
02:21we become first responder. Do some more text, touch it again,
02:25resignFirstResponder, the keyboard goes away.
02:28However, in a typical iOS application, that's not everything.
02:33What I'd also expect is that if I touched somewhere in a blank area of the
02:38interface or if I came down and touched say the Return button on the keypad, that
02:42it would also go away, and that's not happening right now.
02:46So quit out of this and return into Xcode.
02:49Let's take care of touching a blank area of the application.
02:52The way that I'm going to do this might seem like a bit of a hack.
02:55In my XIB file I'm going to just drag on another Round Rect button and use the
03:00grab handles to maximize it and make it the size of the interface.
03:06Now that doesn't look all that useful right now because it's now
03:09obscuring everything.
03:11What we need to do with the big button selected is go to the Editor menu and I
03:15can go down here to Arrange > Send to Back.
03:20But it's still a large white button, which is not what we want.
03:24Well, with the button selected, I'm going to go over to my Inspector section and
03:29I need to find my Attributes Inspector, which is the fourth button here.
03:33And what I'm going to do is change the Type of the button, which is the first
03:37attribute, from Rounded Rect to Custom.
03:40Now Custom is there to allow us to create our own buttons, by providing our own
03:45images for the normal state and the highlighted state and so on.
03:48But if I just change to a custom button, it becomes invisible.
03:52It's still the full width of the interface.
03:54It's still actually there.
03:55It might be a little difficult to grab hold of. One other way I could do that
04:00is by expanding the doc here, and I can see that I still have all my selectable objects:
04:04the button with touch on it, the text field, the label, and behind them all,
04:09the larger button. I can even see the small grab handles at the side of the canvas there.
04:14But I do need to connect this to my code, so I'm going to do it the quick and easy way. [00:04:20.2 6] With the XIB selected, I'm going to switch into the Assistant mode, close that down.
04:26Clicking the Back to make sure I've got the button selected, and then I'm going to
04:30right-click it, come down, find the Touch Up Inside event and drag it over here
04:38to insert an action.
04:42I'll create an action called dismissKeyboard. And then switching back to the
04:47standard editor, what I'm just going to do is select my implementation file
04:51where I should now have a dismissKeyboard signature here, and once again all I
04:57need to do is say myTextField resignFirstResponder. Save that, run it again.
05:06Now we should be able to tap into the text field, but if I tap a blank area
05:09the keyboard goes away.
05:11Back into the text field again, type in the name, the button works. Again we can
05:18resignFirstResponder however we do this.
05:21And there is one last thing, which is, when we tap this Return key, we might
05:26expect the keyboard to go away, but it's not doing that yet.
05:29That's the last thing we're going to do, but the way we do this is a little different.
Collapse this transcript
Dismissing the keyboard with delegation
00:00So we've seen how to make the keyboard go away by using the
00:03resignFirstResponder calls.
00:06That's what I'm currently using driving it either from the touch button or from
00:09the invisible button on the background.
00:11But both of these ways were driving this behavior from outside of the text field
00:16and outside of the keyboard.
00:17So if we want this Return key to also dismiss the keyboard, the question is, how
00:24do we react to that?
00:25Well, we use something called delegation.
00:27What can happen here is that the UITextField itself, which is responsible for the
00:32keyboard, can announce towards that hey, someone's done editing.
00:36They've pressed that Return key. And we can choose what to do in response to that.
00:40Now if it's the first time you've seen delegation, it's going to look a
00:43little strange, but let me show you the process, and then we'll talk
00:45about what happened.
00:47I'm going to jump over into my User Interface Editor.
00:51I'm going to highlight the text field itself and open up my Utilities panel,
00:55and in the last section of the Inspectors is the Connections Inspector here.
01:00Now I can see that I have all the same events that I might be used to looking at
01:04on, say, a button, like Touch Drag Inside and Touch Up Outside.
01:09I can even see where my outlets are hooked up so that my code can refer to this text field.
01:14But I have another outlet up at the top, and you'll see this on several of the
01:18user interface elements.
01:19It's called delegate.
01:21What this means is we can nominate some other piece of code to do some
01:26behavior on behalf of this text field. So I'm going to grab that Plus sign for
01:31delegate and drag it onto anywhere else on the user interface itself, but
01:36over here to File's Owner.
01:38If you remember, File's Owner is connecting us to the ViewController.h and .m
01:43files, so I'm going to let go.
01:45Now often I'd expect to see that pop up something--what method do I want to
01:50call?--but it didn't do at that time, and there is a reason why.
01:54I can see that we seem to have connected it successfully, that with that text field
01:59selected, delegate is File's Owner. What does that mean?
02:04Well, let me show you.
02:05With that text field selected, I'm going to switch to the second Inspector, which
02:08is our Quick Help, because I want to go to the UITextField Class Reference.
02:14I could also get to this from the main organizer window, using the Help menu.
02:19So I click that. The Organizer window opens with this documentation, and it's
02:23all the information about the UITextField, all the things that it can do, and
02:28its built-in behaviors.
02:29Now the third paragraph here for the Overview tells me that a text field object
02:34supports the use of a delegate to handle editing-related notifications.
02:39We don't have to have a delegate, but if we have one, we can react to these things.
02:43For more information, it has a link to the UITextFieldDelegate protocol, whatever
02:48that is. Talk about it in a second.
02:50I click that link, and it takes us to a separate document.
02:54Now what's actually happening here, without getting too deep into it, is there's a
02:58whole bunch of notifications that the text field can tell us about: whether the
03:03text field is beginning editing or ending editing or somebody has hit the Clear
03:08button or someone has hit the Return button.
03:10So by calling ourselves a delegate what we can do is opt into these messages. We
03:14can choose to respond to them.
03:16And one of them is called textFieldShouldReturn.
03:20Clicking that link, it takes me to this part of the documentation,
03:23textFieldShouldReturn asks the delegate if the text field should process the
03:28pressing of the Return button. And that's key part of it, asks the delegate.
03:33We can choose to respond to this.
03:35And if this thing looks like a method signature that's because it is.
03:38I'm going to grab the entire thing, including the Minus sign at the front,
03:43and just copy that.
03:45Jump back over, go into my implementation file.
03:49It doesn't matter where I put this as long as I put it before the At sign end.
03:54I'm going to paste in that method signature.
03:58It didn't give me any braces, so I'll put those in myself. And what we're doing
04:02here is by being a delegate, we can respond to any of the methods that were
04:06listed in that delegate reference.
04:08This is the only one I'm interested in.
04:11It means somebody pressed the Return key. What do I want to do?
04:14Well, in my case I could just copy that same line, the myTextField
04:19resignFirstResponder. Having said that, another option that I could use is this
04:23delegate method, textFieldShouldReturn, is actually getting in a parameter called text field.
04:29So alternatively, I could use that too.
04:32Now it wouldn't matter for me here, because there is only one text field, but
04:36potentially I could be a delegate from multiple different text fields, and I want
04:41to make sure that I was resigning the correct one.
04:42However, one last thing I need to do. I can see up here that this
04:46textFieldShouldReturn is meant to return a Bool saying whether this got handled or not.
04:52So I'm going to agree to that and say return YES.
04:56Of courses it's an Objective-C Bool, which means it's all in caps.
05:00It's not true or false. It's yes or no.
05:02Now save this, run it.
05:07We open up. The text field becomes first responder. The keyboard pops-up.
05:11I can type some name, hit the button. The resignFirstResponder the keyboard goes
05:15away. Again tapping into the keyboard then we hit the blank button,
05:19resignFirstResponder the keyboard goes away.
05:22Tap into the keyboard, come down and hit the Return key. We'll hit the delegate
05:26method, the textFieldShouldReturn, resignFirstResponder, the keyboard goes away.
05:31Now this delegation option might have struck you as a little bit strange, but it's
05:35a hugely powerful ability in Objective-C and iOS development.
05:40And in the next movie we'll talk a bit more about exactly what happened there.
Collapse this transcript
Using delegation in iOS
00:00The first time you hear this term delegation, it might sound like some abstract
00:05ivory tower idea and it isn't.
00:07Like MVC, delegation is one of the core design patterns in Apple development and in iOS.
00:13All iOS apps use delegation, all of them.
00:17Even the most basic Xcode project templates are already using it in the
00:21code they give you.
00:22Delegation in iOS is how you accomplish tasks that in other languages you might
00:26do with inheritance or event handling. It's important.
00:30But what does it mean?
00:32So, a delegate in iOS development is really like the idea of a delegate in
00:36real life, a delegate in politics or in business.
00:39It's someone who acts on behalf of someone else.
00:43And to delegate is a formal way that one person hands off responsibilities to another person.
00:49Now for us developers, it's a formal way that one object hands off work to another object.
00:56An object in iOS, often a built-in object, including several of the user
01:01interface elements, already has its own internal processing, sure.
01:06But they can be connected to your objects, your view controllers, or your custom classes.
01:13And they can delegate certain responsibilities to your objects.
01:20Now later, perhaps much later, you might be the one delegating.
01:23You might pass work off to somebody else.
01:26But first in iOS, you learn how to be a delegate, how to have responsibilities
01:32handed to your custom classes.
01:35I like to say that being a good delegate in iOS is like being a good delegate in
01:40business or in politics in real life.
01:42There are steps to this. There are rules.
01:45Step one: know the rules. Know what you have to do.
01:49What are the responsibilities in that role?
01:52This is not casual.
01:53If you wanted to be an official delegate for a political party or government or
01:57royalty, it means there are formal documents that describe exactly what is
02:02expected of that delegate in that role. Step two:
02:06say "I can do that."
02:08This is where you're volunteering.
02:10You're putting your hand up. It is a choice.
02:13Now step three: have a plan to actually do it.
02:16If you're going to volunteer for this role, you better be able to follow through.
02:20And step four: actually get the job. Make sure you're in that role.
02:26Volunteering is not enough;
02:28you need to know that whoever is handing those responsibilities out is actually
02:32going to give them to you and not to somebody else.
02:35So if that's how you might approach being a delegate in real life, what is it
02:39in iOS development?
02:41Well, exactly the same thing.
02:43Step one: know the rules. Know what you have to do, and there are formal rules here too.
02:49The rules are called the Delegate Protocol.
02:53You can get to them through the Xcode documentation, and each Delegate Protocol
02:58is a formal list of method names, and that's all they are, just method names. Step two:
03:04say "I can do that."
03:06You're volunteering and you're marking yourself as volunteering.
03:09You're being a delegate for something specific, and what you do in code in one of
03:14your custom classes is that after the usual declaration of the class, you'd use
03:20these angle brackets and a specific world and you'd say, I can be a delegate for
03:25a UITextField, or I can be a delegate for UITableView.
03:29You can volunteer to be a delegate for more than one thing. Step three:
03:33have a plan.
03:35This means, you must have to look at the Delegate Protocol and actually
03:39implement the necessary methods, and you choose the methods you want to support.
03:43And what you write in your code in your classes must exactly match the rules in step one.
03:51And step four: get the job. Marking your class is not enough.
03:58Implementing those methods is not enough.
04:00Whatever object is handing those responsibilities out, what we call
04:04the delegating object,
04:05you need to make sure they're going to give them to your class and not someone else.
04:10So you have to say, my class is going to be of the delegate for that particular object.
04:15An example might be that I can highlight a text field, I find the delegate
04:20outlet for that, and hook it up to the file's owner.
04:23That makes my file's owner class the delegate for the text field.
04:27You can also hook up delegates in your code as well.
04:31Now if it's your first time approaching this concept of delegation, it probably
04:35still sounds a little confusion.
04:37But like being a delegate in business or in government, in all likelihood you
04:41still begin by having someone show you around and walk you through a couple of examples.
04:46And as we go through more of the course, that someone is going to be me.
Collapse this transcript
Creating alert messages
00:00One of the first questions I get from developers in other languages is, how do I
00:04make an IOS app that can pop up what might be called a message box or an alert
00:09box in other languages?
00:10Now, iOS, not surprisingly, has a specific object for doing just that.
00:15I'm going to make a single view application in Xcode.
00:18This I'll call AlertMe. And I'll make sure to have Storyboards unchecked and
00:24Automatic Reference Counting checked.
00:27Click next and I'll save this to the desktop.
00:29We're going to make a very simple app that immediately pops up an alert message.
00:34Now of course you could use the techniques we've seen so far to make this happen
00:38on a touch event or anywhere else in your code, but I'm to have it happen
00:42immediately, and that will give us two things:
00:44one, how to make an alert happen at all, and two, how to execute some code as
00:49soon as the application runs for the first time.
00:51So if I look at my ViewController.m file here, I see that Xcode gives me a file
00:57with a few placeholder methods here, and these allow us to inject our code at
01:02several different points in the lifecycle of an application.
01:05There is one here called viewDidLoad, not surprisingly for when a few loads and
01:10when a view unloads.
01:11There's one down at the bottom here that answers the question, should
01:15this application rotate to a particular interface orientation, like
01:19portrait or landscape?
01:20There are several more built-in lifecycle events, things like viewDidAppear
01:26and viewWillAppear and depending on the version of Xcode you're using, or if you open
01:31older projects, you might even see more of these placeholder methods here in
01:35the boilerplate code.
01:36Xcode 4.3 made the default code for a view controller a little simpler than in
01:41previous versions of Xcode.
01:43But one classic place I could write some code when an application loads for the
01:48first time is in this method called viewDidLoad.
01:52This will be called automatically after the controller has loaded all the
01:55interface elements that are defined in our .xib file.
01:59So I'm going to leave the line super viewDidLoad present so it can do any
02:04necessary code that's defined in the superclass, and I'll put my own code
02:08after this comment.
02:09I'm going to create a built-in object called a UIAlertView, and this has a
02:16custom initializer so we can allocate it and set it up with all the
02:19information it needs. It's initWithTitle message, and as we'll see, a few other things here.
02:25I'm just going to split us apart onto multiple lines so we can read it a little better.
02:28You don't have to do that.
02:31As we can see, there are several arguments to it.
02:34The first one that it takes is a title, and this is an NSString.
02:38We can just use the NSString literal format here, so I'll call it Alert Title,
02:44and we will see the impact that this has.
02:47Next is another NSString for the message.
02:50Let's say "Here's the message -- there was a problem!"
02:54Now we have this argument called delegate, and what's it asking for here?
02:58Does this thing does this UIAlertView object need to be pointed to another
03:03object to handle any extra processing?
03:07If we wanted to have a complicated UIAlertView with multiple buttons on it and
03:12we needed some extra code to be defined to handle when those different buttons
03:15were pressed, we could define a delegate here to respond to that.
03:19So you can connect delegates in code as well is in the visual interface builder.
03:24But I just want a regular old UIAlertView.
03:27I don't want anything special.
03:28I just want it to go away when it's done, so I don't need a delegate. And I
03:32won't always need one.
03:34It's quite common that you don't.
03:36But the way here that I would say I don't need one is just used the word nil,
03:40N-I-L, all lowercase.
03:42This is the equivalent of null in some other languages.
03:46It's basically saying a nonexistent Objective-C object, no delegate.
03:50Then we jump onto the next one, which is the cancelButton Title.
03:53What do you touch to make this thing go away?
03:56What does the button say that you actually put your finger on.
03:58And I'll just give it another NSString, again using the at sign format, and just say Okay.
04:05And finally, we have the otherButtonTitles argument.
04:09This is using an unusual format with the ellipsis, the dot, dot, dot.
04:12What it's basically saying is we could give it multiple arguments separated by
04:16commas, multiple titles for other buttons.
04:20So we could provide multiple options here, and they do have to end with nil.
04:25That's will actually tell the alert view we're actually done.
04:28The are no more other button titles.
04:30In fact if I don't want any other buttons, I just get rid of that and make sure
04:34that the only thing that passes is nil.
04:37If you want to do other buttons, take a look at the documentation for UIAlertView.
04:42This defines and allocates and initializes our object, but it doesn't show it
04:46yet. So I have this new object called myAlert, and I'll just call show.
04:52Save that and run it.
04:58It pops up an alert message. Now if you can see your debug error, you might see a
05:03message like this: "Applications are expected to have a root view controller at the
05:07end of application launch."
05:08That's because what I've done here is kind of interfere with the process a
05:12little bit of pumped up this modal dialog boxes waiting for a response without
05:18actually letting the view completely load.
05:21It's not too much of an issue because we're just doing an example here, but if
05:25you do see that message, it might be because you're kind of interfering with the
05:28initial process. So I've got the one cancel button here.
05:32We can see where the alert title is corresponding with init with title with the
05:36message and the cancel button title.
05:38We click okay and it takes to the application, which doesn't really do anything.
05:42Here, however, is one thing you might notice.
05:46If I come out of the application by clicking the Home button and then go back in
05:50again to alert me, well, I actually don't get that message.
05:56That's because when we leave the application using this Home button, it's not fully exiting.
06:02It's going into a background state, and when we reopen it, it's not calling
06:07viewDidLoad again, so this method is actually only being called that first time.
06:11And this is the default behavior of multitasking in iOS.
06:15The viewDidLoad method will be called the very first time someone opens this
06:19application but not when the application opens from a background state.
06:23Now maybe that's what we want and maybe it isn't, but what it does mean is we
06:28need to start becoming a bit more aware of the lifecycle of an application so
06:32that we can introduce our code in the correct places along the way.
Collapse this transcript
Understanding the iOS application lifecycle
00:00After they've created a few simple projects, most developers become curious
00:04about what's actually happening in the lifecycle of an iOS application.
00:09What do those other files represent?
00:12How do we get from someone touching an icon on the iPhone screen to running the
00:16code that we write in a view Controller?
00:18Well, the most basic idea is this.
00:21This is an Objective-C program, which means our iOS applications begin by running main.
00:28And in an iOS project, we do have a main.m file.
00:32It's in our supporting files folder.
00:34As a rule, you won't touch it.
00:36You're going to leave it alone, which is why Xcode puts in that folder.
00:39Now main makes one call to a function called UIApplicationMain.
00:45This is a predefined function in iOS that creates an object, UIApplication, that
00:50represents a standard, typical iOS application. It's the foundation, the
00:55processing that every iOS app is going to need. So it sets up a Run loop so the
01:01application stays active, it responds to events, and so on.
01:04But our app is different from a base generic application object, and we need to say how.
01:11We don't use inheritance for this in iOS. We use delegation.
01:15And we always need a class in our project that is the delegate for the standard
01:20built-in iOS application object, and this is something Xcode does for us.
01:26Looking at the standard files created in a single view application,
01:30you can probably have a pretty good guess as what the class might be that is the
01:35delegate for our application object.
01:38Of course, it's AppDelegate.h and AppDelegate.m. And this is where we can put
01:44some code to respond to application- level events, like our application starting
01:48and application terminating.
01:50But right at this part of the process, we have no user interface yet.
01:54This is all happening in the background.
01:56So one of the things the AppDelegate immediately needs to do is say hey, we need
02:00a user interface. And it does that in two steps.
02:03First it creates an object called a UIWindow.
02:06Now think about a window.
02:08A window is clear.
02:10It's transparent, although it does have certain size.
02:13It has boundaries. And really that's what happens in iOS.
02:17This UIWindow object represents the boundaries of an iPhone or an iPad screen.
02:23It's immediately created and it exists for the lifetime off our app.
02:27There is just one of them.
02:28But it is effectively transparent.
02:30There is nothing in it, because what we then do is load in our view
02:34controllers, which contain our user interfaces and their controller code, the
02:39.h, .m, and .xib files.
02:42Now when we create something like a single view application, we're loading a
02:47single view controller into that UIWindow.
02:50In more complex applications, we can switch multiple different view controllers
02:55in and out of that UIWindow.
02:57Now if this looks a little intimidating, fair enough.
03:00There is a lot going on here, but here's the thing.
03:04Looking at this overall process, you don't touch .ain.
03:08You don't touch UIApplicationMain. You don't really do anything directly
03:13with UI application or with the window object.
03:15Your interaction with this entire structure is in two primary places:
03:19your app delegate code and your view controller code, and your user interfaces.
03:24You just need to know where you are in the structure,
03:27because as your application runs and the event loop runs, it's going to call
03:32methods, like the application: didFinishLaunchingWithOptions.
03:37And it will pass that across to your AppDelegate code.
03:42You get to process that and respond to it.
03:45It spawns up the UIWindow, spawns up the View Controller, and view controller
03:50gets things like viewDidLoad and viewWillAppear.
03:54We can choose whether or not to respond to these in our view controller code.
03:58When the first view controller is made active, the app is now fully active and
04:02back in the AppDelegate, we get the application:didBecomeActive notification,
04:07and we can use that if we want.
04:09This kicks off events like viewDidAppear in the view controller.
04:13And this is all happening in a split second.
04:17If someone presses the Home button to leave the app, we'd get things like
04:21application will resign, application did enter background, but we'll see more of those later.
04:26So what is important to know is that there's nothing really hidden behind the scenes.
04:31All this stuff is actually in your project, in your application.
04:36If I jump across into a typical application, I can find main.m. I can see the
04:42call to UIApplicationMain.
04:45That's going to create that object and point it to our AppDelegate, which is, not
04:50surprisingly, over here.
04:52I can look at the AppDelegate implementation and find this application
04:58didFinishLaunchingWithOptions.
05:00And while this code may look a little confusing right now, what we're doing here
05:04is creating the window that transparent boundary of the frame.
05:08On line 22 is the code that then creates the first view controller.
05:14We have this method called initWithNibName, so we're loading both the class
05:18files and the .xib as well.
05:20On line 23, we're loading that view controller into the window. Line 24 makes it visible.
05:27All the code is provided for you.
05:30Once you understand a little bit more about these different options and as you
05:34can see, they're all quite well documented here,
05:37it's very specifically defined, and the order is explicit.
05:41This structure is provided for you in all the iOS project templates.
05:45You just have to decide where to interact with it.
Collapse this transcript
Understanding multitasking
00:00So when the user hits the icon for your application for the first time, it's
00:05going to start up, and in that first launch it's going to be calling methods in
00:09the app delegate like applicationDidFinishLaunchingWithOptions, and in the View
00:13Controller, like viewDidLoad as part of that startup process.
00:17But you can't count on these two methods alone, because when the user hits
00:22the Home button, your application is going to disappear, but it doesn't
00:26completely terminate. It doesn't exit all the way, and that means the next time the user taps the
00:31icon to open the app,
00:33it would look the same to them, but they will not be hitting those same events.
00:38And this is because iOS devices by default use multitasking, but what Apple
00:43means by multitasking may not be what you mean by multitasking.
00:47It certainly does not mean that your app just runs all the times after someone
00:51has pressed the Home button.
00:52That would be a far to uncontrolled state of affairs for Apple to allow.
00:57So your app would disappear from the screen and enter a background state, a
01:02suspended state, not an actively running one.
01:05If the user taps your application icon to run it again, your app moves from that
01:10background state to the foreground state again.
01:12They can also double-click the Home button to get the list of applications that
01:16are in the background and relaunch it that way, and the cycle continues.
01:20So we don't just have lifecycle events for launching the app and terminating
01:25the app, but also for moving to the background or moving to the foreground. And
01:29these methods include applicationWillResignActive,
01:31applicationDidEnterBackground. The app disappears. We launch it again, we get
01:38applicationWillEnterForeground, applicationDidBecomeActive, but of course the
01:43cycle can continue.
01:45Hit the home button.
01:46We'll resign again.
01:47We'll enter the background, and whether it's a minute later or a week later,
01:52applicationWillEnterForeground, the applicationWillBecomeActive, this can happen
01:55time and time again.
01:57These will be called automatically when that process happens, and they're going
02:00to be the key methods to respond to if you need to do anything when the user
02:04moves in and out of your app,
02:06as they could be called dozens of times between the first
02:09applicationDidFinishLaunchingWithOptions and the final
02:13applicationWillTerminate, which rarely gets called, but can be if your app is
02:18indeed fully executing, because your app can still be required to exit all the
02:23way out, either because iOS commands it--
02:26the operating system on the device can decide it needs the memory--or the user
02:30can also exit your application by double-clicking the Home button to see the
02:34list of apps and then holding them down and tapping the minus button. And in that
02:38exit processm iOS will call applicationWillTerminate in your app delegate.
02:43But do you notice when you're looking at the boilerplate-provided app delegate
02:48call, that these are very well commented: applicationWillResignActive,
02:51applicationDidEnterBackground, WillEnterForeground, DidBecomeActive, and
02:57applicationWillTerminate.
02:59And whether you're truly terminating or just moving to a background state, you
03:03always have to be quick about what you're going to do in any of these methods,
03:06because you only have a few seconds to exit before iOS decides you're taking too
03:10long and just kills your process. But if you've actually transitioned to the
03:15background, well, what is your application doing in the background?
03:19Well, by default absolutely nothing.
03:22Oh, sure, your app is taking up a little bit of memory, but no processing cycles.
03:27So if you had started a long-running calculation or a long-running network
03:31operation, those are not just continuing in the background.
03:34Your app is not running.
03:37Now, but can your app do something in the background?
03:40Well, maybe, there is a very short and controlled list of what an iOS app is
03:45allowed to do once it's moved to that background state. And you have to ask
03:49permission of iOS by making a change to one of your app's supporting files to do any of these.
03:55The five very specific things an app can do is play audio, so you can move to
04:01the background and continue to play audio from a network stream or from the iPod library.
04:05You can react to location changes, perhaps for creating a navigation app with prompts.
04:11You can keep a voiceover IP connection alive to make calls over your
04:14Internet connection.
04:16If you write a Newstand app, you can download content while your app is in the background.
04:20And if you're connected to an accessory, your app can talk to that.
04:25You can also ask permission to perform some small generic background tasks, but
04:30you do not get free reign on the processor.
04:33Now, all of these are specialized options outside the scope of this class.
04:37We won't be working with background operations here. But if you did have
04:40something in mind that needed to do these, they are available.
04:44What we'll be working with are the ways to react not just to application
04:48launch and terminate events, but also to our app moving between background
04:52and foreground states.
Collapse this transcript
5. Troubleshooting
Troubleshooting a basic application
00:00I'm going to illustrate a few of the most common issues when you're new to iOS development;
00:05I'm just using a simple program here.
00:06It has a button and a label, and it's meant to update the label with the current time.
00:11I'm going to say that the NIB file here looks correct. Then I might jump
00:15across to an implementation file and find that, yeah, I seem to have a method
00:19here called updateTime.
00:20What this is actually currently doing is using something called an
00:24NSDateFormatter to get the current date and change it to just the time, hours and minutes.
00:30We haven't gone through date formatters, but it should be fairly obvious
00:33here what this is doing.
00:34And we're then changing the label. Looks correct.
00:37I'm going to go ahead and run this.
00:39Build has Succeeded, so obviously there is no problems with the code.
00:43I go ahead and I click the button and nothing happens.
00:47This is a very common problem.
00:49Your buttons don't do what you think they should do--or your sliders, or your switches.
00:53Some kind of user interface element does not seem to be doing the job it's supposed to.
00:57But what I'm not sure about is where the problem is. Is there a problem with the button?
01:02It's not calling the method properly, or perhaps there's a problem with the method.
01:05It's not updating the label property, so we'll take them step by step.
01:08Going into my XIB file, I'm going to turn on the Utilities panel, and while
01:12there's a few different ways of seeing this information, I can see this
01:16Connections Inspector over here.
01:17I'm going to select the button, and I casually see that, yeah, I seemed to be
01:20hooked up to something.
01:22I'm hooked up into File's Owner to update Time, so there is an event on the
01:26button, but if I look a little closer, it's actually the wrong one.
01:30What I have here is the Touch Drag Outside is connected to File's Owner, and I
01:35could see this information one of three ways.
01:37Using the panel over here I could also right-click or Ctrl+Click the button and
01:41it shows me the Touch Drag Outside. If I could drag this a little wider, so you
01:46see more of it. Touch Drag Outside.
01:47I could also see it in the File's Owner or even code.
01:50So how do I fix this?
01:51Well, I'm just going to turn this off by clicking that little X button over there.
01:55Now the button isn't hooked up to anything.
01:57Now, a little earlier I did show you an option where we can connect our user
02:02interface elements using the Assistant Editor, and I could Ctrl+Drag across in here.
02:07That's not what I want to do here, because I don't want it to create a new
02:12method for me. I just want it to hook up to an existing one. But I can still use this format.
02:17I'm going to right-click or Ctrl+Click the button, grab the correct event, which
02:21is Touch Up Inside. Making sure I have that,
02:23move it over the updateTime method definition and let go.
02:28Now I know it's correct.
02:29I'm going to go ahead and run this, click the button, and still we have nothing.
02:34Quit out of that and go back into the code.
02:36And I'm looking here in my implementation file.
02:41There is still a problem, but I don't know what it is.
02:44Well, let's do one low-tech way of dealing with it. In my updateTime method what
02:47I'm going to do is just put in an NSLog message. Save that, run this again.
02:55I want to be confident about whether I'm calling this or not.
02:58Now I click the button. Well, I don't know for sure, depending on what parts of
03:02Xcode I've hidden, but if in the background here I open up the lower section--
03:07I'm actually going to use this button to show just the console here--
03:10it does appear indeed that I can call that method.
03:14So the method is being called correctly. That's fine.
03:16I can go back into my code just quitting out of that and take another look.
03:21So I made sure that my action was hooked up, but I didn't make sure my
03:24outlook was hooked up.
03:26I can see that in my header file I have this declaration, this property, a
03:30UILabel that is an IBOutlet, but it's not connected. And in fact, there is a
03:35clue right here in the code that it's not connected.
03:38So when you're looking at the code files, the header files or the implementation
03:41files, and things are marked with IBOutlet and IBAction,
03:44you have these circles over here in the gutter.
03:47If the circle has a dot inside, it's connected to something;
03:51if the circle is empty, it's not.
03:53So this is telling me I've written it correctly in my code, that it can
03:57be connected to a user interface element, but it's not connected to a user interface element.
04:02If I wanted to see where that equivalent was in the interface file itself,
04:06I'd find my label, and right-clicking it, I see there is nothing connected to this label.
04:11What we're interested in from this side of things is what's called a
04:14referencing outlet.
04:15Again, multiple ways to connect this, but I'm going to drag across to File's
04:20Owner, which is representing our code files. And then it's asking, what should I
04:23be connected to, label time or view?
04:26Well, it's label time, do that.
04:28We now see that we're hooked up to that label in the File's Owner.
04:32And if I went back into the Code view in my header file, I should see from this
04:35perspective this circle now has a dot in it.
04:37If I actually click that dot, it will tell me what I'm connected to, the
04:41Label in ViewController.xib, or in the equivalent here, the Button in the
04:46ViewController.xib.
04:47So very useful to pay attention to the gutter here.
04:50I'm going to go ahead and run this, and we seem to be working correctly.
04:55Connecting your user interface elements to your code is one of the chief
05:01stumbling blocks of any new developer in iOS, because missing connections
05:06won't cause errors.
05:07They will just cause nothing to occur.
05:09Make sure that you're looking at both your actions and your outlets and viewing
05:14all the visual clues possible, such as the circles that you'll find in the
05:17gutter and the things that you can get by right-clicking on these user
05:21interface element. Very common issues for anyone new to iOS development.
Collapse this transcript
Creating breakpoints and using the Xcode debugger
00:00Simple troubleshooting techniques like using NSLog messages can be very useful.
00:05But sometimes it's not quite so clear where the problem is. You don't want to
00:08start writing dozens or even hundreds of NSLog messages all through your code;
00:12instead, you want to step through your code line by line as it executes.
00:16We are going to do that here using the Xcode debugger.
00:19So I've got a simple iOS single view application and in my NIB file I have one
00:24label and a button that's interestingly titled Boom!
00:28This button is going to call a method in my implementation file here that's
00:33going to take a couple of values, divide one by the other, construct a string,
00:37and change the value of the label.
00:39And this code is syntactically correct. It will compile.
00:43I can hit Command+B. I'll get a Build Succeeded.
00:46And it is hooked up correctly to the user interface elements, but we still have problems.
00:52So I am going to go ahead and run it.
00:53We then click the button and we jump back into Xcode, but it looks a little different.
00:59Because we are running from Xcode, we are jumping back with all these great
01:03debugger options already loaded up.
01:05Our application is actually still running.
01:08It's still over here in the Simulator in this kind of paused section with
01:12the button depressed.
01:13But it's allowing us in Xcode to view the inner workings of what's going on.
01:18The first thing to see is this green line here.
01:21Xcode is telling us this is where we've paused is on this line of code, and it's
01:26giving me this strange term, Program received signal: "EXC_ARITHMETIC."
01:30Okay we'll get to that.
01:32But what else are we looking at, because this does look a little different?
01:35Well, over here, on the left-hand side we are actually in a different navigator.
01:39We are in the debug navigator, which is the fifth on the seven navigator options.
01:44And what it's showing us here is what's called a stack trace, meaning a list of
01:48who called what called what to get us where we are right now.
01:52And it goes from the most recent at the top.
01:55So I go from the bottom up, I can see we actually began with a call to main and
01:59then to UIApplicationMain.
02:01That looks familiar from my lifecycle discussion.
02:04And then to something I don't recognize, then to our method.
02:07In fact, there is a bit more going on than this.
02:09And if I look down towards the bottom of the stack trace window, we have a slider here.
02:15And the stack trace can be dragged to the right to actually show more
02:18details about the whole path between the call to main and our doSomething
02:23call in our ViewController.
02:25Now quite often the stack trace can give you a clue of how you got to the code
02:29that's calling a problem.
02:30But it isn't really helping us much.
02:32We know that we touched the button,
02:34it called our code, immediately there was a problem. Well, what else?
02:37Well, on this lower section over here, I have a split between the Variables view
02:43on the left-hand side and the console on the right-hand side.
02:46Now when we are in this paused mode, I can see a list here of the Local Variables.
02:51I've got variables like firstVal, result, secondVal.
02:55Those three are just integers, whereas this one is an NSString object, so
02:59it's a bit more complex.
03:00When we have objects inside objects, we can actually start to drill down inside it.
03:04There is still nothing in it yet, because we haven't created and allocated it probably.
03:08This section, this Variables view, allows us to see local variables or all
03:13variables, giving us a few more, or an automatic view.
03:16I am leaving it on Local.
03:17And while I can see the values of a couple of local integer variables here, one
03:22of the other things I can do is just mouse over them in the code itself.
03:26Sometimes you have to step off and back on again.
03:28Let's go for firstVal mouse over.
03:30Its 10,000 and then back over to secondVal, which is zero.
03:34So there is the problem, because on line 38 I'm trying to divide firstVal by
03:39secondVal, 10,000 by 0.
03:41Well, you can do a divide by zero on a computing system. That's a problem.
03:45But I can see, I got secondVal from calling some other method called
03:50calculateSecondValue, so maybe I don't know what that one is doing.
03:53So imagine it's a bit more challenging to figure out where these values are coming from.
03:57Well, what I am going to do is I know I can't continue, so I am just going to go
04:00ahead and click the Stop button to come back into our regular code.
04:04And what I am going to do is in this method, I am going to come over to the line
04:08that I'm about to call, calculateFirstValue, and just click directly in the gutter
04:13here and we get this blue arrow. This is a breakpoint.
04:15You are telling the debugger when you hit this line of code, stop.
04:20So we've got this blue icon.
04:20If I click it again, it will become kind of a halfway transparent, which
04:24means it's de-active. You can kind of flip them on and off.
04:27If I wanted to get rid of it entirely, I click it and drag off to the side, till
04:32I see the little cloud and then let go, but I actually want it there, so
04:36first-line inside my doSomething method.
04:38I want to be on a line where code can actually be executed.
04:42So with breakpoints enabled, I am going to come back up here and click Run.
04:46Now I'll jump across, click that button, and we immediately jump back into the code.
04:50It looks very similar, but instead, we see this message here, Thread 1:
04:54Stopped at breakpoint 1.
04:55And before the code that cause the error.
04:57So I have the opportunity to figure out what's going on.
05:00And what I'm interested in here are these buttons down here in the debugger.
05:04We have Step over, Step into, Step out, Continue program execution.
05:09This interesting-looking one on the left just merely hides the whole Debug area
05:13or expands it back up again.
05:15I am going to use this one, which is the step into and just click it once.
05:20We're currently paused before line 35 gets executed, before the call to
05:25calculateFirstValue.
05:27So when I hit this, we are going to jump in to that call.
05:31calculateFirstValue has one line of code, and we are right before that line,
05:35which says return 10,000, so I click step into again and we jumped back out,
05:39back into the next line, which is a call to calculateSecondValue.
05:43I am going to continue on jumping in.
05:45We jump into that calculateSecondValue method. It sets up an integer a = 0 and
05:50integer b. That's a call to calculateFirstValue again.
05:54Well, let's say I don't want to actually jump into that method.
05:58I don't need to go through it. It looks fine.
06:00What I am going to do instead is move and click the other one, which is Step over.
06:05Now Step over does not mean bypass this line of code.
06:08It means execute it,
06:09but if it's making a call to another method, don't go into that method; just
06:13execute this line and move on.
06:15So click that once, we execute line 24.
06:18If I mouse over b, I can see that it's set to 10,000, which were the results from
06:23calling calculateFirstValue. That looks correct.
06:26And now we are into the start of the for loop.
06:28If I was clicking this here to step into, what's going to happen is I am just
06:32going round and round the loop right now because we have a loop set up to go 5000 times.
06:36Every time around it's adding one to b.
06:39This is going to be a little tedious if I have to go around 5000 times. I
06:42really don't want to.
06:44So what I am going to do instead is say, I just want to pause before that call
06:47to a here, so I'm going to set another breakpoint,
06:50Then come down to the controls of the debugger and just say Continue program execution.
06:55That means continue until the next breakpoint
06:58if there is one, so hit that.
06:59We're going to have gone around that loop 5000 times.
07:02I can even check it by seeing the value of i was 5000, b is equal to now 15,000,
07:0710,000 plus 5000. And we're about to return a.
07:11There is the problem. We're returning 0.
07:13Well, I didn't want to return 0.
07:15I want to actually change that value.
07:17In fact, let's double-check that this will work.
07:19I am going to change the value of a while we are in this paused state.
07:22Could do it a couple of different ways The easiest one is in my variables view,
07:27I'll just double-click the value of 0 and say 300, hit Return. A is now 300.
07:32I am going to hit Step into to execute that Return statement.
07:36We come back to line 38.
07:38This is the line that was giving us problems before.
07:41But hopefully what we should be able to do now is just try an example of
07:4510,000 divided by 300.
07:46So I am going to try and execute this line of code.
07:50Looks good. We don't have any arithmetic errors, so we are onto line 40, which we
07:54hadn't got to before, which we hadn't gone to before.
07:55In fact, what I am going to do is move over and just say, Continue program
07:59execution, just keep going now.
08:02And what this does is continue. Now the program goes back to running as normally.
08:06We actually get that label being updated, the result is 33.
08:08I am going to quit out of this and go back into the code, because I can see here
08:13that this was where my problem was.
08:15I could fix this any way I see fit.
08:17Obviously, we were just doing some very simple and very straightforward code.
08:21I just want to make sure it's not returning zero.
08:23Now what's a very common thing is as you go through this process quite a bit,
08:27you'll end up with a lot of breakpoints.
08:30I've only got two, but it's quite easy to have several, to have several dozen in fact.
08:35So if I wanted to switch between the modes of having all the breakpoints on and
08:39having them all off, I don't want to have to go through and either deactivate
08:42them or indeed drag them off all the time.
08:45So if I have several breakpoints set through different parts of my code, what I
08:49can do is use this button up here on the toolbar to just temporarily deactivate
08:55the breakpoints, which means if I run it this time around, we can run it without
08:59breakpoints and just see the result. Looks good.
09:02I am going to quit out of it and then just come back up, turn all the
09:06breakpoints on again.
09:07Run it again. Clicking the button will immediately take us into that paused mode.
09:13These are the major parts of this debugging environment.
09:16We have the debug navigator on the left-hand side, giving us the stack trace.
09:21We have the Variables view and the Console in the lower section.
09:25We have the ability to set and turn off breakpoints, multiple ways to step
09:30through our code, and the option to change variables as our code is actually running.
09:35And just these few options should give you the ability to debug most of the
09:39situations you'll run into in your first couple of years of iOS development.
Collapse this transcript
6. Using UI Controls
Creating user interfaces (UI)
00:00Just buttons and labels can get a little boring, so I'm going to create another
00:05single view application that'll let us experiment with a few more of the
00:08controls and other ways of setting out a user interface.
00:13So I'm going to open up my ViewController.xib, my NIB file, and I want to make
00:19sure that my Utilities panel is open on the right-hand side, so I have access to
00:23my inspectors and to my Object Library.
00:25Now, we've seen the Dock over here when we were editing the user interface file.
00:30This can be maximized, or it can be minimized, but it can't be hidden; we
00:33always need it. And the icons in the Dock are the File's Owner, First
00:38Responder, and View.
00:39File's Owner, as we've seen, is an icon that represents a connection from this
00:43user interface out to the corresponding view controller object.
00:47It's basically how we connect our .xib to our .h and .m. And the First Responder.
00:54We've heard this term working with the text field.
00:56For us, it's simply a placeholder object.
00:58We won't need to touch it.
00:59And this View icon. Well, this represents a UI-View object and if I click it, I
01:06can actually take a guess that it's representing this one iPhone user interface
01:10screen that we're currently working with.
01:13As you probably noticed, when we're designing these screens, we have the Status
01:16Bar at the top with battery charging symbol.
01:18That's because for a typical app, the Status Bar is always shown, although it's
01:22not really part of your app.
01:24So actually seeing it here is a bit of a lie.
01:27It doesn't represent anything real in this interface.
01:30It's here as a guideline for you to set out your interface correctly, so that
01:34you see your user interface elements in context on the normal-sized layout.
01:39So, there's the question: What is a normal layout? How much space do we have?
01:43Well, a regular iPhone held upright is 320 pixels wide by 480 pixels high.
01:51Now, if I make sure I've this view selected by clicking it so it has the blue
01:55outline, I'm going to switch over here in the Inspectors to the Size Inspector.
01:59It's the one that looks like a ruler and will give us our measurements for
02:03whatever's currently selected.
02:05It's telling me this view is 320 wide and 460, not 480, high, and that's because
02:13the Status Bar is taking 20 pixels.
02:16There's a question:
02:17What about iPhones with a retina display? Because as you may know, the iPhone
02:224 and 4S, well, they have screens with double the resolution of the original iPhone.
02:27They are 640 pixels wide, not 320.
02:30They're 960 pixels high, not 480.
02:33Well here, it doesn't matter.
02:36In the interface builder part of Xcode, these measurements are in points not
02:41pixels and they'll automatically be treated as 1 pixel on a non-retina iPhone
02:46and 2 pixels on a retina display.
02:49Now there are a couple of places in Xcode where you can provide different assets
02:53for the different size screens.
02:55For example, if I'm editing the project settings, there are places I can
02:59drag and drop a regular application icon and a higher-resolution icon for a retina display.
03:06Well when we're working on a regular user interface, it doesn't matter. It just works.
03:12So with that view selected, I'm going to switch to the Attributes inspector,
03:16the fourth one, and you'll find this is the inspector where you'll spend most of your time.
03:21With the View selected, I have things like being able to turn the Status Bar
03:25from gray to black or translucent black.
03:27I have options for setting a Top Bar with a Navigation Bar and the Bottom Bar
03:32to a Tab Bar, selecting the different options to see how large they can actually get.
03:38But notice at the top here of this section it says Simulated Metrics.
03:42These are not adding functionality;
03:44they just allow you to turn these placeholders on for this view, so you can set
03:48out the rest of your controls correctly if you know that you will be using
03:52navigation bars and tab bars.
03:53So I'm going to switch this back just to using a regular gray status bar and no
03:59top bar and no bottom bar.
04:01We also have the option to switch from portrait to landscape and lower down
04:06in the Attributes inspector, we can do things like change the background color of the view.
04:11There's not an awful lot more you would do with a regular background view.
04:15So let's see a few other controls.
04:17I'm going to drag my Object Library up a bit, just so we have more of them here.
04:22And you've properly scrolled up and down in this library and seen that there's
04:26quite a lot of things, but if it's more useful for you, you can filter down to
04:31see the subset of just controls or the subsets of gesture recognizers.
04:36If I select Controls, you'll see there actually aren't that many basic controls;
04:40there's only ten here.
04:41For a great single paragraph about each one, select it and then hover, and what
04:47you'll have is a popover that comes up for that particular control, just giving
04:51you a great introduction to it.
04:53To go a little deeper on any of them, you want to drag one onto your user interface.
04:58In fact, I'll drag on a few.
05:01As ever, I can use the lines to center them on the view.
05:05It will give me some guidelines about when I'm getting too close to another user
05:10interface element and if we have multiple elements, I can also use the Editor
05:16menu to do basic things like aligning the left edges.
05:19I'm going to drag the object library down just so I can see the inspectors a bit
05:25more now. And with any of the user interface elements selected, I can use the
05:30Quick Help inspector, which is the second button, to get that information, to find
05:34the actual reference to that element, and the Attributes inspector to find out
05:39what's specific about that.
05:41With this Segmented Control, we can change the style of it.
05:45We a can choose how many gegments are in it and what the title of each segment
05:50is. With a Stepper selected, instead here I have minimum and maximum values.
05:55With Continuous checked, we can have things like the ability just to hold down
05:59on the plus sign and have it continue to rise.
06:05I can select any of these user interface elements obviously by clicking
06:09directly in the screen.
06:11I can also click on it using the expanded view of the dock here and just
06:16selecting them. Or I can use the Jump Bar, which tells us where we are in the
06:21XIB inside the view with the stepper selected, but I can use this to change to,
06:26for example, the switch.
06:28While it seems obvious just to select them on the view itself, when you have a
06:32complex UI with several overlapping controls, or even controls that you want to
06:37be turning on and off in code, the Dock and the Jump Bar can actually be a more
06:42reliable way of getting directly to a control.
06:45And if you're building more complex layouts, you can actually make use not just
06:49of the view that we already have, but another view as well.
06:53The view that we have, this background, is really just a container, but you can
06:57have containers inside containers.
07:01You'll actually find that the Object Library, if I view all the objects
07:05available in it, has something just called a View object, a rectangular region
07:12for drawing and handling events. This also works very well as a container.
07:15Now, of the things you can do with it is select a few elements, go up to the
07:21Editor window, and then you have an Embed In option.
07:24I'm going to embed those in a view, and what that actually means is they're now
07:28contained and I can treat them as one unit.
07:31Perhaps in code, I could even turn this on and off, make it visible or invisible.
07:35If you have the expanded view of the Dock, you'll actually see that it now
07:39considers our main view, which is the main screen if you will, to have another
07:43view inside it with three controls inside that.
07:47So there're multiple ways of managing controls and containers of controls.
07:51Now, we saw that filtered view here with ten on them,
07:55if you remove that search term. But obviously, we don't just have ten controls.
08:00These are the basic ones.
08:01We have a lot of more complicated controls with greater functionality.
08:05There's a section just of gesture recognizers for swiping and pinching.
08:10There's a section just for windows and bars for navigation and for searching and
08:15using the toolbar, and we'll see those a little later. And a section for what
08:19are called Data Views, giving us things like the Image View to hold one or more
08:24images, the Map View, the Text View and controls like the Picker View or the Date Picker.
08:31And the Data Views tend to be very powerful and very useful.
08:34So let's see some of those next.
Collapse this transcript
Using and customizing a picker control
00:00Let's see one of the more interesting controls, the Picker control.
00:03I am going to make a new project here, go into my XIB file, and with the Object
00:12library open--and I will make sure all objects are viewable here--
00:15I am just going to filter on the word picker.
00:18I can see that I have two of them here, and I am going to work with the Date
00:22Picker right now, which is the most straightforward one.
00:23We'll see the other one next.
00:25We'll drag it onto this interface, making sure to slide it into the right spot;
00:30it's quite easy to move it off screen.
00:33And with that selected, I can see that in my Attributes Inspector, this Picker
00:37control has multiple different modes:
00:39We can be just a time, just a date, date and time, a countdown timer.
00:45I am going to select just Date and use that.
00:48Now, you'll find that when this Picker control is run, by default it will just
00:52set itself to today's date.
00:54You could write a little bit of code to change that, if you wanted to.
00:59What I want to do is allow the user to select a date from any of the possible
01:03options here and then find out what day of the week that was.
01:07So I am going to go back into my code, quit out of this simulated application,
01:12remove the filter from my Object Library so I can find a Round Rect button,
01:17drag that on, and just type in "What day is that?"
01:23This button will need to send a message to our code so it will be an IBAction.
01:26I am going to hook that up, give myself a bit more room here, and switch to
01:32the Assistant Editor.
01:34I'll right-click the button--Ctrl+ Click works too--and connect the Touch Up
01:39Inside over here into my interface.
01:42The action that I'll call, I'll call displayDay, and hit Connect.
01:47Similarly, what I'm going to need is to address this Date Picker control from my
01:53code, so I need to hook this up as an outlet.
01:56I can right-click somewhere here.
01:58I am not interested in the Picker Events; what I'm interested in is the
02:02Referencing Outlet Connection.
02:04The benefit for me of using the right- click menu is that when we drag across
02:10the interface, it doesn't ask whether we want to insert an Action, Outlet,
02:14Outlet Connection; we have already limited it so it knows to insert an outlet.
02:19I let go. All I have to provide is a name, and I will call it datePicker.
02:25And I should be now ready to add my code.
02:28I am going to change back to the Standard Editor view, turn on my Project
02:32Navigator so I can select the View Controller implementation file.
02:36Down towards the bottom I should find where it has inserted the IBAction
02:41skeleton. I'm just giving myself a few more lines to bring it up closer to the top.
02:47Let's take this line by line.
02:48When the button is touched, we are going to grab whatever date the user has just
02:53selected on the datePicker.
02:56So create a new NSDate variable and set it equal to the datePicker date property.
03:05Next, I am going to create an NSDateFormatter object.
03:09You have seen this briefly already. What a DateFormatter allows us to do--not
03:14surprisingly--is format our dates in all sorts of different ways than the
03:18internal representation of an NSDate object, which is going to be date and time
03:24and seconds and hours and minutes and all this stuff that I don't want.
03:28What a DateFormatter object does is use Unicode date format. It gives us hundreds
03:33of combinations of different ways of writing this out.
03:37If I open up a web browser, what I can do is quickly search for something like
03:42unicode date format patterns.
03:46And I see the first entry here is the Date Format official document on
03:51Unicode.org, and in fact, I'm going to click the link to jump to Date
03:55Format Patterns here,
03:57which tells us that a date pattern is a string of characters.
03:59We have a few examples here of writing out these letters and what result that
04:04would give us for a particular date.
04:07If I scroll down a little further here, we will see the Date Field Symbol Table.
04:11We have different kinds of letters for representing years, quarters, months,
04:16weeks, days, periods, zones.
04:20What I'm interested here is this, weekday. We are using the letter E, the
04:25uppercase E. If I use one through three Es, that will give me the short version, like Tues.
04:31But if I use four uppercase Es, that will be Tuesday.
04:35That's what I want.
04:36I am going to jump back into my code and show you how to do it.
04:39I have created the formatter object, just called formatter.
04:42I am going to say setDateFormat, passing in a string which will just be four Es.
04:52Now I am going to create a new NSString object, which is going to contain
04:57that day of the week.
04:59I'll get it by telling the formatter to go ahead and create a string from the date chosen.
05:07This is the one that we just pulled out of the datePicker.
05:10So the formatter is transforming that date using its set format into just
05:15the day of the week.
05:17Next, I am going to create a new NSString object and I'm going to use the init
05:22with format initializer so I can construct a message here with a placeholder in it.
05:28"That's a," and whatever the day is going to be.
05:31I need a placeholder here, which I'll use percent sign, at sign, close the
05:35quote, comma, and then week day, which is the string that's going to actually
05:41represent that day of the week.
05:44So that will construct our message, and then the final thing I'll do is pop up an alert.
05:49I don't actually have a label or any other way of getting it out to the
05:53interface, so I'll use a UIAlertView.
05:56Using the init with title version, just break that apart to make it a bit more
06:02readable. And I'm going to do a very simple UIAlertView here.
06:08The title of the alert will be "What day is that?"
06:11The message will be msg, which is what we just created on line 71, hit Tab.
06:17We don't need any delegates so that will be nil. The cancelButtonTitle can just be Thanks.
06:24And otherButtonTitles, we don't need any other buttons, so I'll just leave that
06:28at nil, square bracket to close this, just break that onto the separate line,
06:33and we have a UIAlertView.
06:36Finally, I need to show it.
06:40Save it, hit Command+B to build, make sure everything is looking okay.
06:43No issues, Build Succeeded, looks good.
06:46Go ahead and run this.
06:50So I will spin a few of the wheels a few times.
06:52Let's find April the 4th, 1992. Apparently that was a Saturday.
07:01March 4, 2028, that will be a Saturday too.
07:05Let's double-check the third, is a Friday. Looks good.
07:10So yes, a simple application, but this is how you'd start to work with the Date
07:14Picker: hook it up to a button in your code and manipulate it.
07:17Now, Picker is capable of more than just dates, so we'll see that next.
Collapse this transcript
Using data sources
00:00We've seen how to read and set simple single values in text fields and labels,
00:05but we are now going to see how to load more complex data sources.
00:09We are going to use a control called the Picker View, which is a great example
00:13of how more complicated user interface view objects can interact with our code.
00:17Now, we have seen one preconfigured version of this being used with the Date
00:21Picker, but this time we are going to configure it ourselves.
00:24So in my Object Library I am just going to filter down on the word Picker, and
00:28instead of the Date Picker, we will take the Picker View, and I will position
00:32that in the bottom of my main view here.
00:35It has some dummy data.
00:38Now, what I am looking at is this Picker View with one component.
00:42Now, a component in the Picker View is the official name for this movable piece.
00:47You can think of the component as a column that can have multiple rows.
00:51So if we were looking, for example, at that Date Picker, this one and this view
00:56of it has four components.
00:58If I switch that Date Picker to the Count Down Timer, this has two components.
01:04With just the Date, it has three components.
01:07Each component can hold a vastly different amount of data in it.
01:11So I am going to delete the Date Picker because we are not using that.
01:14We are going to make our own.
01:15And if we are going to define our own picker, we need to say how many components
01:19exist and how many rows are in each component. What's the content of each row in
01:25each component? And we can also say what happens when somebody chooses between
01:29them and selects a row.
01:30Now, you might think that if you drag one of these Picker Views onto your user
01:34interface, you could then go to your Inspector, say the Attributes Inspector,
01:39and start loading it with data somehow.
01:41But you are not going to be able to do that.
01:43We're going to have to provide the data from our code.
01:47Unless all we want is the Apple- provided list of cities in California, we
01:51have to do it ourselves.
01:52So let's talk about the simple situation of configuring a Picker View.
01:56I want to have a picker that has a straightforward single list of items. For
02:00this app it will be a mood checker.
02:03We can spin it and say whether we are ecstatic or happy or cheerful, and this
02:07data has to come from somewhere.
02:09And the way we do it is by connecting the picker to an object that can be
02:13its formal data source.
02:15And the data source has to answer two questions.
02:18How many components does this picker have,
02:21and how many rows does each component have?
02:24In this case we will have one component and we will have maybe a dozen rows.
02:29But we also need to connect this picker to a delegate object.
02:34And the delegate answers to more questions:
02:37What's in each row, and what happens when any row is actually selected?
02:42Now, you'd be forgiven for thinking that the data source and the delegate could
02:46really be combined into one thing, and it does feel like that, but we do formally
02:50describe them as two different pieces.
02:52However, one of the easiest ways to deal with this is we will nominate our
02:57current View Controller as both the data source and the delegate.
03:02And we will put all the necessary code in that one View Controller.
03:05And we support the situation just by writing methods with particular names
03:10inside that View Controller.
03:12So back in to XCode. How do I hook this Picker Control up to my View Controller code?
03:17Well, the same way we hooked anything up there.
03:20I'm going to jump across to the Connections Inspector.
03:23We could also do this by right-clicking. And I will see that the Picker Control
03:27has two outlets listed here: the two we just mentioned, dataSource and delegate.
03:32Technically, they could actually be connected to different objects, but I'm
03:37going to grab the plus button beside dataSource and drag it over to File's
03:42Owner, which represents the link to the ViewController.h and ViewController.m
03:46files, and I will do exactly the same with delegate.
03:50I can see in the Connections Inspector they are both registered as being
03:53hooked up to File's Owner.
03:55Now I am going to jump over into my header file for that, because if I want to
04:00do this properly, what I should also do is make that promise in my class that
04:05we're going to be the delegate and we are going to be the dataSource.
04:08We have talked about using the little angle brackets before.
04:11So after UIViewController, I'm going to put the opening angle bracket and type in UI, start
04:19typing PickerViewDelegate.
04:21We see that we have got two options here:
04:23UIPickerViewDataSource, UI PickerViewDelegate.
04:26We actually need both of these.
04:27It doesn't matter which order they are in.
04:29So UIPickerViewDataSource, comma, UIPickerViewDelegate.
04:35And be careful with the delegates, because there are many of them, so you don't
04:38want to select the wrong one.
04:41I am now marking my class.
04:42I'm saying we are promising to support, being both the dataSource and the delegate.
04:46One of the benefits of marking it this way is if I save this and then hit
04:50Command+B to build, we are going to get a compile error.
04:54Over here in my Issues Navigator, it's telling me there is a semantic issue, an
04:59incomplete implementation.
05:01I can actually expand these ones here that say there is a method in the protocol.
05:06We are promising to support a protocol, but we are not actually supporting it.
05:10Now, we could actually click further into this to find a few more details, but
05:13we actually know what's going on. Because in my implementation file I said we
05:19are UIPickerViewDataSource and we are a UIPickerViewDelegate, but what does that mean?
05:23Multiple ways to find out.
05:25One would be holding down the Option key,
05:27I'm going to hover over UIPickerViewDataSource and click it.
05:31We will get the popover window. And I have two ways of getting to the
05:35meaning behind this.
05:36I could go to the reference and see the actual documentation of it, and here it
05:41would give me the protocol reference for being a dataSource. What must I do?
05:45I can see there's only actually two tasks, and they are both required.
05:50This is where I say how many components do I have? Number of components in
05:53Picker View. And how many rows does each one have? Number of rows in component.
05:59I could copy these and paste them into my code.
06:02Alternatively, another way I could have looked at this is, again, by
06:06Option+Clicking it, and instead of going to the documentation, I could go to the
06:10header file for UIPickerView. I click that,
06:13it takes me right here to the protocol for being a UIPickerViewSource, and I
06:19have actually got code here.
06:20We must provide methods with the signature.
06:22Okay, I'm going to copy both of these, the numberOfComponentsInPickerView
06:28and the pickerView: numberOfRowsInComponent. Copy that.
06:32This isn't our file.
06:33We're deep inside the iPhone OS framework.
06:36I need to go back over into my ViewController.m file, and I am going to paste
06:42them inside the implementation.
06:44You can put them anywhere.
06:46Now, right now these aren't actually proper signatures, so I need to replace
06:48that closing semicolon with an opening brace, for both of them, and now we have
06:54that skeleton functionality.
06:56So first, return the numberOfComponentsInPickerView, one of them return 1.
07:03That's it, first step is done.
07:05Second, return the numberOfRowsInComponent. Well, that one is different.
07:10I don't actually know right now.
07:12What I'm going to do is something fairly simple.
07:14I'm going to just create an array with a certain amount of values in it.
07:18I want to access that array from a few different places in this class,
07:21so I am going to go ahead and just create it as a property.
07:23Jumping into my header file, I will just say property.
07:27It will nonatomic and strong, NSArray, and I will call it moodlist.
07:36Jump over into the implementation, where I want to make sure that I
07:39synthesize that. Done. And I want to load that up with a few values when this application loads.
07:48I could do that from a few places, but one of the places that will work is for
07:52me to write it here in viewDidLoad, moodlist, which is already defined as an
07:58NSArray equals--this is where we create i-t-NSArray alloc, and I'll use the
08:06method called initWithObjects.
08:09We can just give it a series of strings, for example, separated by commas, and
08:14just finish it off with a nil.
08:19Here of course I could have been loading some information from a web service
08:23or from a database like SQLite or using core data. That's a whole another discussion.
08:28So I just want something simple.
08:30Seeing as this array is going to be instantiated as soon as the view has loaded,
08:35that's going to be before this numberOfRowsInComponent is called.
08:40And I need to return the number of rows it should show.
08:44I don't want to make a manual count, but I don't have to. All I am going to say
08:47is, return moodlist count.
08:53However many options are in it will return that number, but we are missing something.
08:59We had said in our View Controller that we were going to have the dataSource
09:03connected to File's Owner, and we've done that.
09:05We've provided the two necessary methods, but we are also the delegate.
09:10Now, what does that mean?
09:11Once again, we can hop into the header.
09:13We have seen what it means to be a dataSource, but I could also click here and
09:18see what it means to be a delegate.
09:20And if I have that PickerViewDelegate selected, and even reading in Quick Help,
09:24the delegate of the UIPickerView must adopt this protocol and implement at
09:28least some of the methods to provide the pickerView with the data it needs to construct itself.
09:33So I am going to come down here and click on the PickerViewDelegate
09:36Protocol reference.
09:37Again, the list of tasks that we have, we don't actually need all of these, but
09:41if I scan, we can see things like Setting the Dimensions of the Picker View, the
09:45row height or the width for a particular component, because when you have
09:49multiple components, they are not all the same width. Take a look at the
09:52datePicker. Months and days and years all have different widths.
09:56What we are interested in is the Setting the Content of Component Rows.
10:01Now, notice the text here. The methods in this group are marked optional.
10:05We would be able to compile our application without providing them, but as it
10:09says, to use a pickerView, you must implement either the
10:13pickerView:titleForRow:forComponent or the
10:17pickerView:viewForRow:forComponent:reusingView:.
10:21Neither of them have a wonderful- sounding method name, but the one we want is
10:25this, pickerView:titleForRow:forComponent.
10:30I am going to copy the signature of that, including the minus sign, jump
10:35back over into my code.
10:37I want to be in my implementation. It doesn't matter where I put it, but I'm going
10:42to put it after my two dataSource methods, and paste it in there.
10:47I need my opening and closing braces.
10:49This is a delegate method, meaning we don't care about how this is called.
10:54We just know it will be called.
10:56What's going to happen, automatically, is that when that picker component loads,
11:01it will ask the dataSource how many components it's suppose to have, and it will be told 1.
11:07It will then ask the dataSource how many rows are in that particular component
11:12and be given the answer: Well, how many entries are in the array?
11:15And then this delegate method is going to be called for every single one of
11:20those where we have to provide the actual correct entry for each correct row.
11:24This is simpler than it sounds.
11:26We are being given several parameters here:
11:30a pickerView, a row number, and a component number.
11:34The only one I'm interested in is the row number, because I know we only have
11:38one pickerView and I know we only have one component in it.
11:42So this method is going to be called passing in 0, 1, 2, 3, 4. All I need to
11:48do is take that parameter of row and use it to access the correct piece of the array.
11:53So I am going to have a return statement that just says return, and then accesses
11:58my moodlist array, which is already loaded up with values.
12:02Whatever object comes from the particular index of row.
12:06Save it, build that, Build Succeeded, no complaints, and run it.
12:12And we have our picker being loaded up with the information from our array.
12:16Of course, we can take this a little further to see how to respond to these
12:20different items actually being selected, but we will see how to do that in
12:24a moment.
Collapse this transcript
Selecting items in user interface controls
00:00So if we have a customized Picker View that's been loaded with some data, it's
00:03almost certain that what you want to do is handle a selection.
00:05When someone changes the row here, we're going to do something about it. Let's see how.
00:11Going back into Xcode, this is not something that's done with say a touch up
00:16inside, like a button;
00:17it's best done by implementing another delegate method.
00:21Now, one of the benefits we have is we're already hooked up as a delegate to
00:25the file's owner; we simply need to implement another method that we haven't done yet.
00:29If I look at my header file, I could select the PickerViewDelegate area
00:34and either use Quick Help, or click with Option held down and go to the
00:39Delegate Protocol Reference.
00:41The brief description here--it's not very long, but we do have this section that
00:45says--here's how you respond to a row selection.
00:49This Delegate Method is optional, because perhaps you don't want to respond when
00:53somebody changes the actual picker; maybe you're waiting for something else to
00:57happen, like a button touch. But we do want to respond here,
01:01so I'm going to copy the signature of that, jump back into Xcode, into my
01:05implementation, and I'm just going to paste it in below the other Delegate Method.
01:12Need my opening and closing braces, and look at what we've got.
01:16I'm going to split this across a couple of different rows, just to make it a bit more obvious.
01:20This method gives us three pieces of information:
01:23the pickerView, and the parameter that represents which pickerView;
01:28didSelectRow and a row;
01:31inComponent and the component. All I'm interested in is the row.
01:36I know what pickerView it is. We've only got one.
01:38I know what component it is. We've only got one.
01:41But of course we could have an interface here with, say, two pickerViews on it,
01:46with multiple components on each, and both of those pickerViews could be hooked
01:50up to this class file as the delegate.
01:52So then the same method would be called repeatedly for different pickerViews,
01:56and using these different parameters, I could tell which one it was.
02:00Right now I don't have to worry too much.
02:03So inside here, what I'm going to do is first set up a new object called a UIColor.
02:09We'll see why in a second.
02:11Then I'm going to do a switch statement, by typing switch and then hitting tab.
02:16It will fill in basics for me.
02:18What I'm going to switch on is the integer called row.
02:21So I'll just type in row. And then we have multiple options this could be.
02:26The value I'm going to get will be zero based.
02:29I'm going to do something fairly simple here, actually do multiple case
02:33statements at the same level.
02:36In this switch statement, I'm just checking various ranges of values and then
02:41storing a new color: yellow, gray, or black.
02:44I want to make sure that I've got the break statements in all my cases;
02:48otherwise, we'll get some fall-through going on.
02:51And you might wonder, what do these ranges represent?
02:54Well, I know that when I created the array
02:57I loaded up several different options here for mood, and they're kind of grouped
03:00together into the happy end, the middle end, and the sad one.
03:05So I'm just doing something very simple that gives each of these its own little category,
03:10its own little color coding.
03:11And the last thing I'm going to do after the switch statement is change the
03:15background color of the current view.
03:17The question might be, well, how I do this? I haven't hooked it up to anything.
03:20I haven't made it an outlet.
03:23Well, luckily there's an easy way to get to it.
03:25I'm in the ViewController. If I say self-- and I'll do dot syntax here actually.
03:30I'll do view.backgroundColor = newColor,. Save it, run it.
03:39Now, when this first loads, that delegate method is not being called. What I
03:44need to do is start moving around and selecting it.
03:48When I let go, I should have that delegate method called, and it will actually
03:52change the background color of the view. I just changed it to the same one.
03:55We go down to the lower end. It becomes black; in the middle it's gray; up at
04:00the high end, it should be yellow.
04:02And all of this is being done through delegation on this.
04:06This control itself does not have any actual touch events happening; it's all
04:12being done through the data source and the delegate.
04:15It's another example of how more complicated UI elements use delegation to
04:19handle their behavior and do anything interesting.
Collapse this transcript
Using the Apple Human Interface Guidelines (HIG)
00:00Now that we've seen several of the built-in controls, it's worth stepping back
00:04and going to the Apple Developer site, developer.apple.com. And in the iOS Dev
00:09Center, there is a document you really need to read at some point early on in
00:13your iOS career, and it's the Human Interface Guidelines, or HIG, for iOS.
00:18Now, you will often not even need to be logged in to get to this one.
00:22You will often find it just on the homepage, or you can search for it, if it's not obvious.
00:27These are Apple's rules for what your interface should look like, how it should behave.
00:32And they aren't just suggestions.
00:34If you deviate too much from these rules, it's a common reason for your app to
00:38be rejected from the App Store.
00:39Now, this document is not super technical. It's not about code.
00:44You can get it online on the web, or you can download a PDF version for
00:48printing, et cetera.
00:50It's about 180 pages or so, but it's great, useful content.
00:54It's split up into several sections, including the basics of the platform and
00:59the principles behind it.
01:00There is a section on your app design on actually planning the application,
01:04creating your definition statement, figuring your audience out.
01:07There are some really good case studies on things like the conversion of Mail
01:12on the Desktop to an iPhone application, or taking Keynote on the Desktop to a
01:18successful iPad application.
01:21But there are two other sections that are particularly useful.
01:24The User Experience Guidelines, because while this section is non-technical, it
01:29gets very specific, the short principles that you should be adhering to,
01:34things like de-emphasizing settings, so you don't have to make your users leave
01:38your application to go into the Settings App.
01:41And very specific parts, like making your targets fingertip-size.
01:46Down to the level of what exactly that should mean, that, say, on a calculator all
01:51the buttons should have a target area of the atleast 44x44 points.
01:55Further down in the User Interface Element Usage Guidelines, you have things
02:00like the system-provided buttons and icons, and these are the ones that are
02:04actually provided for you by Apple and available in the iOS.
02:09So when you're using things like tab bars and toolbars and certain terminology
02:14for that, you're doing the right ones.
02:15Now, this document doesn't just describe visual items here;
02:19there are also sections on things like audio behavior and expectations.
02:24And down towards the bottom of the document is the Custom icon and Image
02:28Creation Guidelines. It covers in depth things like the size of your application
02:32icons, what they should be for a regular iPhone versus the Retina display, and so
02:37on, the size of your app icon, the size of launch images.
02:42Now, we'll come back to these a little later on.
02:45So these are very specific guidelines that you must pay attention to.
02:49Not only is this documentation full of really good content, do remember that
02:53if you deviate too much from it, it can be a reason for your app to be
02:57rejected from the App Store.
Collapse this transcript
7. Using Table Views
Introduction to table views
00:00You might think Table Views sound like a new thing to learn, but you really
00:04already know what's in this section.
00:06You have already used table views.
00:08If you've used the Settings application, if you've used the iPod or Music
00:13application, you've used Safari or Mail.
00:16You have used Table Views.
00:17They're everywhere.
00:18They're very common.
00:20Anytime you see a list like this that you can scroll up and down.
00:23It's pretty much in that Table View.
00:25Now if you've thought about it you might have thought things like this would
00:28different, because they can look quite different from each other.
00:31Some have big text, some have big text and small text, some have images,
00:36but they're all Table Views, and probably the most common control in an iOS application.
00:43So let's talk about some core principles here.
00:46All Table Views are one column wide. That's it.
00:50It might occasionally look like more than that, but it isn't;
00:53Table Views are one column wide.
00:55Now these table views don't store your data. They just show it.
01:00So don't get them confused with database tables, for example. This is MVC.
01:06These are view objects, and they show data that is stored somewhere else,
01:11whether that's in an array or a property list or one of your own objects.
01:16As you scroll these Table Views up and down, each piece of data that you see in
01:21a Table View is considered one row, and each row contains one UITableViewCell.
01:29And even when you see Table Views with significantly different formatting, plain
01:34text, bold text, perhaps even images in those individual elements.
01:38It's because that one cell has been formatted to populate the cell with more
01:43than just a basic piece of text.
01:45But we want to know how to start working with these.
01:47So what we have to do with a Table View is fill it with data, and the way we do
01:52that is by hooking up the Table View control to a data source, very similar to
01:57working with the Picker.
01:58We have to have a class defined as the data source for this Table View, and in
02:03that data source we can say at its most basic, how many rows exist and what's in each row.
02:09And you can also say little bit more such as, is that Table View split up into sections?
02:15And that's what the data source provides.
02:17There is also a Table View delegate which can handle things like what happens if
02:22somebody selects one of these rows.
02:24Do I want to do something, do I want some operation to happen?
02:27We need to hook up our Table View to a class, and very commonly that's going to
02:33be our View Controller.
02:34It doesn't have to be the View Controller.
02:36You can make your data source, or your delegate any class in your application,
02:40but we're going to use the View Controller and put the necessary methods in
02:44there to see an example of one of these.
Collapse this transcript
Creating a table view
00:00So I have a single view application right now.
00:03There's no change from the default project type.
00:05I am going to go into XIB file and from my Object Library, I am just going to
00:10filter on the word Table.
00:13I'll see three things here: the Table View, the Table View Cell, and the
00:16Table View Controller.
00:17I want a Table View.
00:20I already have a View Controller.
00:21I am going to click that guy, drag it across, and make it fill this screen.
00:26If I look at my Attributes Inspector, there is not an awful lot we can do.
00:32We can change a few things about the Table View like whether it's plain or
00:36grouped, and we'll see that in a little while.
00:38The important thing I need here is in the Connections inspector, the last part
00:43of the Inspector panel.
00:44My two outlets for dataSource and delegate, and both of these I am going to hook
00:50up to File's Owner, so we can just write the code in our View Controller class.
00:54dataSource over to File's Owner and delegate over to File's Owner.
00:59What I want to do is populate this table view with some data that's actually
01:03stored in a file right now.
01:05I have a file called courses.plist which is on my Desktop.
01:10You can get it in the exercise files or create one yourself.
01:13So I am going to grab courses.plist, and I'll talk about this in a moment.
01:17I am just going to drag it over into my project. I'll put it in the Supporting Files folder.
01:22It doesn't really matter where it goes, as long as it's in the project.
01:26Now when this window pops up, it's very important that we choose to copy the
01:31items in to the destination group's folder if needed so that we have our own
01:36copy of it, and it's not just linking back to it on the Desktop.
01:39We want to keep all our files together.
01:41So I have courses.plist here.
01:43This is a property list file, and all I have in it is a list of a few courses
01:49from lynda.com related to iOS and their authors.
01:53You can of course create property list files yourself if you go to the
01:57Xcode New File menu.
02:00One of the options that you will find in the Resource section is a Property List file.
02:06Creating this--and you don't have to, I am just going to create a dummy one
02:10here--would give me this plist file with keys and values, and all I have really
02:15done is do the equivalent of putting in a course title and tab over and the author goes here.
02:21Hit Return a couple of times to get a new one.
02:25I haven't done anything more complicated than creating multiple entries like this.
02:29I'm going to delete that plist file because I don't need it.
02:32Choose to delete the whole thing.
02:34The only thing to bear in mind here is that I'm using these as keys and values
02:39and keys need to be unique.
02:41So I can't have a duplicate entry in this left column, although it doesn't matter
02:46if I have duplicate entries on the right; the key is the important part.
02:50So I want to load this file into our application when it's running.
02:55Now to do this, I am first going to jump over to my ViewController.h file,
02:59because I am going to define a couple of objects that can hold this in our application.
03:05First I am going to define NSDictionary object, which will hold multiple keys
03:09and values, the course name and the author.
03:12Then because a dictionary doesn't have a numeric index--it's all based on the keys--
03:18it would actually be quite useful in this example for me to have one.
03:21So I am going to create a simple NSArray, so that I can make a numeric index for this.
03:26And what I can make in a moment is a zero-based array that will just contain all
03:32the keys for that dictionary.
03:34So, I jump across to the implementation file because here I do need to synthesize
03:39both of those properties.
03:41I am going to go ahead and drop down into--viewDidLoad will work here, to write
03:48some code to load in that file.
03:50First thing I need to do is construct a string that has the path to the file.
03:56And the question is, well how do I get to that well? Here is how.
04:01Split that out a bit.
04:02Now what I'm doing here is using this NSBundle mainBundle method call.
04:08This is really a way of getting to the installed file system on the iOS device
04:13when I don't quite know what it is. This line might look a little strange.
04:17It's really a way of obtaining that courses.plist file that's part of our
04:21internal bundle, our internal packaged application.
04:25We don't have direct access to the file system on an iOS device, so this is the
04:30way we get hold of our own assets.
04:32Well next, I need to create that NSDictionary that I've already defined.
04:37It was called courses. And I'll set it equal to NSDictionary.
04:44We'll do a normal alloc, but I'm going to initialize and the useful method
04:50I have is this one, initWithContentsOfFile. And I am going to just use the myFile
04:56string that I created on line 26.
05:00So really we're just grabbing the path to that file and loading it into the NSDictionary.
05:05Now the next thing I am just going to do from that dictionary, I am going to
05:09create that array just so I have a numeric-based way of getting to all the
05:14keys in the dictionary.
05:16I can do that very easily by just calling the allKeys method of the NSDictionary.
05:22That's all I need to load the file and create my NSDictionary and my NSArray.
05:26I have got all that information in my app;
05:28I am just not doing anything with it yet.
05:31Well, in our interface file, we had already decided that our Table View is
05:35hooked up to File's Owner as the dataSource and delegate, but what does that mean?
05:40Formally speaking, what I should do in this class definition is volunteer and
05:46say we are now a UITableViewDataSource, comma, and a UITableViewDelegate.
05:54And one of the best reasons for doing this is just so we can Option+Click
05:57on them and actually link to either the protocol reference or just to the header file.
06:02Either way would work. And it's going to tell me that if I'm volunteering to be
06:06a UITableViewDataSource, there are a couple of required methods that I must
06:12implement, which is this one, tableView:
06:16numberOfRowsInSection and this one tableView:
06:19cellForRowAtIndexPath.
06:23I am going to grab this whole block here in between the @required and @optional,
06:29copy it, jump back over into my implementation, and I will paste it a couple of
06:35lines after my synthesize message.
06:37I am going to just get rid of that comment so we can read this a little better.
06:42And of course I just copied the declaration, so I need to add some curly braces
06:46on both of these method signatures to make sure I can add my code.
06:51So watch this first one here: tableView:
06:54numberOfRowsInSection. So how many rows are there going to be in the Table View?
07:00Well, that all depends. How many entries are in that courses plist file?
07:04Well, they are going to be loaded into the NSDictionary, so all I really need to
07:08do is return courses count.
07:13This next method is really the important one, tableView: cellForRowAtIndexPath.
07:21This method will be called multiple times and every time it's going to pass in
07:26a new index position: zero, then one, then two, then three.
07:30We need to build a create the contents of each row and pass it back.
07:35If you notice, that's what we have to return, a UITableViewCell.
07:40This is our job as the data source.
07:43So I'm going to go ahead and first create a UITableViewCell.
07:50I'll just call it cell, we alloc it. And I am going to use one of the more
07:56interesting inits, which is initWithStyle.
07:59What does this mean?
08:00Well, the different TableViewCells can have different styles.
08:04This is an enumeration, so if I start to write--there we go--it pops up here,
08:08UITableViewCellStyleDefault, UITableViewCellStyleSubtitle.
08:13I am just going to go with Default right now.
08:15We'll see the other ones later.
08:17And then we have another argument here, reuseIdentifier, which accepts an NSString.
08:23Right now, I'm just going to give it a string of cell, all lowercase.
08:29What we're really doing is tagging this new object,
08:32this new cell, with a name. And the reason why you might use that reuseIdentifier
08:36is you could have several different kinds of cells in your application, some
08:40with images, some without, some with subtitles, some without.
08:43And we'll see this in the next movie.
08:45We're only going to have one kind of basic cell, so we can call it whatever we want.
08:50I could say cell. I could say Fred.
08:52I could say ABC. It's just a tag.
08:55So the cell is now created, but we are not doing anything with it yet.
09:00I need to give it some kind of value, some piece of information.
09:03I am going to create a new NSString object that holds a course name, and I'm
09:08going to go and grab that from the array that we created a little earlier.
09:14This is a zero-based array that's going to contain all the names of the courses
09:19that I have pulled out of the NSDictionary.
09:21The question is, how do I know which position to go to?
09:24Well, it's been passed into this method, and the cellForRowAtIndexPath gives me
09:30an index path parameter that I can use to get to that.
09:33Again, if you're puzzled about how was this method being called, don't
09:37worry about it; the Table View is calling it automatically because we are the dataSource.
09:42So this method gets called multiple times, passing in different row numbers every time.
09:47We just have to grab the row number and use it.
09:50So I am going to go into that array using objectAtIndex and I'm using the
09:55indexPath parameter that gets passed into this method, but not just indexPath,
09:59just a part of it that says indexPath.row.
10:03Alternatively here again, I am using dot syntax there.
10:07I could also use square brackets and just say indexPath, space, row and access
10:12the property that way.
10:14We should now have a string, and what I'm going to do is set the textLabel
10:20on that cell object that we have just created and set its text to the currentCourseName.
10:28Finally, this method needs to return a UITableViewCell.
10:32Well, we created one. We changed the text on it.
10:35I'll say return cell.
10:38Save it and we'll find out if I missed anything.
10:42It looks pretty good actually.
10:44We have got the Table View. It's scrollable.
10:46It's loaded with data.
10:48Now technically it's a little inefficient right now, and I'm going to talk about
10:52proper ways that we should be creating those cells that are more recommended
10:56techniques for doing it.
10:58But this is the general process:
11:00we add a Table View, we hook it up to a dataSource, we provide the required
11:05methods to say how many rows does it have and what's in each row, and we return
11:10a cell for each different row that we have.
Collapse this transcript
Reusing table cells
00:00An important part of working with table views is reusing your table view cells
00:05correctly, and here's the problem this solves.
00:07Imagine we have a table view with a large amount of data.
00:10It could potentially be hundreds of rows.
00:12And as we swipe up and down, new cells are being created for that table view so
00:17that new rows can be seen.
00:19But there is the question: If we're swiping up and down all the way, do we
00:23potentially have all of these in memory, even the ones that we can't see?
00:27Because of course all we're interested in is the stuff visible at
00:31that particular moment.
00:32We don't need cells in memory if they aren't being displayed and can't be touched.
00:36Well, actually the idea for this is already built into the table view control,
00:41and with just a little bit of code, we can make use of this.
00:44So the solution is this.
00:46We have the table view control, and when a cell moves off the visible section,
00:51it becomes dequeued.
00:54The table view control itself knows that this is not visible.
00:58So rather than us creating a new cell object, we can ask of the table view if it
01:04has any dequeued cells available, and if so, what we can do is just reuse one
01:10instead of creating a new table cell from scratch.
01:13So I'm back to the code that I had for creating the table view cell.
01:19On line 21 through 23 we're creating and allocating that cell.
01:24We're setting its values and then on line 28, we return it.
01:28Well, I don't know for sure that there will be a reusable cell available every
01:32time, so I'm going to ask for one.
01:36I'll create a new UITableViewCell, and the way I'll do it is by asking the table
01:42view--and the table view is being passed in here as a parameter--to
01:47dequeueReusableCellWithIdentifier.
01:51I'm going to ask, are there any reusable cells with the identifier of cell?
01:58Again, this is just the tag that we used to create that.
02:02Now that line can't guarantee me that I actually have one.
02:07There may be a reusable cell available, but maybe this is right after the
02:11application's opened and there isn't any.
02:14So what I'm going to do below it is ask. I'm going to write an if statement.
02:18If cell = nil, or if you prefer to phrase it around the other way,
02:23iust in case you do the single equals sign, if nil = cell\,
02:28I'll copy this code that actually allocates and initializes a cell with
02:32that same identifier.
02:34I have my Pointer symbol in there.
02:37So we already declare it up here and we try and grab one from the table view.
02:42If we hit the next line and I don't actually have one, then we allocate and initialize it.
02:48Either way, by the time we get to line 29, we have a UITableViewCell, we set the
02:54details on it, we return it. But we're not creating a new cell if we don't need to.
03:00Save it, run it, and everything works just fine.
03:04It's actually a little bit quicker.
03:06It's more efficient. It's better practice.
03:08This is something you should always be doing with your table cells.
Collapse this transcript
Customizing a table view
00:00So if this was what all our table views could do, it would be pretty limited, but
00:04luckily they are more flexible.
00:06And we still have to work with a limited amount of space, but let's see a couple
00:09of the other things we can do for them.
00:11So I'm going to deconstruct some code here rather than do it all from scratch.
00:16I have a very similar project to the one I've created before, but rather than
00:20just having this one plist file, I've now added a second plist file with a
00:24second set of courses. And what I'd like to do is change the appearance of this Table View.
00:31Now luckily a lot of this is already built-in.
00:34I'm going to open up my Utilities panel, and with that Table View highlighted,
00:38I'm going to shift it from the normal style of Plain into Grouped. And you've
00:44probably seen this before when using things like the Settings application, that
00:48we now have multiple sections in the Table View.
00:51Again, it's just showing dummy data, but we can fill this in ourselves.
00:55So here's how we support this.
00:56I'm going to jump into my header file.
00:59I've got a couple of lines that are commented out.
01:00I'm just going to explain what they are.
01:02On line 13 and 14 is where I set up the NSDictionary and NSArray to hold my
01:08details about the first files.
01:10I'm just going to uncomment line 17 and 18, where I'm essentially doing the same
01:15thing but with a different NSDictionary and different NSArray, because I need to
01:19hold them all in memory at the same time.
01:21Up in my implementation file, I better have a synthesize statement for those two
01:25new properties, and while I've got a little bit of code that I'll come back to,
01:30I'm just going to jump down to my viewDidLoad.
01:32I could scroll down. Another thing I can use is the Jump Bar here and jump to viewDidLoad.
01:38That was where I was loading in the files originally, and it's where I've also
01:42got the code to load in the next file. Pretty much duplicating exactly that.
01:49We're making new path, we're loading in the NSDictionary with
01:52initWithContentsOfFile, and we're creating an array. Nothing particularly
01:58magical on that one.
02:00But that by itself won't do it.
02:02We've seen that we're implementing this data source protocol, and previously
02:08what we've been implementing on this were the required methods, which were how
02:13many rows in a section and what's the cell for each row?
02:17However, there's a couple of optional methods we can also provide, like number
02:23of sections in the Table View, and this is the important one if we want to
02:27group different sections.
02:29So as you see the comment is, if we didn't provide this, the default would be 1.
02:33Well, I do need to provide this.
02:36So in my implementation I have it, and I've actually written it up at the top.
02:40I'm going to uncomment it there.
02:42We have the number of sections in Table View and instead of one, we're going to return 2.
02:48Not only that, but in my number of rows in section, I can't just return the count
02:54of the dictionary, because I've got two different dictionaries now.
02:57So instead, I have this version.
03:00We're just asking, which section is it?
03:03If I'm in the first section, I return the count of the first course's file.
03:07If I'm in the second one, I'll return the new one.
03:10Here's another optional method that I just had commented--
03:14I'm going to uncomment this--which allows us to provide a different title for each section.
03:20This will be called twice, the first time I'm passing in a section parameter of
03:240, second time section number of 1.
03:27So we'll first set iOS Courses, the second block is Web Courses.
03:31And finally we have the work that we need to do.
03:35We can't just access one array or one dictionary object here.
03:40Instead of grabbing the current course name from the courseKeys array,
03:44I'll comment that one out, because we have to do something very similar to the previous code.
03:50We have to ask what section we're in.
03:52If we're in the first section, I'll use the courseKeys array;
03:55if we're in the second section, I'll use courseKeys_web. We save that.
04:01I'm going to build it, Build Succeeded, and let's run it and see what the end effect is.
04:06And we have quite a different look now.
04:09We've got the iOS Courses header here, showing this group, and as I scroll down,
04:15the Web Courses, showing the second group.
04:17We're still reusing cells and all the other good stuff, the best practices, but
04:22this is the ability to group your content into sections by simply implementing a
04:27couple more methods of the UITableView data source.
04:30But even this I think could be improved a little bit, so let's take it further
04:34next by customizing not just the Table View, but the individual cells themselves.
Collapse this transcript
Customizing table view cells
00:00You can do a lot more with table riew cells other than just having a single line
00:04of text, like we're looking at here.
00:06Now, you can go all out and start creating your own table view cells, even using
00:10Xcode to design them.
00:12While we're not going to do that here, there're a few things we can do just with
00:16a line or two of code.
00:18So, I'm going to go back into Xcode, into this project I have here, very similar
00:22to what I've been building in the last couple of movies.
00:24We're using a grouped table view and I'm loading in information from two
00:28different property list files.
00:30I've just added a little code that's currently commented out and I'm going to go through that.
00:35So as we've seen, the primary method to actually create the contents of the
00:40cell is the tableView:
00:41cellForRowAtIndexPath. And up to this point, we've been grabbing the name of the
00:48course just by going against the arrays that we created from those property list files.
00:53However, the dictionaries we created should also have the author name.
00:57So what I'm going to do in this lower section here is ask, what section are we in?
01:04If we're in the first section, what I'm going to do is use the same call that
01:08I've been doing on earlier lines, go and find the course name, and then use that
01:13course name as the key for the dictionary, to then retrieve the author name.
01:18Now, in the same way, that on line 57 here we have this cell TextLabel setText
01:24call, which we've been using all along to set the main text of the cell,
01:28we also have a detailTextLabel, and here I'm setting the other part of the cell.
01:34Now, if I save this and run it, let's take a look at what it does.
01:39Well the answer is, not very much.
01:41I can't see a change at al,l and that's because the default style that we're
01:46looking at for TableView cells doesn't allow that bit of detail text to show up.
01:51We have to change something about it to make it show up.
01:55Quit and return back into the code. And it's all to do with the line of code
02:00where we actually create, allocate, and initialize that cell object.
02:05We're initializing it with the style of UITableViewCellStyleDefault.
02:10This is an enumeration.
02:12So if we start typing UITableViewCellStyle, we should see under that,
02:17UITableViewCellStyleDefault, CellStyleSubtitle, Value1, Value2.
02:22I'm going to switch to the SubtitleStyle. Save it, run it.
02:28Now what we find is we have the subtitle display, and it's actually doing a
02:32little more than just showing the subtitle.
02:34Whether it was noticeable or not, it's or not it's also slightly shrinking the
02:38size of the main black text.
02:40The subtitle view is very commonly seen inside things like the music
02:43application, so we can have song and album or artist.
02:46So what else we can we do? Well, going back into the code,
02:50I'm in the same method here, but below there, I have a few lines of code that's
02:54going to allow us to retrieve an image.
02:57I'll just squeeze this all onto the same line.
03:00Now, this image I've actually already dragged into my supporting files.
03:05It's just a simple PNG file.
03:08It's 44x44 pixels, which is the default height of a UI TableView cell. And it's
03:14kind of an Apple guideline for the average best size for a finger touch.
03:18So, I jump back into my implementation and what I'm doing here is grabbing a
03:24path to that cell image the same way I grabbed the path to the property list
03:29files, using the NSBundle mainBundle call pathForResource.
03:34On Line 73, we create a new UIImage object just using the initWithContentsOfFile
03:41method, and then on Line 75 find out that cell has an imageView property. The
03:46same way that it has a textLabel property and it has a detailTextLabel property,
03:51there's the imageView, and we call setImage.
03:55Save that, run it, and because we're not doing anything conditional, we're
03:59using the same image for all of them, but it doesn't seem to have a problem
04:03loading any of them in.
04:04Now, while the image goes on the left by default, you can also affect what's
04:09going on on the right.
04:11Back into the code, we have this thing called accessoryType.
04:15It's a strange name if you haven't come across it before, but it means to add an
04:18accessory, to add a little addition to this cell.
04:21I'm using .syntax here.
04:23I could also have called cell setAccessoryType. And our options are
04:28another enumeration.
04:31If I start typing UITableViewCellAccessory, we see we've got AccessoryNone,
04:36which is the default, DisclosureIndicator, DetailDisclosureButton, Checkmark.
04:41I'm going to use UITableViewCellAccessoryDisclosureIndicator. Save that, run it.
04:49What it's now adding is the little disclosure indicator here, which is that arrow.
04:54Now, you've probably seen this one a lot.
04:56What you're often probably used to is being able to click it and be taken
05:00somewhere else, and we'll talk about that in a second.
05:03But obviously, we have multiple options for this UITableViewCellAccessory.
05:09We have things like the DetailDisclosureButton, and if I use that, we get a
05:15different icon there.
05:16Now, bear in mind that you really want to be reading the Human Interface
05:20Guidelines when you start to use these things, because a lot of people pick the
05:24DisclosureButtons and the DetailDisclosureButton as if they're identical and
05:27it's just some aesthetic choice and it's really not;
05:30they are meant to mean two separate things.
05:32So pay attention to those interface guidelines that Apple published.
05:36But what does this actually do?
05:38We're often used to seeing something like this and thinking "Well, that's
05:42touchable. That row is selectable."
05:44We might be expecting it to shoot off to the left and bring in a new view on the right.
05:49Now, when you've used the applications where it seems you must be drilling down
05:53from one part of a TableView to another,
05:56if you're thinking that must be a nested TableView or a TableView inherently
06:00with multiple levels, it's really not.
06:03We're typically going from one view controller to a completely different view controller.
06:08It just looks like it's a nested control.
06:11The complexity of a lot of applications is actually tying your view controllers
06:16together so we can move from side to side and interact with table views and
06:20other elements like buttons and navigation controls.
06:23So, we're going to get into that as we get into the idea of applications with
06:28multiple views. But you can see with just a few basic lines of code how we can
06:33start to affect the image, the disclosure buttons, the accessory, the subtitles,
06:38and the text on a TableView cell.
06:40And if you want to take it even further than this, you can even create your own
06:44TableView cells where you specify exactly what the full layout of these are.
Collapse this transcript
8. Creating Apps with Multiple View Controllers
Introduction to multiple-view applications
00:00Everything we've done so far has been on one main screen.
00:03All the examples I've shown have used the single view application project type,
00:08one view controller made of .a, .h, .m, and .xib file.
00:13And this is not a bad thing;
00:14there're perhaps hundreds of thousands of single view applications for sale in
00:18the App Store today, but it's not always enough.
00:21Now, these can be made a little bit more flexible.
00:24You can group multiple controls into sections and hide them or show them, but
00:29it's quite common to hear phrases like "I need more than one screen or more than
00:32one page or more than one window," though you need to be really specific about
00:36what those words mean on iOS, as we don't have multiple windows the way you might
00:41have on a desktop app.
00:42We have one window.
00:44Okay, with very few exceptions, such as connecting an iPad to an external display,
00:50an iOS has one window object, and it takes up the entire device screen.
00:57It's transparent. But what we can do is move multiple views in and out of that
01:02window, and a good example of this is what's known as a Utility Application, like
01:06the Stocks app or the Weather app on the iPhone.
01:09They have two very separate view controllers: a MainViewController and a
01:14FlipsideViewController, and you go between them.
01:16Each of these is an entirely independent view controller with its own .xib, its
01:21own .h and .n file and they're handing responsibilities back and forth.
01:26But these views don't even have to take up the entire window, and they don't have
01:31to completely replace each other.
01:33We can load them in layers.
01:35So another very common model is that we load in one view into our window,
01:39here represented by view controller 1, that itself is there to help manage other views.
01:45This would be quite common with a tab bar, and what then happens is this helps us
01:50move other views in and out of the application. And these different pieces of the
01:55app can be built as completely separate view controllers, with their own header
01:59and implementation files and their own .xib.
02:01So, in your applications, you want to be comfortable with switching
02:05between different views.
02:07It's a very common iOS task,
02:09so we're going to explore a few different ways of doing this.
Collapse this transcript
Deconstructing a utility app
00:00We're going to begin working with multiple view controllers by using the Utility
00:04Application that Apple provides.
00:07So selecting an iOS Utility Application I'm just going to call
00:11this UtilityExample.
00:13I want to make sure that for right now we're still not using Storyboard, but we
00:16are using Automatic Reference Counting.
00:19I'm going to click Next and create it on my desktop.
00:24Notice straightaway over here in the Project Navigator, there's not just one
00:28View Controller, but two sets of them:
00:30the MainViewController.h and .m files, the FlipsideViewController.h and .m files
00:36and the Corresponding.xib.
00:39So two sets of view controllers.
00:41So what's happening when this app runs?
00:43Well, let's take a look.
00:45If I jump into the AppDelegate implementation file and look at the main startup
00:50method, which is application didFinishLaunchingWithOptions--don't worry too much
00:55about remembering this exact syntax;
00:56that's not important here--
00:58but what I can see is on line 20 I'm instantiating a UIWindow object. That's our
01:03transparent boundaries on our entire screen.
01:05On line 22 I create a new instance of the MainViewController.
01:11I load that into the window on line 23, and on line 24 I make the window visible.
01:16So the AppDelegate is taking care of loading this guy, MainViewController.
01:22So if I go into my XIB file, I can see that I've got a fairly dark background here.
01:27There's nothing special about it.
01:29If I look at my Inspector, what I can see is we've just changed the actual
01:33background of that to be this dark color.
01:36Other than that, it's the same as what we've been using all along, except we do
01:40have at the lower-right, this button here.
01:42Now, this is a regular Round Rect button.
01:45There's nothing special about it; the only difference is it had its type changed
01:50from the regular Rounded Rect into an Info Light button.
01:54Well, knowing what we know about buttons, we can see if it's hooked up to anything.
01:58I could either right-click the button, though it's a little small.
02:01I'll make sure it's selected and go to my Connections Inspector, and I can see
02:05that I've got my Touch Up event is hooked up to File's Owner looking for a
02:09method called showInfo.
02:11Well, I can presume that that showInfo method should be in the corresponding
02:15implementation file for MainViewController.
02:18I can either scroll down or use the Jump Bar to find it.
02:21There we go, showInfo.
02:23So what's happening here?
02:25We have four statements.
02:26On line 70 we're going to allocate and initialize a instance of
02:30FlipsideViewController, and we'll call it controller.
02:34Then on line 71 we'll say, hey controller, your delegate is self, meaning the
02:40FlipsideViewController's delegate is the MainViewController.
02:43We'll talk about why that's important in a second.
02:46Then on line 72, we say the controller's modalTransitionStyle is
02:51UIModalTransitionStyleFlipHorizontal.
02:54You might make a guess, but that's what's going to do the horizontal flip in the
02:58Utility app for us, and that is indeed it. And then finally on line 73 we say
03:03presentModalViewController,
03:05passing in that view controller we just created and saying animated:YES.
03:11That is going to present the new view controller and make it the boss.
03:15If we run this to test it, I can expect this to just work.
03:20The MainViewController loads, we click the button,
03:23it creates the new one, flips it horizontally.
03:26I could click the Done button and go back.
03:29I'll quit out of this and back into the code.
03:32So that's how we're handling it from the main view to the flipside view. What
03:36about the other way round?
03:38It's a little different.
03:39So, I'm jumping to the FlipsideViewController.xib file here, where we can see
03:44we've got a Done button at the top.
03:46This is using what's called a navigation bar and a bar button item.
03:50It's a little different from a regular Round Rect button.
03:53Even so, I can see using my Connection panel that this Done button is hooked up
03:58to the FlipsideViewController class files.
04:02I'm going to jump across into the header file for FlipsideViewController because
04:05there's something slightly different about this one.
04:09Before the regular interface to create this class, we have what's called a
04:13protocol definition.
04:15The FlipsideViewController can ask someone to be a delegate for it, and what that
04:20means is if you are going to be a delegate for the flipside view, you need to
04:24provide a method called FlipsideViewControllerDidFinish.
04:28It doesn't say here what that method must do, but you need to have one.
04:32The only other things we have here, on line 19 there is a property that can
04:36represent that delegate, and on line 21, one IBAction called Done.
04:42So, what does this mean?
04:43Well, up to now, we've been acting as a delegate for other objects.
04:46We've been being given work to do, but creating protocols like this is the way
04:51that your own classes can describe themselves as being delegating objects,
04:56meaning they're in charge.
04:57They can pass work off to someone else. And what's happening here is that the
05:02FlipsideView is going to pass work off back to the main view.
05:06What it actually means is when we press the Done button I'm not going to take
05:11care of dismissing this view away inside the FlipsideView; I'm going to go and
05:15tell the MainViewController to do it.
05:17So in the implementation for FlipsideView I'm going to use the Jump Bar and find
05:22the Done action, and all it's going to say is, hey, call whoever is the delegate
05:27and let them know FlipsideViewController is finished.
05:30There's no code here to move the ModalViewController away or to change the way
05:35it looks or describe any kind of transition.
05:37It's not doing it in the FlipsideView;
05:40we're doing it back in the main view.
05:42So, if I look here at MainViewController, first I'm looking at the header file,
05:46where we're volunteering to be the delegate for the FlipsideView.
05:49Yes, you can pass work back to us. And then finally in the MainViewCcontroller
05:54using the Jump Bar I should actually expect just to implement that method, and
05:59it's right here, FlipsideViewControllerDidFinish, and this is the one line of
06:03code that says, hey, we're dismissing that ModalViewController back out.
06:07Now, this is not the only way this could be done, but it is a common way to do
06:13it. And what we're really setting up here is that the MainViewController is
06:16in charge of both animating to the FlipsideView and in charge of animating it
06:21back away again, even when we can't see it.
06:24So, the MainViewController is kind of staying in charge, and we're staying in
06:27control the whole time, and doing this through delegation. And simply what we
06:32could do is start to add our controls and build on top of this, and this is
06:36what's created for you with the Utility Application in Xcode.
Collapse this transcript
Understanding navigation controllers
00:00But sometimes one screen is not enough and even two screens flipping between
00:04each other aren't enough.
00:05Now if you've used applications like, say, the Settings application,
00:09you'll have used navigation controllers.
00:12Here, I'm not talking about the contents of the screens themselves.
00:15These could be table views, like seen here, or images or video.
00:19I'm talking about the blue bar at the top, something that lets us keep track of
00:23where we are and how to get back.
00:27Settings uses it. Safari uses it to manage Bookmarks.
00:32Contacts uses it, the music applications use it, and this is something called the
00:38Navigation Controller.
00:40It's a built-in object that can keep track of where you are and automatically
00:44provide you that single breadcrumb level to get back to the previous view.
00:48And when your app can now always fit on one screen, you have multiple levels
00:52going from a master level to a detail level and even further down. This is the
00:57classic iOS way of managing it.
01:01To use this navigation controller, when our application opens, we'll create the
01:05empty window object as usual.
01:07But instead of loading our first view directly into the window, we will create
01:12a navigation controller object, which has that blue bar, and it can hold other view controllers.
01:18We will load our First View into it, and then we'll move the whole thing into the window.
01:23And as you start to use the application, say perhaps you touch a button in the
01:27first view controller, instead of that view controller directly creating and
01:32transitioning to the next view controller, as we saw in the utility app, it does
01:37create it, but it tells the navigation controller to handle the transition.
01:41And the navigation controller takes that second view controller and makes it
01:45appear. The term we use, it's pushed to the top of the navigation stack.
01:50You can think of this like a deck of cards.
01:52We are loading this in at the top of the deck.
01:55Say we select something on the second view controller.
01:57We talk to the nav controller again, we get the third one loaded on top.
02:01Now the other view controllers right now still exist;
02:04they are just not visible.
02:05And as the navigation controller has been the one responsible for pushing these
02:09onto the stack, it also knows how to go back and push them off.
02:13So as someone taps the Back button on the navigation controller to go back, it
02:17will take care of taking whatever's the top of the stack and moving it away.
02:21The term it's actually used is, that view controller is being popped off the stack.
02:26We click the Back button again, we get the second one popped off and we are back at the start.
02:31The job of the navigation controller is to take care of the stack of view
02:36controllers so we don't have to.
02:38And to get started with this, Xcode actually gives us a project type for master-
02:42detail applications that creates a simple example of this.
02:45Then in the next section, we are going to see how to go ahead and take a look at that.
Collapse this transcript
Creating a master-detail application
00:00Let's see the Navigation Controller being used in an example.
00:03I'm going to create a Master-Detail Application in iOS.
00:08I will just call it MasterDetailExample.
00:10I want to make sure at this point we're still not using Storyboard, but we are
00:13using Automatic Reference Counting.
00:15Click Next and I will create it on my desktop.
00:19I can immediately see over in the Project Navigator that we have two sets
00:24of View Controllers:
00:25a MasterViewController.h, .m and .xib, and a DetailViewController.h, .m, and .xib.
00:31I am going to go ahead and run this, and this is what it gives us right out of the box.
00:37It looks like we have a table view here.
00:38We have one row in it that says Detail.
00:41I touch that. It jumps into a different view.
00:44I can use the navigation bar to navigate back up to the top.
00:48It's simple, but all the principles are here, and it's all based on this blue
00:53bar at the top of the screen.
00:54So let's go and take a look at our interface files.
00:57Quit out of that and go back in.
00:59I am going to select the MasterViewController.xib file.
01:03I can see that I've got a table view here, but I certainly don't see that
01:07navigation bar at the top.
01:09Even if I expand the dock, yeah, I've just got a table view here.
01:14There's nothing else on this .xib.
01:16Jump to the DetailViewController, maybe it's there.
01:19Well, it doesn't look like it is. In fact, looks like all I've got here is a label.
01:24So there's the question, where is that navigation controller, because it
01:27obviously does exist in this app, so where is it coming from?
01:30Well, let's take a look at the application startup code in our AppDelegate file.
01:35Jump into AppDelegate.m, and what we're interested of course is the classic
01:40application didFinishLaunchingWithOptions method.
01:44Now, usually this code will say create the window, create the first view
01:48controller, and then load that view controller into the window.
01:51Well, what's happening is on line 20 we're creating the window, as usual. line 23
01:56we create the MasterViewController as usual.
02:00That's the first one we want to show, which is fine.
02:02But line 24 is new.
02:04Here is where we allocate and initialize a new instance of the
02:08navigationController object, and we load in masterViewController into it, in the
02:14initWithRootViewController: masterViewController.
02:18So we have a combination of our first view and that top bar of the
02:22navigation controller.
02:23Then we move the whole thing into the window on line 25, and on line 26 we make it visible.
02:29Again, it's not about the syntax here.
02:31You shouldn't need to change this.
02:33It's about the understanding the process of what's happening here.
02:36We're loading both things into the window right at the start of the app.
02:40So we can see that the masterViewController is using this table view here,
02:44although there is only one piece of data in it.
02:46Let's take a look and see where that data is actually coming from.
02:50I'll quit out of that. And jumping into the MasterViewController.m file, the
02:54implementation, what I would expect to see if I use the jump bar is to find some
03:00of the table view data source methods, so things like
03:04numberOfSectionsInTableView, numberOfRowsInSection, things that we talked about in
03:09the table view part of the course.
03:11I'll jump to numberOfSectionsInTableView, and we have return 1, and then
03:16numberOfRowsInSection.
03:17Well, that apparently always returns 1 as well.
03:20And then below it we have the classic cellForRowAtIndexPath, creating the
03:26individual rows for that table view.
03:28The code here is just the standard code you'd always expect to see in here about
03:32creating a cell and dequeuing it if there's one available.
03:35In fact, the only thing we're doing with the cell is on line 96 we're just
03:40setting the text of the cell to say Detail.
03:43Now, here we're actually using the NSLocalizedString instead of an NSString.
03:48This is just the boilerplate code that Apple has created for us.
03:52Localized strings are great.
03:54They support having a separate strings file in our app that can look up a
03:58replacement word or phrase if we have that provided for another language. They're great.
04:03They're not that complex, but they're just a little beyond the scope of this course.
04:06You can leave this as is, but understand that there is nothing magical going on here.
04:11I could have just used a regular NSString object.
04:14That would have been fine too.
04:15So this table view is being loaded with very basic literal data.
04:19You could use some of the techniques from the table view section of this course
04:22to load in something different.
04:24The only thing I'm going to change here is in numberOfRowsInSection, where I'm
04:28going to say return 5, so that we can at least get five rows of data, even if
04:34they all say the same thing.
04:39But then the question is, what actually happens when we're tapping a row in the
04:44table view that will take us to the detail view?
04:47The navigation controller won't automatically do it just because we've tapped a
04:51row in the table view, so there must be something else going on in this
04:54boilerplate code, and of course there is.
04:57Quit out of that and back into the code.
04:59What's happening is that the provided code here is implementing another delegate
05:04method, and it's tableView: didSelectRowAtIndexPath.
05:09I'll just open up my navigator so we can see all this properly.
05:12There is really not very much going on here.
05:15Line 140 asks, do I currently have a reference to a detailViewController object?
05:22You might think, well, where did that come from?
05:25If I look at the MasterViewController header file, it simply has given me one
05:29property that can hold a reference to a detailViewController.
05:35So back in my implementation, all I'm asking here is, is there an object in that property?
05:40If there isn't, create one and initialize it with the existing NIB, the XIB
05:46file in our project.
05:48Then on line 143, talk to the navigationController and tell it to push that new
05:54detailViewController that we have onto the stack, animated: YES.
05:59That makes it slide on, whereas an animated: NO would just make it up here.
06:03And that's all the code we need to make it transition from the master view,
06:08whenever we touch one of these rows, to the detail view.
06:12But one problem we have is that no matter what row we're touching, it's always
06:16doing exactly the same thing, taking us to the same detail view that never
06:20looks any different.
06:21The whole point of going from a master view to a detail view is not just to have
06:25the screen transition, but that you're going to pass some information between
06:28these view controllers. So let's do that.
06:30I am going to quit out of this and back into the code.
06:34Now, if I look at the header for my DetailViewController--and this is the
06:38Apple-provided code here-- I have two properties.
06:41One of them is an IBOutlet that I can see is connected, and it just represents
06:45the label that is actually in that .xib file, that at the moment always says
06:50Detail view content goes here.
06:53But we do have one more property here on line 13.
06:56This is a property for something called detailItem of type id. Now, type id just
07:01means this could be any object.
07:03It's a placeholder.
07:04In your app, if you knew you wanted to pass in a product object or a song object
07:09or a player object, you'd be specific here.
07:12But this could accept anything.
07:14Now, jumping to the implementation file for DetailViewController,
07:18I can see that I have a couple of synthesize statements to synthesize both the
07:21DescriptionLabel and detailItem.
07:23Now, if you haven't seen this format here, it just means it's synthesizing the
07:28instance variable names with an underscore.
07:31It's not important here.
07:32However, the part that is a bit more important starts on line 22.
07:36They've provided a custom setDetailItem method, so if someone wants to set this property.
07:43Now, it's still pretty basic.
07:44It accepts a generic object of type id. You can pass in anything into this:
07:48an array, a string, a custom object, whatever you want.
07:52On line 24, it's just going to ask, did you pass me a new object or are you
07:56trying to pass me the same object I am already?
07:58If it's a new object, all it's going to do is call self configureView,
08:03the configureView method that's down here on line 32, and all that does is ask,
08:07is there some object in this property?
08:10If self.detailItem, if it exists, then I'm going to change the text on this view
08:17to whatever the description method for that new object returns.
08:21You might ask, well, how do you know the object will have a description method?
08:24Because all of them do.
08:25Description is a method defined on NSObject, so everything you could possibly
08:30pass into this will have a description method, even if all it will say is the
08:34name of the class and the address in memory.
08:36And the reason they've done it this way is just to be as generic as possible.
08:41You don't have to have a label.
08:42You don't have to accept something of type id. It's just to allow you to pass
08:46anything into this detailViewController and have it update the label with some information.
08:51So how do we do it?
08:52How do we pass information between view controllers from our master to our detail?
08:58Well, I know that usually what I'd want to do is pass different information.
09:03I want to be able to pass information that's different if we click the first row
09:07to the second or the third.
09:09So the place I need to be to pass that information will be back in our
09:13didSelectRowAtIndexPath.
09:15So I jump into the implementation of the MasterViewController, and I have it
09:20selected, or I could use the jump bar to jump right here.
09:23And what we've seen already is this is where we just ask, does the
09:27detailViewController object exist? And then push it on top of the stack.
09:32So between asking if it exists and pushing it to the stack, I'm going to create
09:36a new object, and I'll just make an NSString, which is perfectly fine.
09:40It's a first-class object all in its own right, but you could be creating
09:45anything and passing it in here.
09:49And rather than create one string that always looks the same, I'll do an
09:52initWithFormat so I can slightly change it based on the different row
09:56that's just been touched.
10:00Give it a placeholder, You chose row %i, because I know that I can have
10:06an integer for that selected row, and grab that integer from the
10:10parameter indexPath row.
10:13I can either use indexPath row in square brackets or indexPath.row in dot syntax.
10:20Close that method call.
10:21Finish that statement.
10:23We now have an object, but I need to hand it to the detailViewController.
10:29I know that I have a reference to a detailViewController, because on line 140 I
10:32asked if it existed, and if it didn't, make it.
10:35So I know I have something called self.detailViewController, and that should have
10:41a method called setDetailItem--
10:43there we go--which takes type id, meaning pass me anything.
10:47I will pass the string. Save it, run it.
10:55We're in the master view controller.
10:57We click, say, the first one, and what we're doing is passing in the correct row,
11:03which is 0; it's 0 based here.
11:05So You chose row 0, or You chose row 1.
11:10Selecting the fifth should say You chose row 4, and indeed it does.
11:14So while it's not tremendously dramatic, we are now passing different objects
11:20from the master view into the detail view automatically using the navigation bar
11:24to navigate back up.
11:26And this is how to get started with the master-detail app and the navigation
11:29controller, and you can use the same principles here to start adding more view
11:34controllers to this project and even transitioning further down.
Collapse this transcript
Creating a tabbed application
00:00Let's take a look at the Tabbed Application, which is another project template
00:04that has multiple views in it,
00:08once again making sure I'm using ARC, but not using Storyboards right now, and
00:13click Next and Create.
00:15Looking in the Project Navigator, I can immediately see that I've been given
00:19two view controllers: FirstViewController and SecondViewController, both the
00:24.h, .m and .xib for those.
00:27I am going to go ahead and run this.
00:34And what I see is this First View option.
00:37I have this tab bar down at the bottom.
00:39It's divided in to two sections that I can switch between.
00:42The tab bar can have multiple sections.
00:44It's not recommended on an iPhone that you go beyond five.
00:47And what this is doing is similar in concept to the navigation controller, in
00:52that it's the tab bar itself that's controlling this switch between the
00:56different view controllers that we have.
00:59Well, let's take a look at that in our project.
01:01I'm going to quit out of this and go into FirstViewController, which should look
01:06reasonably recognizable here.
01:09Now, it looks like this might be representing the tab bar down at the bottom of
01:13it, but it's really not.
01:15I am just selecting the view right now, and if I take a look at my inspectors
01:19here, my Attributes Inspector, shows me that I have got a simulated tab bar at the bottom.
01:24That doesn't actually do anything programmatically.
01:26It just lets me set up the rest of my interface correctly.
01:29If I click on SecondViewController, this one is doing exactly the same thing.
01:33Bottom bar is tab bar.
01:35But neither of them contain anything other than a label and a text view.
01:42These .xib files do not contain a tab bar controller, because what's happening,
01:48again, is all in the AppDelegate.
01:51Expanding this. Again, don't worry about the syntax, just pay attention to the
01:55concept of what's going on.
01:57As usual, on line 22, we are creating the window object.
02:01Line 24, we instantiate the FirstViewController.
02:04Line 25, we also instantiate the SecondViewController.
02:08On line 26, we are creating a new instance of a tabBarController object.
02:14That doesn't have to have an associated class file or .xib, because we're using
02:19the standard tabBarController object that's built into iOS development.
02:23And then on line 27 what we do is we load the tabBarController up with our
02:29custom viewControllers, number 1 and number 2.
02:32And then on line 28, we take the whole collection, the tabBarController and
02:36those two viewControllers, and load it into the window.
02:39That's why we are not seeing it on the interface itself. It's all done in code.
02:43So let's see how we would add a third section to this application.
02:48What I need to do is create another view controller, the whole set of .xib, .h,
02:54and .m. Very easy to do.
02:56I am going to go up to the File menu, come down to the New option. Instead of
03:00New Project, we say New File.
03:02I'm interested in the iOS section, and I can filter down into Cocoa Touch.
03:07The one I'm interested in is in the Cocoa Touch section and it's the
03:11UIViewController subclass.
03:14Notice the description of it.
03:15It's an Objective-C class which is a subclass of UIViewController, with a header
03:19file and an optional XIB interface file.
03:23You don't always have to do it together, but this way is a pretty classic way of doing it.
03:28I click Next. It's going to ask us to give the class a name.
03:31Well, we have FirstViewController and SecondViewController.
03:34Let's not break tradition.
03:36Let's have ThirdViewController.
03:38We do want this to be a subclass of the built-in UIViewController, so I get all
03:42the normal behaviors.
03:44And then I am going to make sure that I click the check box With XIB for user interface.
03:50Click Next. It's asking, do I want to add it to the current project, and yes, I do, and Create.
03:58I have my .h, my .m, and my .xib.
04:01So I am just going to add something simple to the XIB here.
04:07Drag on a label, widen it out a bit, and call it Third View.
04:13I will center-align this and just increase the Font a little bit.
04:19If I wanted to, I could also do the same thing as the other two XIB files are
04:24doing, which is by selecting the background view and then simulating the bottom
04:28bar of the tab bar, but again, that's not necessary.
04:31It would just stop me putting on some controls in the wrong positions.
04:35I am not going to touch the class files for this view controller yet.
04:38I am just going to go back over into my AppDelegate and add the necessary code here.
04:44I am just going to expand this so I have a bit more room.
04:47And here is the benefit of the way they have created it.
04:50I can really just copy some of this code.
04:53I have a pretty good idea of what to do. I am going to create a new UIViewController.
04:56I will call it viewController3.
04:58I need to make sure that I am using the ThirdViewController class name to create it.
05:04I can see that it's giving me a problem here. It doesn't know what that class
05:06is, because although I created the class files, I haven't imported the header file up here.
05:12So right after line 13, I am going to do another #import, tab across, and that
05:18needs to be in quotes and not in angle brackets. And this will be, there we go,
05:22ThirdViewController.h. So now it knows that class exists.
05:26So on this line I can instantiate it with ThirdViewController alloc and make
05:31sure to init with the correct Nib, I don't want to mismatch those.
05:36So now we have viewController3 being created.
05:41Well, it's not going to make any difference if I don't then load that new
05:45viewController into the tabBarController.
05:48Notice here is where I am creating it with the first two, using an
05:52arrayWithObjects called viewController1, viewController2, nil--
05:57nil indicating the end of the array.
06:00So after the first comma, I am just going to say viewController3, and add
06:04another comma so that there is a comma before the nil. Save it, run it.
06:13We have a section on the tab bar for First, section for Second. And we do have a third section.
06:18There is nothing actually going on here yet, but it does actually allow me to
06:21switch to that ThirdViewController.
06:24So it seems to be working just fine.
06:27The missing link being, well, how can we have a title, how can we have an icon?
06:31Well, let's look and see what's happening there.
06:33Quit out of this and bank into the code.
06:37Notice that when these view controllers are being instantiated,
06:40viewController1, it's using initWithNibName, a pretty classic way to do it.
06:45Same with viewController2, initWithNibName, and
06:48viewController3, initWithNibName.
06:50I could go into the implementation for the FirstViewController,
06:54so FirstViewController.m and here is the initWithNibName.
06:58It's got some standard text in here, making sure that it exists, but what it's
07:02doing are these two lines.
07:03Line 17, setting the title to First and, again, it's using the
07:08NSLocalizedString, though this could be just a regular NSString that's said First.
07:13And then Line 18, self.tabBarItem.image and extracting an image from this call
07:19to UIImage, imageNamed first.
07:22Now, if you might have noticed, over here we have a couple of placeholder images
07:25here: a first.png and first@2x.png--
07:31essentially one of them for a regular iPhone,
07:33the other one for a Retina display.
07:36second.png is a square and @2x for a square for the retina display.
07:42So we could use this model, and we could essentially just copy and paste this
07:46code for our third one and also set an image.
07:49I haven't actually created an image for that position, but I could copy this
07:53code, jump into my implementation in ThirdViewController, and I have got my own
07:59initWithNibName method here with a place for my custom initialization.
08:04Now, I could just set this to a localized string saying Third, Third.
08:09Again, I am not using localized strings in this example.
08:12So I am loading it in there, setting the title, and I am just going to borrow
08:17the first named image.
08:18Let's run that and check that it works. And it seems to work just fine.
08:25The dark images that are provided are automatically going to be
08:29correctly color coded by iOS.
08:31You don't have to worry about that.
08:33However, there's another option we could use if I didn't just want to
08:35reuse that simple circle.
08:37Instead of creating my own title using my own images, what I'd like to do is
08:43reuse one of the built-in system-provided tab bar items, and here's how you do it.
08:49This view controller, self, is going to have a property called tabBarItem, and I
08:53am going to create a new instance of tabBarItem. So I'll just do UITabBarItem
09:01alloc. And there is an initializer called initWithTabBarSystemItem.
09:08That's the one that I want.
09:09This allows me to select from an enumeration that has a bunch of pre-provided
09:14tab bars that are the standard ones used in things like videos and the music
09:18application and all sorts of other applications.
09:20So I will start typing in UITabBarSytemItemMore, History, Featured, Favorites,
09:26MostRecent, MostViewed, TopRated, and several more above that.
09:31Let's select, for example, Contacts.
09:34Then I will hit Tab, and it's telling me that we also need a tag
09:37parameter that's an integer.
09:39Tag here doesn't actually matter.
09:41It doesn't matter what the number is. This is a way of associating your
09:44different tab bar items with a number.
09:47And that's because in more complex situations, like the iPhone music app, you
09:51can reconfigure the tab bar to contain your choice of buttons and your choice of
09:55order, and it means you can associate each button with a particular number.
09:59We don't really care about this here.
10:01I could put in any number that I wanted.
10:03I just need to provide something.
10:05I am going to close that method, finish the statement with a semicolon, save it, run it.
10:13And now we are using the pre-provided and built-in tab bar item or one of the
10:18many, and you can see all the available options for tab bar items in the Human
10:23Interface Guidelines document.
10:25This is how we get started with a tabbed application.
Collapse this transcript
9. Using Storyboards
Introduction to storyboards
00:00When iOS 5 and Xcode 4.2 released in late 2011, we got storyboards.
00:05These are a great way of visually laying out an application with multiple views.
00:10Now, we have seen techniques up to now where we could create individual NIB
00:14files to represent each separate screen in an app and then create code to
00:18transition between them.
00:19But now we can have one storyboard that describes all the screens in our app,
00:25whether that's 1, 2, or 100, and the relationships and transitions between those screens.
00:30Unlike the idea of a storyboard in filmmaking, a storyboard here is not a mockup.
00:35It's not just a visual aid.
00:37It is the real user interface of your application.
00:40A change to the storyboard is a change to the app.
00:44And it's not just a convenient way for you to see several screens at the same
00:47time; storyboards help manage transitioning between screens, and they help with
00:52passing data between them.
00:54They help you build the flow of your app.
00:57Unlike things like ARC, storyboards will let you write less code.
01:01Typically, it's one storyboard per app.
01:04You can create storyboards for just part of an application, but the general rule
01:09is, you only need one.
01:11If you make a storyboard, you don't then need separate NIB files.
01:16The storyboard is your UI, and working with a storyboard is very similar to
01:21working with individual NIB files, as we'll see.
01:23Now, if you are creating a universal app that can alter its appearance based
01:27on the device, you can have one storyboard for the iPhone part and another for the iPad version.
01:33In fact, that's what Xcode gives you when you make a universal project that uses storyboards.
01:38The two main ideas in a storyboard are scenes and segues.
01:42You begin with one scene and you create a new scene for each screen in your application.
01:48And a scene, if it looks familiar, is of course of good old view controller, but
01:52instead of one per NIB, we are just managing them all together in one place.
01:57On an iPhone, a scene does typically represent a full screen, though on an iPad
02:02it could represent part of a screen.
02:04So if you are working with a master detail view, you might have multiple
02:07scenes visible at the same time on the iPad, because they can transition
02:11separately from each other.
02:13But not every scene in your app needs to go to every other scene in your app,
02:17so you then describe segues between the relevant scenes.
02:21And segues describe the visual transitions between your view controllers.
02:25There are built-in segues like a Modal segue and a Push segue.
02:29You can even define your own custom segues, but we won't get into that here.
02:33A segue is typically triggered by something the user does on screen, like
02:37touching a button or a table cell, although you could make these segues happen
02:42programmatically in response to perhaps a gesture or accelerometer movement.
02:46And the great thing about designing everything in a storyboard is Xcode helps
02:51you wire these all up, and it handles loading the different pieces in and out of
02:57the storyboard efficiently.
02:59And of course, you often need to do something programmatically as you're about
03:03to segue between these scenes,
03:05so there is an important new method in UIViewController when using segues. It's
03:10called prepareForSegue:sender.
03:13You would override this method in the view Controller you are about to leave and
03:18it will be called automatically when the segue is about to happen.
03:21And here you can prepare some data to pass into the next scene, into the
03:25next view controller
03:26that you're about to segue to.
03:27So that's the basic concepts.
03:29Let's see how to do it.
Collapse this transcript
Creating scenes and segues
00:00I am going to create a new Xcode project.
00:02This will be a Single View Application this time, but we will use the storyboard
00:07check box to use those.
00:09I am going to just call this StoryboardExample.
00:12Make sure it's for iPhone because iPad storyboards can become enormous, and with
00:18Storyboard and ARC checked, I am just going to go ahead and create it.
00:22I can see in the Project Navigator that I have class files for a
00:26ViewController: my .h and .m. But instead of having a .xib, I have one
00:31storyboard file here, MainStoryboard.
00:34Selecting that, it jumps us to this Canvas view, which doesn't look all that
00:38different from the NIB editor we've been used to so far.
00:42And indeed, it really isn't.
00:44At this point, we could select objects in our Object Library.
00:48We could drag and drop them onto here.
00:50It'd behave very similar to what we're used to.
00:52So we begin with this one scene.
00:54This is the scene that will automatically load when this app begins.
00:59That's what this arrow represents is the starting point.
01:02There are a couple of differences.
01:04When I click this to select it, I will see that instead of having icons on
01:08the left-hand area,
01:09I have them down at the bottom in this doc area.
01:12It shows us objects like the First Responder, which we rarely need to touch, and
01:17View Controller, which is more useful, because like File's Owner,
01:22we need to be able to describe how this interface is connected to some
01:26class files. And with that selected--and I can see the blue bar surrounding everything--
01:31I can go into my Identity Inspector, which is the third button here, and see
01:37that it is hooked up to a custom class called ViewController. And that's how we
01:41connect this to the actual code files.
01:43You also do have the collapsible Doc area, which contains that other way of
01:48viewing the elements in your scenes.
01:51But you can collapse it all the way because the basic icons will always be
01:54visible on the storyboard.
01:56So, how to add new scenes?
01:58Well, scenes are view controllers.
02:00We add them by finding view controllers in our Object Library and just dragging
02:04them onto the canvas.
02:05I am going to filter my Object Library to Controllers & Objects here, and I'll
02:10see I have a view controllers, table view controllers, navigation controllers,
02:14page view controllers.
02:15I am going to just add a couple of regular view controllers.
02:19I have zoomed out one level, just so I can see things a little better.
02:23Now, I do find that interacting with objects on a storyboard is only really
02:27reliable when you're zoomed in at the 100% level, but zooming out can give you
02:32a good perspective.
02:34So I am going to zoom in there and just rearrange these a bit more, and you will
02:38see that even the storyboard itself has helper guides for aligning our scenes.
02:44You don't have to add them in a left-to-right fashion, though that is useful and traditional.
02:48You can put them beneath. You can put them on the left.
02:51You can put them on the right. It really doesn't matter.
02:53Now, I'd like to be able to see the difference between these scenes without
02:57having to add too much in the way of user interfaces,
03:00so I am going to select the second one and just go into my Attributes Inspector.
03:05In fact, I am going to zoom in one more piece because I do want to be able to
03:09interact with them better. I want to get the actual view selected.
03:15So I can then select Default.
03:17I'll give that one a Group Table View Background Color, just to distinguish them,
03:22and then select the third one.
03:24Again, you may have to be zoomed in all the way to be able to grab this
03:27properly, and selecting from background, I will give it the Scroll View Textured
03:32Background Color, just so they're obvious which screen we're on.
03:36So I have these two new scenes.
03:39Now these scenes are considered view controllers, but Xcode has not generated
03:46custom view controller class files for anything other than the first one, and we
03:50will often need those files, although we can add them later and then hook them
03:55up to these visual view controller elements.
03:58But first, what I want to do is just add some basic segues, so how to do this.
04:03A segue needs to be triggered by something, so we might as well have, say, a
04:07button to do this. I am going to filter on my controls, grab a Round Rect
04:12Button, drop it onto the first one.
04:14I can see here it's not actually allowing me to drop it on when I'm zoomed out,
04:18so I am going to zoom into 100% or just click the Equals sign, see whether that works.
04:23Nope! Not doing it.
04:25Let's zoom all the way in, drag on the Round Rect Button--
04:30that will do--and then drag it onto the second one as well.
04:33It doesn't really matter where you put them.
04:35I will put them towards the lower-right.
04:40I will just double-click them to give them some text.
04:45So how do I make these triggers segue?
04:47Well, we don't even have to do an IBAction or write any code, none of that.
04:51I'm simply going to go to the first button, hold the Ctrl key, click, drag onto
04:57the second view controller, let go, and it's going to do this pop-up, oh!
05:01You want to do a segue, what kind?
05:03Push or a Modal--there's actually several kinds of modal--or Custom?
05:07I am going to choose Push, click, and we have the segue icon. And the icon
05:12here is actually a clue that this is a Push transition because a Push
05:16transition is the classic right-to-left, shifting one view controller from the
05:21right over the top of the other.
05:23I'm going to do the same with the next one.
05:25Ctrl+Click, drag, Push segue.
05:29I am going to just go ahead and run this, and let's see if it made any change.
05:34I click the Next button and nothing.
05:37Now, here is the problem.
05:39Not all segues make sense in all circumstances.
05:43This Push transition, the classic right-to-left move, is associated with a
05:49navigation controller in iOS so that we can keep track of which screen we're on,
05:54and iOS still wants to do the segues that way. And that would control the Push
05:59and the navigation back so we would typically expect to see one here. Can we do that?
06:04Of course we can, and it's very, very easy. Here's how.
06:07We just select the first view controller.
06:09Now, if you remember when we created navigation controllers, the idea is we
06:14create the navigatio controller, and then we load in our first view
06:18controller into it.
06:19We can do that here.
06:20I select it, I go up to the Editor menu, and then I have an option that says
06:25Embed in, and it allows me to embed this first view into a navigation controller.
06:31I am just going to rearrange that a little bit. And notice what it's doing now.
06:36It's smart enough to understand that actually our first controller that we load
06:41in is a navigation controller that itself is instantly going to load in this
06:46first view controller, the one that we're interested in.
06:50Now, it's shifted the UI a little bit,
06:52so we may need to rearrange that.
06:54But I am going to go ahead and run it and see how that works.
07:03I can see the navigation controller at the top. I click Next.
07:06We do a Push segue to the second screen. I click Next.
07:09We do a Push segue to the third screen. Navigation controller takes charge of
07:13moving them back and forth. Very easy to do!
07:18Not a line of code.
07:19Now, we're typically going to write a little bit of code so we can have things
07:23like more interesting title bars and so on, but this is the basics.
07:29Next, we're going to take it a bit further and start make something a bit more
07:32interesting, and even passing data between our different scenes.
Collapse this transcript
Passing data between scenes
00:00Let's see how to pass information from one storyboard scene to another.
00:03I'm going to create this simple photo viewer application.
00:08It allows us to select from a list of photographs, go to a new scene that
00:12will actually show the image itself, go to another scene that will show
00:15information about that image.
00:17And while it is simple, it's still using multiple scenes.
00:20It's using navigation controllers, it's using Push segues and Modal segues,
00:26table views and image views, and it's passing an object from one scene to the
00:31next. I have a custom object called photo object, which can be passed around and
00:35show different information about that same object from scene to scene.
00:39I'm going to do this in five short steps.
00:42Here is the overview.
00:43Step one, we'll create the storyboard.
00:46We'll layout the application, the scenes and the segues in the different user
00:50interface elements. In this step we write no code.
00:53Step two, we're going to create the custom class.
00:56This will be a photo class so we can create multiple objects of this and pass them around.
01:01This is very simple, really just a straightforward data structure.
01:05Step three, when we set out multiple scenes in a storyboard they don't actually
01:10have their own class files attached to them.
01:14So we're going to create custom view controller classes for each scene and then
01:18in the storyboard, hook them up so each scene can have its own class file with
01:24its custom behavior.
01:25Step four, we'll write code to load in the data, loading in multiple rows into
01:30the table view and then writing code to show an image or writing code to show
01:33information about an image. And this will be possible by step five.
01:37We're going to be passing the object between the scenes so the code we write to
01:41load the data will actually work.
01:43We're going to hand off a photo object from the Table View to the scene that can
01:48show it, and then onto the scenic that can show information about it.
01:51That's the general approach.
01:53Let's get started.
Collapse this transcript
Step one: creating the storyboard
00:00So I'll create a new iOS Single View Application.
00:04I'm going to call this one PhotoViewer and make sure that it's an iPhone
00:08application and that we're using both storyboards and Automatic Reference
00:12Counting. And I'll just save this to my desktop.
00:14Now, if I want this to show some photos, it will be useful to have some
00:17photos in this app.
00:19Well, I do have a folder that I currently have on my desktop, but you can get it
00:22from the exercise files, that contains just a few photos in it.
00:26I'm going to drag this into Xcode.
00:28I'm going to put it in my Supporting Files folder.
00:31And when the pop-up appears, I want to make sure that the check box to copy
00:36these items is selected.
00:38Now, it doesn't matter that you put them in Supporting Files, although I find
00:41that's the most useful place for them.
00:43They're just simple, preformatted images, the right size for an iPhone screen.
00:48So I'm going to jump to my MainStoryboard.
00:50Now, currently here what we have is the basic setup.
00:54We have the view controller area with its corresponding .h and .m files in
00:59the Project Navigator.
01:01I actually don't want to start here, so what I'm going to do is get rid of it.
01:05I'm going to just highlight and delete the whole thing, go back to a blank canvas.
01:10Not only that, but over here in my Project Navigator I'm going to delete the
01:14header file, make sure to completely delete it, and the implementation file, so
01:22I really am starting from ground zero here.
01:25The reason that I did this is I actually want to start this off with a table
01:29view controller, not a regular view controller.
01:31And with my Object Library open, I'm going to find a table view controller, not
01:36a table view, but make sure you've got the controller one, and drag it on.
01:41Because we dragged it onto a blank storyboard, we do have this little arrow here
01:46that represents being the initial view controller.
01:49And if I look to the Attributes Inspector, I would also see that checked,
01:52that the Initial Scene, this is the initial view controller.
01:57Then I'm going to drag on a regular view controller.
02:00This is the one that's going to display our photo.
02:03And then a third, and this is going to show the information about our photo.
02:08Now, I know that my first table view controller is also going to be embedded in
02:13a navigation controller, so that we can do a Push segue between it and the one
02:18that displays the image.
02:20So what I'm going to do is select the Table View Controller, go up to my editor,
02:24and tell it to embed in a navigation controller.
02:28Now, I'm going to add a couple of segues.
02:31I'm going to zoom into full size here.
02:35I know that what I want to have happen is when someone taps a cell in the
02:40Table View Controller, we're going to move to the second view controller that
02:43will display that photo.
02:45Here's how we do that segue in the storyboard.
02:47I simply hold down the Ctrl key, tap the blank cell, and drag over to that
02:52second view controller. Let go.
02:55It will ask what kind of segue is this.
02:57I'll say it's a Push segue, and it knows now, because the first one was embedded
03:01in the Navigation Controller and we're pushing to the second, that it's also
03:05going to embed that in the Navigation Controller too.
03:07Now, I do want this second View Controller to move to the third, but I don't
03:12want to have it a Push segue.
03:13I want a Modal segue here, and something needs to trigger a Modal segue.
03:17So I'm going to open up my Utilities panel, filter down to Controls, and drag on
03:23a Round Rect Button, position it there, give it a double-click, and say details.
03:31This View Controller is of course also showing an image on it, so I'm going to
03:35switch to the Data Views section of the Object Library, find the Image View,
03:40drag that in there, and make sure that it's sized appropriately.
03:46It's currently going to be over the top of my button, so I can use the Expanded
03:50window here to make sure that it's behind there.
03:56Next, I'm going to make sure that the button is selected so I can see the
04:06This will be a Modal Segue, and we'll see how to manipulate that in a moment.
04:11Now this final screen is going to show us information about that image,
04:15so for that, I'm just going to do a couple of things.
04:18First, I'll just click the blank area to select the view.
04:22I want to change the background to, say, a light gray color.
04:28Then I'll drag on a label from the Object Library.
04:34I'll widen this out a little bit and perhaps even use the Attributes Inspector
04:43to manipulate the font or the text color.
04:48Change it to System Bold, for example.
04:50Now, at the moment a label would only show one line of text.
04:54That's what it's limited to.
04:55So one more thing that I'm going to change it to is at the top of the Attributes
04:59grab handles around it, and I'm going to hit my Ctrl key and Ctrl+Drag to the final View Controller.
04:59Inspector, change this to Lines Supported are 0.
05:01That allows it to be multi-line.
05:04And we will need a way of dismissing this View Controller.
05:07We won't have a Back button, because it won't be in the Navigation Controller.
05:12So I'm going to add on another button. Just position that down the bottom and
05:18double-click it and say done.
05:20I am going to zoom out, take a look at this.
05:25Looks okay. The only thing I'm going to do, and I don't have to, is on the Table
05:29View, I'm just going to zoom in here and double-click the first Navigation Bar
05:33to say something like Photos.
05:35We'll talk about how to set the title of that bar for other scenes in a moment.
05:40So I have my storyboard. The next step is I need to do some prep on this.
05:45I need to create the custom class that we're going to use to pass between
05:49these different scenes.
Collapse this transcript
Step two: creating the custom class
00:00So step 2. Before we get much further, I am going to create the custom class that
00:04we will be passing between scenes.
00:07So in Xcode, go to my File menu, create a new file, and what I am going to look
00:12for here under iOS is just a Cocoa Touch Objective-C class, a plain class here.
00:18Nothing to do with view controllers or test cases.
00:20Click Next, and I will call this Photo and it will be a subclass of NSObject.
00:27I do want to save it into my project, so I'll just click Create here.
00:31It has taken me to the implementation of my Photo class.
00:34I need to actually jump across to the .h file into the header.
00:39In here I am just going to declare three properties.
00:43They are all going to be non-atomic and strong. And all I am having here is a
00:54name, a file name, and a notes property.
00:56They are all just NSStrings.
00:59Of course if I define the properties in my header file, I better jump across
01:03into my implementation and make sure that I have the synthesize statements for these.
01:12And that's our custom class created.
01:14I am not going to add any methods to this. All I really want is a basic data structure.
01:19On to the next step.
Collapse this transcript
Step three: creating the view controllers
00:00So for step 3, here's the problem.
00:03In our storyboard we've dragged on multiple View Controller scenes, but we
00:07don't have any corresponding View Controller class files for these scenes in our project.
00:11There is nowhere we could write custom code for each of these different scenes.
00:16So we need to provide our own View Controller classes, the .h and .m files.
00:21And if we don't, all these scenes on our storyboard are just going to use the
00:25built-in View Controller classes in iOS, meaning no custom behavior.
00:30So how many new class files do we need?
00:32Well, we're going to need three.
00:34The first one will be for our Table View Controller so we can show the list of photos.
00:39We'll need another class for the scene that displays the image, and then we'll
00:44need a third one for the View Controller scene that shows information about each photo.
00:49The only thing we won't need custom code for is for the Navigation Controller,
00:54because we don't need it to do anything other than what it usually does.
00:58So how do we add these files?
00:59Well, up to the File menu, and I'll click New > File, not New > Project, not New >
01:04Target, but New > File.
01:06We are going to add an Objective-C class, so making sure that Cocoa Touch is
01:11selected under iOS and then Objective-C class here. Click Next.
01:16We're not doing a standard class that inherits from NSObject.
01:20We want a very specific class for each of these.
01:23They are expecting a class that can already deal with the basic functionality
01:28involved in being a UIViewController or a UITableViewController, and that's
01:33dependent on what we actually dragged onto the storyboard.
01:36So our first one is going to be a subclass not of NSObject or UIView or even
01:41UIViewController, but UITableViewController. I am going to do this for the first
01:46one, and I'll call it PhotosTableViewController.
01:51I am paying attention to the capitalization here so that it will look correct
01:56when we view it in our storyboard.
01:59This will be a subclass of UITableViewController, and I want both of these
02:03check boxes unchecked.
02:04We do not need an extra XIB for the user interface, and we're doing this
02:08right now on the iPhone. So click Next.
02:12It asks, do we want to add them to a project? Absolutely, and Create.
02:15And it gives me the .h and .m files.
02:18Now, before I change anything, I am going to just go ahead and add the others.
02:23Up to the File menu, New > File. The next one will again be an Objective-C class,
02:28this time for the section that actually displays the image.
02:32I'll call it DisplayViewController.
02:34That will be my name for it.
02:36This time around, this is not a TableViewController.
02:39It's a UIViewController.
02:41Once again, both check boxes unchecked.
02:44We'll click Next and add it to the project.
02:47And one last time, for the final scene that will display information,
02:53we'll create a new Objective-C class.
02:55I'll call this one InfoViewController, and this one also is a subclass of
03:00UIViewController. Both check boxes unchecked, click Next, and Create.
03:05Now, if you're wondering, how would I know which class to inherit from?
03:09Well, it's actually very easy.
03:10When we were building the storyboard, if I open up my Utilities panel here, what
03:15did you actually drag on for the scene?
03:17If you dragged on a View Controller, then you want a corresponding class that
03:20inherits from UIViewController.
03:22If you dragged on a Table View Controller, you want a class that inherits from
03:26UITableViewController, and that's so these scenes can have the right base
03:30functionality and we don't have to write it all.
03:32Now, here's the very important step.
03:35We've added these three new classes, but there is no connection between those
03:40and the three scenes that are actually sitting in our storyboard.
03:44So before I go any further, I'm going to hook up these scenes to their correct
03:48corresponding classes.
03:49Now, to do this I'm going to do two things here.
03:51First, make sure that I am zoomed into 100%. Even though it doesn't look all
03:57that useful, this is the only way of reliably interacting with the
03:59storyboard right now.
04:01I am going to open up the Utilities panel. Now making sure that I am looking at
04:06the right one, I can ignore the Navigation Controller.
04:08I am looking for my Table View Controller.
04:10I am going to just click in there to select it. And I want to see these two
04:15icons on the dock, because I need to be able to select the second one, the View Controller icon.
04:20With that selected, I should see the blue bar being highlighted around this.
04:24Why am I doing this?
04:26Because with the Utilities panel open, I am going to go over to the third part of
04:31the Inspector, what's called the Identity Inspector.
04:34And this is where it's telling me what this scene is using as an underlying
04:38class definition, and right now it's UITableViewController.
04:42They're built in one in iOS.
04:44This is not what I want.
04:45I want my custom one that I just made.
04:47If I click the dropdown box, we can see that it's smart enough to look through
04:51the classes that are in my project and say, hey, the only other one that counts,
04:56because it has to inherit from UITableViewController, is
04:59PhotosTableViewController, and that's how I make the connection.
05:03Back into the storyboard, drag along into the second one.
05:06This is the scene that will display the image.
05:09I am going to select somewhere in there, make sure I can click the second
05:12icon that represents View Controller so I see everything highlighted with the blue outline.
05:17Again, in the Identity Inspector it says it's right now using just the built-in
05:21default UIViewController class.
05:24We need that to be our new DisplayViewController class.
05:28Now, there are more built-in and not built-in classes here that are options, but
05:33I want this one, DisplayViewController.
05:36And finally, on to the last one, we'll highlight this, highlight the View
05:42Controller for the third one that will show us the information about the photo,
05:45and if I browse through it, we can find InfoViewController, which was what I
05:50defined over here in my project.
05:53So now we have the different scenes connected to their corresponding class files.
05:58Well, what's the next step?
06:00If I look at these scenes, I think, how many of these scenes actually need to
06:04know about that new custom class that I created, the photo class, in the previous step?
06:10Well, all of them.
06:11The TableViewController will be showing a list of them;
06:14the DisplayViewController will show an individual image;
06:17and the InfoViewController will show information that's part of the object.
06:21So what I am going to do is before I go much further, I am going to select my
06:25PhotosTableViewController header file and add an import statement for Photo.h.
06:32And then I can just copy that and paste it into the header files of my
06:37DisplayViewController and InfoViewController, because they all need to know
06:41about that custom class.
06:43Well, while we're talking about which scenes and which classes need to know
06:47about which other scenes and which classes,
06:50we know that we're going to go from the PhotosTableViewController to the
06:54DisplayViewController.
06:55We're going to segue from this one, and then we are going to segue from the
06:59DisplayViewController to the InfoViewController, and we're going to be
07:01passing information.
07:02And what that means is our PhotosTableViewController--and I'll jump into
07:07the header file here--
07:08this one also needs to have an import statement for the
07:11DisplayViewController header file.
07:14That's the one we are going to segue to.
07:16And in a very similar fashion, if I jump to my DisplayViewController header
07:20file, this guy needs an import statement for the next one along, the
07:24InfoViewController header file.
07:26And this is because we're going to pass information between them. Okay.
07:30Well, what else?
07:32Well, our TableViewController scene will need to have a way of holding these
07:37different photo objects.
07:38So I am just going to have them stored as an array of photo objects.
07:42I will jump into the PhotosTableViewController implementation file.
07:46Now, I could do this as a property, but I really don't need to, because I don't
07:50need any other class than this one to be able to use it.
07:53So inside the implementation, all I am going to add is a declaration here for an
07:58NSMutableArray. And I'll call this photos.
08:03We're going to write the code to load this array in a minute when the
08:07actual application loads.
08:09Now, while this one will need to hold an array of photos, the
08:13DisplayViewController only needs one and the InfoViewController only needs one.
08:17It needs a place we can pass a single photo object around.
08:21So they actually need a property that's accessible.
08:24So with the DisplayViewController, I am going to jump into the header file here
08:29and actually just create a property. And I'll call this one currentPhoto.
08:35Copy that line of code, because we're going to use it again in the next class,
08:39but before I jump over there, I better jump into my implementation and make sure
08:43that inside the implementation we have a line that actually synthesizes it.
08:49Similar thing in the final ViewController.
08:52I'll paste in a property declaration so we can reach in and set this, and in its
08:57implementation, we'll have a synthesize statement for that. And this is all
09:02being done so we can pass some information between the scenes.
09:05Now, jumping back into scan the storyboard. Because I can tell from looking at
09:10this, we will need to programmatically be able to set the image on this
09:14DisplayViewController and set the label on the Information View Controller,
09:18well, we better get those set up ready to take that code.
09:22So I am going to just zoom in to Full Size so I can interact with this properly.
09:27And giving myself a bit more real estate, I am going to open up the Assistant Editor.
09:33This is going to make it easy to add properties that represent my image view on my label.
09:39So I am selecting the DisplayViewController here, and I want to make sure that
09:44the Image View section is highlighted.
09:46If I am not totally sure, I can use the Jump Bar and make sure I've got Image View selected.
09:51And with the Assistant Editor open, I should be looking at the code for
09:55DisplayViewController.
09:56And what I can do is just Ctrl+Drag from the Image View inside the
10:01interface somewhere. I'll do it as an outlet.
10:03I'll call this one currentImage.
10:06Just checking, yes, it's a UIImageView. That looks correct.
10:09And after you've done that, just scan the property to see if everything looks
10:13right. It's an IBOutlet of type UIImageView called currentImage.
10:17Fine, We'll have the synthesized statement will have been generated automatically.
10:21And similarly, on the final scene I want to highlight Label, I should notice in
10:26Assistant View that we've changed to InfoViewController header file, and
10:30Ctrl+Drag from this into the file, let go, it should be of type UILabel.
10:35It should be an outlet, and I'll call this one detailsLabel and Connect.
10:42Again, just scan it, make sure that the generated code looks correct.
10:45It's a UILabel called detailsLabel.
10:48So while we haven't done an awful lot with these parts of our storyboard, we're
10:52pretty much set up and ready to go, and we'll start interacting with these in
10:56the next step.
Collapse this transcript
Step four: loading the data
00:00So step 4, let's get some data loaded into the Table View.
00:03I am just going to switch back into the standard Editor mode and jump to the
00:08implementation file of my TableViewController, which is
00:11PhotosTableViewController.
00:13I have already defined an NSMutableArray here, so what I need to do is just load
00:17this with some basic data, create some of those photo objects and load them in.
00:21I am going to use the Jump Bar just to jump down to say viewDidLoad.
00:25We are just going to do some static objects here.
00:38First, just initialize that NSMutableArray object, then create the first Photo object.
00:49The only reason for this to exist is so we can hold some data in it, hold some information.
00:54So I'll just set its Name, its Filename, and its Notes.
01:24And then finally, add that to our photos array.
01:30And rather than make you watch a lot of this, I am going to just paste in a few
01:33lines of code that's doing exactly the same thing, just a few more times.
01:38The only difference being of course if I am reusing the pick reference, I don't
01:42need to actually create it as a pointer there.
01:45So we are just creating multiple photo objects, adding them to the array.
01:50So I have these objects, but there's nothing that's actually going to load them
01:54into the Table View itself.
01:56So that's the next step.
01:58In the photo's TableViewController, I'm going to click on the Jump Bar.
02:02Because this was created as a UITableViewObject, I have automatically got the
02:07TableView data source methods, and they are actually going to have boilerplate code in there;
02:11so numberOfSectionsInTableView, how many rows in the section, what's in each cell?
02:16If I jump to the first one, numberOfSectionsInTableView, it's going to give me a
02:20warning that this is a potentially incomplete method implementation.
02:24This needs to say how many sections does the TableView have.
02:27I am going to delete the warning and just say to return 1.
02:31We move down to how many rows are in the section?
02:34Again, it's giving me the warning here. Fill this out.
02:37Okay, I am going to.
02:38NumberOfRowsInSection will be based on the array.
02:41The array is called photos.
02:43It's just going to be photos count.
02:45And then, we finally have the important one,
02:48cellForRowAtIndexPath.
02:50This method will be called repeatedly based on however many objects are in that photos array.
02:56Now, we need to create the content for each table cell.
03:00We've got the standard code in here for dequeueing a reusable cell with
03:04identifier, the same kind of thing we've talked about in the other examples of TableViews.
03:08Let me just hide the navigator to see this a bit clearer, because all I want to
03:13do when this method is called is pull the corresponding photo out of the array
03:17and grab the text, grab the title of that photo.
03:22So I'll create a variable to just hold a photo.
03:26I don't need to actually instantiate it. It already exists.
03:28It's in some position in that existing array.
03:31So I need to access the array and pull it out based on the current cell.
03:36This I am just going to get from the parameter indexPath.row.
03:42Because this method is called repeatedly, passing in a parameter of indexPath, so 0, 1, 2, 3, 4.
03:51It means we could adjust our array.
03:53We could just load it up with more information and all this code would still work.
03:57Then we could use just the square brackets of Objective+C. I am using a bit of
04:00square brackets and a bit of .syntax here, whatever you are comfortable with.
04:05And then we can use the cell that was created on line 129.
04:08We are interested in its textLabel property, which itself has a text property,
04:17because the label could have setText, setFont. There is a whole bunch of
04:21different options that it has here. But I am just going to set it to the name of
04:26the current photo that we just grabbed on line 134.
04:29Again, whatever you are happy with, whether it's .syntax or the Objective-C
04:34square brackets, whatever works.
04:36There are multiple ways to write this.
04:38Now, one more thing that's very important here.
04:42We've talked a little bit about this idea of having reusable cells with identifiers.
04:48When a cell is instantiated, it's given a little tag, just a string, a few
04:52pieces of text, and the idea here is that you might have multiple kinds of
04:57different cells, and when we are reusing them, we don't want to reuse the wrong
05:01kind of cell object.
05:03Now, we are only using one kind of cell here, but this is still important to
05:07look at, because if I jump over to the storyboard and highlight the individual
05:15cell on my TableView, bring up my Utilities panel, I am currently on my Identity
05:21Inspector, but I need to go to my Attributes Inspector.
05:24The TableView cell, again, making sure that is what you have selected, has its
05:29own reuse identifier.
05:31You can tag it here and, in fact, you should tag it here.
05:35I am going to give it a name of PhotoCell.
05:38Really, it doesn't matter what you call it, but just some way of identifying this.
05:42Again, the benefit being that in the Storyboard View, you can actually just lay
05:46out and design multiple different kinds of cells that could all be used
05:50together inside one TableView, and you'd want to be able to identify each kind of cell properly.
05:55So if I've called this PhotoCell, then what I need to make sure back in my
06:00TableViewController, is that's the word that I use when I instantiate it.
06:05I am going to save this all, build this project, and we'll see what happens.
06:09It's not finished yet, but we should be able to get at least some parts of it working.
06:14Build has Succeeded. I'll click Run.
06:16And the application loads in the Simulator.
06:20I can see that I am certainly getting the individual entries.
06:23Of course they are not loading into the DisplayViewController, because I haven't
06:27written anything to do that, because now we need to start passing information
06:33between the scenes, and that's the next step.
Collapse this transcript
Step five: passing objects between scenes
00:00Okay, step 5.
00:01Now, we need to start passing information from first the Table View Controller
00:06to the Display View Controller, and then if necessary, from the Display View
00:10Controller to the Info View Controller.
00:13And we do this by using the new View Controller method called prepareForSegue,
00:17and this is automatically called when any segue is triggered.
00:21And what that means is that in our PhotosTableViewController implementation
00:26file, what we're not interested in is the didSelectRowAtIndexPath method, which
00:32is the usual one that you tap on for table view.
00:35When you're working with storyboards and you have your segue set up, you don't need that.
00:39So we're going to create a new method here--and I could put this anywhere.
00:43I'm just going to put it up at the top here, just underneath my
00:46MutableArray definition.
00:51It returns void, and it's called prepareForSegue.
00:54That is a built-in method, so even as I start typing, it's going to bring it up here.
00:59I need my opening and closing curly braces.
01:02And we've got to think about what we're doing.
01:03Well, we are currently in the PhotosTableViewController, and we're going to
01:09segue over to the DisplayViewController.
01:13And we want to be able to pass it some information.
01:16And here's how we do it.
01:17In the prepareForSegue method, I'm first going to create a reference to the
01:21DisplayViewController we're about to segue to.
01:25I'll call it dvc, but how do I get this?
01:28Well, here's the great thing.
01:30When we're preparing for a segue, the whole infrastructure here that's going on
01:34actually knows what we're about to segue to, and I can ask for that information.
01:38I can ask the segue parameter here, what is the destinationViewController?
01:43Where are we about to go?
01:44Because we could be segueing out of this View Controller to multiple places.
01:49Then what I'm going to create is an NSIndexPath reference to the currently
01:55selected cell in the TableViewController, in myself. So where am I?
02:02self.tableView indexPathForSelectedRow.
02:08And this will allow me to grab the right photo object so I can pass it over in just a second.
02:14All I'm interested in about the Index Path is the row, but that's fine.
02:17What I'm going to do is just create a Photo Pointer to grab the selected
02:22photo out of the array.
02:24It's the photos array, and I'm interested in objectAtIndex, and we're going
02:29to use the path variable we just created, and we're interested in the row element of it.
02:36Again, this could be .syntax path.row, or I could use the square brackets and
02:42say path, space, row.
02:44So I have a reference to the DisplayViewController we're about to segue to.
02:49I have a reference to the current photo that we've just selected, which I've
02:53called c. So I'll use that reference to the DisplayViewController and say
02:57setCurrentPhoto, which is the property we created in, in that object to c. This
03:06is all the code I need to do to grab a reference to where we're going and pass
03:09it some information.
03:10Now, for good practice I'm going to add one extra thing to this
03:14prepareForSegue method.
03:16Because we could be segueing out of this View Controller to multiple places,
03:22this method could be being called multiple times, and you might want to ask,
03:26well, which segue am I about to do?
03:29So we can actually create an if statement.
03:31I'll fill in the condition in just a second.
03:34And what I first want to ask is, if it's the correct segue, we're going to do
03:38that code that I just wrote.
03:39Well, how do I know what the correct segue is?
03:42If I jump back to the storyboard, we can actually name these segues.
03:47We can give them an identifier.
03:49So I've clicked on the Segue itself to select it and I open up my Utilities panel.
03:54You see the segue only has two properties here:
03:58an Identifier and a Style-- is it Push, Modal, or Custom?
04:01I'm going to give it an Identifier of ShowPhoto.
04:05Now, jump back into my implementation file, and what I'm going to ask up here is
04:10if we can ask the Segue parameter, are you equal to that segue?
04:25Are you the ShowPhoto segue?
04:27If so, we can transition there.
04:29This is not strictly necessary in our example, because we only have one segue
04:33out of this View Controller, but you get the idea.
04:36If we had multiple segues, this is how we'd ask which one are we about to do, so
04:40we can make sure we're passing the right information to the right
04:44destinationViewController.
04:46So we're passing the photo object over into the DisplayViewController, so we
04:51better go and load it in there.
04:53So I'm in the DisplayViewController.m file.
04:57I'm going to come in and uncomment my viewDidLoad method, and this is what's
05:01going to be called when the storyboard creates this View Controller and loads it in.
05:07So after the call to super viewDidLoad, I'm going to instantiate a new
05:11UIImage object, and I'm going to call it by using the very useful UIImage imageNamed method.
05:21imageNamed just takes the name of an image file.
05:24It's going to go and find it in our applications bundle.
05:27All I need to do is give it the file name of the current photo object that we passed in.
05:36I've grabbed that image.
05:37Now I'm going to set the Image View that's actually on our View Controller.
05:42This was named as currentImage when we hooked it up as an outlet, and I'll just
05:47use the call to setImage:
05:48image we created on the previous line.
05:52Just going to save that and run this. Let's check it.
05:56So in the TableViewController we take, say, the Beach object, we pass it over,
06:00and we're loading in the Beach image.
06:02Haven't done the final View Controller yet, but we'll get to that in a second. Quit out of that.
06:08Now, one of the things I'd like to do is also set the title of this View
06:12Controller so that it will appear properly in the Navigation Bar at the top.
06:16That's very easy to do.
06:17What we're going to just call is a self setTitle, which is a property of the
06:23View Controller, and we want it to be the name of the current photo object,
06:29which will be currentPhoto, space, name.
06:33Again, .syntax or square brackets, it's up to you. Run that again.
06:38And because we're passing the entire object in, if I pass in Olives, we can use
06:43Olives and grab the ping and we also set the title on the Navigation Bar.
06:49Flag, Overlook, it's working just fine.
06:54But this scene in the DisplayViewController can segue to the next scene by
06:59clicking this button, so we better go and fix that one.
07:02So in our DisplayViewController we need another prepareForSegue method.
07:08For purposes of time, I'll just put it right here.
07:10It is again (void) prepareForSegue.
07:14I want to grab a reference to an InfoViewController.
07:17This is what we're about to transition to.
07:20I'll just call it ivc.
07:21And again, I get it by asking the segue, what's your destination, where are
07:27you about to segue to?
07:29We now have a reference to that destination, so all I need to do is use its
07:33property of setCurrentPhoto, there we go, to my own currentPhoto object.
07:40Again, we're passing this from one object to the next and then on to the next.
07:47That's all I need to do in this prepareForSegue.
07:49For this one, I'm not going to check the name of the segue.
07:53You saw that example previously.
07:55We don't actually need to do it here.
07:58What I am going to do is jump over into the implementation file for my
08:02InfoViewController, so that in viewDidLoad here--and I need to come down and
08:06uncomment it-- we can make sure to set the text of the label, which is simply
08:16going to be the notes property of our currentPhoto object.
08:20Save that, run this, objects are created and loaded into the Table View.
08:27We tap one of them.
08:28We segue passing that object to the second scene, click the button.
08:33We segue, passing that object to the final scene.
08:36Now, what we don't yet have is a way of hooking this button back up.
08:41Because we're not embedding this one in the Navigation Bar, it doesn't give us a
08:44Back button, so we need to fix that.
08:47So quit out of this, return to the storyboard, and I'm interested in our
08:51final View Controller.
08:53I'll zoom in so we can see that properly, and open up the Assistant Editor,
08:59so that in our InfoViewController we can cause an action to happen from this button.
09:04It's an IBAction.
09:06Making sure that I have both the button selected on this final View Controller
09:10and the correct file selected here, which is our InfoViewController header file,
09:14I am going to Ctrl+Click, drag into the interface.
09:18I'm not adding an outlet;
09:19I'm adding an action.
09:21And I want this to dismiss this current View Controller.
09:24So I'll just call it dismiss;
09:25you could call it whatever you want.
09:28Jump back into the standard editor, because I need a bit more space here, and
09:32find the implementation of that InfoViewController, which should have created
09:37our skeleton method right down at the bottom, and there it is.
09:40And here's where we need to dismiss this current ModalViewController that we
09:45did a Modal segue to.
09:47All I need to do is say, hey, dismiss yourself, self
09:51dismissModalViewControllerAnimated:YES.
09:56Save, run.
10:00Load the Table View, tap one of these, transition to the next scene.
10:05We've set the title properly.
10:06We've set the image properly.
10:08Tap the button, transition to the next scene.
10:11We're looking at the notes loaded into the label.
10:13Click the Done button.
10:14We transition away from the ModalViewController.
10:17The only thing I don't really like is this Modal segue.
10:20We're taking over the entire screen, and we really don't need that much of it. So let's fix that.
10:26Jump back into the storyboard, and when I select the final segue that's segueing
10:31into the final scene, I'm going to open my Utilities panel, and with that segue
10:35selected, I'll see that with the Modal style, I have multiple transitions:
10:40Cover Vertical, Flip Horizontal, Cross Dissolve, or Partial Curl.
10:44And Partial Curl should do the trick.
10:46I set that, we run it again.
10:50Now we load the Table View, select an object, pass it to the second scene, click the button.
10:56We do the Modal segue with the animated page curl.
10:59I'm done, back, and alter the next.
11:10So while this is not the most complicated application in the world, we can see
11:14that with just a few lines of code here's how we can have multiple View
11:17Controllers segue into each other, interacting between Table View Controllers,
11:22Navigation Controllers, Custom Objects, different types of segues.
Collapse this transcript
10. Using Blocks and Grand Central Dispatch
Introduction to blocks
00:00There is a language feature in Objective-C called blocks.
00:03This was made available in iOS development with iOS 4 in 2010.
00:08We use blocks to group code together into reusable chunks.
00:12You might first hear that description and think, okay, and then a few
00:15seconds later think, but, surely that's what we do with classes and
00:19functions and methods.
00:21And yes, they all do allow us to group code together into reusable chunks, and
00:25there are similarities, but blocks are used for very specific reasons.
00:29So why do we use them in the first place?
00:31Well, first and main reason is that you're going to have to. While you can get
00:36by with the Foundation Framework and UIKit without blocks fairly well, many of
00:41the newer and the updated and the more interesting frameworks in iOS
00:45development use blocks.
00:47If you want to use the Assets Library, Grand Central Dispatch, new audio and
00:51video features, the Game kit, you're going to have to get to know these.
00:55Blocks are not some weird esoteric feature that you get to ignore.
00:59If you're going to work seriously with iOS development, you'll be about as able
01:02to avoid blocks as you would be able to avoid integers.
01:06And they can make your life easier.
01:09They allow you to write less code, more readable code, and they easily allow you
01:12to tap into powerful techniques in iOS development. Things like multithreading
01:17and callbacks become a lot easier using blocks.
01:20And in fact, this is why blocks, or at least their equivalent concept, are
01:24common in other languages.
01:26In fact, Objective-C was a little late to the party with blocks.
01:30Other languages have had blocks or their equivalents for years.
01:34You might be working with a language that has something like an anonymous
01:37function or a closure or a lambda.
01:40Well those are the equivalent of blocks in other languages.
01:43So how do we actually do this?
01:45Let me show you a simple example of the syntax.
01:48We are talking about blocks being reusable chunks of code,
01:51So let's take one that we already know how to use.
01:54Let's say we've got a function, and this could be in just about any C-based language.
01:58It's not even a method, just a very basic function here called myFunction, and
02:02we know how we'd call it in our own code.
02:05So the function is made of a return type.
02:08It's made of a name.
02:09It's got some arguments defined in it, and it has a body to it.
02:13The body could be one line of code, could be a dozen lines of code, could be a
02:17thousand lines of code, so a very typical function.
02:20And when we think about a reusable chunk of code, we might think of
02:23something like this.
02:24We define it and then we call it.
02:26Now, if you want to see its direct equivalent using blocks, you might see
02:31something like this, and you will quite commonly see this format shown when
02:35you're being introduced to blocks.
02:37I don't find this format is all that useful, and I will explain why.
02:41Yes, a block can be created like this where we have the official return type.
02:46We have the name of the block like we'd have the name of a function, and it's
02:50got the caret symbol before that.
02:52We'll talk about that in a second.
02:54And here we have something that says arguments.
02:57But in fact, in this particular format we will have another section that's
03:00officially called arguments as well, and it doesn't really look like we've won anything.
03:05This is more code than we used before, and it's actually bit more annoying to
03:09look at because of the caret symbol.
03:12The problem is this.
03:13When you see the full declaration of what a block could be, it's a bit
03:18misleading because it's giving us a lot of optional stuff,
03:21things we would have to do for a function, but we don't have to do for a block.
03:26One of the things we're looking at here is actually two blocks, which is why
03:29we're seeing two of these carets.
03:32Effectively, we're seeing the first part here being a block variable and the
03:36second part being a block literal.
03:39Block variable means we're actually naming it like a variable.
03:42We're seeing it has a return type and it says parameters, and on the
03:45right-hand side of the equals sign, we're actually saying what is the block,
03:49what is the literal?
03:50And in fact, the block literal part is the most important part of this, and
03:54the most useful part.
03:55An analogy I could make is say when we're working with strings.
03:59We can do something like this and it's quite common to create a string
04:03variable and set it to the value using a string literal, or at least a string literal format.
04:10But a lot of the time, we just want to use a string as a literal.
04:14We just want to write one without having to go through the whole problem of
04:17defining an NSString variable and alloc it and init it.
04:21We just want to use it.
04:22In the same fashion, if we go back to our block declaration, while this is the
04:27full formal declaration of a block, what we can often do is just dump the first
04:32part of it and say, no, this is all I need.
04:35I need the caret symbol, some return types, and then in braces, I just have some code.
04:40That's it! But how do we use them?
04:42Well, just like string literals, you don't really find them by themselves.
04:46That will be embedded and used in some other code.
04:49But if you're seeing that caret symbol, the first symbol that we see here, on a
04:54US or a UK keyboard, this is the Shift+6.
04:57Now, if you're using a different international keyboard, you may have to hunt for it.
05:01But the caret symbol is what tells us this is a block.
05:04Once you see this symbol, you've got a block.
05:07So your first exposure to them is likely to be seeing them being used in some
05:12call to one of the newer API features, one of the newer frameworks.
05:16I'll show you an example.
05:17Again, don't worry too much about what this exact syntax is. This is a method
05:23that's defined in one of the new classes, in the Assets Library framework, to
05:28help us work with image assets and video assets.
05:31There is a method called writeVideoAtPathToSavedPhotosAlbum, and it takes an
05:36argument of a URL for a piece of video that you might have taken. And then there
05:42is another parameter called completionBlock.
05:45What this allows us to do is make a method call that's actually going to take a
05:50couple of parameters.
05:51Let's say I have got one called myAsset that represents the URL to some video,
05:55and I want to save it to my SavedPhotosAlbum.
05:58completionBlock allows me to write this block of code, pass it into this method,
06:04and this code will be executed when this method completes,
06:07in this case, perhaps checking if there was any errors with it.
06:11Now, you might think, well, why don't I just put that code after the method call?
06:15Well, the benefit here is it allows us to call methods that run on another
06:19thread without worrying about doing multithreading or callbacks.
06:23This method executes. It immediately returns to our code, but it will try and
06:28save that video, which could be quite a long process.
06:30When it's done, it will call this completionBlock, and go through this code.
06:34So it's quite common to write a block like this we're using the caret symbol and
06:38just writing it straight inline inside one of these method messaging calls.
06:44Another alternative is you can also create a block as an object.
06:48The way they're defined, that same example, I can actually save this block as a variable.
06:54The type of this variable will be ALAssetsLibraryWriteVideoCompletionBlock, and I
06:59have just called this one block.
07:01I save the value, all the code that I want, and it could be dozens or even
07:05hundreds of lines, and then a little later, I use the block.
07:09I just pass it in as a parameter.
07:11So it's allowing me to create this chunk of reusable code and pass it into a method call.
07:17Now, this is all a little bit new.
07:19Just keep in mind to recognize the caret symbol as the immediate red light that
07:23goes off and says, here, I have got a block.
07:26You don't have to get obsessive about the syntax immediately, though if you'd
07:29like to, there is some really good documentation on the Apple Developer sites.
07:33But we're going to explore how to use these blocks with one of the newer
07:36features in iOS, something called Grand Central Dispatch.
Collapse this transcript
Understanding Grand Central Dispatch
00:00Grand Central Dispatch, or GCD, was a new feature with iOS 4, and if you read
00:05the official documentation from Apple about it, you'll see lots of phrases
00:09like "it provides systemic comprehensive improvements in the support for
00:12concurrent code execution."
00:14Well, at the end of the day, we want Grand Central Dispatch because it makes
00:18multithreading easy.
00:20Your question right back on this might be, well, why do we care that
00:22multithreading is easy?
00:24And the end result, no matter how you spin it, is we want to have a more
00:27responsive user interface in our application.
00:30We want our apps to feel more professional.
00:32We want them to be able to do multiple things at once.
00:35Now, here we're talking about multithreading, not multitasking.
00:40Multitasking, which we have, is the idea of multiple applications at the same
00:45time. And as we've seen, iOS handles switching different applications between
00:50background and foreground states. But we're talking about multithreading.
00:54This is just for our app, the ability for our application to do multiple
00:58things at the same time.
00:59And you still might be thinking, well, why is this important?
01:03And the issue is that we can have a problem with the idea of our app having one
01:08queue for processing.
01:09We have this main queue, and it performs tasks one after the other, strictly
01:14in order, whether it's updating the UI, performing calculations, connecting to
01:18a database, whatever.
01:19We can, with GCD, create a custom queue and take some of these tasks off, make
01:26them run on their own queue, and Grand Central Dispatch in iOS will take care
01:30of all of this, making sure it happens responsively and it happens smoothly.
01:34And the key benefit here is particularly the ability to make sure our
01:38user interface stays responsive even while heavy processing goes on in the background.
01:44So how do we use and work with Grand Central Dispatch in our iOS applications?
01:49There are two steps.
01:50Step 1, you create a new queue.
01:53We'll see this in a moment.
01:54We give this a name, whatever name is meaningful for us. This queue might be
01:58just for networking or just for long-running calculations.
02:01Then step 2, you create blocks that we've just talked about and you drop them in the queue.
02:06That's step 2. Step 3 is nothing.
02:10That's it. Okay, so there is a little bit more when you get into advanced parts of this,
02:15but for most people, most of the time, the whole process of using Grand Central
02:20Dispatch is, make a new queue in your application, add blocks to the queue,
02:24let iOS take care of everything else.
02:27And if you're someone who has programmed multithreaded code before, you'll know
02:30that it's a fairly unpleasant thing to do.
02:32Grand Central Dispatch doesn't just make multithreaded code easier. It makes it easy.
02:37Most of the time we're going to be interested in two main commands that
02:41we're going to execute.
02:42One is to create a new queue, and it's this function, dispatch_queue_create.
02:48The way that we use it is like this, to create a variable. In this case I've
02:53called it myQueue, and I give it a label, just a string.
02:56That's pretty much it.
02:57I've said myQueueName.
02:58This could be a descriptive label for what this queue is being used for.
03:02The reason we give it a label is if we want to see it in debugging information later on.
03:07When I show you an example in a moment, I'll show you that the typical label we
03:10put in here is actually reverse DNS notation, but you can put any text in here
03:15that's meaningful for you.
03:16So we've created a queue.
03:17I've now got a queue variable called myQueue, and then I'm going to use the
03:21other most important command in Grand Central Dispatch, which is dispatch_async.
03:27And this simply takes two parameters:
03:30the name of the queue that we're dispatching to and a block.
03:33I can see the caret here with the curly braces that contain my block, everything
03:38that we want to do asynchronously, which in this case is just passing in one
03:42message, one call to a long-running operation method.
03:46So we do have to use blocks to be able to use Grand Central Dispatch, but
03:50between these two calls and learning a little bit about them, you'd be amazed
03:54at the amount of stuff that you can do creating your own multithreaded applications.
03:58Well, I've talked for a while about how easy this is, and I've shown you a
04:01couple of the keywords, but to prove it is easy, in the next module we're
04:05actually going to go through and show how to take an application from
04:08single-threaded into multithreaded using Grand Central Dispatch.
Collapse this transcript
Creating a multithreaded app
00:00In this example, I'm going to use Grand Central Dispatch and blocks to take an
00:03application that's currently not very responsive with the UI and make it
00:08multithreaded with just a few lines of code.
00:10So right now I have the simple application here.
00:13It's got a date picker on it that I can spin around and a button that says
00:17long running operation.
00:18I'm going to start interacting with the date picker and then click the button.
00:21And what initially will happen is the entire user interface is locked up right now.
00:26It's not responsive until we get the result back from that operation.
00:30Because the operation itself is blocking, even the button itself is staying in
00:34the depressed state.
00:35So it's just not a responsive UI.
00:38Your users aren't going to like something like this. It doesn't feel professional.
00:41It doesn't feel useful.
00:43In fact, it feels like there might be a problem with it. So let's deal with this.
00:47First, I have to explain what's actually going on.
00:49Well, for a start, I don't really have a complicated UI.
00:52In fact, this date picker is not even hooked up to anything.
00:56It's just to show that even the simplest, most independent user interface
01:00element will become non-responsive if your main thread is actually blocking.
01:05So my button here is just connected to a simple piece of code in the
01:09implementation file,
01:10this IBAction here that says perform the longRunningOperation. And
01:16longRunningOperation is going to do simply two things.
01:19First, on line 21, it's going to go to sleep for five seconds.
01:23And then on line 22, it will change the text of the message label with a random
01:28number using the arc4random function. But that's it.
01:32I don't have anything in here to do with threading at all, but this is enough to
01:36upset our user interface.
01:38Whether this was a sleep for time interval call, or it was a complex
01:43calculation, it could all upset it.
01:45So I want to turn this into using Grand Central Dispatch and use its queues.
01:51So first off, in here I'm actually going to define just one queue that we can use locally.
01:56So it's going to be dispatch_queue_t, and I'll call it myQueue.
02:06I'm just defining it here so it's global in this View Controller across multiple
02:10methods and whatever functions I might have.
02:12And then the question is, well, where do I create it? Where do I put something in this?
02:17And I could do this in a whole bunch of different places, but just for our
02:20purposes, I'm going to do it when the button is actually touched here.
02:26I'll say myQueue =, and we make a call to dispatch_queue_create.
02:32It's brought it up here, so just hit Return, jump into the first parameter.
02:38I give it a label and an attributes list, and right now the attributes list isn't being used.
02:43Now, they're both actually optional, but the recommendation is you give it a label.
02:47Now, we don't have to use the at sign here.
02:48This is just a C-style function with C-style character array.
02:54The official recommendation is that you use reverse DNS notation,
02:59so something like com.lynda and then something that would describe my app.
03:03Let's say it's a Grand Central Dispatch test app.
03:06Then I hit Tab to the other parameter, which isn't needed, and here I just put null.
03:11And this is more of a C-style function call than a Objective-C object.
03:16The reason that we give it a label, this com.lynda.gcdtest, is so that later on
03:22if there are issues with the queues, it will actually show up in instruments and
03:26allow us to diagnose it.
03:27So what am I going to do with this queue?
03:30Well, currently on line 19 is here where I make a call to that longRunningOperation.
03:34This is what I'm going to do.
03:36I just want to do this on another queue.
03:39So here's how I do it. dispatch_async, first parameter is myQueue.
03:51The second parameter is the block.
03:53This block can be small. It can be large.
03:55It just needs to contain the code that we want to execute on the other thread.
04:00So I use the caret.
04:02I'll do my opening, space, closing braces.
04:06That's the block format.
04:07And then inside this I can just put the code I want to run, which is simply this call.
04:13Cut that out, paste it in, and just make sure that I'm putting a semicolon at
04:19the end of the line. That's it. We create the queue.
04:23I'm just going to go ahead and compile this and run it.
04:27And it's as simple as that, to actually start that operation running on another thread.
04:31If you notice when I clicked the button, I still have this response. It didn't hang.
04:38However, one of the problems is we don't actually see much of a response coming back.
04:42My label is not being changed.
04:44That's because the way I've created it, we have one more issue.
04:47And to tidy that one up, I need to go back into my code.
04:51The issue is back here.
04:52We're calling this longRunningOperation on that secondary queue, and that's fine.
04:57But I've got to look at what this operation is doing.
05:00Well, first it's going to sleep for five seconds, which is not a problem, and
05:04then it's updating the label on my user interface.
05:07Well, that's the issue.
05:08You're not meant to update user interface elements from any other thread than the main one.
05:14And it's not that you can't, it's not that it's going to crash.
05:17It's just not reliable, because you don't have a lot of control about how
05:21quickly things are updating to that main screen.
05:24So this myLabel setText call really needs to be executed back on the main thread.
05:30And the question is, well, how do we do this?
05:33Well, here's the great thing.
05:34I can use dispatch_async within this call to actually put this part back on the main queue.
05:41So I'm just going to type another dispatch_async.
05:43Now, you might think, well, what's the name of the main queue?
05:50I don't technically know, but that's okay.
05:52I could make another function call called dispatch_get_main_queue, which itself
05:58just takes another block.
06:00We use the caret symbol, opening and closing braces.
06:04Let's just finish that statement off, and then I could cut this. Let's break it
06:10upon to a couple of different lines and paste it in. Save, run.
06:15And what should happen now is we can mess around with this user interface.
06:20I can click the button.
06:21We immediately are still responsive.
06:23It doesn't hang the UI, but in a few seconds we get our result back.
06:27I can do this multiple times.
06:29We have a multithreaded operation working just fine.
06:33And this is how we can use Grand Central Dispatch and blocks to very simply,
06:38very easily turn our application from using a single queue into multiple queues
06:42without even saying the word thread anywhere in our code.
06:45So very simple stuff, but powerful stuff to do.
Collapse this transcript
11. Saving Data
Understanding the options for saving data on iOS
00:00The applications we've created so far will always begin in the same way.
00:04We've never saved any information for the next time the application loads after
00:08the iPhone has restarted.
00:10Now, some of the times this is okay.
00:12If your application is simple, it can load and unload repeatedly without there
00:15ever being a problem with this, but it's more likely that you will want to save
00:19some data, to persist it to storage on the iPhone so it can last when the device
00:24itself is restarted.
00:25Now, your first key question here is what kind of data are you saving?
00:30Option one: you might be just saving a few simple values, some strings,
00:35Booleans and arrays.
00:36Now, a very easy way to save these is you can save them to a property list file,
00:40like the one used in earlier to load data into a Table View. And these are
00:45useful because many of the most common objects, things like dictionaries,
00:49strings, and arrays just have simple methods to save their contents directly out
00:54to a file and read them back in.
00:56Now, option number 2, related to this one, is if the data you want to save is
01:00really just application settings, meaning preferences for your app, well,
01:05this is an odd one.
01:06You see, the first suggestion is, don't. Try to write an application that does
01:11not have much in the way of settings.
01:14Now, if you must, Apple has a very well- defined set of rules for working with settings.
01:19It's something called a Settings bundle, which essentially means that you can
01:22tell iOS what settings you want to store and it can take care of saving that
01:27data for your app and even generating the interface for you.
01:31But using this does mean that these settings will be accessed through the
01:34Settings application on iOS, not your application.
01:38So it does require that user exit out of your application to do it and then go
01:43over to the Settings app where there'll be an entry for your program.
01:46But in the last couple of years Apple have moved from recommending this option
01:49to recommending you don't, simply because of the need to exit the app.
01:54They don't quite say "don't ever use this," but the Human Interface Guidelines
01:58say to deemphasize settings in general and using the Settings app in particular.
02:03So if you have to, they suggest using your own screen to handle application
02:08settings, like having the flipside view of the Stocks app or the flipside view of
02:13the Weather application.
02:14But what if it's more involved, if the data in your application can't be easily
02:19stored in something like a property list file?
02:21Well, we have several other solutions available in iOS for storing and
02:25retrieving more complex content.
02:27First off is the SQLite and Core Data options, which are often talked about
02:32together but are very different from each other.
02:34Now first, SQLite as it might sound, is a database. It's a lightweight SQL
02:39database that's built into iOS, and we can create and use simple tables inside it;
02:45whereas, Core Data, now this is the most substantial data storage mechanism on iOS.
02:51Rather than thinking about databases or flat files, it lets you take a complex
02:56object graph, meaning all your objects and all their data, all their references
03:00to other objects, and just save the whole thing, just freeze dry and place when
03:06you need to or re-create it from storage.
03:09Now, Core Data is fantastic and I'm a huge fan, but it is notoriously
03:13unfriendly for new iOS developers, and I suggest you regard it as phase 2 of your iOS learning.
03:19First get comfortable with the general iOS development before you dive into it.
03:23Even Apple's own Getting Started with Core Data guide begins with the phrase
03:28"Core Data is not an entry-level technology." And with iOS 5 your apps now also
03:34have the option to use the iCloud service.
03:36If a user's device is signed into iCloud we can detect that and we can use it.
03:41So, instead of just saving locally on the device itself, your app can save into
03:46iCloud, store data there, and have that data automatically synchronized with
03:51other iOS 5 devices, and even with Macs and PCs.
03:54Now, you as a developer don't have to pay anything to Appe to use this; the
03:58documents saved by your app are part of that user's allocation in iCloud.
04:02Now a full exploration of SQLite, Core Data, or iCloud is way beyond the scope of
04:08this essentials course.
04:09Bill Weinman has a course here at lynda.com on Building Data-Driven
04:13Applications with iOS that uses SQLite, and in 2012 watch the space for more on
04:18Core Data and iCloud.
04:20So, the next question has to be, if we're saving simple data, where are we saving it to?
04:25Now, iOS does have a file system, although it's not quite what you're used to.
04:30You just don't have free access to browse the file system like you might do on a desktop.
04:35Your application can only access its little sandbox part of it.
04:40Every application gets its own documents folder as well as a library and a temp folder.
04:45But it's controlled by iOS, and what that means is the path to this document
04:50library is taken care of by the iOS operating system.
04:54It's not obvious, and it's not up to you.
04:56You have to ask iOS to tell you what it is before you start to use it.
05:01So, you can only read and write from your own area, and other applications can
05:05only read and write from theirs.
05:06They can't touch yours.
05:08There are a few notable exceptions, such as reading from the built-in Address
05:12Book, from the iPod library, or from Calendar events, but pretty much you're
05:17limited to just your own data.
05:20Now, the next question, when do you save?
05:23We'd like to think that our application is special and the users will treat it
05:27kindly, but the truth is that any moment the user can hit the Home screen
05:30button and your app is going to have to exit immediately, they are not going to hit a Save button.
05:37They're going to leave and you're going to need to respond to that very, very quickly.
05:41The perfect event when they leave the app is an event called
05:44applicationDidEnterBackground in the App Delegate, and this will be called by
05:49iOS when something is triggering your application to leave and it has to leave immediately.
05:54So your application goes into the background and you've saved the data.
05:58Well, when we open up the application again, when do you load it?
06:02If we're restoring from the background, the perfect place would be
06:06applicationWillEnterForeground to do the reverse of anything you did in
06:10applicationDidEnterBackground.
06:13Now, neither of these will be the time and place to pop up UI alert views and ask questions.
06:18It's the time to get out, get out as quickly as possible, or get back and running
06:22as quickly as possible.
06:23And with these things in mind, we can go and see an example of saving data on
06:28an iOS device.
Collapse this transcript
Saving and loading data from property list files
00:00Here's the problem that we are going to solve.
00:01We've got a very simple application here with a Text Field and a Date Picker.
00:06If I type in a value here, let's try First try,
00:10I could spin the Date Picker.
00:12I'll select a value that's pretty easy and memorable, January the 1st, and then
00:17we hit the Home button to exit out of it. Go back in again, we'll see those
00:21values, because when moving from a foreground to a background state just regular
00:26user interface elements are taken care of by iOS.
00:29However, if we exit and either double-click the Home button and decide to
00:34completely exit out of that application, or I could also restart the
00:39Simulator, which would be like restarting the device, and then I open it up
00:43again, we're back to blank.
00:45We're back to square 1, because this information is not being persisted in any way.
00:49So we're going to save some data from the user interface, so it can be created
00:53even if the iPhone is restarted.
00:56I've got a project here that I have created some skeleton placeholders for, just
01:00to break down what I have.
01:02In the user interface all that I have here is a Text Field,
01:06there is a Date Picker, and there's an invisible button behind to make the
01:09Text Field go away.
01:11In my header file, I have outlets for the Text Field and the Date Picker.
01:15I have one IBAction for dismissing the keyboard.
01:19These aren't important.
01:20But what I have done is defined three methods that I am going to go and
01:24provide the code for. One to get a file path on the system;
01:28two, to save some data;
01:30and three, to load some data. I haven't done anything with these yet.
01:33So I am going to jump over into the implementation file where I can see my
01:37three methods up here.
01:38This getFilePath that returns a string, right now it's returning just an empty
01:43string just so this would compile.
01:45So I need to provide some code to provide a path to this application's documents library.
01:52Now this should be a really simple call to iOS saying, give me my directory, but
01:57it's a little longer than it strictly needs to be because we are still dealing
02:00with older-style Desktop Cocoa functions rather than new iOS-only ones.
02:05So I am first going to create an array, and the call I am going to do is to
02:13this rather long NSSearchPathForDirectoriesInDomains, which takes a few
02:18different arguments here.
02:20I'll just type them first before I talk about them.
02:32I pass in this function, three parameters;
02:35NSDocumentDirectory, which means, yes, we are looking for the
02:38document directory;
02:39NSUserDomainMask, which is basically saying, yes, it's really just me, the
02:44current user;, and then I am using a Boolean, YES here that says I want the full path.
02:50I don't want any kind of relative path.
02:52Now this is a regular C-style function call, so it doesn't need to be in square brackets.
02:58This will return me an NSArray object, and what I am actually interested in is
03:03whatever is in the first position there, because it could theoretically return
03:07me multiple paths, although I only care about what's at position 0.
03:17So I am going to have a return statement against the path at position 0, which
03:21will be our document directory, but I want to also append a file name to it.
03:26So what I am going to use is stringByAppendingPathComponent, and then I'll just
03:31make up a name for this file.
03:34I'll call it saved.plist.
03:37You can call it whatever you want. Give myself a bit more room here, and
03:42that method will now return the current file path to this application's
03:46saved property list file.
03:48So how would we use it?
03:49Well, here in the method called saveData, I am actually going to write some
03:53code to grab the values of the Text Field and the Date Picker and just store them in that file.
04:24So I create an array and allocate it just with two things:
04:28the value of the Text Field and the date currently held in the Date Picker.
04:32That's all I need to do.
04:33So now I have an NSArray and it knows how to save itself to a file, and I am
04:38just going to say value, and I want to call the writeToFile. Where is the file?
04:43Well, we can call the getFilePath on the current object, on self. And
04:49atomically we are just putting in a Boolean variable of YES. This should be pretty instant.
04:54Now what if that file already existed?
04:56Well, it doesn't matter;
04:57it's just going to overwrite it.
04:59So that's me saving the state of this application.
05:03Okay, it's very simple.
05:04It's just two user interface elements, but you could start saving whatever you wanted here.
05:10And next, we've got the load method.
05:12So what actually happens if this application is loading and trying to read in these values?
05:16Well, first, I better go and get the actually file path,
05:19so I'll create a string for this.
05:39I am first going to use a little helper method of the NSFileManager to say, does
05:44anything exist at that path?
05:49If so, then I can read it in and fill the values on my user interface.
05:54And I am basically going to do, in reverse, what I did in the saveData.
05:58Creating an NSArray and initialize this with the contents of the file, which we
06:11just retrieved a couple of lines before.
06:14Then simply set the values of the Text Field and the Date Picker to the
06:19entries in that array.
06:21I could use dot syntax like I am using here, or I could have used the Objective-C square brackets. It doesn't matter.
06:30Whatever is at position 0 goes into the Text Field. Whatever is at position 1
06:44goes into the Date Picker. But right now, of course, none of these methods are being called.
06:49Nobody is calling saveData. Nobody is calling loadData.
06:52There is nothing magical about those method names.
06:55So the first easy thing I want to say is, if this application is loading from a
06:59device restart or Simulator restart,
07:02we're going to call loadData to ask if that file exists, and if so, load the
07:07contents of it into our user interface.
07:09Now there is one easy place to put this, but it's not going to fix all our problems.
07:13I am going to put it here in viewDidLoad. It's just going to be self and a call to load data. That will do it.
07:20The thing is, viewDidLoad is only called when the app is launched from scratch.
07:26This is not called when the app moves in the background to the foreground, and
07:29if we were worried about that, we have to be careful here, because we can't rely
07:34on any of these view-based methods:
07:37viewDidUnload, viewWillAppear, viewDidAppear, viewWillDisappear,
07:40viewDidDisappear. None of these will be called when the background. Foreground
07:44operations are happening.
07:46You see, we are interested in the application-level events.
07:51We are interested particularly in applicationDidEnterBackground and
07:53applicationWillEnterForeground, but these get called in the AppDelegate.m file,
08:02not in your ViewController file.
08:04Now there are ways that we can volunteer.
08:07We can opt in our ViewController to also respond to these events. But because
08:13the saveData and loadData methods are declared in our ViewController and the
08:17AppDelegate created the ViewController object in the first place, meaning that
08:21it did it up here, as self.viewController,
08:26I can actually call them directly here.
08:28So in applicationDidEnterBackground, I am going to say self.viewController
08:33to access that one ViewController, and we should have the accessible method, saveData.
08:38applicationWillEnterForeground, self.viewController loadData, save.
08:47I am going to build this application, Build Succeeded. I'll go ahead and run it.
08:51Now before I actually test this, I am just going to quit back into Xcode.
08:57I've installed this application correctly.
08:59The reason I just quit right back out of it is when you are running directly
09:02from Xcode and you decide to both leave the app, go back in, terminate it, and
09:07check a few things, Xcode can get very confused indeed.
09:11So I ran it once to install it on the Simulator, and now I am just going to use
09:15Spotlight to actually access the Simulator directly.
09:18So we're not currently in Debugging mode.
09:20I am going to open up that application.
09:23We're on Today. I'm going to go to our Text Field here.
09:27I am going to type something in: "Does this save?"
09:32Change the wheel to an earlier date, like January the 14th.
09:35Now if I just exit out of it, go from the foreground to the background, well,
09:40this would working anyway.
09:42The real key issue is can I exit the application by double-clicking the Home,
09:47clicking the Minus button?
09:48And when this opens again, it still has the data.
09:52We're actually loading it in from that file.
09:55I could even quit out of the Simulator, then open it back up again.
09:59It's like a restart the device. Click the app and it's loading that information.
10:07Technically speaking, this was indeed even a little bit of overkill.
10:11If all we were doing is trying to recreate a user interface,
10:14it pretty much does a good job of that anyway.
10:17But this would be one basic approach for a simple ability to persist data to a
10:23file on the iOS device.
10:25Testing foreground and background events in the Simulator and using Xcode can be
10:30a little tedious, and it's definitely one place where some patience and some
10:33NSLog statements can come in very useful indeed.
Collapse this transcript
12. iPad Development
Understanding iPad development
00:00So what's different when developing for the iPad?
00:02Well, first off, not a lot.
00:04We still use all the same techniques we have been using so far:
00:08view Controllers, delegate, storyboards, actions, outlets.
00:11We still work with the idea of one application at a time that takes up the full screen.
00:15Everything we've done so far will work on the iPad just fine.
00:19The little alteration we would need to do is mainly just awareness of screen size.
00:23So this screen size, this resolution, which is 1024 x 768, or 768 x 1024 depending
00:30on which way you are holding it.
00:31Now if you can call any screen resolution a classic, then this is one.
00:35Now as you have seen, all the Xcode project templates allow you to choose iPad
00:40and they then create an iPad- size View Controller for you to use,
00:43though some of these projects types that you are familiar with them on
00:47the iPhone, like master detail app and utility app, are implemented slightly differently.
00:51The utility app on an iPhone, for example, does the horizontal flip back and
00:55forth, and this just wouldn't work on the iPad screen.
00:58So on iPad, it uses a new interface element called a popover to show the flip
01:03view, but everything else is the same.
01:05We will see that in a moment.
01:07So the technique changes in a few places because we have these new user
01:11interface elements like popovers and Split View Controllers, which aren't
01:15available on the iPhone.
01:17But what if you don't want to develop for the iPad?
01:20Well, of course you don't have to.
01:22If you have a simple iPhone application that's not been specifically changed to
01:26deal with the iPad, it will still run on the iPad but in compatibility mode.
01:31I'm going to shift to my hardware menu in the Simulator here and change this to the iPad.
01:36And I will open up the iPad at 50% view here, just because I don't have a lot of real estate room.
01:41I am going to go back to the application and open it up.
01:44This is an iPhone application, and you have probably seen this before when
01:48you can actually run the iPhone app either in the same native resolution as
01:52the iPhone, or by tapping the 2x button to double the size of it on the larger screen.
01:58But there are a few issues here.
01:59First, it doesn't actually take up all of the iPad screen because the aspect
02:03ratio is different between the iPhone and the iPad.
02:06Secondly, it's technically usable, but if you're just doubling the pixels of your
02:11application, you could get a blocky look that's undesirable. But more
02:15importantly, classic iPhone application models like navigation-based apps and
02:20utility apps are usable but kind of clunky.
02:24They just aren't taking advantage of the space that we have available in
02:27the way that we would if we had an application specifically designed for
02:30this larger screen size.
02:32An another issue is that when someone with an iPad is browsing in the App Store,
02:36they will see iPhone only apps in a different de-prioritized section than iPad
02:42apps or apps that we work on both iPhone and iPad.
02:45So compatibility mode is not iPad support.
02:48It's the lack of iPad support.
02:50That's what happens when you do nothing.
02:52So your choices are, you can create two totally different applications--
02:56one for the iPhone, another project for the iPad--and there will be two different
03:01entries in the App Store, or you can create a universal application.
03:05This is one choice in your project creation, and it will mean one entry in
03:09the App Store, but it will count as a fully fledged iPad application because it
03:13will adjust itself according to the device it's running on, using different NIB
03:18files for each different screen.
03:19Now one very important piece you should know is that unlike with the iPhone,
03:23Apple do recommend on the iPad that all orientations are supported,
03:28and that your user should be able to use your application holding it any way they want.
03:32Now sure, some applications might only realistically work in just portrait or
03:36just landscape mode, but if possible, you should support both modes.
03:41The difference is that while you're able to do that on an iPhone, it's not required.
03:45It's just a nice-to-have.
03:46On the iPad it is recommended that that's how you do it.
03:50So as the user interface for the iPad is what contains the most significant
03:54changes that things we will naturally encounter the first few times we try to
03:58do iPad development, we're going to cover a couple of those next.
Collapse this transcript
Using iPad-specific UI elements
00:00In the first hour of using an iPad you'll have come across most, if not all, of
00:05the different user interface elements from the iPhone.
00:07And because it's an Apple device, you probably didn't think about them that much;
00:11they just seemed natural.
00:12But while you or users in that role don't have to care, as developers we need to
00:17make sure we know what these different elements are in each circumstance so we
00:20can use the right one.
00:22Now the most significant new user interface idea is the split view, typically
00:27used when you have nested data or some kind of master-detail relationship.
00:31So if you were in the Settings app on the iPhone, you get used to go in left to
00:36right through multiple screens. Same thing with the Mail application.
00:38But here it's all on the same screen.
00:41You select from the list on the left and the area on the right, the Detail page,
00:45changes to handle your selection, and it's very common.
00:49You'll see this in a lot of applications on the iPad.
00:51You'll see it in Mail.
00:53You'll even see things like the Notes application uses this. Though it's been
00:58given a customized view; it's still the same idea.
01:00That's very common for the split view to change when you switch between
01:04Landscape and Portrait mode, switching from the dual-pane view to a single pane
01:10showing only the detail.
01:11Same thing happens with the Notes application.
01:14Now the difference is in this case we actually technically lose some data,
01:18some part of the screen.
01:19The area that allows us to select a new note has disappeared, but we can get it
01:23back with the popover, and that's the term for this new floating element that you will
01:28find very common in a lot of different iPad-based applications.
01:31Now it sometimes feels like a menu, as it's often initiated from tapping a
01:35button on a toolbar.
01:37But this popover can appear from a few different places.
01:40It doesn't have to come from the top.
01:42It can come from somewhere in the middle or lower on the bottom like when using a map.
01:46Now the classic model here is that you won't find a button to dismiss a popover.
01:52The idea is you're either going to select something on this popover or you'll
01:56just tap somewhere else on the screen to dismiss it.
01:59And now as we have more screen space, we can also design view controllers and
02:04make them appear modally, so that when we're choosing options, say, from the
02:08toolbar, we can have screens within our app that will dim the background and
02:12require us to focus and perform an action before they go away.
02:16In many applications you'll have a variety of these.
02:20Modal views have a few different presentation styles to take part of, or all of, the screen.
02:25But even going through the Settings application to configure an email account
02:29will have using split views, and modal views, pop-up keyboards for text entry, and
02:34all of these can be configured in your own iPad applications.
02:37They're not very different from creating iPhone apps, but there are a few
02:41gotchas to be aware of as we begin to write code to use these.
02:45So we're going to cover a couple of the classic new UI elements.
Collapse this transcript
Creating iPad apps with popovers
00:00Let's go ahead and create an application for the iPad.
00:03I'm not going to make a single view application here because that really
00:07would be kind of boring.
00:08It just is a big iPhone app.
00:10There's nothing remarkable, nothing different about it except for a bigger view.
00:14I am going to go ahead and make a utility application, which is a little
00:18different on the iPad than on the iPhone.
00:21I am going to make sure to select the iPad Device Family and keep on
00:28Automatic Reference Counting.
00:30Now, the reason I'm doing this is not to make a utility app as such;
00:34it's to demonstrate popovers.
00:36Though because it's a useful comparison, I will be contrasting some of the things
00:41we see here to the iPhone utility app we deconstructed earlier in the course.
00:45I am going to click over here and take a look at my MainViewController.xib.
00:49Now, one of the downsides here is because I'm recording on a small screen size,
00:55it's difficult for me to see the entire iPhone screen.
00:58If I was using storyboards, I could zoom out, although that isn't always
01:02reliable for actually interacting with the view.
01:04But we have a MainViewController.xib.
01:08We have a FlipsideViewController.xib, and this one just looks like an iPhone
01:12screen, and we'll see why.
01:14They do call it a FlipsideViewController, which is the same as the iPhone
01:18version of this project, even though we won't actually animate a flip.
01:22Let me show you what happens when we just go ahead and run this application.
01:26So it opens up in my iPad Simulator, which I am at 50% here, and whereas on
01:32the iPhone version we'd expect to see a little tiny little button at the lower-right,
01:36that could get lost in a big iPad application, so instead we're using the bar up
01:41at the top that has an Info button.
01:43I hit that, and instead of flipping, which would be a bit intrusive, we just
01:47have a popover, this thing with the drop shadow and the surround on it and a
01:53little arrow that points to the button.
01:54So let's see how they're doing this.
01:55I am going to quit out of this and go back into Xcode.
01:58Looking at the MainViewController.xib, right up at the top here, we can see I've
02:03got a bar on the top, and this is not a simulated user interface element;
02:07it really is a real one, with a Bar Button item on that.
02:12And if I open that up, I'll make sure to select the Bar Button item itself, and
02:17sometimes it's beneficial to use the expanded dock here.
02:22I can see that in my Connections Inspector
02:25it's hooked up to File's Owner and the showInfo method, which is exactly the
02:29same as it was on the iPhone version of this project.
02:32So let's take a look at some of this.
02:34I am going to jump into the header file for my MainViewController.
02:39This is the first time I actually see a little bit of a difference.
02:42So this MainViewController class is going to be responsible for creating and
02:47showing the FlipsideViewController and even making it go away.
02:51So on line 13 here, I have a property that's going to hold a reference to it,
02:55but instead of holding it directly, it's actually going to create a container,
03:00something called a UIPopoverController, and that's what's going to be
03:04responsible for adding the surround and generating the drop shadow and so on.
03:08So in the implementation file for MainViewController, I am going to find
03:13the showInfo method.
03:15We have a little bit more code here, but it's not all that complex.
03:19We're first asking, does this object even exist?
03:23If it doesn't, we're going to allocate and instantiate a new instance of the
03:28FlipsideViewController from our FlipsideViewController NIB file,
03:32set its delegates to self, meaning MainViewController. This is the same as
03:37in the iPhone version.
03:39However, what is a little different is we're going to instantiate then a new
03:43UIPopoverController and load in that FlipsideViewController we just created.
03:49So rather than show the FlipsideViewController directly, we create a
03:53PopoverController and load the FlipsideViewController into it.
03:56On line 77, we ask is the popover visible?
04:00If it is, we dismiss it;
04:02if it isn't, we're going to show it. And we call
04:04presentPopoverFromBarButtonItem: permittedArrowDirections: animated.
04:11Animated you can guess; present Popover you can guess;
04:15permittedArrowDirections helps iOS generate an arrow from the popover to
04:21the button that caused it to appear, without us worrying about exactly what that looks like.
04:25Let me show you what that means.
04:29I open the Simulator.
04:30I am quickly just going to zoom in from my window scale to 100%, just so we can see this.
04:36I tap the Bar Button item and it makes the popover appear.
04:40I can see I've got this drop shadow that surrounds the popover, and I've also got
04:44an arrow on the right-hand side of the popover pointing to this info button.
04:49Now, that does not mean that popovers always do an arrow on the right.
04:52They don't have to.
04:53If I quit out of this, then I can just very quickly--and this is just to show
04:58you as an example--jump into my xib file for the MainViewController, drag this
05:04Bar Button item to the left- hand side, and run it again.
05:08We'll see that in this case it's actually smart enough to generate the arrow
05:12on the left-hand side.
05:13That's the benefit of using this PopoverController.
05:17It can do all this for you.
05:19I am going to quit out of that and go back to the code.
05:22That's all we need there to show the popover.
05:25Above this showInfo method is the flipsideViewControllerDidFinish method that
05:29just has one line of code to dismiss the PopoverController.
05:33This is using exactly the same delegation technique as the iPhone version of this project.
05:39The FlipsideViewController will ask us, the main screen, to dismiss it; it
05:43doesn't dismiss itself.
05:44Now, the only other thing worth mentioning is actually in the initializer for
05:49the FlipsideViewController.
05:51Because this is a popover, it could potentially be a different size;
05:55it doesn't have to be the same size as the iPhone screen.
05:58That is a pretty classic size, the 320x480, but if I decided in this code to say
06:03this was going to be 680, for example, save that and run it,
06:08that's all we'd need to do to make the popover a different size.
06:14Notice also that if I touch on a blank area of the application, a non-popover
06:19area, it's still going to take care of dismissing itself.
06:22We didn't have to write any code to make that happen.
06:25So as you can see, the same process, the same approach, yes, an awareness of the
06:31size of the views and an awareness of a couple of small techniques, and this is
06:35one way to build an iPad version.
Collapse this transcript
Creating iPad apps with split views
00:00The Split View Controller is unique to the iPad.
00:03It's what allows us the use things like the Settings application and have this
00:06split view with the two panes, like you'd see in the Settings app or in the Mail
00:11application on an iPad.
00:13On the left-hand side you have the master area. You select an entry and you see
00:18more about your selection on the right-hand side. It's the detail.
00:24And it's something that changes based on the orientation.
00:28In Landscape mode you see the split view, but if you switch to Portrait mode,
00:33the default technique is that the master becomes hidden and all you see is the detail.
00:38The master becomes available as a pop-over.
00:42If you see this kind of arrangement on a desktop application, you might expect
00:46to be able to shift the divider to the left or right and adjust the width of the
00:49panes, but no, not here.
00:52The left pane of a Split View Controller is fixed at 320 pixels wide and the
00:57detail pane on the right takes whatever is left.
01:00Now although a split view generally changes when rotated to portrait, there are
01:04a couple of applications that don't do that. The Settings application is exactly a
01:08good example of this one.
01:10When this one shifts to portrait, it stays with the split view.
01:13But we're going to create an application and go with the shifting behavior, for two reasons.
01:18One, it is a good model, and it works really well, and two, a lot of the work is done first if we do.
01:24I'm going to go ahead into Xcode and make a master-detail application, making
01:29sure that I choose to do this as an iPad app. So iPad from the Device Family.
01:35I'll just call it MasterDetail and as ever, save it to my desktop.
01:42First off, this project does not look that remarkable.
01:46I can see that over on the left-hand side I have a MasterViewController and a
01:50DetailViewController.
01:52I can view the NIB files for that.
01:57MasterViewController appears to have a table view that doesn't look all that
02:01remarkable and the DetailViewController, that's pretty simple too.
02:05What I don't see over here is any signs of a Split View Controller.
02:10I don't see it in either of the interface files.
02:13I don't see it referred to as a code file.
02:15And that's because I really don't need to see it.
02:17The Split View Controller is kind of dumb.
02:20It doesn't look like anything.
02:22This is a controller that has no visual appearance.
02:25It's just a container that can hold two real view controllers that provide the
02:30actual visible content.
02:32So the great thing is, our focus is still what it's always been, on our own view
02:37controllers, on our own application content.
02:40We create a Master View Controller that represents the left pane,
02:44we create a Detail View Controller that represents the right, and we just load
02:48them into the slots on that Split View Controller.
02:50It takes care of transitions and managing the rest.
02:54But it can go further than this, because as you've probably noticed, panes in a
02:58split view can actually switch between multiple view controllers.
03:03If you're using the Settings application, for example, the Detail pane often
03:07shifts from left to right.
03:09It looks like it's got a navigation controller at the top.
03:13If you're using the Mail application, you'll find it's the left-hand side that
03:16shifts between different inboxes and different folders.
03:19And just from looking at these, they kind of look like navigation controllers at
03:24the top keeping track of a navigation stack.
03:26And that's exactly what they are; each pane can have its own navigation stack.
03:31So a classic layout would be create the Split View Controller, our container.
03:36Then create a Navigation Controller.
03:39Load our first Master View Controller into it, then make a second Navigation
03:44Controller, load our Detail pane into it.
03:48Then slide the first Nav Controller into the left-hand side and the second Nav
03:53Controller into the right-hand side.
03:55And that's exactly what's happening in this example project.
04:00If I run this application from Xcode without making any changes to it, we start
04:04up in Portrait mode just showing the detail view, but it looks like we have a
04:08navigation bar at the top.
04:09I can hit this button to bring up the pop-over.
04:12But this master actually does contain a navigation controller, and it can shift
04:16itself back and forth.
04:18That may or may not be what you want.
04:21Shifting into Landscape mode, we go to Detail View, and they both have the
04:26navigation bars at the top.
04:27They're not being used in any substantial way in this project, but they're supported.
04:32The ability is there.
04:33Let's see exactly how.
04:35Well, in our application, we have the MasterViewController class files, the
04:41MasterViewController.nib, the DetailViewController class files, the
04:45DetailViewController.nib.
04:46And it's all going to come down to the AppDelegate code.
04:50So when our application launches, here's what we do.
04:54Line 25, which obviously is split across two lines here, create an instance of
04:59the MasterViewController.
05:01No big surprises there.
05:03Line 26, we'll create a navigation controller and load the Master
05:07View Controller into it.
05:09Line 28, we create the DetailViewController.
05:12Line 29, we create its navigation controller and load the
05:16DetailViewController into it.
05:18On line 31, that's where we instantiate the SplitViewController, and on line
05:2333 is where we load it with the masterNavigationController on the left and
05:28the detailNavigationController on the right, obviously bringing along our view controllers.
05:33Then we load that into the window and make it visible.
05:37And while the MasterViewController code still drives a lot of the things, bear
05:41in mind it's the Detail View that's actually always being shown.
05:45But because it's the DetailViewController, that's always shown regardless of
05:49what position it's in.
05:51Here is where you'll find some code, at the bottom of DetailViewController.m,
05:55for both hiding and showing the masterViewController when the
05:59splitViewController shifts position.
06:02We have a method here that's going to automatically be called,
06:05splitViewController willHideViewController, withBarButtonItem,
06:10forPopoverController.
06:12That's where in Portrait mode we'll actually create the barButtonItem at the top-
06:16left that in this case just says Master and control loading that master view
06:21into a pop-over controller.
06:23The flipside of that, below here, when it's going to show the Master View
06:27Controller, we'll take the barButtonItem off, and we'll detach the
06:31masterViewController from being a popover because it's going back into Landscape
06:35mode where it actually shows up in Split View.
06:37But once this is all up and running, once it's loaded, using the Master and
06:43Detail View Controllers is the same as with their non-iPad versions.
06:48We can pass information between them.
06:51They can talk to their own navigation controller to control transitions, push
06:55and pop other view controllers off the stack.
06:58Even the DetailViewController class file is created exactly the same as in the
07:02iPhone version, just creating a generic detailItem property that will allow us
07:07to load custom objects in here just to prove that it works and that they all
07:10connect to each other.
07:11So while creating these applications is a little more involved than basic iPhone
07:15apps, the principles and techniques for using them is exactly the same.
Collapse this transcript
13. Finishing touches
Creating an application launch image
00:00You know that cool zooming effect you get when you launch an iOS application,
00:04where there is that split second where we seem to be zooming in on the
00:09application's first screen?
00:10Well, this zoom is a lie.
00:13We are not looking at our app's first view controller or any view controller
00:18of the application.
00:19It might look like that, but all it is is there is an image being provided by
00:24our application, so that while iOS is actually loading the real app, they can do
00:30a nice animated zoom of what your app is supposed to look like.
00:34Now, you may have noticed this when you have been working with these projects in Xcode.
00:38If I create, say, a Master-Detail Application--I will just call this one,
00:43ImageTest, make sure that it's for iPhone, just because that's going to be
00:47easier to look at while I'm recording this--
00:51we can run it and install it in the Simulator, and all the functionality is
00:55fine, but we won't get that animated zoom.
00:58Now I will have to hit the Home button and go out and try it again to see that,
01:02but all we will get is black.
01:04We can see a little bit of a zoomed status bar, but that's it, as opposed to, say,
01:12the Settings application where we get the blank page; or Contacts, where we get
01:16the blank page; or Game Center, where we get the green background.
01:21So what do we need to do to get that cool zoom effect?
01:24Well, we need to provide a launch image the size of the iPhone screen.
01:28These are required before you can submit your app to the App Store, and you need
01:33to provide two if you're making an iPhone app.
01:36One is for a regular iPhone and one is for a retina display, and two images for
01:41an iPad app, but there it's one for the landscape and one for portrait.
01:44Now some applications use this opportunity to show a splash image in that short
01:50time between the application being requested and it actually opening up.
01:55This is actually discouraged by Apple;
01:57you are not supposed to do it that way.
01:59Your application's launch image is supposed to look like your first screen
02:03without any data or text, and that's what you'll see on most of the Apple ones.
02:08Now one of the reasons for this is so you could localize your app into
02:13multiple languages and you wouldn't have a mismatch by having a launch image
02:17with only, say, English on it.
02:19So what would be the best way to make one of these?
02:22What we want really is this first page of the application without any data on
02:28it, without any text, without any entries in the TableView.
02:31I could recreate this in Photoshop or Fireworks, but that would be a little
02:35tedious, because I can get a head start.
02:38While I am looking at the app in the Simulator, I am going to go to the File
02:40menu and I have got an option for saving a screen shot.
02:44That's going to give me an image of the right size and the right type, a PNG file. [00:0249.33] I am going to quit out of the Simulator and just minimize Xcode, and on the
02:53Desktop here, I have the iOS Simulator Screen Shot.
02:57So I would like to make a little change to this.
02:59You could use Photoshop, Fireworks, whatever image editor you have. I am just
03:03going to open up in Pixelmator, and I am just going to do something very basic
03:08in a few seconds here.
03:09I want to blank out the text that we have,
03:12so I am going to go low-tech and just drag in.
03:16Yes, I will continue.
03:17I don't mind editing the original image here. Just drag in a white rectangle to overlay that.
03:24I could go ahead and clear off the Status bar and also the Nav bar here, but
03:29this will do the trick, just to prove our point.
03:32So I am going to save that, quit out of Pixelmator, back into Xcode.
03:37What I need to do is make sure that in my Project Navigator
03:40I have the project itself selected, the very top icon, not any of the individual
03:46files, but this needs to be highlighted.
03:48And then making sure that in the middle section, I have got my ImageTest, my
03:52project target highlighted,
03:54if I expand this a little bit,
03:57in the Project Settings that we have, we have an area where we can drag on the launch image.
04:03For an iPhone app, you will see one for regular iPhone, giving you the
04:07dimensions, one for the Retina Display, and it won't let you drag on something
04:11of substantially wrong dimensions here.
04:14If you are working with an iPad, you would see a portrait and landscape version.
04:18I am just going to open up a Finder window and jump back to the desktop, and I
04:23can grab that PNG and drag it over here into the regular iPhone section. And we
04:29can see a little preview of that.
04:31It also moves it into my project, under the name Default.png.
04:36So let's go back and run this. Build succeeded.
04:39We open up the Simulator. We load it in.
04:41Of course, we don't see it the first time around, but if I reopen it, we can see
04:46that we have the zoom. In fact, the good indicator here is it almost looks
04:50like the words are just flicking on after the app loads, and that is the
04:58approach for doing it.
04:59Now the iPhone and iPhone Retina Display are supposed to be full size,
05:04either 480x320 or 960x640.
05:09I had used a regular iPhone example.
05:12What I could also do is switch in the Simulator in my hardware to the
05:17iPhone(Retina) Display--and important here to make sure I am at 100% Scale, even
05:22though for me that's a little difficult to manage.
05:27Then I could open this up and take another screen shot for the Retina Display
05:32and repeat the process there.
05:34I am not going to actually do that right now, but you see how that would work.
05:38For the iPhone in Retina Display, they're supposed to be the full size.
05:41They should include the status bar. Whereas with the iPad launch images, you are
05:46not supposed to include the status bar.
05:48We actually shave 20 pixels off for both portrait and landscape.
05:53And simply if I went ahead and actually changed that second image that I had
05:58captured, I can see this one by highlighting at 640x960.
06:03I could just drag that one on to the Retina Display size.
06:06Of course, I haven't edited it yet, but you get the idea. And this is you having
06:11the required launch images for your application.
Collapse this transcript
Creating an application icon
00:00As you all have noticed, when you're testing your applications they add
00:04themselves to the iPhone home screen with this generic white icon, with a bit of
00:09a rounded corner, a bit of a shine to it.
00:11But you'll need to provide your own icons in order to publish you app to the
00:15App Store or even just to have something different from the white ones.
00:18So let's see how to do this.
00:20Now an iPhone app needs two application icons, very similar to working
00:24with launch images.
00:25You need one for regular display and one for retina display.
00:29Simply put, we need to create two square PNG files one, that's 57 pixels wide by
00:3557 pixels high and another that's double that, 114 x 114.
00:39And you can use any image editor to do this.
00:44Now if you are developing an iPad app, that needs one icon that's kind of in
00:48the middle, 72 x 72.
00:49At the moment of recording this, we don't have retina displays on the iPad.
00:54I'm sure that's coming, at which point it will be double that size.
00:58Now you might be wondering about the fact that most of the icons you see on the
01:03iPhone home screen have a shine to them, and they have rounded corners to them.
01:07And if you're questioning your Photoshop skills about doing this, it's not a
01:11problem, because we don't do that.
01:14iOS does this for us.
01:16We create our icon perfectly square, without the rounded corners, without the shine.
01:21For the purposes of saving time, I have two very simple icons on my desktop here.
01:26You can get them from the exercise files, or you can just make ones yourself.
01:30I have called one regular icon. It's 57 x 57.
01:33It's about as simple as it gets. And then I have got a retina icon that's 114 x 114.
01:39There's no shine to them.
01:41There is no rounded corners.
01:43They are perfectly flat.
01:45If I was going to open this up in an image editor, you would see something
01:48very, very basic indeed.
01:50And all I need to do is find the application that I want this to work for. Of
01:54course in my case this needs to be an iPhone application here.
01:57We need to be on our Project Settings, and with the target selected in the
02:01Summary section, I will find the two places to drop the app icons, for the
02:06regular one and for retina display.
02:08So switching back to my icons, I'll grab Regular, drop it in there. It will
02:14tell you if they are the wrong size or the wrong type, and drag that one and drop it there.
02:19As I can see, they were added to my project as well.
02:23Let's run this example.
02:24This is just a regular single view application.
02:27It's actually opened up on the retina display iPhone just because I had that
02:32selected in my device.
02:34Of course, I don't see it in the application itself, but if I exit out of that,
02:39I certainly do. And I can scale in to 100% and see that
02:45it's done quite a nice job of adding the rounded corners and the shine on the
02:49slight gradient to this.
02:51If I switch my hardware to the Regular iPhone, the non-Retina one, we get that
03:00example. So very, very simple to do.
03:03Now application launch images and application icons are not just nice additions.
03:08These are required for you to put your app on the App Store.
03:12Not only that, but there are several other images you can provide.
03:16If you look at the iOS Human Interface Guidelines, there is a section for Custom
03:21icon and Image Creation Guidelines
03:24that not only will give you a good reference on the exact size that these things
03:28have to be, but you'll also get other ones you can create, like small icons for
03:32when documents in your application show up in a Spotlight search or document
03:36icons, what size they should be, the specifications exactly for them.
03:41So take a look at the Human Interface Guidelines for more on the optional
03:44icons as well.
Collapse this transcript
Conclusion
Goodbye
00:00In the past few hours you've seen a lot of different subjects in iOS development.
00:04We've worked with Objective-C.
00:05We've explored the tools.
00:07You've seen patterns like MVC, Delegation.
00:10We've used table views and navigation controllers, pop-overs and split views.
00:14We've organized our apps with storyboards, and we've worked with saving data,
00:18multithreading, block,s and Grand Central Dispatch.
00:21And the question is, well, what now?
00:24This was just the basics, so where do you go from here?
00:27And I think it's a great time to re- inspect and revisit the iOS Developer Center
00:32and the enormous amount of content that is available here, if you can find it.
00:37Because it's easy to think of this site as this is reference, this is where you
00:40get your class reference documents, but it's a lot more than that.
00:44Now, the first two documents, I think it's essential for every iOS developer to
00:47know very well, the iOS Application Programming Guide and the iOS Human
00:53Interface Guidelines, or HIG, and these are usually found on the front page.
00:58The Application Programming Guide really is the core information.
01:02If you're unsure about aspects of things like app states and multitasking or
01:07the main run loop, these are all contained here.
01:10We've already seen the Human Interface Guidelines.
01:13The Development Guide is different from the Application Programming Guide.
01:16This is a great document too, and it's the one that you need for getting more
01:20into things like setting up development devices or publishing an app for user
01:24testing, and eventually publishing to the App Store.
01:26Now, if you go to this Developer site and just head straight to the iOS
01:30Developer Library--all of the documentation--you're going to find an immense
01:35amount of content here.
01:36There are hundreds of documents, thousands of pages you can potentially read.
01:40But the most valuable one for recent iOS developers is this section called Guides.
01:46If you click Guides on the left, you'll find there's about 150 of them here.
01:50I'm filtering on Guides.
01:51I'm going to sort by topic, because you'll find that there is a bunch of guides
01:56split into the General section, and then you have guides specifically on, say,
02:00audio and video, Multimedia Programming Guide.
02:03If we move down, we have things on data management, working with
02:06strings, working with text.
02:08Moving further down, we'll get into things like graphics and animation, the Core
02:12Animation Cookbooks, mathematical computation.
02:17And as I continue into Security, then Tools & Languages, more documents
02:22about Xcode itself, Keyboard Shortcuts and Gestures, Xcode Glossary, tools
02:27that we have in there.
02:29If you want to geek out on the internals of things like the LLVM Compiler,
02:33you'll find that stuff here. And also, User Experience areas, working with
02:39View Controllers, working with Table Views, and of course the Human Interface Guidelines.
02:45And these guides are provided as both web-based and you'll typically find a PDF
02:49link as well, although do be aware that they are updated on a regular basis.
02:54Going back into the Developer Library, you'll also find that under this there
02:58will be a Sample Code section.
03:00Right now it looks like there's another 150 or so sample projects.
03:04Some of them, if I order by Date, can be a few years old, so they won't be
03:09necessarily using the up-to-date best practices and APIs, but they are
03:13updated fairly regularly.
03:15You can scan through them.
03:16You can find a bit of information about what each one is, how to create an Image Picker UI.
03:23Or TopSongs here demonstrates importing data from an RSS feed into a core data store.
03:28Let's find this one here, SimpleDrillDown using a Table View and a Storyboard,
03:34and that was updated a couple of months ago to use ARC and storyboards.
03:38Grabbing this as an example, you can actually browse all the code straight on
03:42the web, or you can click the button above it to download sample code, which
03:46will give you a ZIP file.
03:47I'll just open that up, double-click the Xcode project file, and we can open up
03:55and start to take a look at it.
03:59It's opened up a project I already had previously, so let's switch to it and
04:03make sure we're looking at SimpleDrillDown.
04:08Sometimes it's good to just go ahead and run these and you can get a good idea
04:13of what this application is doing and decide for yourself whether you want to
04:17look further into the code or not.
04:19So I'm going to go back into the web site.
04:22And of course, if you know for sure that there is something particular that
04:26you're interested in, you want to explore, say, working with the MapKit or working
04:30with Locations, or Push Notifications, or Core Data, then you'll find there's a
04:34great deal of content here to get started with.
04:37And that's it for this first course.
04:39Thanks for joining me for iOS SDK Essential Training!
04:42Make sure to take a look at some of the other courses here at lynda.com that
04:46we'll have on different aspects of iOS development.
04:49See you next time!
Collapse this transcript


Suggested courses to watch next:

Objective-C Essential Training (6h 35m)
Simon Allardice

Xcode 4 New Features (1h 58m)
Bill Weinman



Are you sure you want to delete this bookmark?

cancel

Bookmark this Tutorial

Name

Description

{0} characters left

Tags

Separate tags with a space. Use quotes around multi-word tags. Suggested Tags:
loading
cancel

bookmark this course

{0} characters left Separate tags with a space. Use quotes around multi-word tags. Suggested Tags:
loading

Error:

go to playlists »

Create new playlist

name:
description:
save cancel

You must be a lynda.com member to watch this video.

Every course in the lynda.com library contains free videos that let you assess the quality of our tutorials before you subscribe—just click on the blue links to watch them. Become a member to access all 104,069 instructional videos.

get started learn more

If you are already an active lynda.com member, please log in to access the lynda.com library.

Get access to all lynda.com videos

You are currently signed into your admin account, which doesn't let you view lynda.com videos. For full access to the lynda.com library, log in through iplogin.lynda.com, or sign in through your organization's portal. You may also request a user account by calling 1 1 (888) 335-9632 or emailing us at cs@lynda.com.

Get access to all lynda.com videos

You are currently signed into your admin account, which doesn't let you view lynda.com videos. For full access to the lynda.com library, log in through iplogin.lynda.com, or sign in through your organization's portal. You may also request a user account by calling 1 1 (888) 335-9632 or emailing us at cs@lynda.com.

Access to lynda.com videos

Your organization has a limited access membership to the lynda.com library that allows access to only a specific, limited selection of courses.

You don't have access to this video.

You're logged in as an account administrator, but your membership is not active.

Contact a Training Solutions Advisor at 1 (888) 335-9632.

How to access this video.

If this course is one of your five classes, then your class currently isn't in session.

If you want to watch this video and it is not part of your class, upgrade your membership for unlimited access to the full library of 2,024 courses anytime, anywhere.

learn more upgrade

You can always watch the free content included in every course.

Questions? Call Customer Service at 1 1 (888) 335-9632 or email cs@lynda.com.

You don't have access to this video.

You're logged in as an account administrator, but your membership is no longer active. You can still access reports and account information.

To reactivate your account, contact a Training Solutions Advisor at 1 1 (888) 335-9632.

Need help accessing this video?

You can't access this video from your master administrator account.

Call Customer Service at 1 1 (888) 335-9632 or email cs@lynda.com for help accessing this video.

preview image of new course page

Try our new course pages

Explore our redesigned course pages, and tell us about your experience.

If you want to switch back to the old view, change your site preferences from the my account menu.

Try the new pages No, thanks

site feedback

Thanks for signing up.

We’ll send you a confirmation email shortly.


By signing up, you’ll receive about four emails per month, including

We’ll only use your email address to send you these mailings.

Here’s our privacy policy with more details about how we handle your information.

Keep up with news, tips, and latest courses with emails from lynda.com.

By signing up, you’ll receive about four emails per month, including

We’ll only use your email address to send you these mailings.

Here’s our privacy policy with more details about how we handle your information.

   
submit Lightbox submit clicked