navigate site menu

Become a member and get unlimited access to every course in the library. Try it free for 7 days

Cocoa Essential Training

Cocoa Essential Training

with Simon Allardice

 


Discover how to build desktop applications for the Mac by exploring the many frameworks and essential design patterns in Cocoa. Author Simon Allardice shows you how to create a better-looking user interface that works on multiple screen sizes with Mac OS X Lion. The course also demonstrates how to use the Cocoa frameworks to build several example applications, and reinforces the best practices to build apps and get them ready for the Mac App Store.
Topics include:
  • Installing the tools
  • Creating your first app
  • Adding basic interactions
  • Understanding the Cocoa application life cycle
  • Creating custom controller classes
  • Creating alerts
  • Understanding delegation
  • Working with buttons, text fields, sliders, and more
  • Using layout and data views
  • Adding and editing toolbars
  • Using key-value coding
  • Binding objects
  • Debugging code
  • Distributing an application
  • Creating icons and full-screen apps

show more

author
Simon Allardice
subject
Developer, Development Tools, Platforms
software
Mac OS X , Objective-C , Cocoa
level
Beginner
duration
5h 21m
released
Aug 01, 2012

Share this course

Ready to join? subscribe


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 is Simon Allardice, and welcome to Cocoa Essential Training.
00:07In this course, we're going to build applications that run on Mac OS X.
00:12That's what Cocoa development is all about. And to do this, we're going to use Xcode, the
00:16development environment for creating, testing, debugging, and managing Mac apps.
00:21You'll see a lot of Objective-C, the main programming language used to create these apps.
00:25And Cocoa development has a long history, so we're going to explore the common
00:30conventions and guidelines of programming Mac applications that have grown over the years,
00:34concepts like Delegation and Model view Controller and how they're used in Cocoa.
00:39We'll also talk about what's new and up to the minute in Cocoa development now,
00:43Sandboxing, Gatekeeper, and more.
00:46And if those terms mean nothing to you now, that's fine, they will by the time we're done.
00:50And we'll go over the process of developing a Macintosh application, see what
00:54can and should be done with a user interface, talk about testing, debugging, and
00:58even publishing your app to the Mac App Store. So let's get started.
Collapse this transcript
What you need to know
00:00For this course, I don't expect you to have done any Mac programming at all, but
00:04I do expect that you're comfortable programming in an object-oriented language
00:09and that you know at least the basics of Objective-C.
00:12You don't need to be an expert in it, but you certainly need to know how to
00:15instantiate objects, call methods, write classes, and so on. And if you're coming
00:20from a language like Java or C# or Ruby and you haven't done anything with
00:24Objective-C yet, I would caution you not to underestimate the differences.
00:28It's common to find Objective-C quite a strange language at first.
00:32So I do suggest you go through at least the first few chapters of the Objective-C
00:36Essential Training course here at lynda.com, then come back to this course so we
00:41can focus here on the Cocoa side of things,
00:43what's unique about developing applications for OS X instead of spending
00:48our time talking about what the square brackets mean and why BOOL is written in uppercase.
00:53Another reason I expect basic Objective-C knowledge here is that I imagine some
00:57of you that are watching this course are coming to Cocoa development after doing iOS
01:01development with Objective-C,
01:03as that's becoming a very common entry point for developing in the Apple world.
01:07Now iOS development is, of course, based on Cocoa, and they share many ideas and techniques.
01:14But if you aren't coming from iOS, as you'll see, there're some key differences in
01:17how we approach things here,
01:19though you will encounter a few ideas in this course that'll make you realize why
01:24certain things are done the way they are in iOS.
01:27So if you know iOS development, that's great. But if not, no problem.
01:31And if you're coming from another developer platform, the experience you have in Java
01:36or Dot Net or Ruby on Rails is very valuable, but try to leave some of that
01:42behind for a few hours. Things are different here.
01:45Cocoa development has a very long history, and we have customs and ways of doing
01:50things that are unlike other platforms, and not just in syntax, but really in core
01:55concepts--even things like when we might use inheritance. And if you try and
02:00force everything in Cocoa into an exact equivalent of something you're used to
02:04in Java or C# or PHP, it's just not going to work, and you're likely to find this
02:10very painful and frustrating.
02:12So forget about your favorite platform for a while, just bring your core
02:16programming skills and some Objective-C, and let's get going.
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
00:04a DVD, you will have access to some exercise files.
00:07I have expanded them here on my Desktop just in this Exercise Files folder.
00:11And inside that each of the relevant chapters has its own folder, and there're
00:14some files I'll be working with during this course, and we'll point out any
00:18files at the relevant time just by showing you the path to the file location.
00:22You'll also find some finished examples if you want to compare and contrast what
00:27you have done with what I have done.
00:29But these are all just for convenience. If you don't have access to the exercise
00:33files, you can follow along from scratch or with your own assets.
Collapse this transcript
1. Getting Started
Installing the tools
00:00If you already know you have Xcode 4.4 or later installed, you can skip this step.
00:05But if not, let's make sure we have got the right tools.
00:08So first things first.
00:10What do you actually need to make Mac OS X applications?
00:13Well, not surprisingly, you need a Mac, the development tools aren't cross-platform.
00:18So you have to have a Mac and needs to be Intel-based, and it should contain at
00:22least a Core 2 Duo chip.
00:24This is nothing to do with Xcode and our tools. That's actually required to run
00:29Lion OS 10.7 or Mountain Lion 10.8.
00:32And your Mac should be running one of these Operating Systems.
00:36Well, you can download Xcode for earlier versions like Snow Leopard it doesn't
00:41include some of features we'd like to use in this course like ARC.
00:44I'll be using both 10.7 and 10.8 as my Operating System in this course and talk
00:50about the differences between the two a little later. But having the latest OS
00:54is highly recommended if you're going to be developing Mac apps because I can
00:59create apps using 10.8 that will run just fine on 10.6, but I can't create apps
01:05using 10.6 that would use the features in 10.8.
01:07Now let's say you have just borrowed a Macintosh to start developing, and you
01:12don't know for sure what it's running.
01:14Well if you check the Apple menu on the top left and click About This Mac,
01:18this will give you the version of the Operating System that we're using, in
01:22this case 10.7.4, which is fine, it's Lion. And it's also telling me that this
01:27processor is an Intel Core 2 Duo which is expected as I wouldn't able to install Lion if it wasn't.
01:33So as far as our requirements go we're ready, but we need to have the tools, the
01:38development environment Xcode. Which comes bundled with a bunch of other useful
01:42programs for development. You get this from Apple, and it's free.
01:45If you have Lion or later as your Operating System, you just go to the App
01:50Store and get it there.
01:52The Category in the App Store you're interested in is the Developer Tools
01:56category, and Xcode should be extremely obvious.
01:59This one download is the best part all two gigabytes, and that's so big because
02:03it's not just Xcode, it's Xcode plus a whole bunch of other programs, tools, and
02:09supporting files, like iPhone and iPad simulators.
02:12The SDK is the Software Development Kits for both OS X and iOS.
02:17So it's everything you need for creating iPhone and iPad apps and Mac Desktop
02:22apps, it's all there.
02:23Some of the stuff in this download, you won't need, and you will never care
02:27about, but it's all bundled together.
02:28And if you don't want to get it from the App Store, alternatively you can also
02:33download a .dmg image from the developer.apple.com site.
02:38So this is our foundation for building both iOS and Mac Desktop applications.
02:44And once you have installed it, it is also pretty useful to have a shortcut to that on your Dock.
02:52The final test, of course is, can you actually open it? And either from the Welcome
02:57screen or from the about Xcode pane, you want to see at least Version 4.4.
03:02Almost everything we do in this course would work with Version 4.3, and even 4.2,
03:07but you don't want to go any earlier than that.
03:10Apple do release updates to their Developer tools frequently--usually every few
03:15months. So you could well have a later version than I have, and that's fine, I'm
03:19a big believer in always having the latest version. Though you may see some
03:23small differences if you do have a later version than mine.
03:26Part of being an Apple developer is really rolling with these frequent
03:30incremental changes to the Developer tools.
Collapse this transcript
About the Apple Developer Programs
00:00If you haven't already signed up with Apple as a registered Apple developer, you
00:04should really do that before you go much further. And this will give you access
00:08to documentation, sample code, videos, and other useful stuff, and it's free.
00:13And to do this, point a web browser at developer.apple.com.
00:18This page will really give you three links that take you to the main developer
00:22centers for Apple, which is the iOS Dev Center, the Mac Dev Center, and the Safari Dev Center.
00:28We're interested, in this course, in the Mac Dev Center.
00:32If you have registered, you can just go ahead and Log In, but if you haven't yet
00:36there is a Register link at the top right. And this will tell you a little
00:40bit of information about what you need to do to Register as an Apple
00:44Developer and what you can get.
00:45Once you have gone to this link and filled out all the information, you can come
00:49back and login to the Mac Dev Center itself.
00:51And for now, this is the place that you need that has the most current
00:55documentation, it has sample code, and it will be very useful to make sure
00:58we have the most up-to-date help information.
01:01So signing up as a Registered Apple Developer is free, but there are a couple of
01:05restrictions to know about.
01:07If you're just a Registered Apple Developer you can't yet publish your apps
01:11to the Mac App Store. And if you want to do that, you'll need to join the Mac
01:15Developer Program--and that's one step up from being just a Registered Apple
01:19Developer--and it does cost money.
01:21Back on that Registration page, towards the bottom, there's a link that tells you
01:26more about the Developer Programs. Now you don't need to be in the Mac Developer
01:30Program for this course, but you should know about it.
01:33The two Paint Developer Programs that Apple has are, the iOS Developer Program for
01:38iPhone and iPad, and the Mac Developer Program, and you need to join this to
01:43release apps in the Mac Desktop App Store.
01:45There's a couple of ways to join, but at the moment--in the US--it's $99 for a
01:50year, 60 pounds in the UK, and so on.
01:52Now you don't get new software after joining, it's the same Xcode. Although
01:57joining the Developer Program will often give you access to some beta releases
02:01of new versions of Xcode.
02:03But after joining you will be able to take your finished applications and sell
02:07them on the Mac App Store.
02:08Now, also with the release of Mountain Lion, which contains the security feature
02:12called Gatekeeper. Apple are pushing the idea that all applications, whether sold
02:18on the Mac App Store or elsewhere, should be digitally signed with the developer ID
02:22And you can get that if you're in the Mac Developer Program. We will talk
02:27about that part later.
02:28Do be aware that if you haven't joined the Developer Program, and you are
02:32holding off until the last possible minute to spend the $99, know that the
02:36process is not immediate, you can't just pay your $99 and then instantly submit to the app store.
02:42Some information needs to be verified, and you may have to wait a couple of days
02:47after you begin this process before everything gets turned on.
Collapse this transcript
Creating your first Cocoa app
00:00We're going to jump right into Xcode to create a simple Mac application, after
00:05which we'll jump right back out again to explain several of the pieces we're
00:08going to see in the next couple minutes.
00:10So I'll open up Xcode, and either from this Welcome screen or from the menu I
00:14want to Create a new Xcode project.
00:17Right now, just think, Project equals Application. Whenever you want to make an
00:21App, you're going to make a Project in Xcode, it's just a way of keeping all the
00:26relevant files together.
00:27Next I'm presented with a list of templates for this Project, and it seems
00:31like we have a lot of choices here. Because Xcode can, of course, be used for
00:35developing iPhone and iPad Applications, System Level plug-ins, Background
00:39Task Programs, Reusable Collections of Classes--known as Frameworks--and of
00:44course, for developing applications for Mac OS X Desktop, which is what we're
00:48interested in here.
00:49We have two main sections on the left of this window, one for creating iOS
00:54apps, and one for the Mac OS X apps.
00:57If you have done any iOS development you'll know that when creating a Project in
01:01Xcode you need to make a choice between several different kinds of Xcode
01:05Project, like a Master-Detail Application, or a Tabbed Application, or Page-Based Application.
01:10Well that might be the case for iOS but that's not the case for Cocoa.
01:15We really have one choice, one option for our Project type.
01:19So if I select the Applications section under OS X, this is what I am interested
01:25in, Cocoa Application.
01:26This is the Project Template we will use for everything in this course.
01:30There're other options but they're not really relevant here.
01:34We can of course create Command-Line Applications without a User Interface.
01:38Underneath here, we have options for different kinds of Frameworks and
01:42Applications and System plug-ins.
01:44But everything we'll do in this course uses the Cocoa Application in the OS X Applications section.
01:51So with that selected I click Next, there're a lot of options on this next
01:55window but only a couple are important now.
01:58We have to provide a Product Name for our Application. What's this App called?
02:03What's this Project?
02:04You can write whatever you want, but by convention don't use spaces and
02:07capitalize each word.
02:09I could do something simple like say, Demo or Example, but it is our first Cocoa
02:15App of the course, so let's use HelloWorld.
02:20Organization Name here doesn't have to be your name or your organization name
02:25this is just going to be inserted into comments in your code, it's not all that important.
02:30And right now the Company Identifier isn't hugely important either.
02:36This is because when creating a real App you intend to sell, the product name
02:40won't necessarily be enough to guarantee it's unique in the App Store.
02:44So this Company Identifier is a name that can be unique for your organization
02:49even if that's just you.
02:51By convention it's usually your Domain Name in reverse, so I might say com.lynda.
02:58And as I type this it's combining the Product Name and the Company Identifier
03:03into what's called a, unique Bundle Identifier, here.
03:07That really should be completely unique if I ever wanted to move this into the App Store.
03:11But don't worry too much about Company Identifier right now, we're just
03:15making simple examples.
03:18I'm going to leave Class Prefix alone here. What ever letters you would type
03:22here Xcode would automatically put at the start of any class and class files
03:26you make in this Project.
03:27Now App Store Category is exactly what it sounds like, giving you a list of
03:32options for the App Store. I'm going to leave that at None, we could
03:36always change that later.
03:37Below this we have a few check boxes for extra features.
03:41Now these are all great options to have, but most of them would add complexity to
03:47our simple HelloWorld Project and one of them removes complexity from it.
03:51So I want to make sure that Create Document-Based Application is unchecked--
03:56we'll see that later--and also that Use Core Data is unchecked.
04:01Core Data is Apple's own persistence Framework, which means it deals with saving
04:06then later retrieving the internal state of our Application, but we certainly
04:11don't need it in this App, and we won't be using Core Data in this course.
04:15Core Data is fantastic, but it deserves a course all by itself.
04:20And unchecked Unit Tests, all these things are terrific later.
04:24Right now, they're getting in the way.
04:26The one that I'm going to have checked is ARC, Use Automatic Reference Counting.
04:33Now depending on when you learned your Objective-C, you might not have used ARC.
04:37As it is a new feature provided in late 2011, we'll talk a little bit more about
04:42it later, but it makes Memory Management easier, and we will have ARC checked
04:47for every single Project in this course.
04:50I'll click Next, next it's going to ask me where I want to save the Project files.
04:55You can put this stuff anywhere you want, there is no magic location for storing
05:00your Projects from Xcode. I'm just going to save them onto my Desktop.
05:04Now Xcode understands both git and subversion for Source Control and well I'm a
05:09huge fan of Source Control, it would get in the way here so I'll be leaving this
05:13unchecked and just click Create.
05:16We now have A Mac Project and Xcode is going to create files for us.
05:21Over here on the left-hand side, we have what's called the Project Navigator, a
05:25view of the different files in our Project.
05:28I can single click around the files here and they will open in the middle
05:31section in the Editor.
05:33If I click a file that represents code, I'll get a Code Editor, and I have a couple
05:37here, AppDelegate.h and AppDelegate.M. Of course, this being Objective-C,
05:42we're used to seeing our class files in pairs.
05:45If I click a file that represents a User Interface, I'll get a User Interface
05:50Editor instead of the Code Editor, what's called the Interface Builder Part of Xcode.
05:54What I'm actually seeing first here is representation of the menu system
05:59for this Application, this will appear in the real menu bar when we run this program.
06:05However, when I think other User Interface I want more than a Menu.
06:08So if I look in the left-hand section of the Interface Builder--what's called
06:13the Dock--I see a few things. Now this Dock can actually be expanded and
06:17contracted doesn't really matter which view you're looking at.
06:21But I can see that by hovering over-- right now I have got the Main Menu highlighted.
06:25Below, I have something called Window, and if I click that we see
06:29what we might imagine as the Window, the main Window of this Application which
06:33will appear when we run.
06:34Now like many other programming IDEs, Xcode lets me write code, test code,
06:39design interfaces, all in the same application. Unlike many IDEs, it lets me
06:44drag and drop User Interface Elements.
06:47In Xcode the place to find them is in the Object Library, which I currently have
06:52visible over here on the right, if I can't see this right-hand panel, I'd need
06:56to click this button on the top menu here to make it visible.
07:00I'm going to just to drag this up a little bit so I can see more of it, and then
07:04moving through this I want to find Label. I'm just going to drag the Label
07:08over here and let go.
07:10With the Label here on my window, I'm going to double-click it, and just say Hello World.
07:16Clicking off to deselect it, I could grab it, start to rearrange it, put it just
07:21somewhere in the middle of this window.
07:23I'm then going to go up to the top menu bar and click the Run button.
07:28And Xcode is going to compile--or build--and then run our Application.
07:35I'm just going to minimize Xcode behind it so we can see this a little clearer.
07:39What we'll get is our Application, which I can drag around the screen here, we
07:42get the Menu at the top here with HelloWorld.
07:46I can actually select from several all of the Menus and see that they have
07:50pretty classic Macintosh style options like Print, which actually seems to have
07:56some functionality here. We have got the classic File menu,
08:00if go over to Help, I can see that even have Help menu with the Search Box
08:04and HelloWorld Help.
08:06Clicking that will tell me well, right now, Help isn't available for HelloWorld.
08:10well that makes sense, I click OK.
08:12I can even go back to the HelloWorld menu itself and click the About option, and
08:18I can see this is being built by some people and designed by some other people
08:22and Testing Hopefully not nobody, special thanks to Mom.
08:26Okay, well that aside, it does seem that right out of the box, we're not
08:30starting with a blank slate.
08:32We have some functionality here, we have this window, we have the menu system, we have
08:36some kind of print functionality, and it's great that we have these, but it's
08:40important to realize.
08:41When we create a Cocoa Application it's not, here's a blank code file start
08:46typing Objective-C. We actually have a basic App that we're going to build on top of.
08:52So we need to understand what we have already got before we start adding anything else.
08:56So I'm going to quit this Application, just the normal way, and return to Xcode.
09:01So looking at this first Cocoa application in Xcode you're probably starting to
09:06think of a whole bunch of questions. What are these code files and what do they represent?
09:10What does this MainMenu.xib represent? What is xib? what are the
09:17different parts of this User Interface view? If you have moused over things,
09:20you'll see First Responder, Application, File's Owner, all sorts of cryptic names.
09:26How would we hook a button up?
09:28Which menu options are going to already work, and which ones don't?
09:31Well we're going to get all of this, but the first piece of understanding Cocoa
09:36development is. What exactly is Cocoa anyway?
Collapse this transcript
What is Cocoa?
00:00Cocoa is a term that could be used informally or formally, and it has a few
00:04different meanings worth exploring here.
00:07Informally, I can just say Cocoa Development as a generic phrase that means
00:11developing applications for Mac OS X, and everything that entails.
00:16The world of creating apps that run on the Mac, the tools, the language, the
00:20available libraries and frameworks, the runtime, the ideas we use when doing
00:25this, just everything.
00:27Now, what we call Cocoa began in the late 1980s with NeXTSTEP, the operating
00:33system created at NeXT Computing when Steve Jobs left Apple.
00:37And when he rejoined Apple in the mid-90s, NeXTSTEP was used as the basis for
00:42Mac OS X, and a lot of the classes, the libraries, the ideas we use in Cocoa now,
00:48come from those original NeXTSTEP days, which is why the letters NS still
00:54permeate so much of what we do in Cocoa 25 years after NeXTSTEP.
00:59Now, Apple's own official documentation sometimes use the word Cocoa for both
01:05Mac OS 10 development, and iPhone and iPad development. Although they often use
01:10the term Cocoa Touch to refer to the specific area of developing apps for iOS.
01:16But if I am talking to someone at a conference and they tell me they're a Cocoa
01:20developer, I assume they build apps for the Mac.
01:23I have never actually had anyone introduced themselves as a Cocoa Touch developer.
01:27They're much more likely to just say they're an iOS developer instead.
01:30So that's the kind of informal use of the word Cocoa.
01:34Now, Cocoa is technically not the only option for developing Mac apps, but it is
01:39the recommended way.
01:41You might also occasionally hear the term Carbon used when talking about Mac development.
01:46Carbon was a set of APIs provided by Apple to allow Mac OS 8 and OS 9 apps
01:52to run on OS X. It's only 32-bit, has been fading for years, most of Carbon
01:58is officially deprecated in Mountain Lion. And it's not something you should
02:02be looking at, unless you have to officially support or migrate much older
02:06legacy Mac applications.
02:08Now, Objective-C is the language we use for creating Cocoa apps.
02:13There are projects like MacRuby, RubyCocoa, and pi Object-C that make it
02:19technically possible to use Ruby or Python to write these Cocoa applications,
02:24but we're not going to use those here.
02:26And even though I am very fond of both Ruby and Python, I don't really recommend
02:30using them for Cocoa.
02:31Cocoa is built on Objective-C, this is not an arbitrary choice, and picking
02:36another language does not remove Objective-C from the picture, it simply puts
02:40another layer between you and Objective-C, which you'd have to learn anyway.
02:44If you are a Cocoa developer, you know Objective-C, end of story.
02:49Now, as soon as you start using Objective-C as a language--even for simple
02:55command line apps without a user interface--you're going to be using the
02:59Foundation Framework, a collection of basic useful classes, things like
03:04NSString, NSDate, NSArray.
03:07Over a 100 classes are written and compiled together into the Foundation
03:12Framework, and you can't practically right an Objective-C program without
03:17linking to this Foundation Framework.
03:20In the simplest of Xcode projects, like this command line tool, if I look at
03:26Frameworks, we're already linking to it, and we can have all the different
03:30headers of those classes that exist in that Foundation Framework.
03:34But great as the Foundation Framework is, it isn't enough for us now.
03:38We need classes that represent user interface elements, like windows and buttons
03:43and menus and fonts and cursors.
03:45We also need functionality that can control what's different about a visual
03:49application over a command line application.
03:52When we write a command line app, it should just run through as fast as
03:56possible and finish.
03:57But with a visual application, we need it to stay running, and to continually
04:01respond to being moved or minimized or clicked on, to continually respond to
04:06events, until we explicitly quit the app. What's referred to as the event loop.
04:11Well, I don't want to have to write all that code myself, and of course, I don't
04:16have to. Apple has already written that functionality--classes dealing with
04:20alerts and buttons and fonts and menus and the application idea itself--and it
04:25has compiled these together into another framework.
04:28And that framework is called Application Kit, or AppKit.
04:32Now, there is an equivalent framework for iOS development containing the iOS
04:37versions of these classes, and that's called UIKit, but every Cocoa application
04:42will use at least Foundation and AppKit frameworks.
04:46Now, there are many other frameworks available to us when developing Cocoa
04:51apps, but all the other frameworks are optional choices, you use them if you need them.
04:55There are frameworks for working with audio or video, talking to Bluetooth or
05:00USB for security or networking, or working with QuickTime. And we'll see a few
05:05of them in this course, but we will always need Foundation and AppKit in Cocoa.
05:11Now interestingly, there's a difference between what Cocoa is officially and
05:17what Cocoa is technically. Here is Apple's official documentation.
05:22They formally state that for OS X development you need, quote, "Foundation and AppKit
05:27frameworks, all other frameworks are secondary and elective."
05:31But it's interesting to see that what they say and what they actually do is a
05:36little different, because technically in Xcode when you make a Cocoa project,
05:40you get three existing frameworks-- not just two--and let me show you that.
05:46A moment ago I showed that in a typical out of the box command line application,
05:50that is with no UI, not a Cocoa application, we link to one framework, the Foundation Framework.
05:57Well, in a typical right out of the box Cocoa application--like the HelloWorld
06:01one I just created--we also link to one framework called Cocoa.
06:07Well, okay, what is that? Well, it's not really anything,
06:10it contains no classes, no actual code.
06:13If I expand the header file, what I see is one thing, Cocoa.h. I click that, I
06:20find that all we're doing is linking to three other frameworks:
06:25Foundation, AppKit, and CoreData.
06:30Even if you don't need it, even if I unselected CoreData as a check box when I
06:34made this Cocoa project, it's there.
06:37Apple consider CoreData to be a very important framework--and I agree it is
06:42important--but important is not the same as necessary, which is why CoreData for
06:47us will be a separate course, but we will always be using Foundation and AppKit.
06:53So Cocoa has an official definition, it has a technical meaning, but when I use
06:58the word Cocoa in this course, I am going to use it the informal way most
07:03developers refer to it. The world of creating apps for Mac OS X.
Collapse this transcript
2. Core Cocoa Skills
Introduction to Xcode
00:00If you have been using Xcode for a while, you might find this movie a bit of a
00:03do over, and you are welcome to skip it.
00:05But if you are fairly new to Apple development, or it has been a while since you
00:08have used Xcode, I am going to take a couple of minutes to go over it.
00:12We will spend most of our time here.
00:14Xcode is an IDE--an Integrated Development Environment--like Visual Studio, or
00:20Eclipse, or Aptana, and this just means it does more than one thing.
00:23You write your code in Xcode, you design your interfaces here, you compile
00:27your applications here, you use it to test and debug, to browse documentation, to find help.
00:33But at its core, Xcode is here to organize the files in our applications, and it
00:38groups them into projects.
00:40Projects are just a way of grouping a bunch of files together and giving them a name.
00:45When you create a new project in Xcode, and I am going to do one now--again,
00:49selecting from the OS X Application section and choosing Cocoa Application--we
00:54are going to do a new project.
00:57Again, it's going to ask me for the naming information, I am just going to call
01:01this project DemoXcode.
01:02Leave everything else unchecked except Use Automatic Reference Counting, and I
01:08am going to go ahead and just Save this onto my Desktop.
01:14But before we go exploring this actual project, I am going to take a look at
01:19what was created when we did that.
01:21If I go to my Desktop, I see here that I have a folder called DemoXcode.
01:25This just got created, and I had deleted some of the other projects I created earlier.
01:30If I go into that--and let's just expand it so we can see a little more here--we
01:35have quite a few files that have actually been created for us. And what you will
01:40see is that some of them match what I see in Xcode and some of them don't.
01:47If I compare the two, I can see that there is kind of a slight difference to the
01:53layout in there, expanding all the folders in Xcode, while some of those folders
01:57don't even seem to exist, or they have different names ,or there is a different
02:01arrangement of files here. Don't worry about that.
02:03Xcode allows us more ways of grouping these files than just the actual
02:08folders on the hard drive.
02:10However, there is one file you will see in the Finder, which is this one,
02:14the .xcodeproj or the Xcode Project file.
02:18This is the file that contains all the settings for this particular project, and
02:23if Xcode was closed, double-clicking this file will be the quickest way to open
02:27Xcode with this project loaded.
02:29So switching back, let's talk about the best way around the Xcode for interface.
02:34We are, of course, in a programming environment, so everything is oriented around
02:39us editing something, and it's really oriented around this middle section.
02:43Whether that's letting us edit code or change the user interface.
02:47The toolbar up at the top of Xcode will let me run the application, as we have seen already.
02:53This center section looks like a little LED screen, and it will show messages
02:57about anything that Xcode is doing as we work with our project. It's kind of
03:01like how iTunes displays messages when you are copying or syncing.
03:08Over here on the top right of the bar you have two groups of three buttons.
03:13What I am just going to do right now is make it so the first button of each
03:17group is pressed in. And this first means we are showing the Standard Editor,
03:22there are different editors, but we will see those later.
03:24And in the second section we have these three buttons with a dark left section,
03:29a dark bottom section, and a dark right section, and all these buttons do is
03:34toggle the different sections on and off.
03:38Unlike some other applications, in Xcode you don't rearrange or detach and drag
03:44and drop panes from one area to another. This is Apple, this layout is this layout.
03:50The section on the left stays on the left, you can choose to make it visible
03:54or not, but that's it. And the left-hand section is the navigator.
04:00The navigator is a way to navigate, to get around everything in and everything
04:04about this project, all the files, the settings, the configuration options.
04:09We have seen that we can expand and collapse files.
04:12If I single click on one of the files in this project, and it's editable, it
04:16will open up in the middle section.
04:18If I were to double-click it, it would open up in a separate window.
04:22I am a fan of a single clicking so that's what I tend to do.
04:26Now, this left section contains seven different navigators.
04:29You can move between them by clicking the buttons at the top.
04:32There is really not much to see in the other ones right now, but you will be
04:36able to view things like issues or log messages when looking at this.
04:40And sometimes Xcode will switch you to a different navigator if that's useful.
04:46But you don't need to memorize them all yet. The most important one of the seven
04:49navigators is the Project Navigator, the first button, the one that looks like a folder.
04:55And a useful shortcut for this is Command+1, and that will open the
05:01Project Navigator even if the left section is completely closed.
05:04You just hit it, it will jump you right there.
05:07The Project Navigator is a view, not just of all the files in your project--
05:11although you can do that by just single clicking around them--but also the
05:16project settings itself.
05:17Clicking the very top icon, the one with the same name as the actual project,
05:22gets you the top level settings of the project here, which can contain things
05:27like the Application icon, what Version is this, I can see places where it can
05:32work with the bundle identifier.
05:34We have checkboxes that allow us to say whether we Allow Camera Access or
05:38Microphone or USB Access.
05:40And clicking across the top here, there is different technical Build
05:44Settings and Build Rules. And we will see some of these little later on.
05:48Now just as the left-hand side, the Navigator Panel can be turned on or off so
05:53can the right-hand side.
05:55This side contains two separate parts, the Inspector's at the top, and the
06:01Library is in the bottom half.
06:02Now, the arrangement here is not random, there is a point to how these things
06:07are grouped together.
06:08We can think of the navigators on the left as showing everything in the project
06:13and the Editor section over here as the one thing that I am working on and then
06:18the Inspectors on the right are context-sensitive.
06:21The Inspectors change as I select different files.
06:25Just as the Navigator section on the left had seven different sections you can
06:29move between, the Inspector section over here on the right also has different
06:34sections you can move between, and that changes based on what you have selected.
06:38If I am editing a code file, I am likely to find that I just have two Inspectors
06:43over here, the File Inspector and the Quick Help Inspector.
06:47If I have a User Interface file selected, an XIB file, I actually find that I
06:52have eight Inspectors that I can move between.
06:54Again, don't worry about memorizing them, we will explore them later as we need to.
06:58Now, below the Inspector section is the Library section here, and the Libraries
07:04are the simplest section and they do not change based on what you have selected.
07:09Libraries contain collections of things you might wanted to add to your project,
07:14like having a library of user interface elements, or a library of code snippets,
07:19and things in the library can be dragged and dropped.
07:21Now Xcode, like any other application has Preferences, things you can customize
07:27about this application to make it work better for you.
07:30Now, I am typically leaving it pretty much as is straight out of the box, but I
07:34have made two small changes just to show you what I have got here.
07:39From the Xcode menu I can select Preferences, and in the Fonts & Colors section
07:44I had switched to the Presentation theme just to make the font size bigger and
07:48more readable for this course.
07:51And then in the Text Editing section I have a check box selected so that we can
07:56see Line numbers so that when I am exploring the code, it's a little easier to
08:00talk about line by line.
08:01Now Xcode of course, does have options to connect to Source Control Repositories
08:07and Debugging options, Code Snippets and ways to help us manage our projects.
08:12But this is really enough to help us get going, because some of the other
08:15options really are not worth bothering with until we have got a bit more code to play with.
Collapse this transcript
Using Model-View-Controller
00:00Before we start adding more interaction to an application, we should talk a
00:04little bit about MVC, or Model-view-Controller, which is a very important concept for Cocoa.
00:09Now if you're coming from iOS, you'll know that MVC is extremely formalized and
00:15enforced over there.
00:16Now it's a little less enforced in regular Cocoa, but still essential.
00:20Now as you probably know, MVC is not just for Apple development, it's been around
00:25for a long time, since the late 70s in fact.
00:27MVC is a software design pattern, meaning it's an idea.
00:32You can do Model-view-Controller in Java, you can do it in C#, you can do it for
00:38the web or for mobile, or you can do it for Desktop Applications on a Mac.
00:42And at the core of MVC, it means the objects that represent your data and the
00:47objects that represent your user interface are kept apart.
00:50And you should be able to change one without affecting the other.
00:54And the model part of Model-view-Controller is your data.
00:59The information your app needs and stores and manipulates, objects that
01:04represent contacts in the contacts application or emails in a mail application,
01:08or customers or employees or orders, but these objects do not inherently
01:14define a user interface.
01:15They don't say whether they show up in a text field or a dropdown box or a
01:20button or what font they use.
01:23But on the other side of things we have view objects.
01:26view objects are your interface, your User Interface elements what the user
01:30actually sees, windows and menus and buttons and sliders and text fields, these
01:35are all view objects.
01:37We might have different ones for a print view and different ones for a web view.
01:42And often we want to use generic User Interface element, so they can be reused.
01:47You can have multiple buttons that do different things.
01:50And a button knows if it's being pressed or released and a text field knows
01:55how to draw itself.
01:56A text field knows if it's being edited, but it doesn't do the job of retrieving
02:01or storing or processing the data typed into it. That would be the model's job.
02:06And the Controller object then is the glue that hooks one side to the other.
02:13A view object talks to a Controller object, the Controller talks to the Model.
02:17But the Model and the view don't talk directly to each other.
02:22And the idea with pure MVC is that every object in your program would fall
02:27exactly into one of three roles, either Model, view, or Controller.
02:32Now that doesn't mean you only have three objects.
02:34You could have hundreds.
02:35But each one is clearly a Model object, or a view object, or a Controller object.
02:40I mean in practice, in Cocoa, our Model and Controllers are written as
02:45Objective-C classes with header and implementation files for each.
02:50And the user interface view objects are collected in a .xib, or xib file, which
02:56is the one that gives us our visual user interface builder.
02:59And we will talk more about what a xib file is later.
03:02In a simple Hello World style application, we can actually get away without defining formal model
03:08objects, simply because we don't have any data worth describing yet.
03:13But if you want any kind of behavior to occur, any kind of interaction between
03:17your User Interface elements and your code, one of the things that you do have
03:22to define very well is the relationship between your view and your Controller
03:26objects, it's not automatic. Let me show an example here.
03:30If I build an interface in Xcode, and I drag on some really basic UI element, a
03:37text field, a button and the label, these are all view objects.
03:42The label is a view object, the button is a view object, the text field is a
03:46view object, the window itself is a view object.
03:48So you can have multiple view objects and one of them like the window can
03:53contain other view objects.
03:54But we have to define very specifically, the relationship between these view
04:01objects in any code we want to connect them to.
04:04Now in Xcode you can do what you might be able to do in other IDEs, which is
04:09drag on a button, double-click it, and write your code.
04:12It doesn't work that way.
04:14We need to first decide what code file represents our Controller code.
04:19And then we look at each view object and think about what kind of connection it
04:24needs to that Controller code.
04:26So, for example, we have a button on the user interface, and I want that button
04:31to cause a method to be run in the Controller code.
04:35So we need to define this button as causing what's called an Action.
04:40This view object of a button causes something to happen in the Controller code,
04:45that's an Action in Cocoa.
04:47Now on the flipside of that, we often want to reach from our Controller code
04:52back into view object, say, like the text field to either read its contents or to change it.
04:58If so, we need to define our text field as being what's called an outlet.
05:03And we might also want to write some code to change the label, in which case the
05:07label is also an outlet.
05:10So when you're building Cocoa applications, you are defining very specifically
05:14your actions, where a view object triggers something to happen in the Controller
05:19and defining outlets, something in the Controller code affects the view object.
05:24Now some User Interface elements could be both actions and outlets.
05:29Perhaps, I want to click a button in the view that causes some code to be run in
05:35the Controller and then that reaches back into the button and disables it, well
05:38that would require the button to be both an action and an outlet.
05:42Well, let's see some examples of actions and outlets in practice.
Collapse this transcript
Creating basic interaction
00:00I am going to create a new Xcode project. This will of course be a Cocoa Application.
00:04I'll just give it a simple name, in this case, BasicInteraction, because I want
00:08to get the view and our code to talk to each other.
00:11Make sure that everything except Use Automatic Reference Counting is unchecked.
00:15I am just going to save that onto my Desktop.
00:19This project template gives me a handful of files.
00:22We have the AppDelegate.h and AppDelegate.m files here, and our interface MainMenu.xib.
00:30Now you will hear these files referred to as XIB files, which kind of makes sense
00:33for .xib, but also as NIB files which might not.
00:37That's because until a few years ago the file extension for your user interface
00:41files was .nib, which stood for Next Step Interface Builder.
00:46We used to use a separate program called, Interface Builder, to work with these
00:50files up until Xcode 4. When it was integrated into Xcode itself and they have
00:55actually been called XIB files for a few years, but a lot of developers still
00:59talk about the NIB file and adding things to the NIB and customizing the NIB.
01:03Now technically, this .xib file will actually be quietly converted into a NIB
01:10file during the compilation process, but you never actually see that.
01:14So informally the terms XIB file and NIB file are interchangeable.
01:19And by default, if I click this XIB file, I just see the menu for this
01:23application, with the name of the project, File, Edit, Format, view, Window, and Help.
01:29To see the actual Main Window I need to find the Window object in the Dock.
01:34Again this Dock can be collapsed or expanded, it can't be gotten rid of.
01:39So you should be able to grab the window either way.
01:42Now what I want to do next is drag some user interface elements onto my window here.
01:47I am going to drag on a text field, a button, and a label, and these will be
01:51in my Object Library.
01:54If you happen to have the right-hand section of the app closed, you get to it
01:59through the view menu, down to view > Utilities > Show Object Library.
02:03I am going to drag that up a bit.
02:08There are a lot of user interface elements and different objects I can select from.
02:12So if it seems a little intimidating, I can use this box down at the bottom of
02:16the library to filter.
02:18I could type in, say, a word like button, and just see all the buttons that I have
02:23options to use or label or text or whatever else.
02:28Well, with buttons selected, I am going to grab one of these.
02:31I will grab the Rounded Rect button, which is as good as any.
02:34All the buttons are actually very similar to each other, they just
02:38have different styles.
02:39We will go through the different user interface controls in a little while.
02:43Now by grabbing the button and moving it around, I can actually see as I move it
02:47that Xcode will give me some helper information, the little lines here that will
02:52tell me when it's positioned correctly or in the middle.
02:55I can just put that anywhere that I want to right now.
02:59We can also grab the handles of the window itself to resize the window and bring it in a bit.
03:05Double clicking the button will let me rename the text that it shows.
03:09I will just say click, and I can grab the handles just to make it a little wider.
03:14Next, I want to add on a label.
03:17I could check that by typing in label at the search box.
03:20I see I have a Wrapping Label and a regular Label that displays text. That will do.
03:25So I'll drag Label on.
03:26If I'm going to put a message in it, I want it to be a littler wider.
03:30So I will drag it the width of this interface here.
03:34What if I wanted to change something about that label?
03:37Well, over here in the Inspectors section of the right-hand panel, the fourth
03:43option that I have here is the Attributes Inspector.
03:45So I am going to click that one. Now this is of course context-sensitive.
03:50So it will show different things based on whether I have the buttons selected or
03:53whether I have the Label selected.
03:55With the Label selected we can do things like change the alignment to center
03:59aligned, or change the Text Color or the Background, and we will see a few of the
04:04other options that we have for this a little later on.
04:06Now the last user interface element I want right now is actually a Text Field.
04:12If I type in the term text here I'll see I have got Textured button, Rounded
04:16Textured button, Text Field, Secure Text Field for passwords and so on, Date
04:21Pickers, Number Formatters. Let's just grab the basic Text Field.
04:25I'll drag that on there, drag it a little wide and let the prompts tell me when
04:29it's at the right position.
04:31With that selected I am going to make sure that I have my Attributes Inspector
04:35selected, the fourth one here in the Inspector section because I want to give
04:39it a Placeholder String. Let's type in Please type your name.
04:44That will just give me the grayed out text here that will disappear when I click into that.
04:51Label I am going to double-click and actually remove the text that's in
04:54there so it's blank.
04:57I'll drag the button up a little bit, position it in the center and then just
05:02shrink the actual window down a little bit more.
05:04Now here is one of the issues. What happens if I have removed the text from the
05:10label, and I don't know if it exists anymore?
05:12Well, there is a couple of ways I could check it.
05:15One is, over here on the Dock if I expand it, so I can see the wider view what it
05:20allows me to do is drill down into the different elements here.
05:24So if I collapse them in, and expand this window I can see I have a view
05:28inside that that has a Round Rect button, and when I click that, it's
05:31highlighted in the Editor.
05:33Static Text which is the label that we have, I can see that's now highlighted,
05:37and the Text Field itself.
05:40Another way of getting to it is up here is what's called the Jump Bar and
05:45clicking any particular section here will allow me to jump between say that
05:49Static Text or the Round Rect button, or up another level between the window
05:55and say the Main Menu.
05:57So there are multiple ways to get to the different pieces here.
06:01So this is my impressive interface, Text Field, button, Label.
06:05I want to have people type something into the text field, click the button, and
06:09change the contents of the label so we can see some basic interaction.
06:13We now have to be very explicit about how these user interface elements
06:16connect into our code.
06:17What we have to say is, what do we want the relationship to be between the text
06:22field and the button and the label and our code?
06:24So first off we want the button to cause something to happen in our code.
06:29It will cause an action to happen.
06:31And on the flipside, I want the text field to be an outlet.
06:34I want to reach into it from our code, grab the contents of it and then be able
06:39to reach to the label and change the contents of it.
06:42So those would be outlets. I am going to show you two ways of doing this.
06:46First, the older slower way, and then the new quick way.
06:49I am going to show you the slow way first so you understand what the quick way is doing.
06:54So every connection between these view objects in our code is a handshake to it.
06:59Something that needs to be done in the code file, something that needs to be
07:03done in the user interface file, there is always two parts to it.
07:06Let's go to the code first.
07:08Well, I said we connect our view objects to a controller object to a controller code.
07:14So where's the controller?
07:15Well, I could create a new class for that, and we will do that later, but for
07:21this simple example I am going to use the only existing class that we have here,
07:25the AppDelegate class.
07:27Selecting my AppDelegate header file, I can see I have something in here called
07:32window, it's given me a little bit of boilerplate code.
07:35I have got this NSApplicationDelegate.
07:37I might not know what that means but that's okay right now.
07:40We will talk about that later.
07:42What I want to do is in my header, I am going to define a method.
07:45I am going to define a method that I want the button to call when it's clicked.
07:50Now usually if I define a method I'd make a simple one like this.
07:58Define it as a method called changeLabel that takes no parameters and returns void.
08:03Well, that's okay, but it's not really going to work in this case, because I
08:08need to create some kind of indicator that the method I am about to write can be
08:12called by a view object in the user interface. To do this, we actually change the return type.
08:19Instead of using void, we have a special return type called IBAction.
08:23So I am going to define that method and start typing IBAction, upper case I, B,
08:29and A. As I type we see that it pops up here with the code sense.
08:34I am going to hit Tab and jump to selector which will be the name of the method.
08:39So I will actually call this changeLabel. It's not built-in, it's my own.
08:44So I will just define it myself.
08:47By default, IBAction should take a parameter of ID, called sender, which is fine.
08:53So I will just hit Tab and finish the line off with a semicolon.
08:57Now if you notice that by defining this as returning IBAction, we get this
09:02circle over here on the left-hand side, and this is an indicator.
09:06It's saying this method can be connected to a user interface element.
09:12If on the other hand I had just created a method with a return type of void, we
09:20would not get that circle. So what is IBAction?
09:23Well in truth, it's actually the same as void. It means this method doesn't return anything.
09:29IBAction is just an indicator, we are announcing to Xcode, we are announcing to
09:34Cocoa that this method can be connected to a user interface element.
09:38Now I don't need that doSomething method. I just wanted to show that.
09:42Now next, I want my code to be able to have access to the label and the text
09:47field objects that I defined and dragged onto my user interface file.
09:52So I need something that represents a Label object and a Text Field object in my
09:56class so I can hook them up to the user interface.
09:59We do this with properties, but these properties won't be integers or string,
10:03they need to be the correct kind of objects.
10:06So I am going to put them beneath the existing @property that I have here.
10:12What I am going to do is use the word weak here. We'll talk about that in a little bit.
10:20I mentioned earlier that if I want something in the view to affect the code,
10:25it's an action. Whereas if it's something in the code to reach out to the view,
10:29it's an outlet. And I can actually see on line 13 above it we have something
10:33saying IBOutlet for interface builder outlet.
10:36That was already there, but I'm going to write my own, IBOutlet, and what is this?
10:42Well, it's actually going to be an NSTextField. That's part of the AppKit framework.
10:50So NSTextField, and it is of course a pointer object.
10:55So I'll just call this one textField.
10:57Right now, there is no connection between this property and the actual text
11:03field I have dragged on to the user interface, but there will be in a moment.
11:06Now next, I am going to write a property, this will also be weak, very similar
11:11to the previous one. This will be IBOutlet.
11:13Now you might think is this an NSLabel? Actually no, it's another NSTextField.
11:20In Cocoa, a label is simply an NSTextField that isn't editable and doesn't have
11:26a white background to it. I will just call it myLabel.
11:34Now these will be generated properties, so we may have to jump into our
11:37implementation file in a moment to add the synthesize statement for those.
11:42So I am going to jump cross into AppDelegate.m, and after the opening
11:48@implementation line, I am going to add in synthesize for both textField and myLabel.
11:58If you're using Xcode 4.4 on Mountain Lion or later, you won't need the synthesize statement.
12:05Now the only other thing that I'm getting a complaint about right now for an
12:09incomplete implementation, which I get by clicking the little exclamation mark
12:13here is, I haven't provided any kind of implementation for the changeLabel method
12:18which I need to do that now.
12:21We use the same format which was IBAction, and it was called changeLabel, and it
12:28took that parameter of ID sender. We have got a little bit of extra code in here.
12:33That is about right.
12:34So I want to say, well, what actually happens when that button is clicked where
12:38we change the label.
12:39What I am first going to do is construct a string, including the contents of the text field.
12:44So I am going to create a new NSString object and construct a message that
12:50begins with Hello, and then what I am going to do is grab the contents of the text field.
12:56So how do I do that?
12:57Well, I will have an object called textField, and the property I need is called stringValue.
13:05Just close the panel on the right-hand side to give us a bit more screen real estate here.
13:12So I construct that new message, and then I better change the label.
13:19On the same way that I used stringValue as a property to grab the contents of
13:24that text field, I will use setStringValue passing in that new NSString object.
13:30I am going to save that, hit Command+B to build, I get Build Succeeded message. So I just run it.
13:37So is it going to work?
13:39No, absolutely not, because right now I have only done one side of the connection.
13:44I said that everything is like a handshake.
13:47There is something you do in the code unless something you do in the user interface.
13:51And all I have done right now is in the code.
13:53So I'll quit out of the BasicInteraction app and jump back in here, grab my
13:57navigators, and jump over into MainMenu.xib. And this is where I define the
14:05connections between these view objects and our AppDelegate.
14:09Well, how do I do it?
14:11There is a couple of different ways, but here's one.
14:13We have seen that by clicking around we have got objects in the Dock here,
14:17one represents Main Menu, one represents the Window itself, the one below it
14:22represents App Delegate.
14:24This App Delegate for us right now is kind of the conduit between our .xib and
14:29our AppDelegate.h and AppDelegate.m. So here's what I do.
14:35I want to connect this button to the method called changeLabel.
14:39So I hold down the Ctrl key, and I do Ctrl-click on the button and then drag,
14:45keeping the Ctrl key held down, move over AppDelegate and let go.
14:52What happens is Xcode scans the header file for AppDelegate and says, hey, does
14:57that header file have anything defined as an IBAction?
15:00Well, yes it does, it has one method defined as IBAction.
15:03It's called changeLabel.
15:04Is this the one you want to connect to? Well, it is.
15:07So I mouse over changeLabel and click it.
15:09We now have a connection between the button and the code.
15:12Now we go the other way around.
15:15What I have defined in AppDelegate.h are these two outlets.
15:20I want to reach from the code to that user interface.
15:24So I am going to click back into the MainMenu.xib, and now I'll Ctrl-click from
15:30App Delegate, Ctrl-clicking there, holding down the Ctrl key I drag over Text
15:35Field, and if you notice as I drag around it, it kind of highlights the
15:39different objects that I can connect to. So I drag over text field, I let go.
15:43It again scans up delegate and says, well, you have got two things defined as
15:46IBOutlets that aren't hooked up to anything yet, myLabel and textField. Which one is this?
15:51Well, I move over textField, click, its text field. Then hit Ctrl and drag again
15:57from App Delegate, find the Label, even though it's invisible, by mousing over I
16:01can find it and let go.
16:03It's given me a hint though that textField is already connected to something,
16:06but myLabel is not, that's the little dash, so I'll click myLabel.
16:11That's how we describe the connection between our user interface and our code.
16:16Now it's a very common problem for people new to Cocoa or iOS development who
16:22have to do this a lot as well to mess up the connections, and it's one of the
16:27first places you should look when you're trying to diagnose where a problem is.
16:30And here is one of the problems right now. I can't see anything.
16:34There is nothing obvious just from looking at this that I just created three
16:37connections between the user interface and the code.
16:40Well, there's a few ways of getting to this.
16:42One is, if I open up the right-hand side panel, select any of these view objects,
16:49and go up to the Inspectors, what I will find is the sixth one with the little
16:53arrow is called the Connections Inspector. And what it can show here is
16:57different connections here, and it's actually showing me as I mouse over that
17:00this textField is connected to App Delegate.
17:03If I highlight the button, I can see here I have got a Sent Action.
17:07This button is calling changeLabel in App Delegate.
17:10If I move over the Label itself, myLabel is going to App Delegate.
17:15Another way I can view them is actually by right-clicking, say the App Delegate
17:20object here which shows me the connections between the Outlets, and as I mouse
17:24over them, it even highlights them and the Received Actions, changeLabel is
17:29being called by the button.
17:31So there are a few different ways of getting to that, and we'll have more than
17:35enough practice as we go through this course.
17:38So let me go ahead and run this application. Build Succeeded.
17:42Please type your name, this is the placeholder text.
17:45As soon as I start typing it should go away, and then we hit click, and we get
17:49the message Hello, Simon.
17:51So very basic interaction here, obviously there is a lot more we can do with it,
17:56but let's leave it at that for the moment.
17:59So now it seems like it's quite a chore to hook things up.
18:02Well, I did say that that was the slow way of doing it and luckily there is also
18:06a quicker way, and we'll do that next.
Collapse this transcript
Creating quick connections
00:00We have seen how to make connections between our user interface view objects and
00:04the properties and methods that we have actually written out in our code, but
00:08Xcode can help us speed this entire thing up. I am going to make another Cocoa Application.
00:12I will just call this one QuickConnections and save it to my Desktop. Making sure
00:17everything except Use Automatic Reference Counting is unchecked.
00:25I am going to jump over into MainMenu.xib and from the Dock select the Window
00:31object to make our Window interface visible. And I am just going to go ahead and
00:36layout a very straightforward and simple interface having a Text Field button
00:40and a Label. And just position them pretty much anywhere on this interface, I
00:51will make this little smaller.
00:53So we know that we always have to be very specific, very explicit about how
00:57these connect to the code files that are associated with this user interface.
01:02And the way we can be really quick about this is by using what's called the
01:05Assistant editor in Xcode.
01:07I am going to give myself a bit more room right now just by turning off my
01:11Navigators and Utilities panel.
01:13You don't have to, I just don't have a lot of screen real estate to work with.
01:18So making sure that I am in the XIB file, I am going to turn on my Assistant editor--
01:23that's the second button up here on the toolbar in the Editor section, looks
01:27like a bowtie and tuxedo, your personal butler or assistant.
01:31Now the Assistant editor will show us two files available for editing at the
01:36same time, an original file and its counterpart.
01:39So if I was looking at the .h header file, the counterpart will be the .m
01:44implementation file, but if I am here in there .XIB, well the counterpart here
01:49could potentially be a few different code files.
01:53Right now, what I want to see is the XIB file on the left-hand side and the
01:58AppDelegate header file on the right-hand side.
02:01Now, if it doesn't show me what I want automatically on the right-hand side, I
02:05can use the Jump bar and manually select that particular file from here, but we
02:11look good right now.
02:13So AppDelegate.h has nothing inside it that corresponds to our user interface
02:19elements that I just dragged on the text field, the button, the label.
02:23They just don't exist there, and they need to.
02:25So what I can do, for example, is connect from the button.
02:30Again, just by holding the Ctrl key down, clicking and dragging. And if we drag
02:35directly into the code file here, I will see this little insert outlet, or action, pop-up.
02:41Now notice that if I am above the interface, or below the @end, it won't let me
02:47put it anywhere there, so it's going to give me an option for where I can
02:51actually place this.
02:52So after the @ sign property line, I am going to let go.
02:56What I get is this pop up window saying, you can insert an Outlet, or an Action here.
03:01It knows I want to make a connection, it's just not quite sure with this button,
03:05whether I want it as an Outlet, or an Action because a button could be either.
03:09Well, what I want to do is an Action.
03:12I want this button to cause something to happen in the code, to cause a method to be called.
03:17Now if it is an Action, what it's asking is, what's the name of the Action?
03:21What is the name of the Method? So I will call it changeLabel, and then hit Connect.
03:26And it will create the method signature here with the IBAction return type--
03:32which is the correct one--and it will make the connection between that button, and that code.
03:37Not only that, but if I use the Jump bar to just jump over to the implementation
03:41file here, it will actually create the implementation stub for that method.
03:47So just by dragging from the interface into the code, I get three pieces.
03:51I get the part in the header file, I get the implementation file, and I have the
03:56connection defined as well.
03:57So I am going to jump back into the header file, I am using the Jump bar here,
04:01and I am now going to make the connections for the text field and for the label.
04:06Once again, I do it the same way.
04:08I am going to hold down the Ctrl key and just drag from the text field, making
04:12sure it's the text field that I see selected there, into the code.
04:15Again, it has to be within the @ interface and @end lines, doesn't really matter
04:21where you put it, but I would like to put all my properties before my methods.
04:25So I will just drag it up here. Now it's saying is this an Outlet or an Action?
04:30Well, this would be an Outlet.
04:31I want to write some code that will reach from the code into the view.
04:37So it's an outlet, whatever I want to call it, I will call it textField, and we
04:41should get into the habit of just scanning this Type here, making sure that the
04:46Type it selects is what you are expecting.
04:48Sometimes it can be a clue if you see something different here.
04:52I would expect to see NSTextField.
04:55So really all I have to do is give it a Name and click Connect, and again, I can
04:59do that from the label, hitting the Ctrl key and dragging over, and I will call
05:05this myLabel. It is of course NSTextField, again, our label is an NSTextField
05:11object, this is an Outlet, and it's weak, I'll click Connect.
05:15So it's correctly marking these things as the IBOutlets and correctly marking my
05:20methods as an IBAction.
05:21Now if you are curious just about the word, weak here.
05:25Well, if you are defining your own properties that are part of your own classes,
05:29you would typically use the word strong, but here these objects that I am
05:33talking about, the text field and the label, they really belong to the XIB, they
05:38belong in that larger view and the view is what owns those objects, not this
05:42AppDelegate class file.
05:44And that means what we are creating are weak references to the objects that
05:48exist somewhere else.
05:49So we are using the word weak, but really I am just letting Xcode do that for me.
05:54But of course, these are properties
05:56that mean they are generated in our code with getters and setters.
06:00So we need to make sure that they are being synthesized correctly.
06:03Again, I use the Jump bar, jump over to the implementation file, I can actually
06:08see that I even have the synthesized statements are being added as well.
06:12So just from dragging and dropping, we are pretty much ready to go, but the
06:16only thing that's missing is to actually provide some behavior in the changeLabel method.
06:21Well, what I am going to do is actually just switch back to the standard editor,
06:25which is the first button here and then just temporarily select from my
06:29navigator just so I can get a bit more real estate here to work with.
06:33And in the changeLabel method I will write some code to grab the contents of the
06:38text field and change the label.
06:39So I will create a new NSString object and use the initWithFormat way of
06:45allocating this, to create a new message that includes the words Hello, and then
06:49grabs the content of the text field.
06:52And we can get the contents by using textField space stringValue, and that
06:59should do that line, so now we have a new constructed string together, and all I
07:04need to do is use the myLabel property and say setStringValue to message.
07:12We are using Automatic Reference Counting, so even though I use the alloc and
07:17initWithFormat, I don't have to care about releasing anything. So I can just
07:21save this and go ahead and run it, either by clicking Command+B just to build--
07:27to double check that everything builds without any errors--and then go ahead and
07:30hit Command+R to run this.
07:32Type something into the text field, click, Click, and it seems to be taking the
07:38contents out of there and changing the label.
07:40So it's not the most exciting thing, but what we have got here is full interaction.
07:44We have Outlets, we have Actions, we have a lot of code being
07:47generated to hook our user interface to our code files.
07:51So we can just come along and put in the code that we want to work, and we can
07:56use exactly this method to create more interesting and deeper user interfaces.
08:00And we will do that shortly.
Collapse this transcript
Understanding the Cocoa application life cycle
00:00By the time they have created a few--even simple--Cocoa Applications, a lot of
00:05developers really want to know what's actually happening inside of a
00:08Cocoa Application, inside of a Cocoa project, even a basic one that we
00:13have just created here.
00:14What do these other files represent? What really is this AppDelegate? And why, if
00:20this is an Objective-C program, don't we do anything with the main function to
00:25begin an App? And if we are using this MainMenu.xib, where is the code that
00:30actually loads that? Well, let's take a look at the processes here.
00:33So I have made this straight out of the box Cocoa Application in Xcode, and
00:38there is a lot going on here. But the most basic idea is, of course, this is an
00:43Objective-C program, which means this program will begin by running main and in
00:48a Cocoa Application, we do have a main.m file, that's actually in our
00:53Supporting Files folder.
00:55Now as a rule, you will never touch main in a Cocoa Application.
00:59You are going to leave it alone, which is why Xcode puts it into that folder.
01:03And main calls a C function, called NSApplicationMain.
01:08This is a predefined C function in Cocoa that creates a new object called NSApplication.
01:15So the basic process is main opens up, calls the NSApplicationMain function that
01:21creates this NSApplication object that represents the standard Cocoa
01:26Application, the foundation, the plumbing, the core functionality that every
01:31Cocoa Application is going to need, setting up a run loop, so the application
01:35stays active, responding to events and so on.
01:38But our application is going to be different from just this generic application
01:43object, so we need to say how.
01:45Well, in a lot of other languages, on other platforms, you would use
01:49inheritance for this.
01:51You'd actually inherit from this NSApplication object, or in other languages,
01:56an application class.
01:58Well, in Cocoa, we don't use inheritance for this. We use delegation.
02:03We need to have an Objective-C class in our project that will act as the
02:08delegate for the standard built-in NSApplication object.
02:12So the NSApplication object can let our delegate class know about various events
02:18we might be interested in, and we can choose whether or not a respond to them.
02:22Now at the same time, the NSApplicationMain function knows we want at least
02:27an initial user interface, so it's going to look in a property list file in
02:32our Xcode project that contains the name of our main xib file.
02:38And by default, that is MainMenu.xib.
02:40And that xib file--and everything in it--Menus, the Window, the other user
02:46interface elements, will be loaded as part of the startup process and exist for
02:51the life time of the application.
02:53Now in Cocoa, we can provide multiple windows--but we will see that a little
02:58later--and by default, that app delegate will be connected to our main window object.
03:03And all of this is provided for us as a basic framework.
03:08So in main.m, we call NSApplicationMain.
03:12If I look at this Lifecycle-info.plist, it's whatever your project is called
03:18-info.plist, we will find an entry in here called the Main nib file base name,
03:23which here it says MainMenu, that's what's loading in MainMenu.xib and
03:28everything inside it.
03:30And when looking at the project files, you might also have a pretty good guess
03:34of what class is acting as the delegate for the application object,
03:38it is of course here the AppDelegate object.
03:41So this is where we could put the code to respond to application level events
03:47like, for example, our applicationFinishingLaunching and later maybe the applicationTerminating.
03:54Now as we have seen, we can also put code in this class to react to events in
03:59our interface, the same class can act as an application delegate, and there is a
04:04controller for our view objects, although and anything nontrivial, will split
04:07that out into another class. And if you finding this all a little intimidating,
04:12fair enough, there is a lot going on here, but here's the thing.
04:16You don't touch main, you don't touch NSApplicationMain.
04:20Most of the times you don't need to touch this plist entry.
04:25This is the framework that is provided for you.
04:28Your interaction with this provided structure is first off to add code into the
04:34app delegate to deal with application level events, laying out your user
04:38interface in the xib file and then creating Objective-C classes to behave as
04:44models and controllers and hooking them altogether.
04:47So when the application first launches, you will automatically have methods like
04:53application:didFinishLaunching, triggered it in that NSApplication object, and sent over
04:58to our app delegate.
05:00We can respond if we want to, to deal with anything we need to do on startup,
05:04and there are a lot of methods that are automatically triggered.
05:08When our xib is loaded, then our view objects are all loaded for the first
05:13time and they'll automatically get send the message awakeFromNib, so they can
05:18have their own startup code before we start responding to mouse clicks and key presses.
05:22Now part of our journey is knowing and finding out the different methods that
05:27will automatically occur during the lifecycle of an app, as well as us
05:31creating our own. And even though the overall process is not something that
05:36you need to memorize at all, what is important to know is there's nothing
05:39really hidden behind the scenes.
05:42If you know where to look, all this stuff is actually right there in the
05:45provided project templates.
05:47It's very specifically defined and the order is very explicit in what happens
05:52and what gets called and which elements are connected to which other
05:55elements, and the structure is provided for you as part of the basic Cocoa Application template.
06:01It's not a blank slate, it's a working application you build on top of.
Collapse this transcript
Diagnosing connection issues
00:00Once you get past things like simple typos, missing semicolons, and
00:05case-sensitivity problems in Objective-C. The single-most common stumbling block
00:09for new developers in Cocoa is making a mistake with the connections, dragging
00:13from the wrong object in your user interface to the wrong part of your code.
00:18And the symptom of these problems is annoying because it's often nothing.
00:24Incorrect connections rarely cause a bug or a message, instead nothing happens
00:29when you expect something should happen.
00:31You click a button, and you expect it to call a method to change a label, and it doesn't.
00:36Well, here perhaps the button isn't hooked up to the method.
00:40Perhaps the Text field isn't hooked up to the code, perhaps the method isn't
00:43doing what it should, or perhaps they are both fine, but the label isn't hooked up.
00:48So if we have no actual error from Xcode
00:52we first go looking at our connections. And typically you drive this from the XIB file.
00:57So I'm going to quit out of this application and jump into this MainMenu.xib.
01:03Now there is no one master view of all the existing connections in your user
01:09interface, you go object-by-object, element-by-element, looking at the
01:14connections for each object.
01:17So know that you can view these connections in several different ways.
01:19You can right-click on each element--or Ctrl and single-click does the same thing.
01:24So if I right-click on this button, for example, I get this pop-up appearing,
01:29and I should see Push button at the top in case you accidentally right-click on
01:34the wrong thing, you might want to just try it again.
01:36Now this details all the possible ways that this object could be connected elsewhere.
01:42I can actually drag this open to see everything here.
01:45Now there are a lot of rows of data here, but as all of these connections need
01:50two pieces I can immediately tell there is actually only one real connection
01:54here in all the possible connections.
01:57Now with the button this is actually what I'd expect to see, one entry under the
02:02Sent Actions section. This button is causing something to happen.
02:06It's causing an action and sending that elsewhere.
02:10And every Sent Action needs two pieces of information,
02:13the target and the action.
02:15The target is the class this button should point to, and right now it's pointing
02:21to the App Delegate class, although it could be any class.
02:24And if you notice, as I mouse over the App Delegate part of the pop-up, I
02:28actually see it highlighting over in the Dock as well, and that's the target.
02:33The action is on the other hand of the method that we want to call.
02:37This is the idea of target action in Cocoa.
02:41What class are we pointing to and what method do we call in that class.
02:46You will also hear the term Selector used to refer to the method.
02:50We are selecting the method that we wanted to execute.
02:52Now if I realized by looking at this that this was pointing to either the wrong
02:57class or the wrong method in that class, I could click this little x to
03:02disconnect this button from that class.
03:05Now instead of right-clicking, another way to see this information is using the
03:10Connections Inspector which is part of the Utility section on the right.
03:14So I'm going to turn on the Utilities Panel and find the Connections
03:17Inspector, which--up here at the top--is the one that looks like a circle with an arrow in it.
03:23I'll just drag down the Library section so we can see this a bit more.
03:27Again, this is completely context-sensitive. So with the Connections Inspector
03:31highlighted, I click the Text field, I see the connections with the Text field.
03:35I click the button I see the connections for the button.
03:37Again, it's always element-by-element.
03:40And I'm seeing exactly the same information here that there is really only one
03:44connection here, it's in the Sent Actions section, going to App Delegate class,
03:48calling the changeLabel method.
03:50If on the other hand, I'm more interested in Outlets, and a good example would be
03:54this text field here.
03:55I select that, the text field itself does also have Sent Actions, but I might
04:00not be interested in that, I'm interested in it as an outlet, so I see this
04:04Referencing Outlets area where we can see what it's connected to, which in this
04:08case is the App Delegate class and the textField property.
04:13Just jumping over into my App Delegate header file that looks
04:17about right. We have got a textField defined as an IBOutlet.
04:20We have got that changeLabel method.
04:23Jumping back into the XIB file, if I felt like it I can go the other way as well.
04:28So I could come down into the Dock, find the App Delegate class, which is where
04:33I have my properties and methods currently that I want to connect to, and if I
04:38right-click that, or Ctrl-click it, I see another view, the other way around.
04:42The Outlets and the Received Actions, that App Delegate is receiving from Push
04:48button an action to call the changeLabel method.
04:51Again, if you see as I mouse over Push button it's even highlighting the right
04:55part of the interface.
04:57Now couple of these connections that I can see by right-clicking App Delegate,
05:01like the window and the delegate part were created when the project was made, so
05:07I don't want to delete them just because I didn't make them.
05:10Now here's another way of looking at it.
05:12In the actual Code view I'm going to switch to the App Delegate view here.
05:17Here's the thing to look out for.
05:19We already know that using the IBOutlet and IBAction keywords can announce that
05:24this property or this method can be connected to the user interface.
05:28Well, over on the left-hand side in this bar here, a filled circle means this
05:34can, and is, connected to part of the user interface, but an empty circle means it
05:41can be connected because it's an IBOutlet here, but it isn't.
05:45So I can actually see here that the myLabel property is not hooked up to the
05:50label in the user interface, even though it could be, it isn't.
05:55Switching back into the interface, if I had right-clicked the label itself, I
06:00could see that from the pop-up or from the Connections Inspector there are
06:04no connections at all, no Outlets, no Actions, no nothing.
06:09Now when I'm connecting Outlets I do prefer to go--rather from the user interface
06:14element--I prefer to go from the code perspective. So in this case, App
06:17Delegate, what I could do here is right-click, and it's telling me that it has a
06:21potential outlet called myLabel that is not hooked up to something in the same
06:26way that textField is hooked up to the Text Field here.
06:29So how can I do this? Well, I just grab this circle.
06:32I mouse over the circle from myLabel, click--I don't have to hit Ctrl here--I
06:37just click-and-drag, and as I mouse over the different elements it highlights
06:40them to let me know what I can let go on, and I wanted to let go on this label
06:44of static text, which is blanked out right now.
06:47I let go, and now I see the connection being displayed both in the pop-up, and I
06:52see it over here in the actual Connections Inspector as well.
06:55It's giving me the same information in both parts.
06:58If I jumped over to the header file, I should see that circle is now filled in,
07:02so multiple ways to see that, multiple ways to get to that information.
07:07And if I go ahead and run it, we should now have that working.
07:11Now one last word of warning, which is a very common issue here, I'm going to
07:16jump into the Interface view and switch into the Assistant Editor, which is that
07:21very useful way of quickly hooking up your interface to your code.
07:26Typically speaking when you have this you want to see the XIB on the left and
07:31the header file on the right-hand side, you may have to manually change.
07:35If you're using the Jump Bar to make sure that you're seeing that.
07:38It's a great ability to be able to use this to quickly create properties and
07:42methods, but it's easy to make a mistake.
07:46So let's say, for example, that I have dragged on a new button onto this
07:50interface, and I want to cause something to happen in my code.
07:58So I Ctrl-click quickly, come down here, let go, and say I want to call a method
08:04called doSomething, I quickly typed that and hit Connect.
08:08Here's the problem. I did that too quickly.
08:11What I have got now here is not an IBAction but an IBOutlet, a button could be
08:16either an Action or Outlet, and I didn't look at that pop-up closely enough.
08:22Now you might think, well no big deal.
08:24Surely just I go through, and I'd delete the code that was added there, I just
08:28delete that out, it's gone. We now look like we did a few seconds ago.
08:31Here's the problem.
08:33If I save and just hit Command+B to build this project, we're going to
08:37immediately get a failure.
08:39Because me Ctrl-clicking and dragging into the AppDelegate.h didn't just add
08:43code there, but it also added the synthesize statement in the AppDelegate
08:48implementation file as well, and also added the connection in the XIB.
08:54So if I did this, and I have to make sure it was gone from the h, and I have to
08:59make sure that this line was gone from the .m. I'd then want to switch back into
09:03the XIB file, right-click that button and make sure to delete that entry, the
09:10connection that it's trying to do to a nonexistent action.
09:14So be careful when you're doing this.
09:16In fact, sometimes if you're just creating an interface, it's actually better
09:20just to delete that button and drag it on and start all over again.
09:26And that's really the key issue here.
09:28If you are using that Ctrl-drag method, when you do that always pause for a
09:34second, look at this pop-up window, make sure is it an outlet that I want or is
09:38it an action that I want.
09:40Not only that, but when you're working with Outlets make sure that the Type is
09:45correct, that it's what you're expecting to see, an NSButton or a Text field.
09:50It's very easy, for example, to accidentally drag from the Window or to
09:55actually drag from some of what are called the Layout Constraints that are
09:59helping us set out our interface.
10:01We'll get into that one a little bit more later. But just pause for a second on that pop-up.
10:05Is it the right kind of Outlet or Action? What's it called and is it the right kind of object?
Collapse this transcript
Creating custom controller classes
00:00We haven't written a lot of code yet, but what we have written, we have put all
00:04in the existing AppDelegate class just because that class was there already.
00:08I have a very simple, straightforward interface here with one-button.
00:12If I right-click the button, or use the Connections Inspector, I can see that
00:17the target of this button click is App Delegate, and the action it will perform
00:21is simpleMethod. And just jumping over into that in the AppDelegate implementation file,
00:27all that's going to do is, in NSLog message to the console, to the debug area.
00:32So if I run it, I would expect that when I click the button, I will just have
00:37the debug area appear, and we'll get that message popping up.
00:40All right, but what I prefer is to have the AppDelegate act just as the
00:44application delegate, and I want to have a dedicated controller class where I
00:49write my code that reacts and behaves and interacts with the interface, and it
00:54is very simple to do this.
00:56So I will just stop the running program and jump back over here into my project.
01:00And here is the thing, to create a CustomController class it doesn't have to be
01:05anything special, any particular kind of subclass. Just a regular plain
01:09Objective-C class will work.
01:11So in Xcode, I am going to go the New > File section, select Cocoa and
01:16Objective-C class, it actually wouldn't really matter if you are under Cocoa
01:20Touch, the basic Objective-C class is the same for both.
01:23Selecting that, I click Next, I will call this Class MyController.
01:28I could call it anything, the name is not important. The dropdown box beneath
01:32gives us many different classes we could inherit from, but I'm just going to
01:36select NSObject right at the top, the most basic Objectives-C class there is, and
01:41then choose to save that in my project.
01:44So the class exists, there is nothing in it, nothing in the header, nothing
01:48in the Implementation file, and the XIB, the interface does not know about
01:52this class, there is no link between this and the MyController class, so let's make one.
01:57Here is the easiest and best way to do it.
01:59I am going to open up the Utilities panel and go to my Object Library, now I
02:04could scroll down and find the thing that I want here, but it's easier just to
02:08filter on the objects and controllers section of that Object Library.
02:13Usually, what we use the Object Library for is for dragging and dropping things
02:17like buttons and text fields and sliders, but we can also use it to represent
02:22non-visual elements, in this case an Object.
02:25So I am going to grab this Object, blue box, but instead of dragging onto the
02:29interface, I am going to drag it over here into the Dock just right at the
02:33bottom here, and I can do this whether the Dock is expanded or collapsed.
02:37Usually, we drag on these visual UI elements, that means that any user interface
02:42element, any object we drag into this XIB will be instantiated when this program
02:47loads, but we can do this with any object, including a class we just wrote
02:51ourselves, that means I won't have to write a manual alloc and init to
02:55instantiate that MyController object. It will happen here, however, I need to do one more thing.
03:01Dragging on the blue object is the easy part, and the next thing is easy too.
03:06But this is the important part, with Object selected, I want to go to the third
03:11inspector in my Inspector section, which is the identity inspector.
03:16Because just by dragging this on from the Object Library, it thinks it's an NSObject.
03:20Well I don't need it to be an NSObject, I need it to be a new instance of the
03:25MyController object that I had, I should be able to type in--there we go--M, and
03:30find it, and just hit Return to set that.
03:33Now if I mouse over it, this is what I'd expect to see, MyController, and now
03:38when the main menus xip is loaded, it will create an instance of this
03:41MyController class just as it creates an instance of all the visual elements
03:45that have been dragged on.
03:46I don't need to write code to instantiate it, it'll just happen.
03:49Now I can use this to write code that interacts with this user interface, so I
03:53am going to drag on another button onto this interface here, onto the Window.
03:59Just give it a basic name change, and then give myself a bit more screen real
04:05estate so that I can open up the Assistant Editor.
04:09Now bear in mind now that the counterpart of this XIB file could be multiple
04:15code files, so you will probably need to use the Jump bar to change to a
04:19different one, in my case I want to jump to the MyController.h, the header file
04:23here, and now I should be able to hit the Ctrl key and drag into this new class.
04:30It's going to pop up. Do you want to make an Outlet or an Action?
04:34I want to do an Action here for sure. What do I want this to be called?
04:38Well, I will also call this simpleMethod, I could actually use the same name
04:42that was in the other class, it doesn't matter, they are completely
04:45independent of each other.
04:46Click Connect, and we get the simpleMethod declaration in the header file, but
04:50if I also a jump over into the implementation file, I'll see the method stub
04:54over there, and I will just put an NSLog message in that one too.
05:03So just to verify this, right clicking that new button will say that we are
05:08going to the target of MyController, calling the simpleMethod as an Action.
05:13And in this one, we are doing AppDelegate as a target and doing simpleMethod
05:18there as an Action. Go ahead and run this, Build Succeeded.
05:23I can call the first one, to Call a method in AppDelegate class, and I can call
05:28the second one to run code in the new MyController class.
05:31So very easy to start to break this out, it would be very simple for me now to
05:35copy any of the methods that I might have put in AppDelegate and move them
05:39across to the new class, if I wanted to keep them separate from each other.
05:43And if it made sense, I could even add more controller classes
Collapse this transcript
Creating alert panels and alert sheets
00:00One of the first questions I'm often asked is how do I get Cocoa to pop up what
00:05might be called a message box, or an alert box, in other languages?
00:08I am going to make a new Cocoa Application--because it is an alert that we are
00:13dealing with--this can either be done as what's called an Alert Panel, or an
00:16Alert Sheet, and I will show you both.
00:18I will just Save that to my Desktop. And all I'm going to do is create a very
00:23straightforward application with a couple of buttons on it.
00:26I am doing this from scratch again just so we're getting into that habit of
00:31dragging on buttons and connecting them to our code.
00:37First one will cause an Alert Panel, and then we'll do another one, which will
00:41cause an Alert Sheet--and I don't really need so big a user interface here, so I
00:48will just shrink this one down.
00:49Of course, these buttons right now aren't doing anything, and I want them to, so
00:54I'm going to switch into the Assistant view, and hopefully we are seeing
00:59AppDelegate.h, if not, we can just select it from the Jump bar. And first I'm
01:04going to grab on the Alert Panel button and make it cause an Action.
01:08So when the pop-up appears, I want to make sure it's causing an Action here.
01:12I will say this one is createAlertPanel.
01:18And I will set up the second one here to call another IBAction, in this case
01:22createAlertSheet--it nearly created an Outlet there.
01:27So an IBAction createAlertSheet.
01:33Now I am going to switch back into the Standard Editor, so I can see a bit
01:37more here, and I can either use the navigator or the Jump bar here just to
01:41switch to that code.
01:42I'm interested in being in the Implementation file here, the .m file for AppDelegate.
01:47So in the createAlertPanel method I'm going to write that C function.
01:52The function is called NSRunAlertPanel, and as I type, I can see it appear in
01:58code sense, I am going to hit Tab. This takes several different arguments, which
02:03can all be put as NSStrings, the Title, the Message, the Name of the
02:08defaultButton, the alternateButton, an otherButton, and then a possible list of
02:13arguments, and we will see what that's for in a moment.
02:16So I am just going to give it a bunch of NSStrings.
02:19First one for Title, then hit Tab. Then the string for the defaultButton.
02:27I will just say, OK.
02:30The alternateButton, I will just call it Alternate, so it's obvious which one
02:34that is when we see it, and then the otherButton, and that will do the trick.
02:39Now we are going to have to add a little bit more to this, but let's just see it work.
02:44I will go ahead and click Run, I am going to click the Alert Panel button, and
02:50we get the Basic alert message.
02:52Title, Message, and the three buttons that we listed.
02:55Now this function is completely modal and is blocking the application, so it
03:00will not let me start to click anything on the application behind it, until I
03:04deal with this modal window, but they are done as completely separate windows.
03:10I will just click OK.
03:12Now this function actually returns a value of type NSInteger, so if I wanted to
03:19find out what that was, I would just create, say, NSInteger result, and get that
03:23back as the result of that. And let's just write it out in an NSLog message.
03:33This is an NSInteger, which is a long integer, so I'll put the li, as the format specifier.
03:37And now when I run it, I should see the message pop up.
03:43If I click OK, we are going to see the result is 1.
03:48It actually returns an NSInteger that can be treated as an enumeration, but
03:52it's really just returning 1, 0, or -1, for the defaultButton, the alternateButton,
03:58or the otherButton.
03:59Now if you don't want to show all of the buttons, for example, you just want
04:03the default one and the other one. You can just use the word nil in place of
04:08that NSString argument, and running this again, the Alert Panel just has the two buttons on it.
04:14Now the second parameter that we are seeing here, the Basic alert message can
04:20take a format string with format specifiers. So we can enter in, for example, %
04:25sign, @ sign to represent a couple of objects at say two different places, it
04:30can be 1, can be 2, it can be a dozen if you want.
04:33Then what you need to do is actually follow the very last button argument with
04:38your list of, in this case, objects.
04:41I will just give it two separate NSString objects.
04:46We Save that, and run it again, and we should see those placed into that message.
04:51There we go, Basic First alert Second message.
04:55That's about as complex as the NSRunAlertPanel gets.
04:59We can also do this alert as an Alert sheet, rather than an Alert panel.
05:04The difference being that a sheet is an attached to an existing window. And that's,
05:09strictly speaking, one of the ways that's more officially approved by Apple.
05:13Creating a sheet is more powerful, but it's a little bit more involved.
05:18So I am going to do that in the second method here in createAlertSheet.
05:23This I am going to do by creating a Objective-C object called an NSAlert.
05:29I'll call this myAlert.
05:30We don't do this typically with the usual alloc and init, we actually create an
05:36NSAlert the way we might create an NSDate by calling a static or shared
05:42function on the object.
05:43What does that mean? Well, really this is the way we do it.
05:47NSAlert, alertWith--and we get two options-- this is probably the classic one here.
05:52Create an alert with a certain MessageText, defaultButton,
05:57alternateButton, otherButton informativeText.
06:00It's very similar in essence to the NSRunAlertPanel, we are loading it up with
06:06the different things that an Alert panel needs to show.
06:10So I will just use my Tab button and quickly go through and add some content
06:14here, defaultButton is OK, alternateButton I will once again call Alternate, to
06:23make it obvious what it is.
06:27And the last one here can also be a format string with format specifiers, the
06:32same way that the second argument could be in NSRunAlertPanel.
06:36This seems a bit more natural to put it at the end if you're going to follow it
06:39with optional arguments.
06:45To make it easy, right now, I'm not going to bother giving it any alternate arguments.
06:49I am just going to use it as a regular string.
06:52So this creates that object, but we are not doing anything with it.
06:56There is a very simple way to do this, which is, we call the myAlert runModal
07:00method, and I will just show you what that does, which is almost identical as
07:06the NSRunAlertPanel, as a very separate Modal Window.
07:13Quitting out of the application, I will go and show you the recommended way to
07:17do that, which is a more complex, more involved, but more powerful method.
07:21Instead of runModal, we are calling beginSheetModalForWindow, and we have to
07:27give it multiple arguments here. First, what window are we attaching this to?
07:31This is going to be a sheet, meaning it's attached to a window.
07:34Well, we are in the AppDelegate, which has a property internally, which is
07:40_window, which is the current window that we are looking at of the application.
07:43Now what I am going to do right now is just pass in nil, as the remaining three
07:48arguments, simply because we haven't really gotten into delegation and selectors
07:52yet, and we will see that a little later on.
07:55Because this beginSheetModalForWindow method does not immediately return a
08:00value, but can call a delegate method when somebody clicks one of the buttons.
08:04So I am going to run this, and we'll see the difference.
08:07Here is the first way, the Alert Panel, the separate window that's modal, and
08:13here's the second way, the Alert Sheet, attached to the main application,
08:18still modal, and that I have to deal with it, but this is the more recommended way by Apple now.
08:25I'll quit and go back to the code, but of course, this begs a few questions.
08:29What are these remaining arguments, like modalDelegate and didEndSelector?
08:34Well we need to talk a little bit about things like delegation, to really get
08:38into the power of these kind of methods.
Collapse this transcript
3. Delegation
Understanding delegation
00:00Like Model-view controller, Delegation is one of the core design patterns,
00:04one of the core ideas in Apple development, and all Cocoa applications use delegation.
00:10We are already doing it with the AppDelegate, but that was provided for us,
00:14that doesn't really count.
00:15We are going to use delegation in other places too.
00:18Its how you accomplish tasks in Cocoa, that in other languages you might do with
00:23inheritance, or event handling. It's important. But what does it mean?
00:28Well, I like to say that a delegate in Cocoa development is like the idea of a
00:32delegate in real life.
00:33If you look up the dictionary definition of a delegate in politics or in
00:37business, it's someone who acts on behalf of somebody else.
00:41And to delegate is a formal way that one person hands-off responsibilities to another person.
00:47Now for us developers, it's a formal way that one object hands-off work to another object.
00:54An object in Cocoa, often a built-in object, including many of the user
00:59interface elements, or even the application object itself, has a lot of it's own internal processing.
01:06But it can also be connected to your objects, your custom classes.
01:11And it can delegate other responsibilities to them.
01:15So instead of, say, subclassing an application object, or subclassing a text field,
01:21you create a new object connected as a delegate, and then you can get that
01:25original object to delegate behavior to send behavior over to your custom class.
01:31We refer to the object who is being handed the work as the delegate, and it's
01:36being handed the work by the delegating object.
01:38So how do we do this? Well, how to be a great delegate in Cocoa is like being a
01:44formal delegate in business or in politics.
01:46There are rules, there are steps, and step one is know the rules. Know what you
01:50have to do, what are the responsibilities in that role.
01:53And this is not casual.
01:55If you want to be an official delegate for a political party, or government, or
01:59royalty, it often means there are formal documents that describe exactly what is
02:04expected of that delegate in that role.
02:07Step two is to say, well I can do that, this is where you are volunteering, you're
02:12putting your hand up.
02:13Now step three is that you need to have a plan to actually do it.
02:17If you are going to volunteer to be a delegate, you better be able to follow through.
02:21And step four, even after deciding, even after planning how you are going to
02:26approach this, you need to get the job of the delegate to make sure you are in that role.
02:31That whoever is handing those responsibilities out is going to give them to you
02:35and not to somebody else.
02:37So if these are the four steps of how to be a delegate in real life.
02:41What is it in Cocoa development? Well, exactly the same thing.
02:45Step one is know the rules, know what you have to do.
02:50There are simple rules here, and in Apple development the rules are called
02:53the Delegate Protocol.
02:55And there are different Delegate Protocols for different objects that
02:59can delegate behavior.
03:00And each Delegate Protocol can be found in the Xcode documentation, it's simply
03:06a short list of method names, no behavior just method names.
03:12Basically saying, if you want to write a custom class and be a delegate for
03:16me, these are the behaviors you should support, and we will see a few examples of these.
03:21Step two is to say, I can do that. You are volunteering, and you are marking
03:26yourself as a volunteering.
03:28You are being a delegate, not in general, you are being a delegate for something specific.
03:34And what you do in your code is after the class definition you use the angle
03:39brackets, to say in this case, I can be a delegate for the NSApplication object.
03:45So in this case, this declaration says we are creating a class called AppDelegate.
03:48It inherits from NSObject, and it can act as a delegate for NSApplication.
03:55And when creating an object you can mark it as being a delegate for more than one thing.
03:59Now step three is, have a plan.
04:02That means you need to look at the Delegate Protocol rules and implement
04:06the necessary methods.
04:08Create methods in your class that match the method names in the Delegate Protocol.
04:14And what you write in your code must exactly match.
04:17And step four then get the job.
04:20Marking your class as being a delegate isn't enough.
04:23Implementing those methods isn't enough because what ever object is handing
04:29those responsibilities out, they are delegating object that's handing them off,
04:32needs to give them to give your class and not to some other class.
04:36So you're telling the object that's delegating who it should delegate to.
04:40Now this can sometimes be done in the Xcode visually, it can actually connect a
04:45delegate of one object to a custom class, but it's also often done in code.
04:51There is often a delegate property of one object that can be set to another object.
04:56Now if it your first time coming across these concepts, you will probably still
05:00sounds a little confusing.
05:01But like being a delegate in business, or in government, in all likelihood, you
05:07would begin by having someone show you around and walk you through a couple of examples.
05:13And we're going to go through that course, and that's someone's going to be me,
05:16and I will walk you through a couple of delegation examples.
Collapse this transcript
Using the application delegate
00:00We are always using Delegation. Even if I create a new Cocoa application right
00:05out of the box in Xcode, we are using it already.
00:09And not surprisingly, the most obvious example of delegation that's already
00:14there is the AppDelegate class.
00:16Now the actual name of this class is not important at all.
00:20This is a regular Objective-C class.
00:23If we look at the header file for it, we are just inheriting from NSObject.
00:26But it has two things that are special about it.
00:30After NSObject we use the angle brackets to say, well I might be a regular
00:35object but can also be a delegate for NSApplication.
00:39That means, an NSApplication object can pass behavior to this object, if it knows it exists.
00:45And this is one of the biggest differences between Cocoa, and Desktop
00:48Development on other platforms.
00:51In Cocoa, we don't subclass an existing application class and extend it.
00:55We just let the regular built-in NSApplication object, do what it does naturally,
01:00but we create a completely separate class to provide any extra behavior, and
01:05that's the idea of a delegate.
01:07Okay, so what does this mean and what can we do if we say we're in NSApplicationDelegate?
01:15Well, to find out, we read the rules.
01:16So with this selected if I have my Quick Help inspector here, I'll get a bit
01:21of information about it that NSApplicationDelegate points to the
01:24NSApplicationDelegate Protocol Reference.
01:27This is the list of rules that we are supposed to support.
01:30So I am going to find out what the possibilities are if we volunteer this class
01:34as being a delegate for an NSApplication object.
01:37Now Protocol Reference is just a list of method signatures, the names, the
01:42return type, the parameters. No behavior, no implementation, just a list of methods.
01:48So as I come down here we see, I have got a bunch of Tasks,
01:52Launching Applications, applicationWillFinishLaunching, applicationDidFinishLaunching,
01:57applicationShouldTerminate or WillTerminate.
02:00Various ones for hiding the application that it will hide or it did hide.
02:05Managing the Dock Menu.
02:07And if we are a delegate for NSApplication, we can choose to respond to any of these.
02:13We don't have to answer to all of them.
02:15We make our own mind up about which ones are important.
02:19Now it is important to understand that this is not like inheritance.
02:21We are not overwriting some default behavior in NSApplication.
02:26If we don't implement certain of these methods in our AppDelegate, it doesn't
02:31matter they are just ignored.
02:32Now what I can do when I'm looking at this set of rules is I can find out a
02:37little bit more information about each of these.
02:39Say, for example, I am curious about applicationWillBecomeActive I will click that link.
02:44And it just tells me a little more sent by the default notification center
02:48immediately before the application becomes active, little bit cryptic but we'll
02:53see what this means. Here's how we would support it.
02:55I will look at this information, and it tells me the signature that this needs
03:00to be a method that's void, called applicationWillBecomeActive, and it takes one
03:04parameter of type NSNotification.
03:07I am just going to highlight that line, copy it, jump back into Xcode, and in the
03:13implementation of my AppDelegate, I am going to paste it in there.
03:16And this is a method so it obviously needs the opening and closing curly braces.
03:22And all I'm going to do in here is put in a simple NSlog message.
03:27And then hit Command+R to run the application.
03:30What I can see happening in the console is that message popped up, Application
03:34will become active, doesn't seem very impressive.
03:38But here's the difference.
03:39If I switch back at Xcode, then hit my Command and Tab and switch back again,
03:44what we're seeing is by switching back and forth between the applications, that
03:49method is automatically being called every time we make this application active
03:53when it's gets the focus.
03:55Now that may or may not be something that you're interested in, quitting out of
03:59this and back into Xcode. But that's the point of delegation.
04:03We get to choose what parts of it we are interested in.
04:07When we act as a delegate, and I'm jumping back here into the Delegate Protocol,
04:12we choose the methods we want to respond to.
04:14Now sometimes certain delegate methods will be marked as required, and if
04:18you say you're going to be a delegate for a particular class, you are
04:22supposed to put them in. But otherwise, they're optional.
04:24You use the ones you need you ignore the rest.
04:27Now one thing you might be curious all is well, I'm being a delegate I can put
04:32in this method, and it will automatically work.
04:34It will get called automatically by the system at the right time.
04:38But don't I have to put something in the header file?
04:40No we don't, that's taken care of by the fact that we formerly say we're an NSApplication delegate.
04:46That means we don't have to declare the signatures of these methods in our
04:50header file, we simply put the ones we are interested in into our implementation file.
04:55And when you create a Cocoa application in Xcode, the one bit of code you do get
05:00inside the AppDelegate is the applicationDidFinishLaunching.
05:04This is another delegate method of the NSApplication class.
05:09It's probably the most common one which is why it's there in the skeleton code
05:13that's provided, but you can use any of them. But of course, this AppDelegate example is easy.
05:20It's already here, it's already hooked up.
05:22And it's a good example to get started with, but it is a very substantial object.
05:28All these methods are very large scale, the application beginning and ending,
05:32switching focus, switching back.
05:34But delegation doesn't have to be quite so impactful.
05:38Sometimes it's used for just a small piece of optional behavior, as we'll see
05:42when using delegation with some user interface elements.
Collapse this transcript
Delegation for UI elements
00:00When you get comfortable with the basic concept of delegation you'll find
00:04yourself able to join in everywhere.
00:07For example, several of the regular user interface elements in Cocoa can
00:11delegate some behavior if we find it useful we can support that.
00:15I will just create a brand-new Cocoa application, save it, and jump into the XIB file.
00:21And select the Window just so we have something we can drop controls onto.
00:26So there is a question. How would you know if a user interface element has some
00:31behavior it's able to delegate? Well, here is one simple way.
00:35You grab one of these UI elements out of the library, and you drop it onto your interface.
00:40I am going to drag on a button.
00:42I'll come down a little bit and find say a text field and drag that on.
00:47Coming down a bit further, I will drag on a combo box, and a Date Picker.
00:54Just four fairly typical user interface elements.
00:56Now here's what I want to do as a clue to find out if they can delegate
01:01any behavior or not.
01:02I am going to go into my Inspector section and open up the Connections Inspector,
01:07which is the sixth one in the list here.
01:10All I'm doing here is scanning the section that says outlets.
01:13I have currently got the Date Picker selected, and I don't see anything that
01:18says the word delegate.
01:19If I highlight the combo box I am going to see that I do have an entry for delegate.
01:25If I select the button I don't have an entry for delegate.
01:28If I select the text field I do have an entry for delegate.
01:32What you will find is that if there is a delegate outlet for a user interface
01:36control then that control can delegate some kind of behavior.
01:40Now we don't know what.
01:41We need to look at the details of this specific class for that.
01:45Just because a user interface control can delegate some behavior it does not
01:50mean we have to respond to that.
01:52But if we want to, we want to find out how to, here is one way to go about it.
01:56Again, we said there was multiple steps for being a delegate and step one
02:01is know the rules.
02:02So I am going to work with this combo box here, and I'll just delete the others
02:07to give us some clarity about what we are actually doing.
02:11Combo box is a very simple control in Cocoa, if I by jump into my Attributes
02:16Inspector I can find that this combo box allows me to just add a few different items.
02:20I am going to click the Plus button three times and then double-click.
02:25We will see later how to start adding a bit more dynamic data into one of these.
02:30I just need something simple right now.
02:32So we saw that in this Connections Inspector the combo box has a delegate outlet.
02:37It can delegate something, but I don't know what.
02:39Well, how do we find this out?
02:41I am going to jump into the Quick Help Inspector here, and if that sometimes
02:46happens Quick Help doesn't actually show you the information you'd expect to see
02:51I can always type in NSComboBox in the Help menu and actually search that.
02:56I can jump first to the NSComboBox class reference, but if I look at the
03:01search results here, I can immediately jump to the fact that I have got the
03:05NSComboBox delegate protocol reference. What are the rules to be a delegate
03:09for the NSComboBox? Again, it's just a list of methods.
03:13In fact, we see there really are only four of them, comboBoxSelectionDidChange,
03:19comboBoxSelectionIsChanging, comboBoxWillDismiss, and comboBoxWillPopUp.
03:25None of them are marked as required.
03:28It's our choice of which ones we want to respond to.
03:32Technically speaking, we don't have to respond to any of them, but if we are
03:36going to be a delegate we want to pick something.
03:38So I am going to click on comboBoxSelectionDidChange.
03:42This just takes us to the method signature, returns void, takes one parameter of type NSNotification.
03:49So I'll copy that entire line. Question is where am I going to respond to this?
03:56Even if I know the rules I need something to volunteer.
03:59I need a class to say, yes, I am going to be the delegate for that combo box.
04:03I could create a brand-new class to do it or, seeing as time of the essence, I am
04:08just going to use AppDelegate.
04:09AppDelegate is already volunteering to be a delegate for the NSApplication.
04:14It is the AppDelegate, but inside these angle brackets what I can do is mark
04:20this as also being an NSComboBoxDelegate.
04:27This is the official way we are volunteering this class and saying, we are
04:30capable of being a delegate for an NSComboBox.
04:32It will often work without this, but I think it's always a good idea to do it.
04:38This same class is now a delegate for both the NSApplication and a delegate
04:42for NSComboBox object. Well step three was, have a plan.
04:47So in the implementation of this class what I'm going to do is paste in that
04:52method signature that I just copied for comboBoxSelectionDidChange.
04:57Once again, just put in a simple message that proves, yes, we actually called this.
05:04Now we could right now go ahead and run this, but this code would never get called.
05:09We wouldn't have an error. We wouldn't have a problem with it.
05:12It's all perfectly valid, but whenever I select one of the options from the
05:17combo box I don't get any kind of message that I'm looking for.
05:21I am getting a warning at the moment that the Content rectangle not entirely on screen.
05:26This occasionally happens if you accidentally nudge something around.
05:30What I'm going to do is go back into the XIB file, and I want to go to the Size
05:35Inspector, which is the fifth one, and just make sure that this is positioned on
05:39screen there by dragging it down.
05:41Hit Command+B to compile again, and now I have no issues.
05:46The reason that it's not working yet is I have really done three of the
05:50four necessary steps.
05:52I read the rules--the Delegate Protocol Reference--I volunteered my AppDelegate
05:59class and said, it's capable of being a delegate for the combo box, I have my
06:04plan in place, which is the code I wanted to run--if the combo box selection did
06:08change--but what I haven't done is actually tell that combo box where to look
06:14for that delegate behavior.
06:15That's what I'm going to use the Connections Inspector for.
06:18I could also do this by right-clicking.
06:21I'm going to say that the combo box is delegate, and I will click on the circle
06:25beside that delegate outlet and drag it over to AppDelegate that represents an
06:30instance of our App Delegate class. Let go. It will not pop anything up.
06:36It doesn't ask me what method I am going to call because all I'm doing here is
06:40saying the AppDelegate is now also a delegate for the combo box.
06:44This could be done in code, but if were working with everything having a visual
06:49entry in our XIB file we might as well do it this way.
06:52So save that and run it.
06:53Not the most exciting user interface in the world, but now every time I select
06:59a new entry, I get the message popping up down here in the console that the
07:04combo box is changing.
07:05Now the question might be. What about actually getting hold of the value of the
07:10combo box when we are in that method? Well, there are two ways of doing this.
07:14One is that I would set the combo box up as an IBOutlet.
07:18I didn't do that, but I could do that to give it a name and then refer to it in my code.
07:23The same way we have set up labels and text fields in earlier examples.
07:28Now another way, is that when I get this delegate method called I am being
07:33passed a parameter here, an NSNotification, and this is true with a lot of delegate methods.
07:40We will talk more about notifications later, but in essence anytime I get passed
07:46on, what I am getting is a container the generic box that holds three things, a
07:51name, an object, and optional parameters.
07:54The name is, what just happened, and the object is, what caused that to happen.
07:59So I will actually get passed a reference to the combo box that caused this
08:03delegate method to happen.
08:04I am actually just going to add a couple of things to this message here.
08:10Adding in two formats specifies for objects saying the notification was, and what I
08:15am going to ask for there is the notification parameter, that we just got passed,
08:20and its property called, name, than a Comma, and then notification.object.
08:28Save that and run it.
08:30Every time I change this now what we're going to get is the message saying the
08:34combo box changed, the notification was, and we actually get the official name
08:39of this notification, the NSComboBoxSelectionDidChange notification and the
08:44object was when it's being passed there is a reference to the NSComboBox.
08:48So I can certainly get to that if I wanted to just in this method.
08:53But bear in mind, this example is not inherently meant to be about the combo box.
08:58It's about the process of being able to look up whether a user interface element
09:03can cause some delegation of behavior, what that behavior would be, how you
09:08would support it, and how you would connect them together.
09:11Do you remember that just because a UI object can delegate this behavior doesn't
09:15mean you have to support it? In many cases you won't need to.
09:19There is more potential delegation going on in a Cocoa application than you
09:23would possibly want to deal with.
09:25You decide where you want to join in and what you want to react to by slowly
09:29becoming familiar with what objects can delegate what behavior.
Collapse this transcript
Delegation for simple objects
00:00Here is one more use of delegation.
00:03Sometimes we create a quick and almost informal object that can use delegation
00:07and just use it on an as needed basis.
00:10Now, I'm going to do this example completely in code, there will be nothing to
00:13drag and drop, really nothing in interface builder at all.
00:16I am just showing I have a very basic example, one button application that does
00:21something we saw a little earlier.
00:23This is calling a method in my AppDelegate that is going to create an NSAlert object.
00:28I am just going to widen this so we have a bit more screen real estate here.
00:33So in Line 12 we create a new NSAlert object, loading it up with some
00:37basic text, Alert Message, OK, an Alternate button, and another button, and
00:41some informative text.
00:43And then on Line 19 we call its method beginSheetModalForWindow: modalDelegate: didEndSelector:
00:53contextInfo, a rather long-winded name. But what it means is it's going to pop
00:59up this as a sheet, it's going to be attached to the underlying window.
01:03I am just going to comment out Line 24, which is changing the background
01:06color of the window itself, and go ahead and run this just to remind us of
01:10what it looked like.
01:12We create an alert sheet which attaches that alert to the window itself.
01:17Nothing particularly remarkable.
01:20Now, earlier we saw a way of creating an alert panel, a separate panel by
01:24calling a C function that returned an integer value.
01:29But here's the problem, this beginSheetModalForWindow method doesn't return
01:35a value, it is void, it doesn't return anything. Not only that, it doesn't actually block.
01:40Meaning, we immediately continue and do code that's after it.
01:44So if I wanted to try and say, well, give me a return code and deal with it, I
01:49don't have a return code yet.
01:50To prove this, I am going to uncomment that line that changes the background
01:54color and run this again. And we will see that immediately after this alert
01:57sheet is popped up, we continue on and do whatever code was after that.
02:01So what's actually happening is that modalSheet is being popped up
02:05asynchronously on a different thread.
02:07So the question is how do I find out what button got pressed?
02:11Well, to actually receive any value back from that, we need to use a
02:15little delegation, because if we look here, this method takes an argument called modalDelegate.
02:22What this means is this method wants to know where to delegate some behavior
02:26after this modalWindow is dismissed.
02:28It wants an object to delegate to, and it wants a method, which is the next one,
02:34the didEndSelector argument.
02:36A selector is Cocoa's way of letting us pass a method name as a parameter.
02:41And the didEndSelector entry here is asking what selector, what method should
02:47this Delegate object call when this window ends?
02:50Now, you might think, well, am I supposed to figure this all out for myself?
02:54Well no, not really. What we can do is do an either Option-click, or use the
02:59Quick Help, to find some information about this method.
03:02This method is contained in part of the NSAlert, so we could look at the NSAlert
03:07Class Reference to get a little bit more information about it.
03:10And what it's telling us is this rather long-winded method,
03:15beginSheetModalForWindow, will pop up this alert sheet, but it can call something
03:20back, it's got an alertDidEndSelector argument.
03:24Like a lot of delegation, one of the big deals here is we really want to copy
03:28this argument signature.
03:30What I am going to do is copy this. I need to paste it into a piece of code.
03:36Again, for our purposes, just to be kind of quick about this, I am going to
03:40use the same class, the AppDelegate, and I will paste this beneath the
03:43createAlertSheet method, but before the @end, doesn't really matter where you put it.
03:50What is this?
03:51Well, this method we are going to want to call after somebody clicks a button in
03:56that modalWindow, whether that's two seconds later or two days later.
04:01We are getting the signature of this method from the NSAlert object itself.
04:06And we will repass a NSInteger called returnCode.
04:13I am going to construct an NSLog message here with a format specifier,
04:17returnCode is NSInteger, so I'll use %li.
04:19Now just having this method is not going to do anything for us right now, I
04:26could run this again, and it would make no difference whatsoever, because we're
04:30not actually telling the modalWindow to call this back.
04:34What we need to do is stop some of these arguments from being nil.
04:38We need to say, when this modalSheet is dismissed, we want to call this
04:42particular delegate calling this particular selector.
04:44Well, how do we do it? Watch the delegate.
04:47Well, what I want to do is have a delegate that's the current object, the actual
04:52AppDelegate that I am looking at right now, this code.
04:54And the way we are going to do this might be the word, this, in other languages,
04:59in Objective-C it's, self.
05:01We have created this new alert object, we are popping it up, and we are saying,
05:06hey, your delegate is me, you are going to call me back.
05:09And in the next argument I say, what part of me, what part of the AppDelegate
05:13are you going to call, which is the selector.
05:16This is the way that we write a selector in Objective-C so we can pass the name
05:21of a method as a parameter.
05:24So it's the @selector keyword, and then in brackets, the actual method name with
05:29no parameters just the colons for each individual part.
05:32In our case it's the alertDidEnd, as I start typing it, it should pop-up, that
05:37will work, alertDidEnd:returnCode:contextInfo.
05:43Now, contextInfo is just here being basically an open-ended object.
05:46It means we can call this method, we can pass in an object of contextInfo, and
05:51when we get call back, we will get that same object passed back.
05:56I am not going to use it right now so I am going to leave that argument as nil.
06:00So we will pop up that modalSheet saying that your delegate itself, the
06:04AppDelegate class, that the selector you call is the alertDidEnd method, and
06:08let's see what happens. We run it.
06:12I should of course expect that it will pop up that, it will change the
06:15background, that's fine, but whenever we click this we should expect to see the
06:20log message come up here, the return code was 1.
06:22If I click it again and click the other, I will see -1, and if I click the
06:27alternate button, I should see 0. There we go.
06:32So another free form simple code based used of delegation.
06:37In other languages the equivalent idea of a selector would be a function
06:41pointer, how we can pass the address of a function around, but this is how we
06:44pass the name of a method in Objective-C as an argument.
06:49And in other languages and platforms you might refer to this as a callback
06:52situation, yes, I am going to call this method, passing in the name of a method
06:57it should call back when it's finishing.
06:59And a possible bit of trivia for you, when you see a built-in method in Cocoa
07:04that starts with the word begin, such as beginSheetModal for window, it's a
07:09pretty good sign that this is an asynchronous method, and it will execute on
07:13another thread and immediately return to this one.
07:15So it's very common to have begin methods take delegate callback parameters.
07:21So we have gone through three examples of delegation pretty quickly, but hopefully
07:26you are beginning to see why delegation is a powerful technique and hopefully
07:29seeing why it's often underestimated.
07:32See, the more experienced you are on another platform, the easier it is to get
07:36the wrong impression about delegation, and that's why I have gone through several examples.
07:40Because if I just show the AppDelegate examples some people assume, oh,
07:45delegation is a kind of inheritance equivalent.
07:48Or if I just show you a user interface element example, some people think, oh,
07:53delegation is just some kind of event handling equivalent.
07:56And if I just showed you the alert example here, it would be easy to think,
08:00okay, delegation is just some kind of callback equivalent.
08:03And it's none of the above and kind of like all three at the same time.
08:08Delegation is a remarkably flexible way of supporting optional behavior while
08:13still keeping our classes very independent and loosely coupled.
08:17We support what we want to support, we ignore what we want to ignore.
Collapse this transcript
4. Creating User Interfaces
Exploring the XIB file
00:00Let's explore what we find in a typical XIB user interface file, just so we can
00:05start to explore some of the other controls.
00:08I will make a brand new project, and I'm just going to go into the MainMenu.xib
00:13file and to make sure that I can see my Utilities panel, so I can get to my
00:17Libraries and Inspectors.
00:19We have seen that we have the Dock area over here on the left of the canvas
00:23which can be maximized or minimized, but not hidden.
00:27And it has two main sections inside it, what are called Placeholders and Objects.
00:32Now, the Placeholders represent shortcuts to important objects, and often objects
00:38outside of this actual user interface file.
00:40So in the Placeholders section I see File's Owner, First Responder, and Application.
00:45And you will always see these three placeholders in every Cocoa user interface.
00:50The easy one is application.
00:52It represents the running application object itself.
00:55Now, we won't do much with this icon in this course, but it's good to have a
00:59visual representation of the actual app.
01:02For example, if I drill into the standard menu that's generated for a new Cocoa
01:09application, we have got the menu that's being generated for the project itself,
01:13which includes the Quit option.
01:15We will go into the menus in more detail, but just if I were to right-click on
01:19that, I could actually see that like having a button or some other control, it
01:24can send actions, it can be an outlet and right now this is set up to send the
01:29terminate action to the Application object.
01:31And if you notice, as I mouse over application, it's actually highlighting up
01:35there in the Placeholder.
01:37So it can be useful to be able to grab hold of something that represents
01:41that application object. Well, what about the other two?
01:44Well File's Owner, is an icon that represents a connection from this user
01:48interface file to the object that owns it that was responsible for loading it.
01:53Now here, this MainMenu.xib is actually loaded by the NSApplication object
01:59because this part of the interface lives as long as the application lives.
02:04So here File's Owner and the Application Placeholder both point to the same
02:09thing, but that's not always the case. If we were to create another window that
02:13didn't need to live as long, say our Preferences panel, it could have a
02:17different File's Owner.
02:19And the last one is First Responder. This is a somewhat cryptic name.
02:24This is a placeholder that can represent different objects at different times in
02:28the application lifecycle.
02:29But it refers to the fact that there's always one object in the UI that should
02:34get the first opportunity to respond to an event.
02:37As a very basic example, say we have been manipulating this interface, and we
02:42have dragged on a couple of text fields.
02:44Well, if you click into a text field, that text field that you have just
02:48selected, should now be the thing that responds to key presses.
02:51But if you click into a different text field, it should be the First Responder
02:56to those key presses.
02:57So sometimes it's useful to be able to ask who is the current First Responder
03:02or even set a First Responder programmatically, and we will see more about this later.
03:07But we have got the main section here below that, the Objects section, and there
03:11are far more of these, mostly representing visual user interface elements on our
03:17canvas, but can be non-visual too.
03:20Because this is an Apple operating system, we have two primary sections set up
03:25for us in a basic Cocoa application.
03:27The Main Menu object, which itself contains a collection of Menu Items and
03:32other menus, and the Window object itself, these things are both contained in
03:37the user interface file, but they are separate chunks.
03:40And of course, Objects can contain other objects.
03:44Beyond the most basic interaction, it is useful to have the expanded view of the
03:49Dock rather than the minimized view of the Dock when you're looking at this.
03:53So I can click the disclosure triangle and start to drill down into the
03:57different sections inside, for example, the Menu.
04:00Selecting any of these objects should highlight it correctly on the actual
04:05screen and the reverse is true as well.
04:08You can treat the menu as a menu to be able to drill down into optional settings
04:13inside it, and you will find that each individual piece of the menu is
04:17essentially its own separate object.
04:20Selecting any particular entry from any particular part of the menu allows us to
04:25look at that individual piece such as Show Toolbar, I could use the Connections
04:30Inspector, see if it has any actions or outlets and just treat it completely
04:34independently of other menu items.
04:37Some of these menu items, you'll find, are hooked up such as the Quit option in
04:41the main application menu.
04:43Right-clicking or using the Connections Inspector, we can see that that's
04:46sending the terminate action to the Application object.
04:49Others say Preferences might be very common, but right-clicking that one I can
04:54see that might be there, but it's hooked up to nothing yet.
04:57And that would be our job to do this to create say a Preferences window.
05:03Below the Menu section we have the main Window section, which itself contains a
05:08view, this main visible area that we can drag and drop buttons and text fields
05:12and other controls onto.
05:13And we will see a lot more about what we can do with this view in the next few movies.
05:18Below this are a couple of non-visual objects meaning, just objects.
05:22These represent an object, an instance of a class, like the App Delegate
05:26represents an instance of the AppDelegate class that's written in our project.
05:31And we have seen this one already.
05:33Having it here visually you know our XIB file allows us to connect to it and to
05:38call certain methods inside it.
05:40We also have, in our basic Cocoa application, the Font Manager.
05:43This is a built-in Cocoa object that's provided here by Xcode so that the
05:48standard font menu inside Format can have an object to talk to.
05:52And we can just ignore Font Manager for now.
05:54But here's the question. What is Xcode actually doing when we say drag on a
05:59button from the Object Library? What does it do here?
06:03On many, perhaps most IDEs, when you work with a visual user interface design
06:08like this, it's actually generating programmatic code behind the scenes.
06:12It might be generating lines of Java, or C#, or VB.NET. That are instantiating
06:18objects and setting their X and Y positions based where you drag them on the window.
06:22Well, this is not the way that Xcode works.
06:25When we start arranging different buttons and controls on the screens are
06:29working with the menus, it's not generating Objective-C, or C, or C++, or any other
06:36procedural language. A XIB file, behind the scenes, is made of XML.
06:40It's not procedural, it's like an XML snapshot of all the objects the way
06:45you have arranged them and the attributes you have set on them, the things that
06:49you have connected them to.
06:50If I right-click this MainMenu.xib file in Xcode, I can choose to open it as
06:56source code, and I actually see that it is just seriously a list of XML in
07:02different settings about how the menu is created, what objects have been dragged
07:06on, and information about those objects.
07:09You do not need to edit the XML, as a rule you just stay in Interface Builder,
07:14so to get back to that I just told it to open as Interface Builder.
07:18So whatever we do, whatever we arrange, whatever we change in an XIB file is
07:23basically saved in a snapshot of XML.
07:26You will often hear the term freeze-dried for this, but when you arrange and
07:29save this XIB file, it's like having a bunch of objects frozen in place.
07:34And when that XIB is loaded, everything is unfrozen, or reconstituted, exactly how
07:40you define the interface in Xcode.
07:41But what we are going to do in the next section is explore more of what we can
07:46do with a user interface in Cocoa, talk about some of the most common controls
07:50you are likely to use from the Object Library, how to lay out an interface well,
07:54make it flexible, and some user interface conventions in Cocoa that you may be
07:58aware of and a few you may not, but you should be.
08:02So I won't be writing a great deal of code in the next few movies until we have
08:06seen what we can do by just using the visual options.
Collapse this transcript
Working with buttons
00:00The first time you create a new Cocoa application and you open up the Object
00:05Library to see your available user interface elements, there looks like there's a
00:10tremendous amount of things here to choose from, and it's true there are a
00:14lot, but not quite as many as it might seem.
00:17For a little bit more information on any of them, you can select them, then
00:21hover the mouse, you'll get a pop-up that tells you a little bit more
00:25information about that particular control.
00:28And this is what I mean by saying there is not quite as many controls as it might seem.
00:32The first bunch here, for example, are all exactly the same class, the NSButton class.
00:37In fact, I have to come down 14 entries to find something that isn't an NSButton.
00:42And in fact, NSButton is actually a really good place to start when we want to
00:48get familiar with the Cocoa controls. So let's see a few of them.
00:51I'm going to jump into my MainMenu.xib file here and just select the Window object.
00:56Drag on a few of the basic buttons here.
00:58We have got a Push button, Gradient button, Rounded Rect button, I won't do every
01:04single one, but I'll have a few of them.
01:08Textured button, Disclosure Triangle, and let's go with a Square button.
01:12They're all based on the same underlying class, although they obviously look substantially different.
01:19If I open up my Inspector section and go to my Attributes Inspector, which is
01:23the fourth Inspectors Panel here, I can actually see that each button has a
01:28style, and it looks like I could change this from say a Square button to a Push
01:33button, to a Disclosure Triangle and back.
01:35But I would say that if you accidentally dragged on the wrong kind, and you
01:39haven't hooked it up to anything yet. Don't just ever change the style.
01:43Delete the button, go back and drag on the one you wanted because there is a
01:47lot more to a button than style, as we'll see in a moment.
01:50But this Attributes Inspector is, in fact, a great way to get an idea of the
01:56options for these buttons and for any controls.
01:59Though for more on each control, with it selected, selecting the second
02:03Inspector will give you the Quick Help menu.
02:06Now, the first abstract here doesn't give you more than you can get just by
02:10clicking in the Object Library and waiting for the pop-up, but you also have a
02:14link here to say the NSButton Class Reference, which will jump us to the
02:19Documentation and tell us the kind of things we could do in code, giving us an
02:23idea of what this button is capable of. Apparently we can set the sound on it,
02:27we can set it to Transparent. It's got things like bezelStyle.
02:32Switching back to the main environment, there is also a link to a guide called
02:36button Programming Topics, although this at least at the time of recording for
02:41Apple is surprisingly out of date.
02:43So let's go back and take a look at a few of these.
02:46I'm going to switch back into my Attributes Inspector.
02:48Many buttons have, as we can see, a Title.
02:50You can double-click in here to change it to something else, or of course, you
02:55can change it in the Attributes Inspector, which will do the same thing.
02:59But several buttons, a Square button, for example, does not have a title, even
03:03though there is a space for one.
03:05You can add one, or you can give a button an image instead of, or in addition to, a title.
03:11But if a button doesn't have a title when dragged on, it can be a clue that this
03:15kind of button is expected to have an image.
03:18So with the Square button selected I can see that I do have a dropdown Image
03:21section here in the Attributes Inspector, and just by clicking that I'm going to
03:26see several entries.
03:27What we're looking at here are some of the official Apple button and Toolbar images.
03:32We have got ColorPanel here, we have got Computer, we have got the images for
03:37Everyone, we have got the images for DotMac and Advanced settings.
03:42However, just because you can select an image here, doesn't mean you should.
03:45Some of these are only supposed to be used in Toolbars, and most of them really
03:50do represent a very specific meaning for Apple.
03:53So you don't want to use, for example, NSUserGroup for your button thinking that
03:59might be a good icon for chat, when in fact this is a very specific Apple icon
04:04meant to be used for user group permissions.
04:07Now, your question might be, well, how am I supposed to know which one of these
04:11I can use and which ones I can't and in what circumstances?
04:14Well, bear with me, we will get to that.
04:17Of course, what's often likely is that you'll want to have your own images for icons.
04:21Now, unlike some platforms, including iOS, there is no one particular size that
04:26you must provide for a button icon because buttons can be large, they can be
04:30tiny, they can be anywhere in between.
04:32But a Square PNG file is best with a transparent background.
04:37I have one on my Desktop at the moment, what I'm going to do is just add it to this project.
04:42I'll click the Supporting Files folder because that's usually where I'd want
04:45this to be, and in Xcode I could just drag and drop this, but I can also go to
04:50File and then Add Files to this project, the project is called buttons.
04:53I'll go and find this, it should be on my Desktop.
04:56I have something called SimpleImage. It's just a PNG, a very small file here.
05:01With that selected, I want to check the box to say Copy this item into the
05:06destination group folder, to make sure I'm not just linking to it on the
05:09Desktop, but I'll keep it in my Project folder, click OK, and now I can see
05:15SimpleImage.png, very straightforward turn up there.
05:19Switching back into the interface, what I should now be able to do with that
05:23button selected is go over here into the dropdown Image, and I should find it
05:27show up in the list. There we go, SimpleImage.
05:33Now, the most common thing of course to do with a button is hook it up to some
05:37code, meaning cause an action.
05:38A button that doesn't cause an action isn't really all that useful.
05:42Now, we have seen this already, but let's just take another look at it again.
05:45I'll give myself a bit more screen real estate here and switch into my
05:49Assistant Editor mode. We want to see the AppDelegate over here.
05:53I could create a new class, but just for the purposes of a quick demo this is fine.
05:58I'm looking at the header file.
05:59I'm going to Ctrl-drag from any of these buttons in here to insert an action.
06:05The pop-up, by default it pops up as Outlet.
06:08buttons can be both Outlets and Actions, but it's certainly more common that
06:12they're all actions. I'll call this doSomething.
06:16We have now connected that button up to this little piece of code.
06:20But while all of my buttons are likely to cause actions.
06:23oftentimes I'll want to also talk to the button in code, I'll want to change its
06:27title or set it from Enabled to Disabled.
06:30Now, to talk to a specific button directly in code, it's useful to define that
06:35button as an Outlet and give that Outlet a name.
06:39So, for example, I'm going to select this Gradient button here.
06:43Ctrl-drag that into the interface.
06:48I prefer to put all my properties before my methods, it doesn't really matter
06:51what order the properties are in.
06:53So this on the other hand, is not an action, it's an Outlet, and I'll give it a
06:57name of myGradientButton.
07:00It's of Type NSButton, that looks correct, and it's weak, there we go.
07:03The reason that I wanted to do this is to show what's probably the second most
07:07common thing to do with a button.
07:08If the first is hook it up and make it cause an action, the second most common
07:12thing is to make a button enabled or disabled.
07:14Now, this can be done in the Interface Builder, so if I have my Utilities Panel
07:19open, I can select that Gradient button and down towards the bottom here we have
07:25a check box here called Enabled.
07:28If I uncheck that, we immediately see the different visual style over here in
07:33the Interface that suggests we can't click this button.
07:36But we often want to do that too in code.
07:38We want to affect whether a button is enabled or disabled in code.
07:42So what I'm going to do now is switch to the Implementation and turn that button back on.
07:51Because we have defined it as an Outlet called myGradientButton, I can just
07:55use the name of that.
07:58myGradientButton has a method called setEnabled, and it's a BOOL, which
08:04for Objective-C is YES.
08:06Alternatively, I could have used dot syntax here, myGradientButton.Enabled = YES.
08:12Save that and Run it.
08:14The application should begin with the button Disabled, but not surprisingly we
08:19click the first Push button, and we should get the option to Enable it.
08:23Of course, very simple and very straightforward stuff, but the two most common
08:28things to do, drag on buttons, hook them up and make them cause actions, or
08:33enable and disable them.
08:34And those might be the two most common tasks, but there is certainly a few more
08:38we can take a look at.
Collapse this transcript
Exploring button states and types
00:00We have seen that buttons can be enabled, or they can be disabled.
00:04If they're enabled, we can click on them. If they're disabled, we can't.
00:08But buttons also have something called State.
00:11And it's an easy beginner mistake to confuse the state of a button with whether
00:15that button is enabled or not.
00:17And State and Enabled in Cocoa, are two very different things. So I have just
00:21created a brand-new Cocoa application, and I'll jump onto the window in my
00:26MainMenu.xib, and drag on a regular push button here.
00:30Now if I look in the Attributes Inspector for this button, Apple won't really
00:35helping me understand the difference here because I do have this dropdown
00:39option called State here.
00:42But if I go down a little bit further to find where I have got the check box for Enabled.
00:46It's in a section called State, and these are completely different from each other.
00:50So let me make this a little clearer. Enabled is simple, it's the easy one.
00:55All buttons care about whether they're enabled or not.
00:58The value of this can be changed in interface builder.
01:01I can uncheck it, or I can do it in code with the Set Enabled method.
01:06If it's enabled, I can click on it, if it's not, I can't.
01:09It's simply true or false.
01:11We're seeing as this is Objective-C, it's yes or no, but State is different.
01:16State--I'll go back up to the top of the Attributes Inspector to find it here.
01:20State is a property that can be officially On or Off or Mixed. And this has
01:26nothing to do with whether this button is enabled or not.
01:29But here is the thing, with many of the buttons that you might drag on, State
01:33doesn't matter. You start changing the State of a regular push button like this
01:38one, you'll see no visual impact whatsoever. So what's the difference?
01:42Well, here is what I consider the best example of the difference between State and Enabled.
01:48I'm going to go into my Object Library here and drag on a check box, and just
01:54copy and paste that. Do it a couple more times so that I have four.
02:06And yes, in Cocoa, a check box is not some special kind of class, a check box is an NSButton.
02:13That is its type,
02:14if I click over there and hover, you will see a check box is an NSButton class.
02:18So I'm going to change the properties of three of these.
02:21I'll leave the first one as it is.
02:23Take the second one, and change its State from On to Off.
02:29Take the third one, leave its State as it was, which is On, but uncheck Enabled.
02:35Check the fourth one, I want to uncheck Enabled, and change its State to Off.
02:42And that's the difference when we're looking at this.
02:45The first two are enabled, the second two are not.
02:48But the first one is enabled with the State of On, the second one is enabled
02:53with the State of Off, third one not enabled and On, fourth one not enabled and Off.
02:59So state is a property that does exist for every button in Cocoa but only
03:04matters for certain types of button. Because in Cocoa buttons don't just have a
03:09style, they have a Type.
03:11The style is the way they look, the Push button, Check, Square, Disclosure
03:16Triangle, but the Type, which is also available as a dropdown here, is the way they behave.
03:22Often these two are very closely linked, but they're not the same thing.
03:25For example, a regular Push button has a certain appearance, a certain Style,
03:31but it also has a particular behavior, a specific behavior when pressed.
03:35You click it, it is momentary. It's got the Type of Momentary Push In.
03:40Now I can go ahead and run this application or another quick way I can do this
03:45is go to my Editor menu and just say Simulate Document, which is a quicker way
03:49of just taking a look at this screen without worrying about compiling code.
03:54button behavior is momentary push in. I click it,
03:57it turns blue for a second and returns to the way that it was a moment ago.
04:01On the other hand a check box, which is still a button, has a different kind of behavior.
04:06I check it,
04:07it changes its State, it moves from Off to On or On to Off, quitting the
04:12simulator, go back here.
04:15So selecting a check box we have a different type of Type switch.
04:19If you drag down a button like a Recessed button, then you would find a slightly
04:23different behavior there, which is the Push On Push Off behavior.
04:27But typically you don't have to worry about the Type because buttons dragged
04:32from the library have the Type that is most usual for that Style.
04:36But it can mess you up if, for example, you decided to have a check box and then
04:41change its Visual Style to Push button but leave its Type as Switch,
04:45that would be a nonstandard use of an interface control.
04:48But there are the occasional times you want to change the type of a
04:51button, here's an example.
04:52I'm going to select this regular Push button here, which by default has a Type
04:57of Momentary Push In, and I'm going to change that to Momentary Change.
05:01What's the difference here?
05:02Momentary Change allows us to put in an alternate title so that while it's being
05:07pressed, it actually shows something different. So I'll just change this to the word, Pressed,
05:15and then go back to the Editor menu and say, Simulate Document again.
05:18I could just run the application, and we'll do the same thing.
05:21Now when we click the button, we get the alternate state of that, this is the
05:26momentary change of the button.
05:27And occasionally that kind of thing might be useful, but most of the time you
05:32drag on a button with the right kind of Style from the Object Library, you will
05:37automatically have the right type.
Collapse this transcript
Exploring the Apple Human Interface Guidelines for OS X
00:00If you have been using a Mac for a while, several of the button choices in the
00:04Cocoa Application are pretty obvious.
00:07You can tell the difference between say using a Push button, and when you might
00:11use something like a Disclosure button.
00:15However, most developers even with long histories on the Mac are less sure when
00:20the question is something like when should you use a Gradient button as opposed
00:24to a Square button as opposed to a Bevel button?
00:27What's the difference between using a Recessed button and an Inline button,
00:31particularly as they look almost identical in the Library section?
00:35And of course, this is Apple, so we can presume that all these choices
00:38matter, it's not arbitrary.
00:40Well, we need to step up our knowledge of Apple's official Human Interface Guidelines.
00:46Now this is a document that you can get from the Apple developer site.
00:53And if I go into the Mac Dev Center, I often don't even need to be logged in
00:58to be able to find it.
00:59I'm going to jump into the Guides section of the Mac OS X Developer Library.
01:06It's usually fairly obvious somewhere on this page, but if not, you can of course search for it.
01:12This is what I'm looking for, the Mac OS X Human Interface Guidelines.
01:16There are actually separate documents for OS X and iOS development.
01:21You can get this document on the web, but you can also download a PDF version of
01:27it if you prefer to put it on a reader or print it out.
01:30PDF is over 300 pages, but this is not your usual dry technical documentation,
01:36it's not primarily about code, and it is written very, very well.
01:40Over here on the left-hand side I can see it is split up into several sections.
01:44We go to section on the basics of the Mac OS X platform, there's some high-level
01:48content like the Philosophy of User Interface Design.
01:51Everything from Consistency, Forgiveness, and Aesthetic Integrity, but it
01:56also gets into very specific low- level content like Designing icons for the
02:01Sidebar or the Toolbar.
02:02And there are two sections certainly worth becoming very familiar with early on.
02:07If I come down to the sections here that talk about the User Interface Element
02:11Guidelines, I'm going to select the Windows section here.
02:15And if you want to make sure that you're good with the differences between a
02:18window, a document, a panel, an alert and a sheet, this is going to break it
02:23down, give you a nice quick reference for that.
02:25It will break down some of the terminology that you will read in Apple
02:28documentation, talking about say the window-frame area, the title bar and the
02:33toolbar, the window-body, because what you'll find is a lot of buttons and
02:37different elements are suggested that they only exist in the window-frame or
02:42they only exist in the window-body.
02:43What this document is great for is making explicit what is often only
02:48implicit when you have just been a Mac user.
02:50After you have gotten familiar with the Window Guidelines, take a look at the User
02:55Interface Element Guidelines for Controls.
02:57Here is where you'll find very specific guidelines for things like button usage.
03:02There is an entire section on Window-Frame Controls.
03:05Again, if you're looking at something that appears in the toolbar that kind
03:09of button there, if it's a separate button the suggestion being it's a Round textured button.
03:15If the visual appearance is something like this the four groups together you're
03:19looking at the Textured rounded segmented control.
03:22It will break down the differences between pop-up menus and pop-down menus.
03:27So when you're asking which button should I use in which circumstance?
03:30This is a great part of the document to get to.
03:33In fact, if you jump into the buttons section, it will break down guidelines on
03:38when Push buttons should be used.
03:40As you read this document, you'll find the guidelines on things like if one
03:43of these buttons is going to pop-up another dialog box, then you should have
03:47be ellipses after it.
03:49As we come down further this guidelines about when to use Icon buttons, what
03:52size you should be working with, there.
03:54Scope buttons, recessed scope buttons versus round rectangle scope buttons.
04:00Again, all of the things we kind of take for granted using the Mac that we now
04:04have to make explicit as Cocoa Developers.
04:07An example of when to use a Gradient button, Gradient buttons often being used
04:12without text, using one of the built- in icons for Apple to add or subtract or
04:17work with settings and preferences.
04:19When specifically to use the Bevel button, and you'll find the Notes that
04:24they're not recommended for apps using OS v10.7 or later.
04:28You should use a Gradient button or Segmented Control instead.
04:31Now earlier I showed examples of selecting images on a button from using some of
04:37the built-in Apple icons.
04:38Well, in Appendix B of this document you can actually find more about what
04:42images are available and exactly when they should be used.
04:46It will break down which one should only be used in Toolbars, which ones are
04:50allowed to be used in Controls.
04:52You see a preview of the image and then what you should expect that image to be
04:56called in the dropdown box.
04:58Images for locking and unlocking, going forward, going back, adding an item
05:02removing an item, they are already there, and these are the ones you should be
05:06using in Cocoa if you need that functionality.
05:08Further on, it has some of the images that are suggested for use, but only if
05:13you're using this in a toolbar, and when certain icons should be used for
05:18Advanced Preferences or User Accounts.
05:21But overall, a hugely important and useful document, something that you should
05:26have downloaded or at least Bookmark and check back with regularly. And it's the
05:30source I'll be using and referring back to several times during this course.
Collapse this transcript
Using text fields
00:00After working with buttons, the next classic control is the Text Field, and
00:04we have seen several of these already.
00:06Now, like buttons, several of the entries in the Object Library are from
00:11NSTextField just differently configured examples ready to drag and drop, but
00:16there is not quite so many this time.
00:18We have the classic text field, that is NSTextField. We have Label which we have
00:23also discussed is NSTextField, it's just a non-editable one.
00:26I will just select my MainMenu.xib file and drag a couple of these so we can
00:32start to work with them.
00:38A couple of text fields and a label,
00:43basic Text Fields, Regular or Label, have one line and don't wrap, but there
00:47are two draggable objects that you will find in the Object Library that can have multiple lines.
00:52We have a Multiline Label, and we have a Wrapping Text Field.
00:58There is nothing particularly remarkable about these.
01:02Again, they come from the NSTextField class, so they have the same capabilities.
01:05It's just worth knowing they exist.
01:08Now, if you need large amounts of text, more than a few lines, we would typically
01:13look at something called a Text view.
01:15But that's a very different class, and we'll see that later on.
01:18But what you'll also find in the Object Library is there are several classes
01:22here that inherit directly from NSTextField and extend it to provide additional behavior.
01:29Now sometimes when I first say that, I have people ask me, hey!
01:33I thought we didn't use inheritance as much in Cocoa. Well, that's true.
01:36As application developers, we don't tend to use inheritance as much as you
01:41might do in Java, C#, C++, as we're often using delegation instead to provide extra behavior.
01:48But if I was building or using a framework of reusable objects, inheritance is
01:53great in Cocoa or in any other language, and it's certainly heavily used when it
01:58makes sense to do so like here.
02:00So there are three classes I am going to show you.
02:02First off, I'm going to drag a container from my Layout view here just drag on
02:07something called a Box. Box is very simple.
02:11It's just a way of grouping a few other controls together.
02:14I am going to drag on this Box and just give it a name of NSTextField Subclasses.
02:23I don't have to do this, but it allows me to group them together.
02:27First, I'm going to find the Secure Text Field.
02:30This is NSSecureTextField, but it's a subclass of NSTextField, mostly behaves
02:36exactly the same as a Text Field except this one just shows bullets instead of
02:41characters, and you can't copy from it.
02:43There is the NSSearchField with a little magnifying glass.
02:49Well, this adds a Search and a Cancel button to the text field, and it also
02:55stores an array of recent search strings available in the pop-up menu.
02:59Now, it's still just a text field, it has no knowledge of how to search.
03:03That would be up to you and your application, it's just really an Apple style
03:07user interface control to support searching in a recognized way, and there is
03:12also this Token Field here.
03:17Again, behaves very much like a normal text field but supports what's called tokenized editing.
03:23Well, let's see a couple of these running.
03:25I am just going to go to the Editor menu and say Simulate Document.
03:30The first couple were normal text fields.
03:34Nothing special about them, you can see that as we're typing we get the blue
03:39highlight around them, that's all built-in by default.
03:42We have the Wrapping Text Field below, then we have the Secure Text Field where
03:47everything pops up as bullets, and we can't copy out of that.
03:50Next is the Token Field which supports what's called tokenized editing.
03:55Think about when you type in multiple email addresses in mail, it recognizes
03:59each email address as one piece, one unit, and it surrounds that with a blue
04:06outline, that's what tokenized editing is, and finally the search box here.
04:11Working with all these different text fields is actually very similar.
04:14The Text Field is a capable intelligent object.
04:17It can even do delegation to let another class know when it's being edited,
04:21and a lot more besides.
04:23But in a lot of circumstances, you really don't need that level of capability.
04:27The most important property that you're interested in is really how do you get
04:32to the contents of a text field?
04:34And while of course we can change any of the attributes in the Text Field when
04:39we're in Interface Builder, it's much more likely we'll get to the contents in code.
04:43The property we're interested in is stringValue.
04:46We read the contents with stringValue, we change it with setStringValue.
04:50Now, it's very common as we have seen that what we want to do with a text field is
04:55make it an IBOutlet.
04:57So using a System view, I can do a Ctrl-drag into a class, in this case App
05:02Delegate and create this as an IBOutlet. And I could do the same with any of them.
05:09But a text field can also be an IBAction.
05:13You can connect it to an IBAction method like connecting a button.
05:17So if I Ctrl-drag, I will do it here from the first text field, and drop it in there.
05:21But instead of inserting an Outlet, insert an Action, let's call this
05:27generically doSomething. We can have some behavior occur.
05:31Now, the question might be, well, what is the action?
05:33It's very obvious, when it's a button click, you click the button.
05:36So when does this occur for a Text Field?
05:38Well, the way it works is that once the user is typing in the text field, then
05:42if they hit Return or click out or hit Tab while they're in that text field,
05:47that will cause the action to happen.
05:50So I could simply jump across and put in a little bit of code into that implementation.
05:54I will jump into Standard Editor just so I can see a little bit more here,
06:01and we'll do a good old NSLog message just saying the contents of the first text field.
06:06Well, we did set it up as an output, so it should have a name,
06:10firstTextField, and again, we get its contents by saying stringValue.
06:17Save that and run it.
06:22Here, I'm getting a small warning about the Content rectangle not entirely on
06:26the screen, that's something I'll occasionally get when I'm dealing with a very
06:30restricted amount of screen real estate. It really doesn't matter here.
06:35So I start typing in that first area.
06:39If I hit the Return key, it will kick off that action.
06:41In fact, if I hit the Return key again and again and again, we'll actually have
06:45that message appearing multiple times. The first text field is first text.
06:52Change the value again, hit Return, we see that happen.
06:56It will also happen if I tab out, or if I'm in there and I click out, and the
07:01same method would work for any of these text fields, or anything based on this text field.
07:07So text fields can be an outlet, you're typically interested in the stringValue
07:11property, and text fields can be an action which will occur when we hit Return,
07:15click out, or hit the Tab.
07:16Now, this class can get a little deeper, but being able to get to its contents
07:20and respond to someone changing it is really all we need a lot of the time.
07:25Now, one thing to be aware of is if you drag several text fields onto a window,
07:29then either run that app as I have done now, or use the interface simulator.
07:34Even if you drag them out of order, it's going to do a pretty good job of
07:38ordering them the way you want and allowing you to just tab through them every time.
07:43And it does this by default based on the top-left position of the user
07:47interface element itself.
07:48So good to know that most of the time that just works, but after getting to the
07:53Text Field contents and being able to respond to an action, the next most common
07:57request is what if we need that actual interface, what if we need that Text
08:02Field to be something other than freeform text, like a date or a price?
08:07Well, we'll get to that next.
Collapse this transcript
Using number formatters
00:00We'll work with text fields and labels a lot, and it's common that the value we
00:04need to put in them is not actually a string object, it's something else.
00:08So if in our code we have say an NSDate object, we want it to be easy to put
00:14that directly into a text field, formatted the way we want it, without writing a
00:18lot of code to convert it, and we can use something called a formatter for that.
00:22A formatter in Cocoa changes a string into another data type or the other way
00:26around, another data type into a string. Let's see a couple of examples.
00:30So I have a very simple application that I have created just to save us a little time here.
00:35The interface has a text field which I want to set to a date value and a
00:39label here, which of course is just a text field that I am going to set to a float value.
00:44I have already declared these as outlets in my AppDelegate header file and
00:48hooked them up so that I can address them in code. And what I am going to do is
00:53in the applicationDidFinishLaunching method, I am going to set their values.
00:58And on Line 19 and 20, this is what I want to put in them.
01:02I want to grab an NSDate object and put that value in the first text field, then
01:06I want to create a float and put that in the second one.
01:09Well, we know that text fields have the set string value method, and new
01:13developers in Cocoa often do something like I am showing here in what I call Method one.
01:18Manually converting those other data types into strings and then using set
01:23string value to change the contents of the NSTextFields.
01:26And this works, if I go ahead and run this application.
01:31I am indeed putting the date into the date field, and this floating point
01:36number into the number field, but that might not exactly be the look that we are going for.
01:41So what are my options here?
01:42Well, while set string value might be the most common way to change the contents
01:47of an NSTextField, we also have the methods set int value, set float value, set
01:53object value, and a few more besides that allow us to pass in a different data
01:57type into that NSTextField without converting it first.
02:01Now, we're still not using formatters yet, but let's do that as kind of an in-between step.
02:06So instead of on Line 24 converting the date into a NSString, what I am going to
02:13use is setObjectValue and just pass in the NSDate object I have called today.
02:21And then instead of converting the float variable, I am going to call
02:27setFloatValue, passing in that float variable I created on Line 20.
02:33Save that and Run it just hitting Command+R. Less code, slightly similar result.
02:41Using this method we actually get a different result for both a floating point
02:44version and for the date, it's probably still not what we're looking for, but it is a step closer.
02:51Let's see what formatters can add to this picture.
02:55Quitting out of this and going back into Xcode, I am going to jump into my
02:59MainMenu.xib file, and I am opening up my Object Library.
03:03I can either come down or filter on the word formatter, and I'll find a few
03:10formatter entries in the Object Library.
03:12There are two that I am interested in here, the Date Formatter and the Number Formatter.
03:18And these really are the two built-in formatters in Cocoa.
03:22You can also create things like a custom formatter to handle your own classes
03:26being converted to strings and back if necessary.
03:30Using these formatter objects is a little different.
03:33You don't drag a formatter onto the interface by itself.
03:37The whole point of a formatter is to format something.
03:40In this case with the Date Formatter, I want to format that date field, so I am
03:45going to click it, drag it, and drag it on top of the text field itself.
03:49I should see it highlighted in blue, and then I let go.
03:52I see no actual visible difference, but it has had an impact, we'll see it in a second.
03:57Next, I grab the Number Formatter and drag that over the label and let go.
04:02I am going to just Save that and Run it again and see the impact that, that has.
04:07Haven't written any code, haven't changed anything, but now we're
04:11certainly getting a different kind of impact. We are formatting the values
04:15of those NSTextFields.
04:17It might not be what we want, so let's take a look and see what else we can do.
04:20Formatters are customizable.
04:23One of the problems is when they're on the interface, you can't really see them
04:26just from looking at it, what we have to do is look at the expanded Dock view.
04:31Selecting that first text field, making sure the disclosure triangle is open,
04:35what I can see nested a couple of levels in there is the Date Formatter.
04:39And we can use the expanded Dock view to select it.
04:43With the Date Formatter itself selected, we can go to the Attributes Inspector
04:47over here on the right-hand side, and we have a bunch of choices to select from.
04:52Date Style, do we want Short Style, and it gives us a little sample of that, Medium,
04:59Long Style, giving the full name of the month. So I'll change it to Long Style.
05:03Again, when you're using a formatter, you always have to be careful here,
05:07because if I just click the text field itself, I am looking at the attributes of the text field.
05:12I need to either use the Dock here, or I can drill down using the Jump bar into
05:16the Date Formatter to change its attributes.
05:19Same idea with the second one I am using as a label here.
05:23We have applied a Number Formatter, we can't see anything on the actual canvas
05:27itself, but over here in the Dock I can see I have got a Number Formatter kind
05:31of embedded in there.
05:32With the Number Formatter we have a few different choices.
05:35We can go for Decimal, we can go for Currency.
05:38And down at the bottom it will give us a sample of, well, if the unformatted
05:42value was 1234.75, the formatted one will use the dollar sign for our sake.
05:47This is localizable, so it can change based on the culture of the operating system.
05:52So we have several options here:
05:53we have Currency, Decimal, Percent, Scientific, and so on.
05:57If you need a little more than that, select from the Behavior the Custom option,
06:03which itself gives you a lot more option for things that you can do in terms of
06:08grouping separators and currency symbols and so on.
06:13I am going to just switch back to default, and I'll select Currency.
06:17We go ahead and run this again, and we're using the new formatter rules.
06:21And it is important to consider that when using these formatters, they do
06:26want say a date object or a number to work with, so don't do your own conversion first.
06:32Rather than the set string value of the text field, use the set float value or
06:36set double value or set object value for a date and then format that.
06:41I do find that formatters are easier to grasp when using them for output.
06:45They can be used for input, too, although there are often better options than formatters for this.
06:51Even though, for example, I am setting that date and formatting it into a text
06:55field, I wouldn't typically require a user to type a date into an open text
06:59field then use a formatter to verify and write code to pop-up errors if there
07:04is a problem, I just use a date picker.
07:06If I am working with say a fixed range of numeric values, I'd use a stepper
07:10control or a slider.
07:11Now, if you have something truly specific, and you need to format either the
07:15output or the input, you're going to need a Custom Formatter, and there is a
07:19class called NSFormatter in Cocoa. It's an abstract class, it's intended to be
07:24subclass to help you do that.
07:26Now, it's a little specialized and beyond our scope right now, so look at the
07:30documentation for NSFormatter for more on that.
Collapse this transcript
Using the slider control
00:00Going to make a new Cocoa application so we can explore the slider control.
00:05Jump into my MainMenu.xib file, select the window and then in the Object Library
00:12either come down to or filter on slider.
00:17We have Horizontal, Vertical, and Circular, that's something called a slider Cell
00:21but that's really just the interior part of an NSSlider.
00:24I am going to drag on a horizontal one because these are the most commonly used in OS X.
00:29But they all worked the same way, and if you get familiar with one, the
00:33others hold no mystery.
00:34I have dragged it onto the center, and I am just going to grab the handles of the
00:39edge and drag it wider just so we have something to play with here.
00:42I am not going to do much else with this interface, so I will shrink it down a bit.
00:47Jumping over into my Attributes Inspector here, I can see that we have this idea
00:52of a Maximum and Minimum values. By default it's 0 through 100, and the Current
00:57value is 50. You can either use the stepper control here, and as you do this you
01:01should see the head of the slider is actually moving on our Design view.
01:06You can change the Minimum and Maximum values, of course, to be anything
01:10that's meaningful for you.
01:11There is something called Tick Marks here, and you don't actually see any tick
01:14marks until you change this value to greater than zero.
01:18I am going to change it to say six here.
01:20What happens then is that the actual head--what's often called the thumb or the
01:24knob of the slider--changes from a circle to this pointer.
01:28And the tick marks are showing up, but they're positioned above by default which
01:32I find kind of odd because Apple nearly always positioned tick marks below the
01:36slider, so let's change that, Tick Marks Position Below.
01:40And we have the choice also to only stop on the Tick Marks.
01:44Going ahead and running the application, it behaves as we'd expect to do.
01:48I am not locking to the Tick Marks, so I get a continuous movement from side to side here.
01:52But one of the best ways to figure out how they can and should be used to
01:57replicate a familiar Apple feel is go and see how Apple use them.
02:01Now if you want to see a lot of Cocoa controls in the same place quickly, there
02:05is no better place than going to System Preferences, because you can jump around
02:09in here and blast through a whole bunch of different screens that are going to
02:13show you the most commonly used Cocoa controls and how they're used.
02:17And sure these aren't pretty conventional Cocoa screens, they are not going
02:21to win any design awards, but it is a great place to become familiar with classic usage.
02:25So if I am in Sound I can see a couple of sliders being used there.
02:29Then in the Keyboard section I see sliders being used here for Key Repeat
02:32and Delay Until Repeat.
02:34And these are typically using Tick Marks with the Tick Marks below.
02:38Now Apple suggests having labels and at at least the start and the end if you
02:43are using Tick Marks. So let's go ahead and do that.
02:46I am going to jump back into Xcode and make sure my running application is
02:50stopped and just giving myself a bit more space for this slider, drag on a
02:54couple of normal labels.
02:59I will position one at the start and then for speed purposes just do an
03:03Option-click to put one at the end here. And change their value.
03:08Double-click that from None to Lots. They are looking a little big right now.
03:16That's because if you go to label beneath a slider it shouldn't be using the normal font.
03:20In my Attributes Inspector here I'm going to change the Font sections for this
03:25label to System Small, do that for the second one as well.
03:35And that's more like it.
03:36Now you'll actually find switching back into System Preferences as an example
03:40that Apple usually capitalize the words being used for the certain end of tick
03:45marks but not always. Sometimes they don't.
03:49And occasionally, you'll also find some tick marks used without labels at all.
03:53Now the value of a slider should typically be enough by itself. It doesn't have
03:58to be shown anywhere else on the screen.
04:00If I'm changing this Alert value, I'm just changing the Alert value.
04:05If I'm using a slider with a keyboard to effect the Key Repeat, it's between
04:09Slow and Fast and Off, but I don't see it updating some other piece of text that
04:14says this is 80% or 90%. But if it's helpful, you might want to do that.
04:19One example would be in the Energy Saver section of Preferences.
04:24We have a long slider here. We have several different labels being used.
04:29But as I grab the head of the slider I get this label above it kind of showing
04:33me exactly what these are pointing to. When I let go, that label disappears again.
04:39Again this should only be done if this is useful, but I'll show you a quick way
04:43we can actually replicate that in our program with no code.
04:46I am going to go over into my Object library and just find a regular label, drag
04:52that up here above the slider.
04:55And with that label selected I am going to go over into my Connections Inspector.
05:00And so far we have seen using a Delegate connection, we have seen using Actions
05:04and Outlets, but I am going to do something else now.
05:07With the label selected I am going to come down into Received Actions where I
05:12have some interesting ones like takeFloatValueFrom from takeIntegerValueFrom.
05:15I am going to grab the circle beside takeFloatValueFrom, click and drag over to
05:22the slider and let go.
05:25I can see the connection being taken up here. If have done it on the wrong thing
05:29I could just hit the little X to break it.
05:31I actually don't need this label to say anything, so I am just going to delete
05:36the contents of it and go ahead and run this.
05:41So grab the handle of this, move and let go, move again and let go, move again and let go.
05:47We're partway there, but we have got a couple of issues.
05:50One is its not updating until we actually let go off the slider head.
05:54And two is it's little more information than I needed to know about the exact
05:59value of this slider. So let's fix those.
06:03Quit and back into Xcode, I am going to select the slider here.
06:06Now the first problem we were having is it was only updating when I paused, when
06:10I let go of moving the slider.
06:12I am going to jump into my Attributes Inspector, and that's because the default
06:17behavior of the slider is to only update when you let go.
06:20But down in the Control section, if I find the check box marked Continuous and
06:24selected that, then just running this quickly again, we'll find that it updates as
06:29soon as possible, and it updates as we are dragging the slider along, but we are
06:34still getting a little bit too much information here.
06:36So back into Xcode and stop the application.
06:39I have got two methods that I could use to take care of this.
06:42First I am going to grab the label, now because it's blanked out its little
06:46difficult to grab hold of so I could use the Expanded view here.
06:50And just click around a little bit until I find the correct one which is this
06:53static text area, and I can see it being highlighted.
06:56Well, one thing that I could do is in the Connections Inspector instead of
07:00hooking that up to takeFloatValueFrom, I could cancel that and then just hook it
07:05up to takeIntValueFrom.
07:08And that would just truncate that value, which would work fine.
07:11Another way we could do seeing as we're working with a format as recently is I
07:16could find the Number Formatter, just drag that on top of the label.
07:21It's not letting me do that right now because it's a bit too empty to drag on top of.
07:26So let me highlight that static text field and just give it a simple bit of
07:35text here so I actually have something to grab hold of.
07:42Drag on the Number Formatter, let go.
07:45And then we can blank out that value again and run.
07:51We have the slider, as soon as I click it and drag down we have the Integer value.
07:56I might change the alignment of that, but it's working just fine.
08:01And what I wanted to demonstrate by doing this is the ability as we get more
08:06and more aware of the different controls in Cocoa that's very common to connect
08:09them to each other.
08:11To have one control directly affect another without having to write any code at all.
08:15Now in Code if I wanted to get the value of the slider, I could set it up as
08:20an IB outlet, give it a name, and then use the floatValue property to get its
08:25current value as a float, or the Int value to get as an Int, or String value
08:29to get as a string.
08:30And you might be thinking, oh, so NSSlider has a String value property just like NSText field?
08:36Well, yes it does because they all do.
08:39Every control has those same properties, Int value, Float value, String value,
08:44Object value and many more besides, because all of the controls we have been using
08:48and all of the ones you'll find here that you can drag and drop onto the screen
08:52end up inheriting from a class called NSControl, selecting the Classic Controls
08:58here, everything like a Gradient button or a Push button.
09:01If I let the pop-up come up, it will tell me it's a subclass of NSControl.
09:08The Text field is a subclass of NSControll or kind of NSControl, as are the rest
09:13of them even say a secure text field inherits from NSText field which itself
09:18inherits from an NSControl.
09:19Now that's an abstract class that defines the core attributes of all controls in Cocoa.
09:25And one of the great things about that is as you start to learn a few of the
09:30controls deeply, you realize that they're often very alike.
Collapse this transcript
5. Arranging User Interfaces
Using layout views
00:00As we begin to make interfaces with more controls and more choices on them, we
00:04need to start organizing some of those controls, or at least making it explicit
00:09which ones belong together.
00:11And when you first start building Cocoa Applications it is a really good idea to
00:15keep in mind some of the things that Apple do and some of the precedents that
00:18they set, whether you're looking at things like iWork Applications or even just
00:22the good old System Preferences.
00:24I'll give you some ideas about what might we expected in an Apple environment.
00:28That will give you everything from say the basic General section in System
00:33Preferences which simply uses some horizontal lines to separate some Radio
00:38buttons and check boxes and a few of these controls what are called Pop-up buttons
00:42that we haven't really explored yet.
00:44If I jump back in and go over to the preferences for Mission Control, we'll see
00:48these ones here just having several control like these check boxes inside a box,
00:53and in fact, that is what this is called in Cocoa is just a Box, it's a way of
00:58grouping some controls together and optionally giving them a name like this
01:01Keyboard and Mouse Shortcuts box.
01:03Jumping over to Desktop & Screen Saver, we have the first of many what are
01:08called Tab Views, where we have two or three or four clickable links at the top of this window.
01:14I'll jump to Security & Privacy. I have four different Tab views, each one
01:20containing an independent collection of controls.
01:23And Keyboard, for example, we have just a couple of sliders, some labels,
01:27check boxes, and regular buttons.
01:29And in the second Tab, Keyboard Shortcuts, we have something this little more
01:33complex here. We have something called a Split view that separating these two
01:37sections, allowing me to resize the amount that I see.
01:40Now while we have seen buttons and check boxes and sliders, we haven't seen these
01:45controls yet. We're going to explore these in the next chapter, the ones with the lists of selections.
01:51What I'm focused on right now on the Containers themselves, the Dividers, things
01:55like the Tab Views and the Boxes and everything that I have just mentioned
02:00Horizontal Lines, Vertical Lines, Boxes, Tab views, Split Views all the typical
02:04ways to contain surround and set out controls inside the same window. These are
02:10all the available for us to drag and drop in Interface Builder there in the
02:14Object Library in a section called Layout Views.
02:17There's eight of them here, ranging from the very simple to just being able to drag
02:22on say a Vertical Line and resize that, to more complex like the Vertical Split
02:28view or Horizontal Split view.
02:30Going to just delete that vertical line and drag on a couple of things to help
02:35me set out this window.
02:37First I'll drag on a Tab view here. I'll use the guidelines to help me laid out.
02:41And with the Tab view itself selected, I can see that we start off with two tabs.
02:45It's invisible on the page. It's visible here in my Attributes Inspector.
02:49I can change that to three or to four.
02:52I do want to be careful because each individual tab will switch my focus here, so
02:57if I click on the word Tab again, we're actually jumping into that first tab
03:02which will allow me to drag and drop different controls here.
03:05So this is occasionally where it's useful to expand the Dock to allow me to
03:09select the Tab view itself rather than the independent pieces, what are I refer
03:14to as the Tab view Item, which themselves are very useful to use such is the
03:18second item, the third, or the fourth.
03:22Selecting any of them allows me to drag on the regular controls or even other views.
03:27The Push buttons, Labels, Text Fields, and so on.
03:31And each of these are completely independent, supported both in your program when
03:35it runs and in Interface Builder itself. If I click the second tab twice we'll
03:39shift into that mode, and I can drag on some new content here.
03:43In this case perhaps Date Pickers and a Combo Box or two.
03:48Now if necessary, one of the things you can also do is have containers inside containers.
03:53I could switch back to my Layout view section here and decide to drag a Box
03:58into that second tab.
03:59Now if I made up my mind that what I really I wanted to have was these three
04:04controls inside that box, well I could move them across, but another way to do
04:08it is use the Command key and select all three of those, and I want to be sure it's
04:13just those three selected.
04:14And come up to the Editor section and say Embed In > Box.
04:20And that gives me the Box with just those three controls. And if you notice,
04:24that as I move the box around those are considered enclosed in it.
04:28And that's the way you'll see them over here in the expanded Dock.
04:34Just collapsing some of these disclosure triangles to make it a bit more
04:37obvious, we have the Tab view which itself includes the separate items, but if I
04:42select the second item and expand that, we have the view inside that that
04:47contains two boxes. One of the boxes itself can be expanded, and that contains
04:52the Combo Box directly.
04:53The thing you have to be careful of here is if you're rearranging an Interface I
04:57don't want to select the Box--I'm thinking I can delete it without deleting
05:01what's inside it because if I do hit the Delete key it all goes away, including
05:05all of its contents.
05:07So I'll just Command+Z here to bring that back.
05:11But of course the Tab view that I'm looking at here is completely independent of
05:14whatever else is happening on that window.
05:17So if we drag on the Box underneath it, and I can double-click the name of that
05:21just to give it a new name, or you can set it to blank if you want to.
05:27Just to quickly drag on the couple of things, if I did expect to create say a
05:31few Text Fields and a few Labels at the same time, one quick way of doing that
05:36is coming down and finding what's called a form which begins by adding two at a time.
05:40Though, if you have more space you can actually increase that to three or four or
05:45however many you need. I'm going to bring that back down to two rows.
05:49Now just quickly running this, we have no code whatsoever, nothing has been hooked
05:53on, no outlets, no actions.
05:55But it's very easy to start to set this out and just start to emulate some of
06:00the kind of presentation styles that you'd see in say System Preferences.
06:05The last thing that I wanted to show was in that Layout view section, the Split view.
06:09I'm going to select the third tab which right now for me is blank.
06:14We can drag one of these on--say a Vertical Split view--and position that,
06:19arrange it, resize it.
06:21Right now, the individual sections inside the say Custom view have nothing in
06:25them whatsoever. We can drag our own controls in to it if we want to.
06:29But what's more usual is that you use a Split view in conjunction with a
06:32couple of the controls we haven't really explored yet, most of which are found
06:35in Data Views, such as the Browser and the Outline view that are showing lists of content.
06:42It's unusual that we'd use a movable Split view and have just buttons and
06:46check boxes on either side of it.
06:48And while I could drag and drop in a Table view or Outline, we can actually
06:53use the same technique that we used on the second view here with embedding
06:58controls inside another one.
07:00So I'm going to jump to that fourth tab, and just ignoring the Split view
07:04completely, I'll drag on first a Browser. Browser we'll see a little later.
07:10That's something that you might use and say a Finder window, and then after this
07:15I'm going to grab a Table view just to have a different control to work with.
07:18I'll drag that into that tab as well.
07:21Now if I decide what I want it once to have a Split view between these two, I
07:27really need to combine them together.
07:29So I'm going to select the second one--which is the Table view--then use my
07:34Command key and select the first one.
07:36And again go up to Editor > Embed In and one of the choices here is Split view.
07:42Things about it for a second and gives us that. We may need to resize some
07:46that content, as you can see.
07:47Just to make it little more even, I can of course still get to each individual font.
07:53If I expand this Split view I'll see that it shows me it's containing both
07:57the first Browser here and the Table view.
08:02So I'm just going to go ahead and Run this, and I can see up at the top I have
08:07this scrollable Split view here.
08:09We can switch to one which has no content in either end. We have got the boxes,
08:13we have got the regular controls.
08:15So in just a few moments, pretty easy to see how we can emulate something that
08:19we'd see in, say, System Preferences.
08:20But one thing that is actually missing between that and a typical System
08:25Preferences is the Toolbar, a very common thing in OS X Applications, and we'll
08:30see how to work with those in a moment.
Collapse this transcript
Exploring Auto Layout
00:01In 2011 Apple released AutoLayout, a new method for how Cocoa user interfaces
00:05arrange and resize and lay themselves out.
00:08Now AutoLayout replaces the older technique called Struts and Springs, which is
00:13still currently what you used in iOS development.
00:15And with Xcode 4.3, AutoLayout became the default layout method for Cocoa projects.
00:22And I am in 4.4 now, and it's what we are going to be using in this course.
00:26I won't be talking about the older Struts and Springs methods.
00:29Now we have been using AutoLayout already, and a lot of the time it just works.
00:33It's worthwhile to know a little bit more about what's going on.
00:36So I have just created a new out-of- the-box Cocoa application, haven't
00:40done anything to it yet. I am going to drag on a button or two.
00:44Now we have seen the guidelines that appear when you do this.
00:47And let me tell you that AutoLayout is not at all about these guidelines, and
00:52it's not really even about the button, it's about what happens when you let go.
00:58We see the guidelines here on the left and on the top, the dotted blue lines,
01:02but if I let go you'll see another couple of lines appear, in this case to the
01:06top and to the left. This is what AutoLayout is all about.
01:11These are what are referred to as Constraints.
01:14And Constraints describe a relationship between two visual elements, two views,
01:18like the relationship between the button and the top of the window here or the
01:22relationship between the button and the left-hand side of the window.
01:26If I click on the button over here on the right, I see two different constraints
01:30again to the top but this time to the right.
01:33As I'm dragging on different elements onto the page, different constraints are
01:38added depending on which part of the window that I put them on.
01:42Oftentimes those constraints are based on say the right-hand or left-hand side
01:45of the window, but if I'm trying to arrange buttons beside each other, say down
01:49here, for example, I will also get constraints between the user interface elements themselves.
01:55So this selected button doesn't have a constraint to the right-hand side of the
01:59window, but it does have a constraint to the button next to it.
02:02And depending on the circumstance, a constraint might try and keep things
02:06together or keep things apart or both at the same time, in this case keep these
02:10buttons close but never allow them to touch.
02:13Well, Constraints aren't actual objects and Cocoa, it's the NSLayout constraint object.
02:18They are added by Interface Builder as we edit our XIB files.
02:23So if you click any of the objects, whether they are buttons or any other kind
02:27of user interface elements, you'll then see the constraints that affect that object.
02:31For this one now I have three constraints, the right-hand, the bottom, and the
02:35one to the next button.
02:37You can then actually click any one of these constraints. Sometimes they are a
02:41little difficult to grab hold of, but you can usually manage.
02:44When you click that constraint, you'll see an amber highlight that will show you
02:48what objects that constraint affects, so this one between the two affects these
02:53two buttons, this constraint just affects this button.
02:56Now as a side note it's a common mistake for new Cocoa developers to
03:00accidentally have a constraint selected when they think they have a button or
03:04some other element selected.
03:06So if you see the amber highlight, know that you have a constraint selected, you
03:10don't want to be trying to Ctrl-drag from a constraint to a code file.
03:14When buttons are properly selected they should be blue.
03:17You can also get to constraints from the expanded Dock view.
03:22So here, for example, inside the Main view I can see the different constraints I
03:25have and actually take turns and selecting different ones vertical space,
03:29horizontal space, and so on.
03:31These are true objects. With any one of them selected, I actually have elements
03:36in the Attributes Inspector that I can affect, and we'll see this in a moment.
03:40Now most of the time you don't add constraint yourself, you just let Xcode do it.
03:45But occasionally you can, occasionally it's needed and worthwhile.
03:49As I am dragging on elements, Xcode makes a pretty good guess of where the
03:52constraints should be, whether that's dragging them on for the first time--
03:56in this case it's choosing to add constraints to the left and to the bottom--or
04:01if I move things around, say up to the center here it's going to add two
04:05constraints, this one which is making it a center constraint, and this one which
04:10is tying it to the top.
04:12So you can feel free to rearrange the object, Xcode will rearrange the
04:16constraints for you.
04:17I have added nothing but buttons right now so I am going to grab a couple of
04:22other things here, and let's grab a Layout view.
04:25I am just going to drag on a Tab view here.
04:28And drag that wide allowing the guidelines to give me suggestions for where it
04:32should be positioned, but noting that with this Tab view selected I have
04:36multiple constraints here, to the left and to the right, to the bottom, and
04:40you know there is a constraint above that button, and there is a constraint
04:44below the button here.
04:46It's interesting often to see how Xcode rewrites this as you are editing it.
04:50If I delete that button and select the Tab view again, we'll see now the
04:54constraint that's focused is really this one over here.
04:57And as I keep on going adding different things, say a pop-up button over here
05:04on the left and deleting the button on the right, we'll see a different kind of focus going on.
05:12Sometimes it will take you a bit of rearranging if you want to get the
05:16constraints back to where you thought they should be.
05:18And the guidelines can be very useful for that.
05:20In this case I rearranged it a little bit to make sure that there was a
05:24constraint between the Tab view and the button above it.
05:27And we'll get more into rearranging some of these in a minute.
05:30So I am going to go ahead and run this just with Command+R. As we'll see in a
05:35moment, we don't actually even need to run this application to see the impact of
05:38AutoLayout, because it works in the Interface Builder view.
05:43But as I resize this, it's actually looking pretty good.
05:46The Tab view is expanding both horizontally and vertically, the buttons at the
05:51bottom right are keeping together the way they should.
05:54Although if I start to collapse it a bit, we are getting some impact we probably
05:58don't want, so we'll see how to fix that a bit. Quit out of that and back into Xcode here.
06:04Well, first, I am going to rename a couple of things because it's important to
06:09understand how Xcode is going to work with this.
06:11I will rename this button down at the bottom left to Import..., which will make
06:16the button a little bit wider, but because of the constraints it will still be
06:19fixed on the left-hand side.
06:22On the other side, if I change this button to the words OK, take a look at the
06:25button to the left of it.
06:27The OK button will collapse, and this one will move to the right based on the
06:31constraint that's written there.
06:33Essentially what's happening is what you would hope would happen, and most of
06:37the time it just works.
06:39So we don't have to actually run the application, as even in design view we can
06:43see the impacts of the decisions that we are making here.
06:46One of the problems is that entire Tab view is collapsing, which is not
06:51something that I really want. How can I fix this?
06:54Well, we are going to add a manual constraint. I am going to select this Tab
06:58view, making sure that it's highlighted, and I could double-check that in the
07:03Jump bar or in the Dock.
07:04And then go up to the Editor section, and what we are interested in is the Pin
07:09menu, this is where most of your manual constraints can be added.
07:12I want to stop this from shrinking too much when we move it up vertically.
07:17So I'm going to give it a specific minimum height.
07:20So I will say Pin > Height, and it adds into this constraint and selects it for me.
07:26And right now this is set to a height constraint of being equal to 240;
07:31it has to be equal to 240.
07:33That's not what I want, which is fine. I can change that.
07:36I just don't want to get too small, so I am going to say it should be greater
07:40than or equal to 100.
07:43I don't care if it's more than that, but it shouldn't be any less.
07:46I will go ahead and hit Command+R just to see this running. We can continue
07:51to resize, we can drag this wider but as I make it shrink I can't make it
07:56close anymore than that because it's actually now staying at 100,
07:59that's the minimum size.
08:00We're still having problems this way, though. It's collapsing too much.
08:05Well, I could do another fixed width constraint, perhaps even based on say the
08:11button width to make sure that these ones don't collapse too much, but that's a bad idea.
08:15In fact, as much as we possibly can we want to avoid any fixed numbers.
08:20Because say if I go ahead and localize or internationalize this application, I
08:25might automatically have the text on these buttons changing and being replaced
08:30with different amounts of text based on the culture settings of the operating
08:33system that user is running this App on.
08:35So I don't know exactly how wide these buttons will always be.
08:38Plus, more than that, I don't want to have to stop measuring the width of my buttons.
08:42I really would just like the Import and the Cancel button to maintain a good
08:47distance from each other.
08:48But what is that distance? Is that 20 pixels or 40 pixels? What might it be on
08:53perhaps a Retina display versus a normal display?
08:56Well, I don't care, and I don't want to have to think about that, luckily I don't have to.
09:01I am going to add another constraint, and I am going to do that by first
09:05selecting both buttons.
09:06So select the Import one, then the Command-click the Cancel one. We have both
09:10buttons and nothing else selected.
09:12Up to the Editor menu, down to Pin, and this time what I'm interested in is the
09:18Horizontal Spacing, though again, I am going to have to tweak it a little bit.
09:22We add that, and we get a new constraint. The constraint is selected. I have the
09:26amber outline, telling me which two object this affects.
09:29What it's saying right now is this need to be equal to 229. That's not what I want.
09:35Again I want just a minimum size. I want some kind of distance between the two.
09:40So I want a greater than situation going on here, and it's asking well do you
09:45want a greater than 229, well no, I don't.
09:47Now I could put in something like 20 or 15, what's a better idea here is that I
09:53just click standard, and that makes it automatic.
09:57I'm telling AutoLayout you go figure it out based on your own internal rules.
10:02So go ahead and Command+R with this one, now we drag it wider we get the
10:07interface resizing itself correctly, if I move it up towards the top we have the
10:12minimum height of the Tab view, and as we close here we see that the buttons get
10:17the perfect distance from each other and don't get any closer.
10:21Very flexible. AutoLayouts are great way to allows us to easily create apps than
10:26in other environments would often require writing code to handle window resizing
10:30and measuring the relative distance between objects.
10:33Now this is just an introduction. It can get more complicated than that.
10:37One thing to be aware to be aware of is that all constraints--and I have one
10:41selected here--have priorities, which by default begin at 1,000.
10:45Sometimes you can get some worthwhile behavior by having different constraints
10:49with different priorities.
10:50Now that's beyond what we need to do in this course.
10:53So take a look at Apple's documentation on AutoLayout for more on that.
Collapse this transcript
Adding and editing toolbars
00:00So a very common need for a Cocoa application is adding the classic Macintosh
00:05style Toolbar, as we're looking at right now in Xcode.
00:08I have a new Cocoa application, I have just created, I haven't done anything to it
00:13yet, and I'm going to switch over to these Windows & Menus section of the Object
00:17Library, and this is where we find the Toolbar.
00:20Simply drag and drop it. It's one of the few times it doesn't matter exactly
00:24where you put it because Xcode is going to say, "I don't care where you drag
00:28this, the Toolbar always goes at the top."
00:30Now begins with a couple of icons for Color, Fonts, and Print, just to give you
00:36something to work with, but you can delete those if you want to.
00:39Now the Toolbar itself doesn't have a lot of options.
00:42If I have it selected and look at my Attributes Inspector, I get a choice here
00:46of whether to show the Icon and Label or just the Icon or just the Label, but
00:52other than that, there is not really a lot going on here.
00:55So I'll leave at the default state of Icon and Label.
00:58The first request of most people is how do I add something to it?
01:01Now I have seen people try and quickly say drag and drop things like a Push
01:06button onto the Toolbar.
01:08That is not going to work and has no effect at all.
01:12First, you need to be editing the Toolbar correctly, and you do this slightly
01:16differently from most of the things we have seen so far.
01:18So if the Toolbar is deselected, click it to select it, and if nothing pops
01:24up, click it again.
01:26You're looking for this, the Toolbar Editing Sheet.
01:29This is how you make any changes to the Toolbar.
01:33And again, just to show that's usually from a deselected state, you need to
01:37select the Toolbar then click it again to pop up the sheet.
01:40So there is two sections to this.
01:43What is Allowed on the Toolbar and below that what is the Default arrangement of
01:48these icons, because Cocoa supports user- driven customization of the Toolbar, so
01:53an application can have many more options available than just the one shown when
01:57they open the app for the first time.
01:59So the lower section is what describes what we currently see on the user
02:03interface and what arrangement it has.
02:06And we can delete from the lower section to change that, you'll just drag off.
02:10So I'll grab the Fonts, drag out of that square, and let go, and we get
02:14the little puff cloud.
02:16The Font option is still there, but it's no longer on the shown Toolbar.
02:20So to add new items to the toolbar, you first need to add them to the top area so
02:25they become Allowed Toolbar Items. What do you add?
02:29Well, you actually can add just a regular Push button.
02:32I see the plus sign there, but I'm not going to do that, it's a bad idea.
02:37Regular Push buttons should not be added to a typical Mac style toolbar.
02:42There are specific controls we should be adding to it.
02:45One of the easiest ways is that in the Object Library here I just filter on the
02:50word Toolbar, and I'll have several options appear.
02:54There is a handful of these, several of them are really the ones that are
02:58already there, the Print Toolbar Item, the Show Colors Toolbar Item, the
03:01Show Fonts Toolbar Item.
03:04There are three here for a Separator and Spacing, and this is probably the
03:08classic nonspecific one, the Image Toolbar Item.
03:12I'm going to drag that across into the top area and let go.
03:16This supports an image but doesn't have one yet, and it's called the
03:19Generic Label Toolbar item.
03:21With that selected, I'm going to go over into my Attributes Inspector and give
03:25it a more useful name, I'll call this one Inspect for a Label, and I'll also
03:30change its Palette Label to Inspect.
03:33And this is the label that shows up when you're actually editing the Toolbar,
03:37either here or if you're allowing the user to do that.
03:40So typically your Label and Palette Label are the same.
03:44And with that Toolbar item selected, I can select from the dropdown here of the Image Names.
03:48We currently have the Apple images here.
03:51Again, you can get a breakdown of all of these images in the Human Interface Guidelines.
03:56I'm going to select a fairly simple one here which is the NSInfo Image.
04:00You can of course add your own by dragging your own PNGs into your supporting
04:06files folder and they will show up here as well in the dropdown.
04:10So that icon is now Allowed, but it's not on the Toolbar, we can see it's not
04:14showing up in the background here, because I have to now drag it from the top
04:18into the bottom section.
04:21After I have dragged it there, I could if--I wanted to--rearrange it.
04:24Move it to the left on the left- hand side of the Flexible Space here or
04:28back over to the right.
04:29However, if you notice, and this would be the same if we run this application,
04:33it's currently showing up as being grayed out, and that's because it will by
04:38default kind of analyze itself to understand whether it's calling a method or
04:42not, and this one isn't.
04:44Going back in to edit this, again, select the Toolbar, and then click it again.
04:49If I select that item, we do all the configuration from the top section, the
04:53bottom section is simply what's there and how it's arranged.
04:57That's what we have got is the Auto Validation Behavior going on.
05:00It's detecting, but it's not doing anything, so it's graying itself out.
05:04I could either turn off Auto Validation, or I could of course just hook this up
05:09to some background code, and you'd do this exactly the same way you do it with a regular button.
05:14In this case, I could just shift into Assistant mode in the Editor and Ctrl-drag--
05:20and again we do all the changing and configuration from the top section--
05:24Ctrl-drag into my AppDelegate header file or into a custom class.
05:28And here I could set it up as an Outlet if I wanted to address this in code.
05:33But if I want to make it an action, and we'll just call that action,
05:37doSomething, we have now connected it. I'm going to shift back to the regular Editor.
05:42Occasionally, depending on your screen size, you may find a bit of screen
05:45corruption in Xcode there but just scroll up and down usually fixes it.
05:49So now I'll click Done.
05:50It hasn't yet Auto-validated here, but if I hit Command+R to go and run this
05:55application, I should expect to see it's showing up properly, because it is
06:00hooked up to a method even if there's nothing actually in that method.
06:03And there we go, it is clickable. But this isn't the only option.
06:08These are the classic image-driven Toolbar icons with the optional label
06:12beneath, but sometimes you want something a little different.
06:15If we take a look at Xcode itself, for example, we don't have those image icons,
06:19we have these Segmented controls or the Run button.
06:23If I were to open up Safari, we see a different style in the Toolbar, usually
06:27with this classic Back and Forward button, and these are a very different style
06:32but we can do these too.
06:34Well, know that you don't mix the big icon style that we're looking at here with
06:38that smaller style most of the times, so what I'm going to first do is just drag
06:42off the ones I'm using.
06:44If I wanted to completely delete them from the Toolbar I drag them off the
06:48Allowed Toolbar Items section, like taking the Colors one and just dragging it
06:52off, but I don't have to.
06:55So my Toolbar is currently empty, and what I'm going to do is go into my Object
06:59Library, into the regular Controls section-- making sure I don't have anything on the filter.
07:05I said I didn't want to add a Push button, and I don't. The one I want here is
07:09the Rounded Textured button that's allowed on the Toolbar.
07:13And if you're curious about remembering that, it's in the Human Interface Guidelines.
07:17Take a look at that, and it will tell you what buttons are allowed in the toolbar.
07:21So we drag on a Rounded Textured button, again, into the top section, which is where we say
07:25what's allowed and where we configure them.
07:28Well, when I do that, what it's doing is enclosing that button in a toolbar item,
07:33so we have really a container going on here, and if I'm editing this toolbar and
07:39select that, click off first.
07:42First I see the Toolbar Item which just has the label, and this is
07:46containing the button itself.
07:48So I'd click it again and see my Inspector change into the actual button inside there.
07:53So I'm going to strip out the title here, because I want to have an icon on
07:58that, not a message, and in the button itself I'm going to find the Image
08:03section and just drill down and find-- let's go for the refresh template, which
08:08is just a little Refresh icon.
08:10Well, that button is now a little too wide, so I'm going to drag it a little
08:14smaller, again making sure to click it a couple of times to, edit it, and there we go.
08:20And then clicking off to deselect it, I'll drag it into the lower section.
08:25Occasionally what you'll have happened here is it will show up a little too
08:29large, and that means that some place it thinks it's got a minimum width.
08:33Even though that's not showing up probably here in the Allowed Toolbar Items
08:37section, I'm going to click it. First, take a look at the Toolbar Items section.
08:42It's got the label here, Custom view.
08:44We really don't need that because I don't want a label on it.
08:47And then I'm going to click into the Size section here, we have got a Minimum
08:52and Maximum width here.
08:55I'll change the Maximum down to say 40, and I can immediately see it had an
09:00impact there on that icon itself.
09:02You may have to do a little bit of experimentation to figure out what the best
09:06size is, but that seems to do the trick.
09:08The only problem we have right now is this is on the wrong side of the Toolbar;
09:13I do have a flexible Space arranger here so I'm going to drag that to the
09:17left-hand side, and we move over there. Well, what's next?
09:19Another common thing we'd have in this style of toolbar would be a Search Field.
09:23That one is very easy to add, so I can just drag that into the top section.
09:28I'll change its label here to Search, which often is allowed,
09:32and then grab and drag it into the lower section where it does typically appear
09:37on the right-hand side.
09:39And the last thing I'm going to add here is the classic kind of Back and Forth
09:43icons that you see in Safari and in quite a few others programs as well, just the
09:48Left Right options here.
09:50This is done by using what's called a Segmented Control, and we haven't seen that one yet.
09:55You don't have to add this to Toolbar, you can add this anywhere, but I'm
09:59just going to filter on the Object Library on this segment, and we'll find
10:02the Segmented Control. Drag that into the top section.
10:05By default it has three elements, in fact, what's being used for Segmented
10:10Control up here is these Editor Icons and the view Icons in Xcode itself.
10:15That's not quite the effect that I want here, so I'm going to look at it, and go
10:19okay, this is my Segmented Control.
10:21Currently I have the Toolbar Items selected, the container, I need to click on
10:26it again to get into the Segmented Control itself.
10:30This is what I wanted to see.
10:32In the Attributes Inspector, I want to change it from three segments down to two
10:37because it's just back and forth is all I want, and in the same Attributes
10:42Inspector this allows us to select between Segment 0 and Segment 1.
10:46So Segment 0, I'm going to select the Image there to be the GoLeftTemplate,
10:52NSGoLeftTemplate will work and then switch to Segment 1 and change that to the NSGoRightTemplate.
10:58Now currently one all of them is depressed, meaning it's Enabled and Selected.
11:05It's not the behavior that I actually want of this Segmented Control, it can
11:10support multiple behaviors, including the style that we see in Xcode where one
11:14stays depressed, it stays pressed.
11:17You jump from Standard Editor to Assistant Editor and back.
11:20I want these really to behave more like regular Push buttons, just momentary.
11:24So I'm going to uncheck Selected. It takes us back to that default view.
11:30Programmatically what you'd also often do here is work with the Enabled state of
11:34it, so if going back wasn't actually valid, you would set that particular
11:39segment to not Enabled, and it would gray it out.
11:42But I'll just leave them both on for purposes of our Toolbar here.
11:46So with that selected, I will grab it and drag it down into the bottom section.
11:51First often having to deselect it just to come out of the Editing mode, drag
11:55it in there, and once it's dragged into the lower section over onto the left-hand side.
12:00Now currently it has a label which I really don't need, so I'm going to strip that out.
12:06Click Done, and then let's take a little look at this.
12:11Now one of the problems that we have is the segmented control is still acting
12:15like a segmented control which is just a option that we have in there, so I'd
12:19have to go back in and edit it again, clicking it once to first select that.
12:24Looks like we might be standing a little bit too wide, so I'm going to shrink
12:28that one down to a Maximum Width of say 60 to bring those two together.
12:33But after I have added the Toolbar Item, click again inside it, because what I
12:37want to do is find the Segmented Control itself, find the Attributes Inspector
12:41and change its mode from Select One, which means one of them will be selected, to Select None.
12:47It will respond to the presses, but neither of the buttons will actually stay
12:51in the pushed state.
12:53Come out of that and click Done, and I think what we could do it here is select
12:57the Toolbar and just change it to Icon Only, Command+R, and we now have a pretty
13:04classic Mac style custom Toolbar with custom rounded textured buttons, segmented
13:09controls, and search field. And that's the basics of using the Toolbar.
Collapse this transcript
6. Using Data Controls
Adding data views
00:00We have seen a couple of controls so far like the Combo Box, where if I drag that
00:05onto a window I can then use the Attributes Inspector and manually add different
00:10items here as the list of entries.
00:13But this kind of thing is not going to work very well when we have something
00:16more complex, when there's lots of data or multiple columns or data that
00:21changes all the time.
00:22So with the several controls, we need to be able to load them with data from our own objects.
00:26Everything from simple arrays to complex objects that change every time the
00:30program runs, and even while the program is running.
00:33And you'll find these controls in the Data Views section of the Object Library.
00:38Now the first looks like there's a lot of stuff here, but most of the elements
00:42you see here are ingredients, different cells, tiny customizable pieces that fit
00:48into the larger controls. Like the first four here at the top.
00:52Right at the top is the Table view, this is the most common, most used the
00:56classic data-driven control of rows and columns of data.
01:00It starts off very basic but can be hugely customized.
01:04A classic example might be in System Preferences in the Sound section, if we're
01:09selecting a sound effect. This is a Table view here.
01:12It's got two columns, Name and Type, so we have the headers with the name and
01:16type at the top, we can scroll up and down and select different entries on it.
01:21The Table view can be as basic as something that we would see in the Displays
01:26section, just a simple list.
01:28One column, no header, just a list of entries we can select from.
01:33Or at the other end of the scale, we could take a look at something like the App
01:37store, the list of purchase software. This could be done in a Table view too.
01:41It's still multiple rows and multiple columns to spend more time on the
01:45presentation of each individual row. We also have the alternating lines here as well.
01:51I'm going to jumping back into Xcode.
01:53Well, if that was the Table view, what else do we have?
01:56We have here the Outline view, the Browser, and the Collection view.
02:00Here is the best way to explain these. I'm going to jump into a Finder window.
02:05Now for a second here, I'm just focused on the main section of content, forget
02:10about the left-hand side, I'll talk about that in just a second.
02:13What I'm looking at here, which you should be very familiar with, where we
02:16have the Disclosure Triangles that allow us to expand and collapse different sections.
02:21This is the Outline view that you see in that part of Xcode.
02:26Rows and columns of data but we can expand and collapse different parts of that.
02:31Classic example here is of course a file system, but you can use the Outline
02:35view for your own data, too, if your data is best presented as multiple levels.
02:40Now from the Finder I switch this to the Column view, where we can actually
02:45drill down into multiple columns here. That is the browser that we can drag and drop in Xcode.
02:51Multiple columns again allowing us to drill down into multiple levels of data,
02:56and it's important to realize of course that this is the same data that we're
03:00looking at in the Outline view versus the Browser view.
03:03It's just a different visual presentation of that.
03:05And the same idea if I go back to the first icon where we just see a grid being
03:10laid out here that allows me again to drill down into different levels, this can
03:15be done with the Collection view that I see in the Object Library.
03:19This will display an array of content as a grid of views.
03:22Again, same data, different visual presentation, and your choices will be
03:27driven mainly by do you have multiple levels of data or can you just present
03:32them one level at a time?
03:33Well, while we're in the Finder window here, what about this area over here on
03:37the left-hand side, the typical sidebar in OS X? Well, what's that? Because we're
03:42still seeing multiple rows of data. Well, that is actually also an Outline view.
03:47It's just been configured to look a little differently, and in fact, you will
03:51actually find it way down in the bottom in the Date Views window here as
03:55something called a Source List.
03:56And if you hover over that you can see it's actually an NSOutline view
04:00configured as a Source List for use as a sidebar.
04:03And pretty much everything else in this section of the Object Library is for
04:08when you want to customize these top-level controls.
04:11I want to have more visual control about what each row and each column looks like.
04:16So how we're going to start going through this?
04:18Well, we're going to focus here on the NSTable view. This is the classic Data
04:23view control in Cocoa.
04:25It's the most commonly used one, it's the one we want to learn first, because
04:29the concepts we learn with it could be applied to the other controls.
04:32In fact, the Outline view is just a subclass of NSTable view.
04:36So we're going to show how to use it, how to customize it, and a couple of different
04:41ways of how to get data into that up next.
Collapse this transcript
Adding table views and data source classes
00:00I have created a new Cocoa application, yet haven't done anything to it yet, but
00:04I want to add a Table view to this window.
00:06So I am going to jump over into the Data view section of the Object Library and
00:11right at the top should be the Table view.
00:13I am going to bring that onto the window here and just drag it wider to take up
00:17as much space as it should.
00:19And the key question is how do we get data into this?
00:22Well, when you're loading data into a control, there are two primary ways,
00:26both very different.
00:28We can use code, and we can use something called Cocoa Bindings.
00:31I am going to show the code method first, and in the next section we'll talk
00:35about Cocoa Bindings.
00:37But here's the thing to understand about Table Views.
00:39Table Views don't store data. These are view objects.
00:43When we have a Table view in our application, what we need is another object, a
00:49helper object that can act as that Table Views' data source.
00:53This is very similar to the idea of delegation. We are asking another object
00:58to do some work for the Table view, and then we will point the Table view to that data source.
01:03The data source can be any class.
01:05It could even be AppDelegate, but whatever class it's going to be needs to have
01:10specific methods that answer the questions, how many rows are in this Table view
01:14and what's in each row?
01:17If you have multiple columns, it's what's in every single column of every single row?
01:22And whatever the data source answers here will be used to fuel the Table view,
01:27and we'll see this in just a second.
01:30As well as a Data Source object, the Table view often needs to be connected to a
01:35delegate object too. It uses delegation.
01:38The delegate object needs to have methods to answer the questions, what happens
01:42if a row is selected?
01:44If anything, what happens if a row is double-clicked on to edit it?
01:48What happens if you have a plus button to add a new row or perhaps the data
01:52source itself changes to add a row or delete a row?
01:56So we're looking for very specifically named methods for both of these.
02:01Now, you could put the data source in one class and the delegate in another one,
02:05but it's very common to combine the two into a custom class.
02:09So let's go see how this is done.
02:11So back into Xcode, what I now need is a class file, an object that can provide
02:17those methods that we need to fill this Table view with data.
02:21I could actually put that in AppDelegate, but I have been doing a bit too much in
02:25AppDelegate, so let's jump up to the File Menu.
02:27I am going to say New > File, and making sure that the Cocoa section is
02:32selected, I'll have an Objective-C class.
02:35This one does not need to be any special kind of inheritance.
02:38I am going to give it the name of MyTableViewHelper, the name is not important.
02:45And I'll make sure we're just inheriting from NSObject, click Next, add it to
02:49the project, and we jump into it here.
02:54Being a data source is like being a delegate, which means we really want to mark
02:58our class as actually supporting this official protocol, these official rules.
03:03You don't have to, it would almost certainly work without this step, but I think
03:08it's good practice to get into.
03:10What I mean by this is we're going to do something very similar as to what's
03:13in AppDelegate, we need to mark the class as supporting this particular
03:18protocol, this set of rules.
03:19So jumping back into my new class here, I am in my header file here, and after
03:24the NSObject, I am going to use the angle brackets and start typing that I want
03:28this class to officially support the NSTableViewDataSource protocol and closing
03:35angle brackets around that.
03:37One of the best reasons for doing this is I can now use my option key, mouse
03:41over this and click it and get the little pop-up that it will point me to either
03:46the header file or the official NSTableViewDataSource protocol reference.
03:50What are the rules to be a data source? What am I supposed to do? What are the
03:55method names that I should support if I am going to be in this role?
03:59Now, there is quite a few different method names for things like Pasteboard
04:03Support and Drag and Drop, but really what I am interested in are just the first two here:
04:08Getting the Values in the Table view.
04:10And it's numberOfRowsInTableView, how many rows are there, and then what's in each row?
04:15So for each Table view, what's the object value for the table column and row number?
04:21So click the first one and grab that.
04:24I am going to just copy that full method signature, jump back to Xcode, and I am
04:29going to paste this in the implementation file.
04:32I don't need to add it in the header file, because I am officially saying that I
04:36am supporting that protocol.
04:38I'll add the opening and closing curly braces just to make that a method signature.
04:43Back into the DataSource Protocol Reference, and I need that second method here,
04:47which is tableView:objectValueForTableColumn:row.
04:53Grab that method signature, copy it, jump back over into the implementation file
04:58of my new helper object, and paste that in. Then what? We need some data.
05:05I could create my own classes here, create an array, load data from a file from
05:09a database over a web service.
05:11What I am going to do for purposes of time is just ask OS X to give me a little
05:16bit of data that I can use for the lifetime of this object.
05:19I am going to say NSArray and just create an array that will last for the
05:23lifetime of this class, and I'll call it languages.
05:25What I am next going to do is just create a new method called awakeFromNib.
05:30We have mentioned this a couple of times.
05:32What it means is any object that's going to be instantiated as part of the load
05:36up process of a NIB file, this method will be called in it.
05:40So I know that this method will be called as I start to wake up.
05:44And what I am going to do here is just call a built-in method that's part of OS X,
05:48choosing something called the NSLocale object, and it's going to give me
05:53something called preferredLanguages, which is an array of language codes.
05:58This has nothing inherently to do with the Table view, I just want a little bit
06:02of data to work with.
06:03So that will fill an array with a bunch of language codes.
06:07The important parts are on Line 19 here, where it says how many rows are in the Table view?
06:13This method will be called automatically from the Table view control, and we
06:17need to return a number, which for us will be returning the count, the length of
06:22that array, so it's languages count.
06:27And down in the next, the most important method here, we need to say what's in each row.
06:34This method, we return an ID, it's an object value, so we can return a string is
06:39probably the classic example here. What's the text that should be there?
06:43Well, I know that I had an array with a bunch of language codes, so what I am
06:47going to do is return and use that array, languages, but instead of count, I am
06:52going to say whatever object is at a particular index.
06:55We are being passed an index every time this method is called, and it will be
07:00called for every single row.
07:02We have this parameter rowIndex so that's what I am going to use here.
07:07So we create an array and load it with a bunch of codes, then we say to the
07:10Table view, this is how long that array is, and then we say to the Table view,
07:14this is what's in every single individual entry in that array.
07:18Now, if I go ahead and run this, we're going to see absolutely no impact at all,
07:23because there's two pieces left to do.
07:27The first is that this Table view Helper object isn't being instantiated anywhere.
07:32I have defined it, but it's actually not part of that start up process.
07:36Now, I could write code in my AppDelegate to instantiate it, but really the
07:40easiest way is to jump into my MainMenu.xib file and then from my Utilities
07:45Panel, I am going to just select from the Objects & Controllers section,
07:50find the blue box, the generic object, drag it into the Dock, and then set its identity here.
07:58I am going to click on the third button in the inspectors, and change its class
08:03from the generic NSObject to MyTableViewHelper.
08:08This is almost a shortcut for doing an alloc and init.
08:13It simply means there will be an instance of this class instantiated when this interface is loaded.
08:19And seeing as this is loaded and lasts for the lifetime of the application, it's
08:23a very convenient place to put this.
08:25So it's instantiated, so what?
08:27Well, we need the last piece of the picture, because right now there is no
08:31connection between this object, the Table view Helper object and the Table view itself.
08:37So I need to select the Table view and hook it up.
08:40Here's something to be aware of, when I drag on a Table view--and this is the
08:44same for the other controls, too--I actually don't just get a Table view, I get a
08:49Table view inside what's called a Scroll view.
08:52And if you notice from deselecting that and then just clicking it to select, up
08:57here if I look at the class identity, it says no, this isn't a Table view, it's a Scroll view.
09:01That's because the Table view is inside it.
09:04Table view could have a thousand entries, and it takes care of showing the rows
09:08and columns, but the Scroll view is what supports us scrolling up and down and
09:12controlling what part of the Table view is visible.
09:14Now, I could click in there again, and I am likely to find the Table view here,
09:20I can see that in my Identity Inspector, or of course I could use the Dock,
09:24which is a very useful way to do it, the expanded view.
09:27I can see I have got a Scroll view, which contains a Table view, and inside that
09:31is the first column and the second column.
09:34Table Views by default, I am going to select the Table view itself and take a
09:39look at its Identity Inspector. They do begin with two columns.
09:42You can add more, you can take it back down to 1.
09:45You have checkboxes for whether it has headers or not. That's up to you.
09:50You have the option of selecting alternate rows of color for every individual row.
09:54So there's a few visual options here that you can select.
09:57But what I am most interested in--and this is making sure that the Table view
10:02itself is selected, not the Scroll view, not the table column--is I am going to
10:06go over into my Connections Inspector and find the Outlet for the data source.
10:10This is where we have hooked up things like the delegate before.
10:13I want the dataSource Outlet, which for me is the second one, grab that, and
10:18point it to the instance of My Table view Helper.
10:22Now the Table view knows which object to talk to. Save that, run it.
10:27And okay, it might not be the most impressive thing in the world, but we're
10:31getting data here, and it's scrollable as well, because we're inside that Scroll view.
10:35Automatically that's what happens. But why is it being duplicated?
10:38Well, that's simply because I dragged on the Table view and set it to having 2 columns.
10:44As part of the start up process, the Table view asked the Helper Object how many
10:48rows do I have, and that returned with 40 or 50, however many it was.
10:52And then the Table view called the Helper Object once for every cell of every
10:58row, for the first cell of the first row, for the second cell of the first row,
11:02for the first of the second row, for the second of the second row, and so on.
11:06So if I jump back over into my Helper Code here, and if I wasn't doing anything
11:11to actually detect what column we're in, we're just returning the same contents
11:16for each row, for two cells.
11:19So I could do a couple of different things here to take care of this.
11:22I could just edit this Table view and in the Attributes Inspector take it down
11:26to having simply 1 column, or I could put different data in different columns.
11:32Well, let's try that one.
11:34Here is the issue, over here in MyTableView implementation file, this method
11:40here that begins on Line 23 will be called for every column of every row, and it
11:45the passes in three pieces of information.
11:47First, the actual TableView parameter, because we could have multiple Table Views on the same window.
11:52We only have one, so I don't care about this. We have the rowIndex, what row is it.
11:58That's fine, we have been using that one already. And then we have an argument. That's the column.
12:02Now, that is not a column index, it's not 0 or 1, it's actually an NSTableColumn object.
12:10So I can't just say, well, if it's the first column, do this,
12:12if it's the second column, do that.
12:14They're not column 0 and column 1, that's because a Table view could
12:19theoretically have its columns rearranged by the user.
12:22We don't necessarily know they're in a particular order.
12:26The best way to identify the columns is to give them an identifier.
12:30Now, how do we do that?
12:32Jumping back into the XIB file, I am going to open up my Utilities Panel here.
12:37I want to use the Dock to select not now the Table view, but expand it and make
12:42sure I can see the individual table columns.
12:45So I can see that I can select one, then the other.
12:47I will go for the first table column.
12:49What I am interested in here is not the usual Attributes Inspector, I am
12:54interested in the Identity Inspector, because we have an identifier here.
12:59It says Automatic, but it's actually useful for me to give this a name.
13:03Well, what I am going to do is say that this first column is going to have the
13:07code of the language, so EN, or JA or FR. So I'll just give it an identifier of code.
13:15Then I am going to select the second column and give it an identifier of name.
13:20And it's up to you, these are your names, you just want to be able to remember them.
13:25So it's code lowercase, name lowercase.
13:27I can actually even see that in the Dock it's changed the title of them so
13:31they're recognizable that way. Now, what do we do?
13:33Well, jumping back into my helper object, I am just going to give myself a bit more space here.
13:38And inside this method, I am going to ask the question, if the parameter
13:43aTableColumn has an identifier that is equal to the string code, then I'll do
13:53what I did a moment ago, which is just return the language code.
13:56Let me put in a few spaces here just to bring that code up.
13:59So I will copy this line and paste it in there.
14:03If it wasn't that column, I am going to do something else.
14:06I'd like to return the name of the language.
14:09Well, how do I do that?
14:11I am going to use the NSLocale object again, and it has a method
14:17called displayNameForKey.
14:21What we're interested in is something called the NSLocaleIdentifier, and the
14:26value, and how we get that is by passing in the actual code that we have already
14:31retrieved, the EN, FR, JA, and so on.
14:34Let me just split this up a little bit so it's a bit more readable. That should do it.
14:41The name of the array, it's languages objectAtIndex, and we can get rid of
14:46that last return here. Save that, Run it.
14:51And we have alternate rows, we have multiple kinds of data being passed in, we
14:55have the Scroll view that will automatically allow us to move up and down with
14:59whatever amount we have chosen to see on the screen at this one time.
15:03And this is the basic procedure for loading information into an NSTableView by code.
15:09We need to connect the Table view to a Data Source object, in this case
15:14MyTableViewHelper, and then provide the necessary methods for that.
Collapse this transcript
Using Key-value coding
00:00I'm going to jump now into a concept in Cocoa known as Key Value Coding, and
00:04its flipside, Key-Value Observing.
00:07And the reason why is the next feature I want to explore, Bindings, relies
00:11heavily on these, and bindings is worth the trip.
00:13Now Key-Value Coding can sound complex at first but really isn't.
00:18Although I will admit that I don't think Apple do the best job of making
00:21it accessible. Their introduction is rather wordy and short on the immediate benefits.
00:27So let me jump into this.
00:28I have got a simple project that I have created here, and I'll go through what I have done.
00:33I have got a very straightforward new Objective-C class called Book, two strings
00:38and an integer, author, title and pageCount, about as basic as it possibly gets.
00:43And I am using Objective-C properties here, because I'm using Xcode 4.4, the
00:48getters and setters for these properties will synthesize automatically.
00:51I don't even have anything in the implementation file.
00:54So I am going to instantiate a couple of objects of this class and then on
00:59this interface I have one button that will just write an NSLog message out,
01:03very, very simple, because I want a setup to allow us to do some Key-Value Coding here.
01:08So if I look at my AppDelegate class, all I have got here I am creating a
01:13NSMutableArray that can hold several of these book objects, and I have got
01:17a listBooks method that as we'll see is going to just write out some NSLog messages.
01:23So here's what it's doing.
01:26In the applicationDidFinishLaunching method, I'm instantiating the NSMutableArray.
01:30Then on line 18, instantiating the firstBook object, setting its properties
01:36using the standard Objective-C methods, set author or setTitle, setPageCount.
01:40Then on line 24, I'll add that to the allBooks MutableArray, line 26 I create
01:47another book object, and I'm using the Objective-C .syntax to set its properties
01:53just to show that we could use either way, it would have no effect whatsoever.
01:58I just wanted something here to compare and contrast.
02:00Then on line 32, we add that secondBook to the array.
02:04What I am going to do now is do some Key-Value Coding.
02:13First, instantiate a new book called thirdBook, nothing special about that.
02:18What I am going to do next is call a method on this thirdBook object. The method
02:25I am going to call is called setValue forKey.
02:30First I will pass it a value of, I'll say "Jan Hanberg" forKey:@"author".
02:41This is Key Value Coding.
02:43We are using a string as the key to get to the property called author and then
02:48setting the value of that.
02:50This line 36 has exactly the same impact as using the method on line 20 of setAuthor:
02:57or as the method on line 28, .author equals.
03:02We have just got a slightly different format on that.
03:07Do it again now, I am going to do it for the title.
03:16And I could go ahead and try and do this for the pageCount, which is an integer,
03:20let's say I wanted to make this 250 for the Key pageCount.
03:27And this is the only one I'm going to have a problem with.
03:30If we want to use Key-Value Coding, the value always has to be an object.
03:35So what I need to do here, because it's complaining about this is instead of
03:39passing directly in an integer, I'm going to pass it an NSNumber that
03:43contains an integer. We are just wrapping that integer up.
03:51And finally, I am just going to add that to my mutable array.
04:00So line 36 to 38 is Key-Value Coding.
04:04Let's run this and make sure it's behaving just like the other additions.
04:07I click List books.
04:09And we got the message coming out exactly how I would expect.
04:12Now if I quit back into the application, I am going to take a look at this
04:17ListBooks method that's actually writing out the contents.
04:20What it's doing is having this format string here, and it's using .syntax
04:24currentBook.title, currentBook.author.
04:27We could of course use the space format inside the square brackets, or we can use KVC as well.
04:33We can use Key-Value Coding here.
04:35So for the title, what I would write is currentBook, and I will use the method
04:41valueForKey, again, treating the name of that title property as a string.
04:51We could do the same thing with the second currentBook space valueForKey:@"author".
04:54And the last one here, what I am going to do is currentBook valueForKey.
05:04I'm still using the name of that pageCount as a string here.
05:09Although I do know that this will return an object, Key-Value Coding
05:13always works with objects.
05:15And what is complaining out right now is it was expecting a direct integer, so I
05:19am going to change that that will format specifier here from %i, to %@, save it
05:25and run it, and we should have exactly the same behavior. That's correct.
05:30But we are using now Key-Value Coding, both on the way in and on the way out.
05:35To set value with KVC, it's setValue forKey. To get it, it's valueForKey.
05:42These methods are already in NSObject, which means this works everywhere.
05:46In every object you can use this approach.
05:48Now we are using standard generated properties in this book class.
05:53And that's what Key-Value Coding expects, the typical getter and setter accessor methods.
05:58Now you can still create your own accessor methods with different behavior, just
06:02be careful with naming them.
06:03If you use nonstandard getter and setter names, if you do that at all, you
06:07can run into problems.
06:08Now the reaction from most people when they first see this is this doesn't look
06:13like it's anything special, it's just some odd Objective-C syntax.
06:17But as we will see, it can be extremely helpful.
06:19Now there are a few advanced usage you can do, because when we are using valueForKey or setValue: forKey,
06:26we can often not just use a single word, the single name of a property,
06:31but we can actually use .syntax in the string to drill down into an object
06:36inside an object inside an object. But we don't need that right now.
06:40We just need to understand this idea that the key is a string that represents a property name.
06:47And we need the basics, because KVC, using that string for a property, let's us
06:52do something called Key Value Observing, which means we use the same idea of a
06:56key, the name of a property is a string, and we can say we want to register as
07:00being an observer for that key, and we will automatically be notified if the value of it changes.
07:06That might sound a little abstract. So let's see an example of what it can do.
Collapse this transcript
Binding an object to a user interface
00:00A great feature that's available to us in Cocoa that isn't available in other
00:04areas of Apple development like iOS is the idea of bindings.
00:08Binding refers to be able to connect, to bind a user interface element directly
00:14to a controller class without writing code, doing it all in the interface
00:18builder part of Xcode.
00:21So I have a Cocoa application here I'm going to use, and I have added a very
00:25simple class to it, a Book class that just exists here as a data structure.
00:29I have two NSStrings for author and title, one NSDate for the publishedDate, and
00:34an integer for pageCount.
00:35There is nothing in the implementation of this Book class, it's just to hold some data.
00:39Now, in my AppDelegate, all I am declaring here in line 16 is a property that
00:44can hold a single instance of a book object.
00:47And in my implementation of AppDelegate, that's all I'm doing when the
00:51application launches is I'm instantiating that book on line 16 and setting its
00:56values on the next four lines. That's the entire setup of this.
00:59What I want to do is get the details of that object onto the interface which
01:03has nothing right now, no buttons, no fields, no secret connections.
01:07Without bindings, what we need to do is several steps.
01:10First, we'd drag on all the user interface elements we wanted.
01:14Then we'd have to take care to connect them correctly to our chosen controller
01:18class as IBOutlets, giving them names, making sure they had the right type.
01:23And then in our controller code, we have to write code to set the values of all those outlets.
01:29If the class is complex, you often have to write quite a lot of what's referred
01:34to as glue code, or the unexciting code that purely exists to get object data
01:39into user interface elements.
01:41Well, we are going to do something a little different here.
01:44I do need to drag on the user interface elements that I want.
01:47I am going to drag on a few labels here.
01:50Just drag this wider and give it a placeholder name.
01:53This will be the Title, drag another underneath it as Author.
02:04Technically, I don't actually need to change the values of this label.
02:08We're going to change them as soon as the program loads.
02:10And just to give us a bit of visual interest, I am selecting the first one here,
02:16and I will just make the font a little bit bigger,
02:24nothing that we haven't seen before.
02:26This will be the point where usually I'd switch into the Assistant view and
02:29start doing the Ctrl-drag method to set them all up as IBOutlets.
02:34But that's not where we are going this time. Here is where I am going instead.
02:38I am going to select that first label, I am going to jump over here into the
02:42Bindings Inspector in my Utilities Panel. This is the second to last one.
02:47This looks like several intertwined elements or a simple Celtic knot of some kind.
02:51What I'm going to do is choose to bind the value of this label to that
02:57class that we created.
02:58Well, the question is well, how do I do this, what am I binding to?
03:03There is a lot of options that we are seeing.
03:05Well, the question is what class contains the data?
03:07Well, it's in the AppDelegate.
03:09That's what instantiates that object and holds onto it.
03:12So I am going to check the box to Bind to and then from the dropdown, select AppDelegate.
03:19But of course there is quite a lot going on in AppDelegate, so I have got a little
03:23exclamation mark here highlighting that this is the important part.
03:27We might be binding this label to the AppDelegate, but what part of the AppDelegate?
03:31And this is where we're using the term key.
03:33We are using the key part of the key value coding which is what allows us to do
03:39a path that drills down through multiple objects.
03:42So, self refers to AppDelegate.
03:44Then I put a dot, and it's actually looking inside AppDelegate and saying, okay,
03:48I know about two properties you have. There is the window property and singleBook.
03:52Well, it's inside that singleBook property. So I will select that and hit Tab.
03:57But that's the entire class, so it knows it can't bind that yet.
04:00I'm still getting the exclamation mark.
04:02I'll hit the dot again, and it's looking inside the singleBook object saying
04:07these are the accessible properties,
04:09the NSString for Author and Title, the Date, and the pageCount.
04:12Well, this is meant to be title.
04:14So I'll select that, and now the exclamation mark goes away.
04:17There are a lot of other options underneath it. I don't need to do any of those.
04:21I'm going to repeat this process for Author.
04:23I will drag that a little wider before I do, select the label, jump into
04:27Bindings, bind that also to App Delegate, but in this case, it's self.singleBook.author.
04:38And again, for date, making sure the label is wide enough, we are binding it to
04:42exactly the same place just a slightly different key path for each one,
04:48singleBook.publishedDate and finally pageCount bound to App Delegate, and you
04:54can see how we could bind them to different classes and different objects here.
04:59Save that and run it. And these are bound user interface elements.
05:06It looks like it's working okay.
05:07It looks like we are running into a couple of issues with the length of the
05:11labels here, and it does seem that there is a bit too much information.
05:15I don't need the full NSDate description that it's giving me here.
05:19So I'll jump back in and fix a couple of things.
05:21First, we will drag that Title label to the full width and then Date, I don't want the full thing.
05:27Well, this is fine. We can use say the NSDate formatter.
05:31So, with that selected, I'm going to find the NSDate formatter which is down
05:35here a little bit, drag that on top of the Date label, and with the date
05:41formatter selected in the Jump bar, I will just go to my Attributes Inspector
05:45and change it to--I'll change it to a Full Date Style but No Time Style.
05:51Run it again, and that's more like what we're looking for.
05:56Very easy to set up, no code that we have written at all.
05:59But we need to take it a step further, because right now this just seems like a
06:03nice way of getting data out onto the interface.
06:06But binding is not just for output, it's not just for labels, it works the other way too.
06:11So, quit out of this.
06:13What I am going to do is go back into Xcode and instead of a label, this time I
06:19will drag on a slider.
06:20I will just put this over here on the right-hand side and drag it to the full
06:24length of the current window, because I'm going to bind this to pageCount just
06:29to show that we can.
06:31With the slider selected, go to the Bindings Inspector, and again I want to bind its value.
06:36So, select to bind that to AppDelegate, and the Key Path, self, referring to
06:42App Delegate, .singleBook which is inside property of AppDelegate and then inside that, pageCount.
06:49Running that, the slider has immediately jumped up to the top, because it's
06:53been set to the same value as the pageCount which is 315 for this object, and
06:58by default, the slider only goes from 0 to 100, so it's as high as it could possibly be.
07:03What I will do is I will jump back into Xcode and just set the attributes of
07:07the slider so it has, say, a maximum value of 500.
07:11In interface builder, it's currently set to 50, but that doesn't matter because
07:14as soon as this application loads, we'll actually get it jumping to the point it should be at.
07:19I am going to change one more thing here which is of the slider.
07:23I am going to select to make it continuous. Run this once more.
07:26It does appear as if the slider is currently stuck at 100.
07:30Let's just go back and make sure that took effect here.
07:37That looks better now. It just didn't have the proper impact.
07:40There we go, 315 which on a 0 to 500 slider would be about there.
07:44But if you notice, as I move this up and down, any control that we have bound to
07:49that value is being updated.
07:52This would also work if I say dragged on a text field and typed into the text field.
07:57They're all connecting, they are all talking to each other.
08:00And be aware that right now, I'm not just changing the value of the user
08:03interface, I am changing the object's value here, and this is the flip side of
08:08key value coding is key value observing.
08:11These controls change the object, and the other controls that are linked to
08:15it, in this case the label, is observing that same key and being notified when the value changes.
08:21And that's the power of binding.
08:23If the object changes, the user interface changes, if the user interface
08:28changes, the object changes, they are bound together.
08:31And there is no code in this application that deals with tying that object to
08:36this user interface.
08:37We have no delegation, no target action, no IBActions, no IBOutlets, no event
08:43handling, just binding, and this is what makes it such a powerful technique, even
08:48with this example, which is very simple.
08:50And while this is still good, binding gets even better.
08:53So next, we'll talk about binding our Data view controls like the Table view.
Collapse this transcript
Binding more complex controls
00:00For simple binding examples, we can bind directly to an object declared in the
00:04app delegate, as we just did.
00:06But as we get more advanced, that won't be good enough.
00:09Now first realize the role that I'm talking about here.
00:12We are still doing Model-view controller. We have go the user interface view
00:16object, something even as simple as a text field.
00:18We have go to model, the actual data, and with the bindings, we can minimize a lot
00:24of the glue code in the middle and the controller, but we can't, and we don't
00:28want to remove it from the picture, it's still a vital part.
00:31So in that previous simple example, we still went through the AppDelegate as the
00:35Controller to act as a middleman between the user interface view Objects and the
00:40Model Object, in this case, one Book object, and again, there was nothing in the
00:44Book object that knew anything about a user interface element.
00:48So it's this bit in the middle I'm talking about here, the Controller.
00:52We have already seen earlier in the course that yes, we can use the
00:55AppDelegate as a controller.
00:57We can create a regular Objective-C class to act in the role of controller.
01:02But there are several classes built into Cocoa to help us in the role of
01:06controller when we're using bindings.
01:09In a more complex situation where we have complex view objects like table views
01:14that we want to use, and complex model objects, arrays, dictionaries, objects
01:20that contain other objects.
01:22We need to ask a few more questions about what's in the middle.
01:25And the key question we need when choosing between the options is first, what
01:29kind of data do you have? What is your model? Is your model object a single object?
01:34Is it a collection, like an array or dictionary? Is it a complex tree of
01:38objects with parents and children?
01:41Because we have some choices about what we can put in the middle, in the controller role.
01:46For single objects, we have something built into Cocoa called the Object
01:50Controller, NSObjectController class.
01:54If you have an array, we have an Array Controller,
01:56we have a Dictionary Controller, and even a Tree Controller for complex trees of objects.
02:03And using these in the controller role can make binding these complex controls much easier.
02:09What they do is stand between the user interface view object and our model, our
02:13data, helping us not just blind, but sort and add and edit and delete.
02:18But how do you use these?
02:20One easy way is that they are already there in Xcode.
02:23If I go into my Object Library, into the Objects and Controller section, I will
02:28find them listed here.
02:30Notice the description here, Object Controller is a Cocoa bindings
02:34compatible controller class.
02:36Bindings Compatible Controller class, Bindings Compatible Controller class for
02:40the Object, Array, Dictionary and Tree Controllers.
02:42There's even a User Defaults Controller to allow us to bind to the user
02:47defaults in OS X. Now these on non- visual Objects, but we can drag them on to
02:53the Dock, like dragging on the blue object box that we have done a couple of times earlier.
02:58In this way connect them between on model objects and our user interface view objects.
03:02Now there's a common misconception I sometimes hear, and I want to clear up.
03:07Is that some people come in to this thinking
03:09you can only have one controller object per window that you must choose what is the controller object.
03:15And that's not true, you can have as many as you need.
03:18Now I occasionally hear this from people who are used to working with MVC where
03:22it's formalized a certain way, even in iOS, where it's very common to have one
03:27controller per view, one controller object dealing with all the user interface
03:31elements on a particular screen.
03:33And that method can work very well, but MVC does not force you to do it that way.
03:38Think about it this way, you can have way more than one view object on this window.
03:42We know that. We can have text boxes and buttons and text views.
03:46In fact, the window itself is a view object.
03:49A menu is, a menu item is, and we know they we can have more than one model object.
03:55We could have an array of books, an array of authors, complex classes being
03:59used on this one screen.
04:00In the same way we could have more than one controller if it helps.
04:04If we had, for example, two arrays of different objects, we might drag on two
04:09different array controllers into our Dock and use those as the middleman, in
04:14between the user interface elements and the data itself.
04:17Now it still sounds a little abstract, so next step, let's see a demo.
Collapse this transcript
Using NSArrayController with table views
00:00Now let's see how to connect more complex objects to more complex user interface elements.
00:05I have a simple project that I have created to get us ready to get started here.
00:09Just to explain what I have, it's that Book class again about as simple as it
00:14gets, two NSStrings and an Integer.
00:16This Book class has no implementation we're speaking of, although I have added
00:20an init method just to begin with an author and title that have some basic
00:25information in those strings, I'll show you why in just a moment.
00:28There's not much else going on. In the AppDelegate, I have an NSMutableArray
00:33called allBooks that can hold multiple book objects, and I have created one
00:38listBooks IBAction method that's going to have just some simple code that will
00:43NSLog the contents of the array out so that we can see any difference between
00:47what we're seeing in the user interface and what's actually stored in the array.
00:51And the last little piece of code worth exploring is in the implementation of AppDelegate.
00:55I have added an init method, and as soon as this class is being initialized, I'm
01:01creating this mutable array, and then I'm creating two instances of the Book
01:06class and adding them to the array. We have seen almost all of this code before.
01:11All I have currently on the interface file is one button that says List Book Objects.
01:16If I go ahead and run this, click that button, there will be no surprises.
01:20I just simply write out a very straightforward NSLog message for each object.
01:29So I am going to stop that application.
01:31So at no point anywhere here is there any code that deals with user interface
01:36elements, writing any of this content out apart from that NSLog message.
01:40So let's start hooking things up.
01:41I am going to open up my Utilities Panel, and from the Object Library drop into
01:46Data Views where I'm going to drag on a Table view.
01:52This is the one that beforehand we had to hook up, create a data source and
01:57implement certain named methods to be able to provide data for every single row
02:01and every single column.
02:02We're avoiding that whole approach and using binding this time around.
02:06Now here's the thing, this Table view does have a Binding section and Inspector, but I can't just bind
02:12it directly to that array in the AppDelegate.
02:15I want to use a different controller to be between this Table view object and
02:20the NSMutableArray of books, and here's how we're going to do it.
02:23From the Object Library, I'm going to select the section called Objects &
02:27Controllers under Cocoa, and here we have the Bindings compatible controller classes.
02:33We have an array, so this Array Controller will work just fine.
02:37This is a non-visible object, so you drag it into the Dock rather than on to the interface.
02:42Remember, this is a controller, it's the middleman, so there are two connections that need to be made to this.
02:48I need to hook this controller to the actual NSMutableArray to the data, and
02:53then I'm going to hook the Table view to this controller.
02:57If both of those things are done correctly, it should just work.
03:01I'll expand my inspectors and make sure that Array Controller is selected.
03:05In the Bindings Inspector, what I'll see is that I have a section
03:09called Controller Content.
03:11This is an array controller, so not surprisingly it's looking for an array to handle.
03:16So it's asking, where is my Content Array, where is that?
03:19Well, that array is the allBooks array that's being stored right now in
03:23the AppDelegate class. So I am going to select to Bind to:
03:26App Delegate, and we're using the key idea out of key value coding.
03:32So self refers to the AppDelegate, but if I hit the dot, it should look into the
03:36properties that are available which includes the NSMutableArray of allBooks.
03:39So our Array Controller is now pointed to our Array Model Data.
03:45Now, one thing I do want to do here is switch into the Attributes Inspector here
03:51because there are some attributes of this Array Controller that I want to change,
03:54too, which is I'm going to tell it exactly what that array contains.
03:59It starts off with this generic entry of an NSMutableDictionary, but no, I want
04:03that array to contain books. I know that is all that, that array contains.
04:08And that will make it easier to hook it up to our Table view.
04:11So that's one side done, the controller is hooked to the model.
04:14Now, the controller needs to be hooked to the view.
04:16So I am going to select the Table view itself.
04:19Remember that whenever we drag on a Table view, what we get is a Table view
04:22inside a Scroll view.
04:24So, I can click again to select it, but if I want to be doubly sure, I will use
04:29the Dock here and expand to make sure I am selecting the actual Table view
04:33itself, not the Scroll view - Table view, and I'm going to bind this.
04:38So jump over into the Bindings Inspector, and it's asking okay, what's my content?
04:43And the main one I'm interested in here and Bindings is the table content.
04:47It's asking, what am I binding to?
04:49Well, this time it's not to the AppDelegate, we are binding the Table view to
04:53the Array Controller. So that's correct here.
04:56We're saying Bind to the Array Controller, and that's all I actually need to do
05:00right now because the Array Controller contains those book objects.
05:03Now, you might be thinking, well, does that mean that everything works?
05:07No, nothing would happen yet because the objects that we have in that Array
05:11Controller could be significantly complex.
05:14We might not want to show everything on this Table view.
05:17So what we have to do next is say what appears in each column of this table view.
05:22Well, right now I drag this Table view on by default, which means it's only got
05:26two columns. I'd like it to have three.
05:28So again making sure the Table view itself is selected, I am going to switch
05:32over into the Attributes Inspector and give it three columns.
05:36And then I want to go column by column saying once in each one, so I will expand
05:41the Table view itself.
05:43Select the first column, and I need to go to its Bindings Inspector and tell
05:49it that its value should be coming from Array Controller, and we're looking
05:54for author. As I start typing it should bring that up because it's looking
05:59inside the Array Controller, it knows it's full of books, so it should tell me the properties.
06:04So, author is correct for that column.
06:06Then I will select the second column, bind that to title, and then I will select
06:14the third column and bind that to page count.
06:20Third column is hidden a little bit here, so I am going to see if I can drag it
06:25a bit wider, and grab hold of that.
06:29Then I should be able to click in and just resize that a little bit.
06:32I am just going to go ahead and press Command+R to run this.
06:36We're opening up our Table view, we're binding, we have got that Array Controller
06:40in the middle that's hooking everything up correctly.
06:43Now, here's one of the great things to this.
06:45If I'd click the button to List Book Objects, we'll just run through that array
06:49and pop out the idea that, yes, this book has 315 pages, and this has 280, but
06:55this is editable by default.
06:56So I can double-click on this and just type in 250, and I am not just changing
07:01the user interface, I am changing the actual object.
07:04So if I press the button again, we'll see we now have 250 pages and 280 pages.
07:10And that's because by default, the Table view hooked up to the Array Controller
07:14does support editing.
07:15You can turn that off if you want to, but it can be very useful.
07:19Well, let's take it a little step further.
07:21I am going to quit out of that and back into the interface.
07:27I'm going to add a couple of buttons here for adding and deleting from that array.
07:32I will jump to my Control section, and what I'm going to use here will be a
07:38Gradient button, which by default has text, but I don't want that, so I'm going
07:46to switch that in my Attributes Inspector and get rid of the title and then come
07:51down to the Image section where I'm going to select from the NSAddTemplate which
07:56is the classic plus button here. Doesn't quite need to be that wide.
08:00So I will make it a bit smaller and then do an Option-drag to copy that, change
08:06the second button to the NSRemoveTemplate, which is the classic minus sign. Well, now what?
08:12Well, usually, what we think about doing is hooking things up to code, writing
08:19some code, calling methods.
08:21What I can actually do is here use IBActions, they're still very useful in this
08:25situation, but I'm going to Ctrl-drag from the plus button over to the Array
08:32Controller because the Array Control that's holding all that data is smart.
08:35I'm going to let go and the Array Controller has these received actions because
08:41it's set up, it understands what an array needs to do which is often insert or
08:45remove or select next or select previous.
08:48So we're going to say Add.
08:51Then I'm going to select and Ctrl-click from the minus button, drag over array
08:56controller, let go, and select Remove.
08:59Go ahead and run this. We still have the editable idea that we can switch any
09:05of these around if we want to, change Under the Moonlight to 200 pages, and
09:10yes, it has 200 pages, but I can click the plus button, and we actually get the
09:14new object inserted. I could click that a couple of times.
09:20We can double-click in there and start adding new title and so on, and it all is
09:26changing that I actual Mutable Array.
09:29So if I am spitting out the output here, I'm seeing all the different objects.
09:33So we're truly affecting the mutable array, not just in the user interface, all
09:38done without code, without connecting this Table view as a data source and then
09:42writing multiple methods to provide the data for each column and each row all
09:46done through bindings, displaying, editing, adding, removing.
09:50We can use the Remove button and just get rid of the two that I don't want.
09:55Now sure, as the situation gets more advanced, we would add code perhaps to
10:00validate what's entered or perform certain actions when a row is selected.
10:04But as an example of binding a Table view, these are the fundamentals.
Collapse this transcript
7. Debugging and Troubleshooting
Using the Xcode Debugger
00:00We have used a few simple troubleshooting techniques like using NSLog to send
00:04messages to the console, and we have talked about diagnosing the most common
00:08issues when hooking up your IBActions and IBOutlets correctly.
00:12But once you're past that, sometimes it's not quite so clear where the problem
00:16is, and you don't want to start writing dozens or hundreds of NSLog messages, so
00:21you want to be able to step through the code line by line as it executes.
00:24And we're going to do that now using the Xcode Debugger.
00:27This is just a brief introduction. If you have already been using the Debugger in
00:31iOS, I won't be telling you anything you don't know already.
00:34So I have got a simple Cocoa application here called DebugStarter and looking at
00:39the MainMenu.xib file, I have got a button here conveniently titled Boom! and a blank label.
00:45Now that button calls some very straightforward code and a method called doSomething.
00:50It creates a couple of integers by calling some inner methods of this class, and
00:56then it divides one by the other, creates an NSString and spits that out to the
01:01label, some fairly simple stuff there.
01:03In fact, this code is all syntactically correct. It will compile if I hit
01:08Command+B, it'll go through and succeed, there is no problem there, but it is going to crash.
01:13So let's go ahead and run it. I came over to the button, I click it.
01:20Now because we ran this directly from Xcode, we're jumping back into Xcode with
01:25all these great Debugger options appearing at the bottom of the screen here.
01:29Our application is still working. It's paused so we can view the inner
01:34workings of what's going on.
01:35So I have got the lower section showing up, if it's not you should be able to get
01:40to it from the view section here.
01:42And there's a problem, I can see immediately by this highlighted line, line
01:4539 here, EXC_ARITHMETIC, we have some problem with Arithmetic. Okay, we'll get to that.
01:52Now, over on the left-hand side what Xcode has jumped us to is the fifth
01:57navigator here which is the Debug navigator.
01:59It's showing us a stack trace, basically a list of where we are and how we got
02:05here, and it's the most recent at the top, this the main thread here.
02:09So it's telling us we're in the doSomething method of AppDelegate but we got
02:14here very gradually from NSApplication, NSApplicationMain and Start.
02:19Now towards the bottom I have this slider here, and if I actually start dragging
02:23that to the right and then to the left, what you'll actually see is different
02:27levels of the stack trace.
02:30And that can sometimes give you a clue of how we got there, but right now most
02:34of these are really internal plots. We have the main method that called
02:37NSApplicationMain which hopefully remember from our lifecycle discussion, and a
02:41lot of the rest of the stuff going on here is basically being handled internally
02:45by NSApplicationMain. It's waiting for events.
02:48It's running, it's gotten a mouseDown, and it's kicked that mouseDown over to
02:51our doSomething method.
02:53So I don't need quite that level of information on my stack trace. I'll drag it to the middle.
02:58We just know we touch the button, it called our code, and there's a problem.
03:02Now in the lower section here in the debug area I have the split between the
03:07variables view and the console. Console is telling me lldb here.
03:12We're using the low-level virtual machine debugger.
03:15Used to use gdb, but from Xcode 4.4 onwards we're using lldb.
03:20On the left-hand side I can see a list of Local Variables, and I can also use
03:25the dropdown here to move between the Local Variables which is what's shown
03:29automatically and All Variables, Registers, Globals, and Statics.
03:33If I want to, and it's easier I can also mouse over the code to see the different values.
03:40Mousing over firstVal here tells me it's 10,000, mousing over the second
03:44one tells me it's zero.
03:46So there's the problem. We're trying to create an integer on line 39 by dividing
03:5110,000 by 0, and that's an issue you can't do a divide by zero on a computing
03:56system, that is a problem.
03:58But let's imagine that it's a little bit challenging to figure out exactly where
04:02did these values come from.
04:04SecondVal is zero that's a problem, but how did I get secondVal.
04:07So what I'm going to do is hover my mouse over the gutter section here, the gray
04:11bar beside the line numbers, that's if you have line numbering on.
04:15I'm going to click in here before the call to calculateFirstValue.
04:19When we set a breakpoint, we will break before this line is executed right at the start of it.
04:25Now because this program version isn't working, I'm just going to hit the Stop key here.
04:30So if I click in this gutter, I get this bright blue icon, which means it is a working breakpoint.
04:35If I click again, it becomes somewhat dimmer, which means it's just not active right now.
04:40And you can kind of flip them back on and off.
04:43If I wanted to delete the breakpoint, I can just drag it off to the side and let
04:47go once I see the cloud icon. But I want it, so I'm going to put it back.
04:52If you actually start adding multiple breakpoints all up and down different
04:56parts of your code, and be aware that you are breaking before the line that the
05:01breakpoint is pointing to.
05:03If I had a lot, I can actually go to a different section of my navigators
05:07here, the Breakpoint navigator is the one that actually looks like the little
05:10blue marker points here, and it will give me another view of all the
05:14breakpoints in this project. What line they are on, what method they're in.
05:19I can delete them from that view, or I can drag them off, and you can actually
05:23see them disappear as I do that.
05:24So I'm going to go ahead and run this with my one breakpoint just in the first
05:28line of the doSomething method.
05:30Our program is going to run normally because we haven't hit that code yet, it
05:34won't happen until I click the button. So I click it, we jump into the break mode.
05:39We're positioned before line 36.
05:41So if I hover over this, we're not going to get any kind of meaningful value here
05:45because I haven't run this line yet, this integer hasn't been initialized.
05:49Down towards the middle section here, I have got the Debug bar that's going to
05:53allow me either just keep going until the next breakpoint, to Step Over the
05:58instruction, and that simply means execute it, but if it was calling a method
06:03don't go into the method, and then we can decide to step into the instruction.
06:08So in this case what that means is if I'm calling calculateFirstValue, which is a
06:12method in this current object, I'm going to hit the Step into, and we will
06:17actually jump into that method, and to calculateFirstValue, I can keep going,
06:22that returns 10,000, and that looks right.
06:24What I should expect now when I am mousing over there is that value is 10000, looks good.
06:29Then I'm going to jump into the next one, which is calculateSecondValue.
06:32There is a bit more going on here. I'm creating an integer called zero.
06:38Integer b here is about to call the calculateFirstValue method again.
06:42I don't want to go into that, I saw it a moment ago, so what I will do instead
06:46is use the Step over version, which still means we called it, we did execute
06:51that line, but I just didn't want to go into that method and look at it.
06:54To prove we did execute it, I can actually see the b down here and our variable
07:00section is set to 10,000, or I could mouse over and see it that way.
07:04So stepping forward, it looks we're in a fairly boring for loop here.
07:11And unfortunately this is going to go around 5000 times right now.
07:14I don't really want to click 5000 times, as it ticks down, so what I'm going to
07:21do is just step ahead and put a breakpoint before the return statement, and
07:24click the Play button to move ahead to that point.
07:27And looking at this, this appears to be the problem.
07:29And we're going to return zero from that. We're saying return a, and we should
07:33really have return the variable called b so there was actually some value.
07:38Okay, so that was our problem. What I'm going to do is just stop.
07:41That was a little quick, so it thought it quit.
07:45Ignore that, I'm going to drag of my breakpoints and say that here I should be
07:49returning b, and in fact I don't need that integer a line.
07:53Of course this was just a constructed way of causing a problem, but you get the idea.
07:59We go ahead and run it, and now our code is executing correctly, that 10,000
08:06divided by 5000 is 2.
08:08And that's a simple introduction to the Debugger.
08:11However, as we'll see in the next movie, sometimes a couple of other things you
08:15want to tweak about that.
Collapse this transcript
Creating an exception breakpoint
00:00So you just saw how to use the debugger to analyze something like a divide by zero situation.
00:05There is actually a problem with using divide by zero, it's a little too
00:09obvious, not just to us but to the computer itself, because if you have a
00:13divide by zero issue, you will actually immediately break into this situation
00:18with the EXC_ARITHMETIC, because it's a very low level, what's called a signal
00:24that it is sending to the computer itself, we can't go any further than this.
00:28But some other cases, the program will actually try and continue on, and you
00:33won't immediately stop on the line that caused the problem, you actually break
00:37when Xcode figures out you can't go any further.
00:39Now there is a couple of different ways that might manifest itself, but let me
00:44show you one of them.
00:45I'm just going to stop this running application and go and fix that divide by
00:49zero exception, which was just returning the variable called b instead of the
00:54variable called a, and then I'm going to go ahead and run this.
00:58I have created the project that has another error in it that's not necessarily
01:02quite so obvious, so I'm going to click Boom!
01:06And instead of jumping into a specific line with a nice green highlight, what
01:10we are getting down here are some error messages being sent out here to the console.
01:15Now sometimes you can diagnose a message from that--I'm just going to widen
01:20this so we can see more about it. We have got mouse downs and sand effects, it's
01:24basically our call stack going on.
01:25And it does appear that we have got an index beyond bounds.
01:29But it's not telling me exactly what line I am looking at.
01:33Now, I could probably figure it out from this line here, because I've got a very
01:37simple application, but there is a better way of doing this.
01:41We can tell Xcode that we want to break immediately, as soon as any exception
01:47happens, as soon as anything detectable causes a problem.
01:51This is the way we do it.
01:53I'm going to stop the app and just clear out my console, I don't need that right now.
01:58I'm going to jump into the breakpoints navigator, that's the one that looks like
02:03breakpoint symbol itself.
02:04Now I don't actually have any breakpoints right now, which is why nothing is
02:08showing up here, but I'm going to add one.
02:10And what I'm going to add is not a breakpoint for a particular line, but I'm
02:15going to add what's called a General exception breakpoint, telling Xcode I want
02:20to break if there's ever an Objective-C exception.
02:22I do this by coming down to the plus button at the bottom of that breakpoint navigator.
02:29So again, I am on the second to last section here.
02:32And I click Add Exception Breakpoint. It gives me a pop-up window.
02:35What kind of exceptions do I want to break on? I'm going to say All of them.
02:40I could choose to do just Objective-C or C++. And Break as soon as the exception is Thrown.
02:46Optionally, I can click to add an Action, like play a sound or run a command,
02:50but I'm just going to leave everything as is click Done.
02:54So I'll now break on All Exception, I'm going to go ahead and click Run, back to
03:00the app, click the button again.
03:03Now we immediately break, but we are breaking on the line that caused the problem.
03:08What's actually happening here is online 42 I am creating an array with three
03:12elements in it, which would be 0, 1, and 2, and then I'm trying to access what's at
03:17position 3, what's at index 3? Well, there is nothing there.
03:20So that's the actual problem here, and we are now breaking at the line that
03:24caused it, so it's much easier to diagnose.
03:27I need to change that it 2 and Stop it and Run it again, and we are looking good.
03:37So if you're finding that when you're running is that you're not stopping in the
03:41most helpful place, try this technique, go in and add an exception breakpoint in
03:47Xcode to make sure that you are actually stopping as soon as possible.
Collapse this transcript
Using assertions
00:00One useful technique for troubleshooting in Cocoa is using Assertions.
00:04Assertions help you find bugs earlier than you would otherwise.
00:08At a particular point in your code you can add Assertions.
00:11You assert something, you say at this point something should be true.
00:15A variable should be greater than 1,000, or a string should be a certain
00:18value, an object should be not nil.
00:21And if what I have asserted is false, that's a problem.
00:24So here I have a very simple method called doSomething being called by a button click.
00:30It itself is calling this complicatedCalculation method.
00:33Now I might imagine there's an awful a lot going on here, but what I'm going
00:38to do is after our for loop, I'm really hoping that the variable foo is equal to 5000.
00:43In fact, that's what I want to assert.
00:46And I create assertions like this with a single call to NSAssert.
00:52It's a very simple line, it looks like a function call, and you can't think of it
00:56like that, but technically it's a macro, and that's very useful for a reason
00:59I'll explain in a moment.
01:01NSAssert takes two parameters, what are you asserting, what is the condition
01:05you're saying is true, phrased like a condition in an if statement.
01:09So for me I'm going to say I expect the variable foo to be equal exactly to
01:145000, that's what I'm asserting. Then the second argument is the string.
01:19It's the message that should be logged if what I'm asserting is not true.
01:24So I'll just do this as an NSString here, the variable foo is the wrong value.
01:33So what happens is we're going to execute this code, we would come through this
01:36for statement, we'd hit line 24.
01:39And if what we see, what we have asserted is true, nothing happens, we simply move on.
01:44However, if what we say what we have asserted is false, it will raise an
01:48exception, and it will log this message. And we could of course do this otherwise,
01:52fill our code with if statements, but this is a compact readable way to do it.
01:57So I'm going to go ahead and run the application.
02:01Click the button to Check Value, the value is 5000, nothing happens.
02:06Everything is as I said it should be, and we just continue.
02:11Quitting and going back into that, what I'll do is pretend we have made a slight
02:15change to the logic of our program. I'll just make a quick tweak to the for
02:19loop and run this again.
02:22Now I click the button, and we instantly jump into the problem.
02:25I don't know if you saw here, but we're getting the messages being logged out
02:29here to the console, including that the variable foo is the wrong value.
02:33And this is important to understand, bear in mind when we use NSAsserts, this is
02:37not casual informational messages like you might do with NSLog.
02:42If an assertion fails, it throws an exception. It's a real problem.
02:46What you're saying is true, it should always be true, this should never fail,
02:50and it will cause your app to stop. And that's what we want here.
02:53The reason that we do it as we're making these bugs more significant as early on
02:57as possible, and it's a great technique for developers.
03:00If we're going to fail, fail as soon as we can.
03:02Let us know about the problem early, so I can fix it, rather than return this
03:07value and pass it perhaps 10 levels deeper before we fail later on.
03:11Now, for example, I wanted to find out what the value of it was, we can
03:15actually call multiple different versions of Assert, there's NSAssert1,
03:18NSAssert2, and so on, just taking a different amount of format specifiers and
03:25parameters after the fact.
03:26So if I wanted one parameter, I would use NSAssert1 and just change my string
03:32here so the variable foo is %i and pass that in.
03:39This time around when I run it, the message should just say: The variable foo is
03:444999, so very easy to add a very compact succinct way to do this.
03:52And one of the great things about this is that because NSAssert is technically a
03:57macro, here is one of the great things about it over, say, a function like NSLog.
04:01We can pepper our code with these assertions, we can put them anywhere we think
04:06is useful, and while we're developing, they come in very handy, but it's pretty
04:10easy for us to add a small parameter to our Build Settings in Xcode.
04:15I haven't talked much about Build Settings yet, but we'll be doing that in the next section.
Collapse this transcript
8. Distributing an Application
Archiving an application for distribution
00:00So how do you get your Cocoa Application to somebody else?
00:04Let's say there are two situations here, first, the informal idea.
00:07You have created an app, even a simple one, and you just want to run it on another
00:11machine or even email it to a friend or colleague.
00:14And then there is the formal idea, you have worked for months on your application,
00:18and now you want to prepare it for distribution, either free or selling it
00:22yourself or of course, on the Mac App Store.
00:25Now we begin all of this the same way, by taking our project and archiving
00:30it, and when we're in our project in Xcode, we find the Archive option from the Product menu.
00:36Now archiving might sound like an odd thing to do.
00:38If you think of archiving, it's something you do to put some old files in
00:42backup and forget about them.
00:44But what we're trying to do is formally bundle our application up at a point in time.
00:50An application archive for us is the application at a certain date in a
00:54certain state, so we may end up creating multiple archives at multiple times,
00:59but each time we intend to distribute an app formally or informally, we create an archive.
01:04So I'm going to select the Archive option from the Product menu. It creates an
01:08application archive and by default we'll open the Archive's Organizer.
01:12This is actually not a new Window;
01:14it's the same organizer window you would use for Documentation or for
01:18source code repositories.
01:20And every time we archive the application, we'll have a new entry show up here.
01:25The application at a particular date and time.
01:27There is not much you can do on this window apart from add a Comment, perhaps I
01:32am creating a First try one for testing here.
01:35I can also choose to right- click this and Delete the Archive.
01:38If I choose to Show in the Finder, I'll see this Xcode archive file. This is
01:43actually a compressed file, we don't need to go into it, but you can find it
01:46there in the Finder.
01:47Here is the two things I'm interested in are the buttons at the right-hand
01:52side to Validate and Distribute our application. What we should first do is Validate it.
01:57When we do this we have two choices:
01:59Validate for the Mac App Store, or for Direct Distribution.
02:03Now Validation doesn't do a tremendous amount, it's not validating your code
02:08just mainly doing some basic checks on the application.
02:12If you Validate for the Mac App Store, you're going to need to give it your Mac
02:16app credentials, and you need to have created an entry in iTunes Connect for
02:20this application, which means you have already got your Mac Dev account, you have
02:24gone through all the contracts arrangement setting up a company name and so on.
02:28That's not necessary for us here, so what I'm going to do instead is Validate
02:32for Direct Distribution.
02:33This will perform a few simple checks. It's telling me that the archived
02:38application doesn't contain an icon. I haven't got a custom icon for this app yet.
02:43Well, I'm going to do that in a little while, so let's skip that for now just
02:47say Finish, and we'll see in the Status field here that we have Failed Validation.
02:52Doesn't really matter because I can choose to go ahead and distribute it
02:55anyway using the default application icon.
02:59So I'll click Distribute, and again, we get a few different choices, do you
03:03want to Distribute for the Mac App Store, Export it with a Developer ID-signed
03:07or some other option?
03:10Now these options do often change in wording and in arrangement, they have changed
03:14between Xcode 4.2 and 4.3 and 4.4, so I don't guarantee that what you'll see
03:19will be exactly the same as what I'm seeing.
03:22Well, I'm going to go as informal as I can, and in this dropdown I have the
03:27option to Export as an Xcode Archive.
03:30That's not what I want. I want to Export this as an Application.
03:34I don't need a Mac Installer Package.
03:36That's not necessary, and it's not necessary for most applications.
03:39Well, I do need to be aware that with the release of Mountain Lion in 2012 with
03:45the security features called Gatekeeper, if I don't sign this app with a
03:49Developer ID, anyone with Gatekeeper set to require a Developer ID won't to be
03:54able to run this unless they change their settings, we'll talk more about
03:58Developer ID in just a moment.
04:00So, I'm doing this at the most informal level, say I just wanted to send this
04:04app to a colleague on the same team, we both know what's going on, I could
04:08even choose not to sign it at all, so I'm going to click Next, and select to Don't Re-sign.
04:13Depending on the level of development you have done your particular machine, you
04:17may have multiple signing identities available in the dropdown box based on what
04:21you have created from your Mac Dev account or your iOS Dev account.
04:26But I'll choose to not to re-sign it, click Next, and so it's going to ask,
04:30where do I want to save this?
04:32I'll put it on my Desktop and click Save. Just go now and minimize that and all
04:38we have is the application.
04:40The reason I have got a folder called Metronome is that's just where I had the
04:43project that I had opened.
04:45This is our app with its default application icon.
04:50Archived, Validated, set up for Distribution. I could email this to someone, put
04:54it to on a share drive, put it on a web site, allow people to download and run it, it's ready to go.
Collapse this transcript
Working with debug and release builds
00:00So we need to archive our applications during the process of distributing them,
00:05but technically we could do a little more informally. You may have noticed that
00:10with something like a simple "Hello, World!" level application,
00:14when you build the application, it is already built as a Cocoa App.
00:17If you expand the Products folder in your project navigator, you'll actually
00:21find the application itself. I could right-click and choose to Show this in the
00:26Finder, and you could take this file just double-click it to run it, whether
00:30Xcode is open or not, or even copy it to another machine and run it there, but
00:35this really isn't the way to do it.
00:37Because when we build, when we choose to run our application or hit Command+R to
00:42do that, what we're doing is running in debug mode, using a Debug Build.
00:48Your project has been compiled and linked together with symbolic debug information
00:53that's useful to us as developers but not to the end user. Might have things
00:56like the state of the breakpoints in the application.
01:00Now when we instead choose to Archive our application, we're using a Release
01:05Build instead of a Debug Build, and that does not include all the hooks into our
01:09code that the debugger needs.
01:11Now it still does have some symbolic information which might help us
01:15diagnose crashes in a Released app, but it compiles and builds with a
01:19different set of options.
01:21So these Debug and release Builds are already set up in Xcode.
01:25They are already configured for a typical application.
01:29If I want to change anything about them, I can go to the Project settings and
01:34find the Build Settings for this just by clicking the top level icon with the
01:38project name in the Project Navigator. In this section we have Build Settings.
01:43Now you'll actually find Build Settings under the both the Project selection and
01:48in the Target selection.
01:50A common question I get is what is the difference between the two?
01:53They both have Build Settings.
01:55Now for an example like this in a new Cocoa Application project, not really any
02:00difference at all. We have one project, this entire project, this application
02:04that we're building that creates one target, the actual compiled application.
02:10In a more complicated project, you might have multiple targets, and each
02:15target could have slightly different build settings from the default project build settings.
02:20Now particularly early on in your Cocoa career, you can leave everything here as is.
02:27If I decide to scroll through the Build Settings, and I can choose either the
02:30basic ones or click the All button here to see all of them, there are a lot of options.
02:36Again, most of them you don't really care about.
02:39What you'll find is that with a few, not many, there are different options for
02:44the Debug and Release.
02:48Coming down, for example, into the Preprocessing section, I have different
02:51Preprocess or Macros for Debug and Release, and one of the few things I might
02:56change, which I mentioned earlier on in the course is in the Preprocessor
03:00Directive section, and you can either scroll through this, you can also use
03:04the search filter button at the top here to filter down to anything that matches those words.
03:11If I'm using Assertions, that I'm using that NSAssert call in my code, what I
03:16can do is make an entry here by double- clicking the Release section, click that
03:21plus button, and I will add in the NS_Block_Assertions entry.
03:31This written in uppercase with this particular format will strip out any of the
03:37NSAssert calls in my Release build. But one of the questions might be, how do I
03:42know what I'm using, how do I know if I'm using a Debug Build or a Release
03:45Build, where is that option?
03:47Well, that's already set up in Xcode 2, and it's in what's called a Scheme,
03:52a collection of settings for the different things you want to do with this project.
03:56Now just to show where those are, if I come to my Product menu, we have got some
04:02Edit Scheme, New Scheme, and Manage Schemes, we already have a scheme for this application.
04:06You can either get it from this menu or you can get it from the
04:09schemes dropdown box. By clicking on this, it'll allow me to see that I have got a
04:14scheme for this application called Metronome running on 64-bit, I can actually
04:19jump in to edit it, so either from the dropdown box or from the Product menu.
04:24And what this scheme is showing me is that I have multiple configuration
04:28settings for what happens when we Build, what happens when we Run, what
04:33happens when we Test, what happens when we Profile or Analyze, and what
04:37happens when we Archive.
04:38Now in this course we don't really get into the whole idea of testing or
04:42profiling, those options are also available from either your Product menus or by
04:48holding and clicking on the Run button.
04:50I'm interested here in the difference between Run, because when we Run, what
04:54we're doing is we're using a Debug Build. I can also change here that I'm using
04:58the LLDB Debugger, I could choose to use the GDB Debugger instead. I'll leave it as default.
05:04There is a couple of options here, like does the program Launch
05:07automatically when we're running it, or do we Wait for the app to Launch if
05:11you're manually launching it?
05:13But the important part here is that we're using the Debug Build Configuration,
05:18but when we Archive, when we select that option, we'll automatically be using
05:22the Release Build Configuration, and there is not many options available for us
05:27in Archive other than do I want to Rename that archive from the default project
05:31name, and when I archive, do I immediately want to Organizer a window to appear
05:36with that recent Archive in it?
05:38And early on you don't really have to change anything about this, but
05:41understand that we always have a scheme that allows us to choose what the
05:46settings we're using between Release and Debug Builds, and that will
05:49automatically be what's called when you select to Archive from the Xcode project menu.
Collapse this transcript
Sandboxing an application
00:00Sandboxing is a technique Apple have introduced to help with security.
00:05Say you download a calculator app or buy one from the Mac Apps Store.
00:09Well, think about this, do you want that app to immediately have complete and
00:13total access to your file system, to the network, to your microphone and webcam,
00:17to the devices attached on your USB ports?
00:20Well, of course you don't, but by default that is the way that applications have
00:25worked in the past, they run with the privileges of the user who's running them.
00:30Sandboxing gets us away from this situation.
00:33When we add Sandboxing, simply put, it means that applications are put in
00:37containers by the operating system, by OS X itself.
00:41Sandboxing limits what the application can do down to only what it needs to do,
00:46and it makes you as a developer say up front exactly what it is your app needs to do.
00:52And if attempts to do something else, that would be blocked and Sandboxing
00:56is important, this is now required, if you want to put your app in the Mac App Store.
01:02You have to say exactly where your application needs, there is a set of options,
01:06does it need the webcam? Does it need the microphone? Does it need
01:10access to the network? And you say exactly whether your app should be entitled
01:15to do any of these things, they're referred to as entitlements.
01:19Now in this course we haven't really done anything that would require special
01:22permission, special entitlements, we're not using the webcam or reading and
01:26writing to the file system or using USB.
01:29Now I do have a very simple project that I have created here.
01:32What I have done is drag on a control called the web view.
01:35We haven't used this before, but in essence it's a very simple control.
01:40It really is a little embedded browser control, and all I have done in my AppDelegate
01:45header file is I set up my WebView as an outlet, and then in the awakeFromNib,
01:51what I'm doing here is simply creating a request to lynda.com and loading that
01:56request into that WebView control.
01:59So if I go ahead and run this, we'll see the impact of that.
02:02Not terrifically impressive, we're simply loading in a web page inside that, so
02:07we're actually making a call out there to the network.
02:10I'm going to quit out of that and go back into Xcode. And let's see how to turn on Sandboxing.
02:15Turning on Sandboxing is very simple, and it's very simple even if you do
02:20require certain entitlements.
02:22So I'm going to jump over in my project navigator into the first section here,
02:27and what I'm looking for is the settings for my Target, so I'm in the Summary
02:31section of my Target.
02:32Here is where you turn on Entitlements. I check this box, and what I'll instantly
02:38get over here in the navigator is a simple property list file.
02:42In this case it has one value in here that Sandboxing is turned on.
02:47If you don't see that value, then I'll click back into the Summary section of my
02:51Targets, and underneath it I'm going to have Enable App Sandboxing turned on.
02:57This is where you will affect the Entitlements.
03:00You're going to say explicitly should we allow Camera Access, Microphone, Printing.
03:04Access to the Address Book, access to say the movies file, and just Read Access
03:10or Read/Write Access, access to the Downloads Folder.
03:14So I have turned on Sandboxing, and right now I'm saying I'm not requiring any
03:18of these Entitlements.
03:20I'm going to click the button here to Validate Settings, project settings are
03:23valid, and I'm going to go ahead and build the application.
03:27Now I'm building this, now one restriction is as soon as you turn on Sandboxing
03:31your app does need to be signed of the process of building it, and if you
03:37haven't already set yourself up with the proper certificates to sign that,
03:41you're going to need to spend a little time in the Mac Dev Center making sure
03:45that you get your own certificates generated for development and then installing
03:49them into your Xcode.
03:51I'm going to just say Always Allow, to make sure that it's using my certificates
03:54to sign this application now.
03:57So, we have compiled correctly, that's it, Sandboxing is turned on. I'm going to
04:01go ahead and Run the application, which should immediately bring back that web
04:06page, but it isn't going to do that.
04:09However, do notice that we didn't crash, typically speaking. Blocked access
04:13won't cause the program to crash, it just won't work.
04:16The reason is we don't want the user being bombarded with problems, so there's
04:20not really a lot telling us why this web view isn't working. But I know I
04:25turned on Sandboxing, so let's go and figure out how we can diagnose this.
04:31I'm going to quit out of that, and then I'm going to open up the console.
04:34When I say console, I don't mean the Xcode console, I don't just mean the debug area.
04:40What I'm going to do is go into Console, I'll just use Spotlight to get there,
04:45and you'll actually find that Console is available here.
04:48I'll click that and open it up.
04:50This is giving me all the console messages for OS X itself, for this operating
04:54system, this computer.
04:56Now what I'm going to do is make sure that all messages are selected by the
05:00system log and then over here in the String Matching section, I'm going to type
05:04in the word Sandbox, and to filter even down, you can put sandbox with the D at
05:09the end, and what I'm actually seeing here is some messages that these are
05:13Sandboxing messages for this particular program, in my case, it's called
05:17SandboxExample is the name of my application.
05:20And what's happening is we're getting this denied network-outbound call, we're
05:25not being allowed to call out to the network, we're being shut down.
05:29So, I need to go and fix that. I'm going to quit the Console, go back into my
05:33Project and in the settings here, I'm going to say yes, I want the Sandboxing
05:38on, but I need to allow outgoing network connections and the difference here
05:42between outgoing and incoming, it doesn't mean that we can't reach out to the
05:47network and bring back some contents from say web page, but I do mean that my
05:51app is not responding to incoming network connections. It doesn't need to do
05:54that, so I don't want to support that.
05:57So we do that check box and then go ahead and run this again, and now we are
06:04able to call out to the network and retrieve some contents there.
06:08So Sandboxing is as of now--June 1st, 2012--is required for all new submissions
06:14to the Mac App Store, and it is highly recommended for every application.
06:18This is the basics of how to turn it on, how to diagnose any problems with it.
06:23If you do need to know more, take a look at the application Sandboxing details
06:27on the Mac Dev Center.
Collapse this transcript
Using Apple's Developer ID
00:00I have mentioned Developer ID a couple of times in this course, particularly when
00:04talking about archiving and creating a distributable version of our app.
00:08Developer ID became important in 2012, along with Sandboxing, and the reason
00:13that it's important is that in Mountain Lion there is a security feature called Gatekeeper.
00:19For most users Gatekeeper just becomes obvious as part of system preferences in Mountain Lion.
00:24There is an option to allow the user to choose and install software only from
00:28the Mac App Store and identify developers.
00:31If this option is selected and your app is not signed with the Developer ID
00:36certificate issued by Apple, it will not launch.
00:39Now let's be clear here, if you're planning to sell your app in the Mac App
00:44Store, you do not need to worry about Developer ID, because all the signing that
00:48you already do to get inside the Mac App Store is good enough.
00:51Developer ID is for the case where you want to sell it or distribute it to
00:56Mountain Lion users outside of the Mac App Store, but of course, you may need a
01:00Developer ID if you want to do both, but becoming an identified developer is not
01:05complex, there's just a few things to be aware of.
01:09To get a Developer ID certificate, you do need to be a paid up member of the Mac
01:13Developer Program, not just a registered Apple Developer.
01:16Now if you're already in the Mac Developer Program, you may find that you have
01:20the Developer ID certificates already.
01:23You could either use the Mac Dev Center or you may even find them in Xcode.
01:27If you go into your Organizer window and look at the Devices section under Teams,
01:32you may find a couple of certificates for Developer ID for Applications and
01:36Developer ID for creating Installers.
01:38If you haven't gone through the process of setting up your developer device,
01:42then take a look at your account details in the Mac Developer Center.
01:46There is an area of this called the Developer Certificate Utility, and if I go
01:53into this area then click on Certificates. It'll tell me the ones that I already have.
01:57If we see a couple for Developer ID, we're good, if not, you can ask for one by
02:02clicking the Create Certificate button and one of the options you'll find is the
02:07Developer ID Certificate.
02:09There are two kinds as we can see here, and the difference just depends on how
02:13you're planning to distribute your app.
02:15There is one certificate for regular applications and one for creating installer packages.
02:21Now I'm not covering Creating Installer Packages in the course. We are working
02:25with the idea of a standard application, so let's see how complex it is to sign
02:29an application with a Developer ID.
02:31I'm going to jump into Xcode where I have a StandardCocoaApplication that I have
02:36just created. It doesn't have any functionality in it, I haven't done anything
02:39with Entitlement or Sandboxing, I just want to share the process of signing this app.
02:44Like Sandboxing, it does require that my certificates are all in order first,
02:48but it will tell me if they aren't.
02:49So to do this what I want to do is go into my Project settings and selecting the
02:56settings for the entire project go into Build Settings, and what I'm looking for
03:01is the Code Signing section.
03:04Rather than scroll up and down, it's just easy enough to filter on, say, the word
03:08signing, and what we should find is this one called Code Signing Identity.
03:13Right now it's set Don't Code Sign this. I need to associate that Developer ID Certificate.
03:19So as long as they have been downloaded and configured already, I can select from
03:22the dropdown box, find my Developer ID Application, and either just directly run
03:28this, come up to Product, and tell it to Build.
03:31Depending on if I have allowed Xcode access to my certificates, I may need to
03:35allow this once or twice. It's actually a lot easier to just say Always Allow if
03:39you're planning on doing this a lot.
03:41So that's how to sign an application with a Developer ID. And then when we go to
03:46the steps of archiving this. It will be signing our Release Build with that,
03:50and when I choose to Distribute it, I can export it as a developer ID signed application.
03:57It's detecting that I really just have one Developer ID here, click Next, and we're done.
04:05That's the entire process.
04:07Very simple, and again, not needed if your intention is to Distribute purely in
04:12the App Store, but highly recommended otherwise and very simple to do.
Collapse this transcript
9. Finishing Touches
Creating full-screen apps
00:00In OS 10.7 Lion, Apple introduced a standardized Full Screen mode for OS X, so
00:06apps can shift into taking over the entire screen.
00:09If I'm in Safari I just need to click this Full Screen icon at the top right
00:14of the Title Bar, and will take over the entire screen, even including the Apple menu.
00:18If I move my mouse up to the top I can make it comeback, so I can shift out of
00:23Full Screen mode, and I can still get to the Dock in most cases, but it allows
00:27us just to take over that space, Safari has it, Mail has it, even Xcode has the
00:31Full Screen option, so any app can choose to do this.
00:35The first question of course is does it actually makes sense?
00:39There is two main reasons why you would want it.
00:41First will be creating a distraction- free reading or writing environment.
00:46For example, if I'm in Preview and reading a document, I can go full screen just
00:50to focus on the actual document that I'm taking a look at, and you'll find a
00:55quit a few writing tools also take over the full screen, even if they don't use
01:00the entire space to help you focus without being distracted by other applications
01:04And of course the other reason for it is when you have limited
01:08screen real estate and a lot going on in the application.
01:12Say you're using Xcode on an 11-inch MacBook Air, being able to make that menu
01:17disappear and use every last available piece of screen can be very helpful, but
01:21on the other hand an application that you want to jump in and out of very
01:26quickly, like System Preferences, this would be a very poor choice for supporting
01:30full screen, and it doesn't support it.
01:33So it's not required, and it's not expected of everything, but it is very easy
01:37to implement if you choose to. Let's take a look.
01:40I have got a brand-new Cocoa application just to show that there is nothing that's been added here.
01:45Now I do want something that we can see on screen, because otherwise when I
01:49implement it will just have a lot of gray, so I want something on screen.
01:54Now it'd be a poor choice here to have just say a button or two, so I'm going
02:00to grab a couple of the larger controls just to give us something to look at,
02:04I'll jump into my Data Views section here, drag on a Table view and an Outline
02:13view and just vaguely line them up. I'm going to embed them together into a Split view.
02:18So just select both of those and then from the Editor menu decide to Embed In > Split view.
02:25Now there is nothing that I'm doing here as anything to do with actually making
02:29something full screen, I just want to give it something to look at.
02:31So I'm just going to take care and drag these and connect these to the edge
02:36of the page so we can see the effect that going full screen will have. That will do.
02:44So now let's do the full screen part.
02:45In our app I'm going to go to the Window making sure the Window is selected,
02:50jump into my Attributes Inspector, and what I want to do is come down to a
02:55dropdown box that says Full Screen, which by default is Unsupported. I'm going
03:00to select it to support the Primary Window, and that's actually automatically
03:05added the standard Full Screen icon to the top right of the Title Bar.
03:10I'm going to hit Command+R to run this application, and we have the app fairly
03:16simple split view going on here, but I have this Full Screen icon. I'm going to
03:21click it, and we immediately shift into full screen, we have taken over the entire screen.
03:26If I do move up to the top move my mouse here, I do have the option
03:29automatically popping up here to go back to the regular size. It works.
03:34However, we also need a touch more, because if I look at the menu for the
03:40application, I do have the regular view menu which has Show Toolbar and
03:43Customize Toolbar there. They are grayed out right now simply because no behavior is happening there.
03:48But if I click back into Xcode, I have that Full Screen button, but what I
03:53usually expect to see is under the view menu I have got an Enter Full Screen
03:57option with the shortcut that is Command+Ctrl+F, and that is the standard way it should look.
04:03In Safari it's in the view menu, Enter Full Screen, Command+Ctrl+F, and what
04:08happens is if I select this we'll go into entering full screen, but if I move
04:13back up to the menu and look at the view menu for Safari again it's changed to
04:17Exit Full Screen, it's just toggling between the two.
04:19So we have got a standard menu option, standard wording.
04:23The last option in the view menu where that shortcut key, and we should support
04:27it in our application as well, so let's do that.
04:30Well, editing this Window I can actually jump up here into the menu itself and
04:35see that in my view menu I do have just the two standard options, Show Toolbar
04:39and Customize Toolbar.
04:41We have a couple of choices here. We could add a manual menu item from the
04:46Windows & Menus section, drag that on and start configuring it, hook up the IB
04:54actions and so on, or we can do it the easy way, which is if I scroll down all
05:00the way to the bottom, I actually have a Full Screen Menu Item. I'm going to
05:05simply drag on that to the open view menu and put it at the bottom here.
05:11Now usually what I'd actually want is this is at the bottom, but there is a
05:15separator above it, a horizontal line, so I'm going to find the separator from
05:19the Window menu section. There it is, Separator Menu Item, and drag that above
05:23Enter Full Screen just to give us the proper look.
05:27Usually when we're working with menu items we would then select them, and we
05:30would look at our Connections Inspector and see if they're hooked up to
05:34anything, but we don't need to do any of that. It's actually already working.
05:37Dragged on, if I highlight this and select my Attributes Inspector I can even see
05:42that I have got the shortcut key entered in.
05:46If I go to the Connections Inspector, it is actually passing the toggleFullScreen
05:50menu to the First Responder, which will get passed itself to the application.
05:54So all I really need to do is go ahead and run it. Currently have the other one running. I'll hit Stop.
06:00The application launches, I come up to my view menu, I have the Enter Full
06:04Screen option, I select it, we shift into Full Screen mode, I go back up to the
06:09view menu, and it's changed to Exit Full Screen. Not only that, but we can
06:14check to see that the shortcut keys work. I hit Ctrl+Command+F, and we Shift
06:18back into the regular mode.
06:21So very easy to implement just with a couple of quick changes in the Attributes
06:26Inspector and a drag and drop onto the menu.
06:28The most work you're going have to do in supporting full screen is actually
06:32testing your layout on a variety of different sizes and becoming familiar
06:36with how auto layout is going to attempt to reformat your user interface elements, and that's it.
Collapse this transcript
Creating icons for OS X applications
00:00So far we have just been letting Xcode use the default application icon for our
00:04Cocoa Apps, that's the one that looks like this.
00:07You might see it in Xcode itself, but this icon is actually attached to the
00:11application itself, and unless we say otherwise, it's the one we are going to be using.
00:16Now creating icons for a Mac application is really two issues.
00:19There is the technical side, what do we need to do to make this work?
00:23And of course the creative side, what are all the things we could do with the
00:28icon design, things like color, perspective, should we use text and so on?
00:32Now for the creative side of things, I am going to point you mainly to the
00:36terrific section in the OS X Human Interface Guidelines, particularly the chapter on Icon Design.
00:41There is a lot of great content here on using perspective and color and shadow
00:47and on other aspects many developers don't really think about, such as the
00:50different genres of icon that, in fact, Apple designs their icons differently based
00:55on the kind of application it is. Whether it's utility or a consumer app will
01:00drive different decisions regarding color and image.
01:03But we are going to focus here on the technical side.
01:06Let's say we have a custom icon.
01:08We want to make how do we make it work, and here's what we have to do.
01:11First know that an icon is not just one image.
01:15We are expected to provide multiple image files, multiple sizes of artwork for
01:19an icon, and that's because on the Mac there are many situations in which an
01:24application icon is used.
01:25From the most basic idea of using the icons in the Dock, then if we switch to
01:30the Applications folder, we see them here at a different size.
01:34In the Finder Cover Flow window where the icons can be shown very large and
01:38support a lot of visual detail, or on the flipside over to somewhere like
01:43Spotlight, where the icons will show up but can be shown very small. So how do
01:48we drive these decisions?
01:50You take your preferred graphics application--Photoshop, Fireworks, whatever you
01:54like--and we are supposed to provide icons at five different sizes and OS X will
01:59choose the right size at the right time.
02:02Size 1 is 512x512 pixels, we have got 256, 128, 32, and 16.
02:10We need to create images for our icons at all of these sizes, and now you can
02:15just provide one large image and expect OS X to scale it.
02:18You are supposed to support the idea that larger icons can support more
02:22detail than smaller ones.
02:24What looks good at 512x512 is going to look messy if you just scale it right
02:29down to 16x16, so it should be redesigned for that size.
02:33But one more thing, it's not just five images, it's actually ten that are
02:38required because we must also provide duplicates of these at double
02:42resolution for a Retina display.
02:45So with the 512x512 icon, we also need that at 1024x1024 and so on, and Mac OS X
02:53will pick the right set of images for the correct device.
02:57And it's very important what you name these ten files because that's how OS X
03:01will pick the right image in the right situation.
03:04And this is the format, the 512x512 pixel images should be icon_512x512.png.
03:14We have icon_256x256.png and so on.
03:19However, we can't just use this same format for the Retina display version
03:23because we'd actually end up with two icons of 512x512, so all the Retina
03:28display icons end in @2x. But although the actual Retina icon might be
03:351024x1024, we would call it 512x512@2x.png, and this is the format that Apple use
03:45for the Retina artwork with the iPhone and iPad as well.
03:48So these are the ten images that we need to create and the names of those
03:52images, and with those together we can start the process of getting them into our project.
03:58So in my Exercise Files folder, I actually have some icons that were created earlier.
04:04Just selecting them, I am going to use the spacebar to look a little bit at them.
04:08Here's the 16x16, same one at twice the resolution, they may go to 32, to
04:15128, to 256, and to 512.
04:17Now I have created them slightly differently for each size, and you'll see why in a minute.
04:23So here is what to do.
04:24Once you have got these images, you don't just drop them into Xcode. That would be too easy.
04:29In fact, the first step doesn't involve Xcode at all.
04:32First create a folder, and this folder can be anywhere. I am just going to put
04:37it on my Desktop, make a new folder here, and I will call it icon.iconset, and
04:43the name is important here.
04:44Now this is a stepping stone to creating a single file that will bundle all our images together.
04:50I have called that iconset. I am getting little confirmation message here, do I
04:53want to add the extension to the end of the name?
04:55Yes I do, so I will add that, and I am going to grab my ten images and just
05:02drag them into that iconset folder, and you might think, well what does that do?
05:08Well, this .iconset name Finder treats a little differently, so I am going to
05:13select that folder and then just hit the spacebar because what will happen is it
05:17gives us a quick look preview here that involves this little slider Bar at the
05:21bottom, and as I drag it smaller, we can actually see the different images
05:25appear at different sizes. That's why I try to make it a bit more obvious what's
05:30happening as we change the image, that we are actually picking the different files.
05:33We are not just scaling it down, we are using a different image.
05:37But the next step is we need to take our .iconset folder and package all these
05:42images together into a single file which is called a .icns file.
05:47And Apple used to provide a separate program called icon composer to do this, but
05:53in Xcode 4.4 it was removed, and we use a command line tool instead.
05:57So I am going to launch a terminal window. I will just do it by typing in
06:02terminal in spotlight, launching it this way. Going to change directories to
06:07my Desktop, which is where my iconset folder is and the command I am going to
06:12run is iconutil, all one word, so we say iconutil space -c for convert, because
06:19we are converting an iconset into an icns, so what I am converting to?
06:25I am converting to icns, and then I give it the path to the iconset folder which I
06:30just called icon.iconset.
06:35Hit Return, it thinks about it for a second, and what actually happened is it's
06:39created that here, I have got icon.icns in the same folder--in my case the
06:44Desktop--that your iconset was in.
06:47Now at this point if you are missing images, you'd have an error message here,
06:50you'll only get this to work if you have got all the images you need.
06:55This .icns file is the icon that Xcode wants, so I am going to go into Xcode
07:02where I just have a very straightforward Cocoa application, haven't done
07:05anything with this yet apart from created, and I am going to just shrink it so I
07:09can see my Desktop here.
07:11I am going to jump over into my Project Settings. So selecting the top icon over
07:15here in the File Navigator, I am going to choose the Target section and select
07:20the app, and we have a droppable area for our application icon. So I am going to
07:25grab that .icns file, drag it over here, let go, that's it.
07:30Now we have an Application icon. Well, let's prove it.
07:34I am going to go ahead and run this.
07:37Build Succeeded, again, it's a very simple Cocoa app.
07:39There is nothing in this, no functionality yet.
07:42I have my Demo up here. If I hit Command+Tab, I can see that I have a proper icon
07:47being selected at that size.
07:49I can even see in Xcode, the actual target itself is using the smallest,
07:53the 16x16 version of the icon, so it's using the correct size for the correct context.
08:01If I come down to my Products section and right-click my Demo app and say to
08:05Show in Finder so we can actually see that application on the File system, I am
08:10going to switch to the cover flow version, and this will give us one of the best
08:15ways that we can see this icon changing to different sizes as I drag it to
08:19larger and then to smaller and then to smaller still.
08:23OS X will take care of scaling this and showing the right set of icons if you
08:28have a Mac with a Retina display, but this is how you bundle your icons
08:31together and get them into your project.
Collapse this transcript
Conclusion
Final thoughts
00:00So we're reaching the end of this Cocoa Essential Training course.
00:03What I wanted to do this course was as quickly as possible take you through the
00:07things you'll always need in every Cocoa application.
00:10Layouts and Controls, Target and Action, Delegation and MVC, application
00:15lifecycle, data sources, key-value coding, and bindings and sandboxing, but of course, it gets deeper.
00:22And while we may have covered the things you'll need in every Cocoa app, we may
00:26not have covered the things you need in the one you want to build right now.
00:30You might need Core Data or iCloud or more on graphics and animation or working
00:35with audio and network communications. So the question is, well, what now?
00:39Now you got the basics, where do you go from here?
00:42And I think it's a great time to re- inspect the Mac Developer Center and the
00:45amount of content that is available here, because it's very easy to think of
00:50this as just reference, as your class reference libraries, but it's a lot more than that.
00:56And particularly the documentation and the guides and the sample code are very usual.
01:00Of the two documents I think is essential for every new Cocoa developer to
01:04keep on hand the Mac Application Programming Guide and the OS X Human Interface Guidelines.
01:10Now, sometimes these can be a little tough to find, but if I go into the
01:14Developer Library section and select the Guides, we're going to find several
01:19hundred here. There's about 336 of them right now, but they can be grouped by topic.
01:24So if I click this to group them together, I'll find first--or at least pretty
01:28shortly--the general guides which includes things like Concepts in Objective-C,
01:33but also includes the Mac App Programming Guide. This is a great single document
01:38for detailing expected behavior of every OS X application.
01:42Now it's a good one to keep on hand.
01:45These guides are provided both with HTML, and they also typically have a PDF link
01:50as well, if you want to download a copy.
01:52Now you can, of course, get to this documentation from within Xcode itself if you
01:56have the Organizer window open. Or if it's not, you can just get to from the Help > Documentation > API Reference.
02:04And then in the left-hand section, drill into the particular library for what
02:08you're working on, whether that's OS 10.7, or if you have OS 10.8 or even later.
02:14Those themselves are split into the different categories. I could jump into
02:17the General section, and in here is where I should find the Mac App Programming Guide.
02:24What I can do here is right-click and add a Bookmark, that gives me the little
02:28bookmark section which can give me the favorite documentation that I have at the moment.
02:32So doing that, I am going to jump back in and then close down General, go into
02:37the User Experience section, and this is where we will find the Mac OS X Human
02:42Interface Guidelines, another really good one to always have bookmarked.
02:46But whether you are using the Xcode Organizer or you're using the web site,
02:50you'll also find a selection of Sample Code. You can get that in the Developer
02:54Library, there is an entire Sample Code section.
02:58Do be aware that though there might be hundreds of sample projects, some of them
03:02are fairly old. In fact, the earliest ones go back to 2003, which doesn't
03:08necessarily mean they are all that useful for you in the current version of
03:11Xcode with current best practices and the current APIs and libraries.
03:16I tend to prefer the ones that are from the last couple of years, so you can
03:20either drill through them on the web site, or you can get to them in the Xcode Organizer.
03:24You'll find this icon tends to represent some sample code here, so I
03:30might find say NSAlertTest. It allows me just to open the project, I can see
03:34that this last revision was in 2011, which isn't too bad.
03:39Directly open that from within the Organizer itself, and then I can take a
03:43look at some of the code that Apple would provide to illustrate certain concepts and ideas.
03:50These won't always be exactly what you're expecting, but they are certainly
03:55worthwhile to take a look at.
03:57And finally, of course, take a look at some of our other courses here at
04:01lynda.com on different aspects of Apple development.
04:04We have more coming all the time, and also let us know if there is anything you want to see.
04:08See 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


iOS SDK Essential Training (2012) (6h 26m)
Simon Allardice


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 100,984 instructional videos.

start free trial 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 1,945 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.


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