The Complete iOS 7 Course - Learn by Building 14 Apps

Over 400+ videos taking you step-by-step through process of building 14 different applications in iOS 7 and XCode 5.
  • Lectures 428
  • Video 37 Hours
  • Skill level all level
  • Languages English
  • Includes Lifetime access
    30 day money back guarantee!
    Available on iOS and Android
    Certificate of Completion

How taking a course works

Discover

Find online courses made by experts from around the world.

Learn

Take your courses with you and learn anywhere, anytime.

Master

Learn and practice real-world skills and achieve your goals.

Course Description

Our iOS Bootcamp teaches the tools needed to develop iPhone and iPad applications for iOS7. Along our journey, we will learn the syntax of Objective-C, the language used to develop for iOS, as well as important design patterns and best practices. By the end of the course, you should be able to understand and recreate many of the features seen on popular iOS applications and extend that knowledge to making apps of your own.

We believe students learn by building. That's why we have you build 14 apps during the course, with the final app being a full featured dating app: A Tinder Clone!

Topics Covered:

  • Objective-C: Learn the language used to develop all native iOS and Mac apps
  • Parse: A revolutionary new tool that allows iOS developers to create a server side in Objective-C
  • iOS7 and XCode 5: Learn the latest technology platforms from Apple
  • API Integration: Connect with third party APIs like Facebook, Foursquare and more
  • Storyboard: Learn how to create beautiful interfaces using Apple’s graphical interface builder
  • Core Data: Store data on your device with the core data database
  • Git: Learn how to us Git for version control and collaboration
  • Mixpanel: Integrate analytics into your apps

Reviews

"I must say that so far, this course is awesome. Having the challenging assignments, daily discussions and feedback from the instructors, has been the missing piece that I have been looking for. I have read a handful of books, watched hours of video & typed in a bunch of tutorials, and finally, having to work through tough assignments and applying what I have been learning, it is all starting to click - Finally!" - Mark S.

“Code Coalition's discussion board is one of the best resources for a beginning iOS developer. So much help being offered” - Omar S.

“I've just completed the iOS101 course, which I thought was a great intro to the XCode environment... I feel it's been well worth the investment. ” - Herdy H.

"Wow, @CodeCoalition! Moving quickly! Week 2 is so different than week 1...and I like it :) Thnx for the challenge" - Melissa B.

“Just discovered @CodeCoalition! An excellent resource for anyone who wants to make their first iPhone app.” -Novall K.

“Can't reiterate it enough how this course is helping me with my iOS dev skills. I think using protocols and delegation is finally becoming second nature. Fingers crossed :-)” -Alex P.

“I am really loving the class. I have taken classes at Code School & Treehouse and both were missing a key element. The ability to ask questions as you complete a section and get an answer. “ -Lisa A.

“Your training is the best out there so far. I wish I had the time away from regular job to follow along.” -Christian S.

“Im loving this.. I have been through at least 5 books, and many online deals. Yours is super so far. Finally, i can get from start to finish on a lesson without wondering why on "Everything" thank youCant wait to do more.. “ -Kevin R.

Why take this course and how much time does it take to complete?

iOS development, and software development as a whole, is a booming career. The demand for new developers at all levels far outweighs the supply. Barrier to entry is not as high as one would think - though passion and hard work are necessary, a degree in computer science or any other technical field is not required.

We aim to take you from complete beginner to junior developer in three months. The apps you create in this course can be used on your portfolio so you have something to show when you apply for jobs.

Course Outline:

  1. Introduction to XCode
  2. Control Flow and Enumeration
  3. What is Object Oriented Programming
  4. Memory Allocation
  5. Methods
  6. Properties
  7. Foundation
  8. Model View Controller
  9. Common Classes and Features
  10. Drawing and Graphics
  11. Core Data
  12. API’s
  13. Source Control

What are the requirements?

  • An intel-based Mac that has Mac OS X Snow Leopard or later installed

What am I going to get from this course?

  • Over 428 lectures and 36.5 hours of content!
  • Code in the Objective-C programming language
  • Use and extend the Cocoa framework
  • Build apps for iOS 7
  • Version your code using git and github
  • Analytics using Mixpanel
  • Build a cloud datastore using Parse

What is the target audience?

  • Complete beginners (no coding experience necessary)
  • Programmers coming from other language/frameworks

Curriculum

Section 1: Your First App!
06:07

1) Open Xcode through dock or through spotlight search.

2) Click: Create a new Xcode Project.

3) Select Single View Application in the iOS App pane. Other options are Master-Detail, OpenGL, Page-Based, Tabbed, Utility, and an empty application that provides no boiler-plate code. Single view application allows us to have a project will all the necessary code already written that connects one plain view upon opening the app.

4) Fill out project data as shown in video. Be sure to select iPhone for device and check storyboards and automatic reference counting. We’ll go over what these mean in depth, but for now let’s start our project with them selected.

07:03

The left side panel in XCode is known as the Navigator.

This is where all the files included in your project are located. You can search for things, analyze errors, and add break points among a host of other things. When you click on a file, its contents will be shown in the center screen. To view two files at once, simply hold down the "option" key and click a file.

The right side panel is known as the Inspector.

In the inspector, you can add UI (user interface) elements to your application. Furthermore, you can change the size and physical properties of those elements here.

The bottom panel is referred to as the debug console or debugger.

When you recieve errors (and you will!), this is where they show up.

And as shown in the video, all of these views can be toggled with the three buttons on the top right of XCode.

We will be using each of these areas extensively throughout the course, so you will have plenty of time to get comfortable with them!

08:53

For reference, the code that was written to change the label's text is as follows:

- (void)buttonPressed

{

self.titleLabel.text = @"Hello Class!";

}

You will learn what all of this means shortly! But for know, notice how the statement between the curly braces sounds somewhat similar to English. This is not by mistake, but instead a characteristic of Objective-C, the programming langugage in which most iPhone apps are written in.

The dot notation signifies "ownership" and can be read as "self's titleLabel's text is equal to Hello Class." Right now, the word "self" sounds a little goofy but bear with me- it's another way of saying "My."

03:57

Try playing around with the attributes inspector (the area on the right side of the screen). Click on your label, and see if you can change it's background to green and try making the font a bit bigger. The best way to learn is to experiment- so go ahead!

06:11

UITextField is a user interface element that allows for users to tap on a field and have the keyboard pop up, which allows users to enter input like “Hi, my name is Eliot” or anything else they want to write. Functionality like this is useful if you have a login form in your app and you want the user to enter their email and password.

07:00

Try adding one more View Controller Object to your storyboard and then transitioning, or in iOS speak, "segueing" to that from your View Controller with the world on it. To do this, you will need to add another UIViewController and a button somewhere in your project.

**Just make sure to click the "push" segue as your segue type! Push segues can only be used when using UINavigationController and are the only segue that will give you a back button for free. If you select something like a modal segue, then the new screen will be presented with no way out! (for now). You can delete segues by clicking the circle on top of the arrow that links your View Controllers and pressing delete.

UINavigationController is a great and popular way to transition from screen to screen in iPhone applications. In fact, if you take out an iPhone right now and open up a few of your favorite apps, you will be guaranteed to see it! Look out for the navigation bar on the top of the screen.

Resource section is available in Lecture 8.

Section 2: Resources
Text

We have provided all of the assets for the course in a single spot in case you have trouble finding them later on!

Section 3: Variables
05:42

Method names in Objective-C are written to be crystal clear. Above, the method viewDidLoad was called every time our view, well uhh, did load. This holds true for all method names like containsObject and supportedInterfaceOrientations. As we progress through the course we'll learn quite a bit about method names and how to construct them ourselves.

03:05

Commenting is a great tool for summarizing procedures that might be difficult to understand upon first glance. A lot of the time, it might not be evident at first what a block of code does, and therefore a comment helps any readers of our code to understand what is being done. And readers include us too down the line! Many times after writing code, you will have to go back to it to maintain it or fix it, and well-commented code will be much easier to fix!

It is really good to get in the habit of commenting out your code. However, my commenting above was definitely over the top and maybe even called egregious. You don’t want to be commenting every line of code. With time, you will be able to find your perfect commenting balance.

04:43

With the variables we've used so far we can add,subtract,multiply,and divide them. A little tip to prevent issues later on. Remember that unlike algebra the variable must always be assigned from the left side. For example: int x = 10 + 3; is a valid statement. However,10 + 3 = int x will break your program!

02:51

For those of you who have gotten a taste of Objective-C before, this syntax (@"some text") is a convenient way of creating an NSString object. An NSString primary responsibility is to hold text. That’s all you need to know for now!

04:10

Remember to avoid spaces between variable names, using symbols in variable names and using reserved keywords like new and property.

05:13

Here are some common tokens we will be using in the course. We'll be going over them quite a few times so you'll have plenty of time to get comfortable using them.

%i for integers.

%d for doubles.

%f for floats.

%@ for objects.

05:38

CODE REPOSITORY

Want to reference the completed code against your written code? The completed code (aka the code repository) can be found here: Funky Unit Converter

06:20

Woah... a lot of new stuff! Methods, class methods and conversions. Don't worry, we will get to exactly what all this stuff is shortly. But because we want you building applications now, we're including some rather simple examples of concepts you will see later.

Section 4: Challenge 1: Age of Laika
Text
Challenge Age of Laika

What is this... a challenge!?!?.

This is your first attempt at a challenge. The first one will be pretty straight forward, it encourages you to repeat a lot of the steps you have just completed. Best of luck!

So what is this great challenge?

Challenge 1: Age of Laika
  1. Create a new single-view project and name it "Age of Laika."
  2. If you don't know who this famous dog is, I would highly recommend you check him out on Wikipedia!
  3. Include a UITextField, a UIButton, and a UILabel in your project (drag those elements onto your view in your storyboard file).
  4. Make the appropriate connections, similar to what we did in Funky Unit Converter. Remember to control-drag from our UI elements (or views) into the .h file of our ViewController.
  5. Our end goal is to convert a number we enter in our text field (say a number of years) to a larger number (maybe dog years). You can find this common conversion anywhere online. Go ahead and write this logic!
  6. Extra Challenge- Include a UIImageView on your application and put in a picture of Laika. Checkout the course info section for a picture of Laika.
  • Although we will go over the answer in a later video, it is very important that you try these challenges! I promise you that this is where the real learning is done so give it a shot. I wouldn't lie to you! If you have difficulty, feel free to ask some questions on the discussion board. And if you get really stuck check out the solution videos. There is no shame in it if you are feeling overwhelmed or confused. Just make sure you code out the solution and then retry it without the solution video.
05:14

The code repository can be found here: Age of Laika

02:34

The code repository can be found here: Age of Laika

Section 5: If Statements
04:32

if statements allow us to test conditionals. Is this number greater than, less than or equal to a value. For now we are just printing out different statements to our console based on the logic in the conditional. In the future we'll have different bits of code run based on our conditionals!

03:03

A BOOL provides us with an introduction to state. Think of state as a light switch which can be on or off. Examples in our future programs could be has the user logged in? If he/she has then the state is YES if not then the state would be NO. We can test a BOOL type with a conditional that we learned about in our last lecture!

03:32

If statements evaluate what is in the parentheses on a YES or NO basis. If what is evaluated is YES, then the logic between the curly braces is evaluated. If NO, either your application continues running or an else if or else statement is reached, in which the same type of behavior is expected.

It is a common error when learning programming to use a single = as the comparator, as opposed to ==, so watch out for that!

Remember what we have at our disposal!

> - Greater Than

< - Less Than

== - Equal To

!= - Not Equal To

&& AND

|| Or

Section 6: Challenge 2: For Loops
05:28

This time, you need to update your Age of Laika app to make it a little more scientifically accurate. What do I mean? Well, our previous converter wasn't so hot. Apparently, 1 human year does not really equal 7 dog years. So how do we change it? A good answer will use if statements!

  • Change the conversion method (which evaluates when your UIButton is touched) to use if statements.
  • The real conversion for dog years is follows. Each human year equals 10.5 dog years for the first two years, and then 4 dog years for each human year after.
  • Sounds like a word problem? Well, it is. You will find yourself frequently taking what is asked of you and translating that into code in your project.

Again, best of luck!

Hint if you want to show the exact age including the decimals substitute [NSString stringWithFormat:@"%i",dogYears] with [NSString stringWithFormat:@"%.1f", dogYears];

03:59

For loops allow us to repeat a set of logic a fixed number of times. They are really useful so we don't have to write the same line of code over and over again.

03:46

Check out the project on github: https://github.com/codecoalition/For-Loops

Section 7: Challenge 3: 99 Sodas
01:53

Get ready!

  • Using a for loop, print the well-known song 99 bottles of (soda) on the wall.
  • If you don't know the jingle, give it a quick gGoogle! The point of the song is to repeat a set of lyrics, however, changing the number of bottles sung with each round.
  • You might not want to initialize your variable at 0 or 1 for this challenge. Take this as a hint!

Again, good luck!

Github: 99 Sodas

Section 8: Intro to Object Oriented Programming
02:07

Time to start a new project! Again we'll be doing some necessary background work for the next 4 sections. Trust me putting in the work and gaining a bit of understanding about the Objective-C language will really payoff when you start coding later. Don't worry we'll be getting into building a more visually appealing application soon!

One little aside:

Prior to iOS 5, Xib/Nib files were used. Although we won’t discuss them right now, they are another way to curate graphical interfaces.

03:14

Classes are the blueprint for how objects are made. Think of having a blueprint for a car, and having to make 50 of them. The Class is the blueprint, while the cars are objects. We say that they are instances of the class.

03:12

In order to make our own class, all we have to do is go file, new file, and click Objective-C class.

We then need to name our file. It is important that we start with a capital letter since all class names begins with a capital letter.

Further we want to prefix our class with two or three capital letters to distinguish it from other classes. These letters are defaulted by the class prefix we choose when we setup our initial project.

03:42

Everything declared in the .h file, all other objects that include or import this class get access to.

For anyone with Java (or other CS) experience, this means that this .h file is public.

For example, if a computer was represented by a .h and .m file, the .h file would contain what is on the screen, and the keyboard as everyone has access to this. However, the internals or how the computer would work, would not be here but would be in the .m.

01:42
The implementation file includes all the logic that makes your class what it is.

For all the information that we declare in the .h file, we must also implement that information in the .m. This is critical to do because if we tell other classes that we have implemented a method in our header file but do not tell the computer what to do the program will break.

In order for the implementation file to be aware of what was declared in it’s header file it must first import that file. Hence we import #import “MBFDog.h”

Next we need to give an area to write our or define the methods from our header file. So that we know where to write this code classes tell you to begin with the @implementation and the class name and tell you where to stop writing implementations with @end. All methods must be defined between these two keywords.

Section 9: Properties
06:47

What you see written: @property (nonatomic, strong) NSString *name;

  • @property - Declaration of a property. All of our objects instantiated from this class will have access to this property
  • nonatomic - For now, we will always write this. This has to deal with thread safety and locking, but just note that declaring a property atomic might hinder the performance of our application
  • strong - This (and affiliated keywords such as weak) are only written when we are dealing with objects. This determines how long an object is kept in memory.
  • NSString *- The class (or type) of our property. Notice that if our property is an object, the class name is followed by an *, indicating that our variable is actually a "pointer" to that object.
  • name - The variable name. It is, possibly unwisely chosen, in this case to be called name
01:05

ViewDidLoad gets called just before our view comes on screen, and therefore makes great spot for setting up code and testing code.

We cannot yet instantiate the object because we have not imported or told the ViewController class about our brand new class.

02:55

Import MBFDog and notice that XCode autocompletes it.

 #import “MBFDog” 

We now have access to what MBFDog has made public, or it has declared in its .h file. Now we can start talking about MBFDogs in our MBFViewController! The “” means local directory while the <> means system directory. We will take a look at an example of the <> in just a second. We use “” which tells the import statement to find my very own header.

Each of our classes and files do not know about each other unless we import them their header files. It is good practice to keep importing to a minimum and only do so when necessary.

02:59

MBFDog *myDog = [[MBFDog alloc] init];

This is the most generic way to create an object. Alloc is a class method called upon our MBFDog class which returns an instance of that class. Init is an instance method that is called on our new instance the prepares it for use.

Although you will encounter different syntax to create an object, the imbedded method call using alloc and init is, again, the most generic way to accomplish this feat. Remember that you should be calling alloc and init together, and never at separate times.

Although this might be much more confusing than code such as int myInteger = 5, we will be doing this so frequently, you will get accustomed to it in no time!

08:56

Let's make sure we can repeat the steps. Think of a property that a dog has (such as color) and add that as a property to your MBFDog class. Set your property to something in your viewDidLoad method and NSLog that value to make sure it was set.

Section 10: Methods
03:03
  • Methods group code together in order to achieve a particular goal. Messages are sent to an object or class in order to act upon them or get them to do something.
  • For instance methods we use the syntax [object methodName], where object is the reciever and the methodName is the sender.
  • For class methods we use the syntax [Class methodName], where the class is the reciever and the methodName is again, the sender.
  • To make a method public, so that it will be visable in other classes, we must declare our method’s name in the header file in the class that will implement the method. Implementing a method means defining the functionality for that method.
  • Method names that start with a hyphen are known as instance methods. The (void) in this statement indicates that the method does not "return" a value. Return values will be covered in a later section.
03:40
  • Either copy your method name from your header file or take advantage of Xcode's autocomplete functionality to ensure the method name in your header (.h) file and your implementation file (.m) are identicial.
  • Don’t forget to remove the semicolon and add left and right curly braces to implement the method in the .m file for the class in question. Code written inside of the curly braces will evaluate when the method is called. This code is the logic of the method.
06:13
  • Methods can take parameters and perform logic differently according to those parameters.
  • The sign at the beginning of a method designates the type of method. A hyphen (-) is reserved for instance methods while a plus (+) is used for class methods. The value in front of the method, (in our cases thus far it has been(void)) is known as the return type.
  • A colon (:) in a method name precedes an argument.
  • After the colon, we give a type for the argument, such as (int) and a parameter name in order to access the parameter, or local variable, in our implementation.
  • Inside of the curly braces of our method, or our method's implementation, we have access to the parameter passed in. Every time we call this method, we will provide an argument of the specified type.
04:48
self is a keyword which refers to the object created from the class that we are in.
  • The syntax looks like this: self.nameOfProperty.
  • For example if we add a property, such as a UILabel named myLabel, we can access it using the self keyword ie. self.myLabel.
  • We can also chain multiple properties together using our dot syntax. For example the UILabel class defines a property text which can be used to update the text of a label. We can therefore access our own property using self.myLabel and then immediately access the label’s text property chaining our dot syntax together ie. self.myLabel.text.
04:33
  • Try using [self methodName] to evaluate a method defined in the same class you are calling the method in.
  • self allows us to access the "implicit local variable self" or the instance of the class that is receiving the message.
  • Sounds confusing at first? Well, like many concepts in programming, seeing a multitude of examples is the only real way to get your ahead around it.
06:10
  • Methods can have multiple arguments. The arguments are interspersed with the method name, which is different than methods in other languages you may have encountered.
  • The syntax for multiple arguments for an instance method might look like the following:

- (void)methodNameWithFirstArgument:(int)firstArgument andSecondArgument:(float)secondArgument andThirdArgument:(NSString *)thirdArgument;

  • The method's name, or how it would be referred to, ismethodNameWithFirstArgument:andSecondArgument:andThirdArugument
  • The method takes three parameters referred to as firstArgument of type int, secondArgument of type float, and thirdArgument of type NSString *.
  • Initially writing long method names can be trying. However, Objective-C method names sound very much like English and by strongly typing each variable, we know the type of argument that must be used to successfully call a method.
06:05

Methods can return a value that can be assigned to a variable. Methods in C-based languages, such as Objective-C, can return either nothing or a single value. We signify the type of the return value inside of the parentheses following the hyphen or addition symbol. Both (void) and (IBAction) signify that the method does not return anything.

07:06

Github: Mans Best Friends Through Methods

Section 11: Challenge 4: Methods
Text

If you get stuck checkout the solution video in the next lecture!

08:26
Problem 1:

Create a method that takes one parameter, an integer, and prints to the console every whole number between it and 1 (including it and 1!). For example, if we passed in 3, your console would show:

3

2

1

Problem 2:

Create a new method that takes two parameters, both integers, and prints every whole number in between them (including the endpoints). For example, if you passed in 6 and 2, your console would display:

6

5

4

3

2

Problem 3:

Create a method that with a return type and an argument that returns the factorial (!) of a number. Give it a google if you have not heard of factorial before! Be careful, don’t pass in too large of a number. Factorials get scary big fast! If you are having trouble figuring out the factorial equation simply make a method that accepts 1 argument and returns an integer value.



  1. Solution 1:

    To solve our first problem we need to create a new method. This method takes 1 parameter of type int. Notice that we add a colon and then the type in parenthesis followed by an variable name. Once we have our method setup it is prudent to test if the variable passed to this method is greater than 0. Once we confirm that it is greater than 0 we use a for loop to iterate down from the parameter to 1. Each time we go through our for loop we print the current value of i to our console.

    - (void)printAllWholeNumbersBelow:(int)number

    {

    if (number > 0) {

    for (int i = number; i > 0; i--) {

    NSLog(@"%i", i);

    }

    }

    }

    Solution 2:

    To solve our second problem we need to create a new method. This method takes 2 parameters both of type int. Pay special attention to the syntax below. Each argument has a name, a type and a variable name. For example in our method below we have the following:

    first parameter:

    name: printWholeNumbersInbetweenFirstInteger type: int variable name: firstInteger

    second parameter:

    name: andSecondInteger type: int variable name: secondInteger

    Once we have our method setup we need to do a bit of logic. Using an if, else if and an else comparison we can test 3 bits of logic. The first comparison we will do is if the two integers are the same. In this case there is no need to print out numbers between the two integers since they are equal. The second comparison tests if the first integer is greater than the second integer. In this case we iterate from our first integer down to our second integer printing out each value in between. In our third case we iterate from our second integer to the first integer.

    - (void)printWholeNumbersInbetweenFirstInteger:(int)firstInteger andSecondInteger:(int)secondInteger

    {

    if (firstInteger == secondInteger) {

    NSLog(@"The numbers are equal!");

    } else if (firstInteger > secondInteger) {

    for (int i = firstInteger; i >= secondInteger; i--) {

    NSLog(@"%i", i);

    }

    } else {

    for (int i = secondInteger; i >= firstInteger; i--) {

    NSLog(@"%i", i);

    }

    }

    }

    Solution 3:

    To solve our third problem we need to create a new method. This method takes 1 parameters of type int but also returns an integer unlike our first two problems. Notice that instead of using void we put int in the parenthesis at the beginning of our method. Inside of our method each time we iterate through our for loop you multiply your answer by your current index -1. For example 5! (5 factorial) would be equal to 5 * 4 * 3 * 2 *1.

    - (int)factorialOfInteger:(int)number

    {

    int answer = number;

    for (int i = number; i > 1; i--) {

    answer = answer * (i - 1);

    }

    return answer;

    }

    Github: Method Challenge Solution

Section 12: Classes
10:34

Draw a UIImageView onto our screen. Make sure your iPhone is a 4 inch. If you choose the 3.5 option, you might have a bit of your screen missing on your bottom.

  • Also drag two labels to the bottom of the screen. Notice the blue lines that come up to assist you make everything pleasing and symmetric. Drag one label to the bottom left and one to the bottom right.
  • Make the bottom left label, the nameLabel, have a font of Futura Condensed Extra Bold size 23 and make the color white.
  • Similarly for the right label, the breedLabel, make the font futura medium size 12 and again color white.
  • Make sure to allign both labels baseline with the bottom of the screen and make them large enough to fit the text.
  • Hook them up in the usual property type way, giving them names such as myImageView, breedLabel, and nameLabel.

In the same way that cars had properties of color and brand, and dogs had age and breed, our view controller has an imageView and nameLabel property

Now back to ViewController.m so that we can set the last property of our dog. We need to give the dog a image so that we will be able to update our viewController’s myImageView property.

 set myDog.image = [UIImage imageNamed@”St.Bernard.JPG”];

myDog.image is of type UIImage. To match that the right side of the equation must produce or return a UIImage object. Thus we know that the imageNamed@”” method takes one argument, in this case a string which we’ve seen created with @”” with characters inside.

This method searched for an image named St.Bernard.JPG and once it finds this file it converts it to a UIImage object and returns this UIImage object.

What is peculiar is that UIImage is a class and not an object. imageNamed is therefore known as a class method, a concept that will be touched on later.

On the bright side there are only two types of methods so you’ve now seen both types! The first type is an instance methods which we call on objects and class methods which we call on classes.

One other note before we move forward: I want to reiterate that being very careful with spelling and capitalization is crucical to computer programming. Just like an essay submitted to a course would be marked off for spelling and punctuation mistakes the computer will not understand you even if you are off by one letter. This can be fustrating when you are starting out. In the long run you’ll appreciate the feedback the computer gives you. Unlike an essay submitted to class where you must wait for your professor to mark out in red ink all your mistakes, the computer can give you immediate feedback.

Now we need to get our dogs attributes on the screen. Well I think we have seen similar things before.

At the bottom of viewDidLoad write the following Code:

 self.myImageView.image = myDog.image; self.breedLabel.text = myDog.breed; self.nameLabel.text = myDog.name;

Check out the github repo here

09:47

When creating multiple MBFDog objects, each encapsulating information about a dog, we used a different variable name within our viewDidLoad method. Although it might seem intuitive, it is worth repeating that we do not use the same variable name designating different dogs more than once inside of a method. Also notice that each instance of our MBFDog class can set its own properties to further define what it is, or make it more unique. After entering the code below we will have four unique objects if we include the myDog object we previously created.

MBFDog *secondDog = [[MBFDog alloc] init];
secondDog.name = @"Wishbone";
secondDog.breed = @"Jack Russell Terrier";
secondDog.picture = [UIImage imageNamed:@"JRT.jpg"];

MBFDog *thirdDog = [[MBFDog alloc] init];
thirdDog.name = @"Lassie";
thirdDog.breed = @"Collie";
thirdDog.picture = [UIImage imageNamed:@"BorderCollie.jpg"];

MBFDog *fourthDog = [[MBFDog alloc] init];
fourthDog.name = @"Angel";
fourthDog.breed = @"Greyhound";
fourthDog.picture = [UIImage imageNamed:@"ItalianGreyhound.jpg"];

*note - pictures may be downloaded from the handouts section.

Now that we have 4 dogs we need a place to store them. Our solution comes in the form of a NSMutableArray, which is simply a container for objects. We can also think of an NSMutableArray as an ordered list of objects. A NSMutableArray is also an object itself and is subject to all of the rules that pertain to objects that we have encountered thus far. We'll learn more about NSMutableArray in a future video.

Since we will be accessing our NSMutableArray from multiple methods, it is prudent to make it a property. Unlike local variables, which only exist inside the scope of a particular method, properties retain their value and name in all methods. In our header file declare the NSMutableArray property:

@property (strong, nonatomic) NSMutableArray *myDogs;

Now that we have a variable name that points to an NSMutableArray object. In order to start using our NSMutableArray, we need to create or instantiate the object. Don’t forget this! Declaring an object as a property does not mean it is already instantiated! Among other things, properties create an instance variable that may be accessed throughout the class. Go to the viewDidLoad method in our ViewController.m file, and below our recently created dogs add the following line of code:

self.myDogs = [[NSMutableArray alloc] init];

That created a container for our dogs (you can think of it as a kennel I guess)! Still within our viewDidLoad method, add our dog objects to our mutable array. To accomplish this, we call a method called addObject: which takes a single argument. This argument expects any type of object, which is why we see id as the argument type. We'll learn more about id later but for now id is an anonymous pointer to any type of object. To add the objects:

[self.myDogs addObject:myDog];

[self.myDogs addObject:secondDog];

[self.myDogs addObject:thirdDog];

[self.myDogs addObject:fourthDog];

Our NSMutableArray property aptly named myDogs has all of our dog objects. As a good exercise, using the NSLog function to print our myDogs array to the console will reveal a list of memory addresses. Although they look like nonsense, each of those correspond to a dog object – our container is working! We use the %@ token when logging objects.

NSLog(@"%@", self.myDogs);

02:06

NSMutableArray is a subclass of NSArray, which means that it has all the functionality of an NSArray.

By being mutable, an NSMutableArray is also allowed to add and delete its own objects.

If an NSMutableArray is simply an NSArray but with extra goodies, why don't we just use it all the time?
Although it might not be apparent now, it is sometimes very good practice to keep containers immutable and thus, not allow other parts of your application (or people!), to mess around with what they contain. Furthermore NSArray has a few performance advantages over NSMutableArray, being a simpler class. In general, the simplier a class is (having less functionality), the faster, or higher performance it is. This might seem obvious.. Downloading a few words is infinatley faster than video!

When we want to access objects in an NSMutableArray, we can do so by their "index" . The index is simply a count, starting at 0, that keeps track of an objects location in an array. The method objectAtIndex: is implemented by NSArray and returns an object for a given integer index. Notice that if we try to access an index that does not exist in an array (ie. there is no object at that index) our application will crash!

Again, the first index in our array is labeled as the 0th index - explicitly not 1 in accordance with zero-based numbering.

If you are feeling smart today or are craving some mathematics, take a look at why below: Why numbering should start at zero.

Below are just a few useful methods implemented by NSMutableArray and NSArray:

insertObjectAtIndex: - instead of adding an object to the end of our list we can insert an object into the middle or beginning of our NSMutableArray.

removeObject: - Using our variable name we can remove an object that has been previously added to our NSMutableArray.

removeLastObject - Sometimes we don't need to remove a specific object but only want to remove the last object NSMutableArray.

If you have a minute take these methods out for a spin and see if you can make each one work properly. Be sure to check the official documentation for others!

02:24

The official documentation is a necessary tool in order to learn more about classes that apple has written and what they can do. Apple’s documentation includes examples, best practices, and even sample code.

To access the Documentation, you can select help from the top menu bar (keyboard shortcut: command + shift + ?) Then select the help option (keyboard shortcut: command + option + ?). Furthermore, you can also hold down option and click a class name in your code - how convenient!

Use the search bar to explore. I would recommend taking some time to look over the documentation for NSMutableArray, NSArray, NSString, and UIViewController at the very least - these will appear in (almost) every application you will ever write! Better know what they are capable of so that you don't have to write the code yourself.

09:22
  1. In order to change the dog the on the screen dynamically, there is a need for a user to be able to interact with our applicaition. We accomplish this by adding a UIBarButtonItem (a fancy word for button) on a UIToolBar. When the user hits this button, voila, a new dog!

    So what happens when that UIBarButtonItem is pressed? Lets step through the code.

    This creates a variable (of type int) that is equal to the number of dogs in our array.

    int numberOfDogs = [self.myDogs count];

    This creates a variable between 0 and numberOfDogs - 1. Notice that this conveniently matches exactly the possible indeces of our myDogs array! arc4random() is a function that returns a pseudo random number between 0 and really large number!

    int randomIndex = arc4random() % numberOfDogs;

    Here we are using the modulo operator, %, to instantly scale our random number to an appropriate size.

    Now that we have a random index, we can simply ask our myDogs array to return a dog for this given index.

    MBFDog *randomDog = [self.myDogsobjectAtIndex:randomIndex];

    We have our dog, lets update our ViewController's UI elements to match.

    self.myImageView.image = randomDog.image;
    self.breedLabel.text = randomDog.breed;
    self.nameLabel.text = randomDog.name;

    As a bonus, we can see that we are also able to alter our UIBarButtonItem's property. How? Although we do not have it as a property of our ViewController, it is passed in as an argument to our action method. The button is referred to as "sender" within the method.

    Update the UIBarButtonItem's title property to "And Another".

    sender.title = @"And Another!";

  2. The code repository can be found here: Man's Best Friend

Section 13: Extra Credit: Animations
04:36

Woah... fancy animation... sign me up!

I'll admit, this video is a little ahead of the curve. But who doesn't like some extra credit animation- I have to show it!

Comment out the following lines of code below responsible for updating your UI elements. To comment out a block of code, you can first highlight it and then press "command" and "/" concurrently.

// self.myImageView.image = randomDog.image;
// self.breedLabel.text = randomDog.breed;
// self.nameLabel.text = randomDog.name;

Replace the above code with:

[UIView transitionWithView:self.view
duration:2.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.myImageView.image = randomDog.image;
self.breedLabel.text = randomDog.breed;
self.nameLabel.text = randomDog.name;
} completion:nil];

As I said before, there is certainly a lot new here. But lets break it down into stuff that we do know, or at least can give an intelligent guess about. You certainly do not have to understand everything that is going on here.

TransitionWithView:duration:options:animations:completion: is a method implemented by UIView (I wasn't kidding when I said Objective-C had long method names). It is known as a class method, and hence, is called on a class and not an object. We will see more of this later!

The number that is passed in after duration: predictably describes how long the animation will take place. Likewise, options: takes an argument that describes the type of animation occurring.

animations:^{} is certainly funky looking. Its structure is known as a block- something that we will get into later. For now, just be sure to notice that this method animates whatever code is placed within those curly braces. In our case, the changing of our image and text.

Lastly, we pass nil into completion:, which just asks for code to be evaluated when our animation ends.

Don't worry about the crazy semantics yet. The purpose of showing this early was two fold:

First, look how easy (well, maybe not easy but it certainly doesn't take much code) it is to add such a complex effect as animation- Apple really does a lot of work for you!

Furthermore, without knowing what this code explicitly says, changes are good that you could have guessed what is does. Objective-C is meant to sound like English. duration: really is going to mean how long the animation lasts.

Section 14: Challenge 5: Debug Recurring Dog
Text

If you get stuck check out the solution video! Also please note that the solution video is missing one line of code to complete the solution so definately check out the notes!

03:12
Important Note:

This video is missing a single line of code:

self.currentIndex = randomIndex;

See below for it's inclusion in the code

We're not out of the woods yet!

Sometimes when you hit the New Dog button it will not show you a new dog. Uh oh, this isn't what we signed up for...

The problem is that sometimes we actually see the same dog. That is, when we choose a random dog from our array, it happens to be the dog that is already on screen. This is the first real bug that you will encounter! Although there are many ways to fix it, it will require a little bit of out of the box thinking.

Need a hint? I would reccommend keeping track of our current index (maybe by making a property?). If we have that information, an if statement could be used to check if our new index is equal to our previous one.

Also, interested in where the term "bug" came from? Feel free to check out below:

Grace Hopper's Bug

Solution

The first step to solving this problem is figuring out a way to keep track of our currentIndex. A property would come in handy since I can access it in all of my methods and I can set a value that will be persisted as long as my ViewController class exists.

In ViewController.h declare the property:

@property (nonatomic) int currentIndex;

In our application we always start with the same dog. This is a result of the code we wrote in viewDidLoad that sets up our initial view. As a result, we need to give our current index an initial value as well. In viewDidLoad write the following line of code to set our initial index to 0.

self.currentIndex = 0;

Great now that I have an initial currentIndex for my application I next need to update my newDogBarButtonItemPressed method to test if the currentIndex property is equal to my random index. My first if statement below tests if the saved currentIndex and the randomIndex generated are the same. It also tests if the currentIndex equals 0. If both of these comparisions are true we need a new number so we add one to our random index and then update the view with the appropriate dog. Next we test if the currentIndex and the random index are the same. If they are we subtract one from our randomIndex. By subtracting instead of adding we won't run the risk of exceeding the number of dogs in our myDogs array.

 if (self.currentIndex == randomIndex && self.currentIndex == 0){ randomIndex ++; } else if (self.currentIndex == randomIndex){ randomIndex --; } self.currentIndex = randomIndex;

The code repository can be found here: Man's Best Friend

Section 15: Inheritance
01:29

All objects have a common ancestor known as NSObject. In other words, all the classes we deal with will have NSObject’s base functionality and behavior (Knowing this, it would be a great idea to check out its documentation!).

If you do check out the documentation, you will notice that NSObject implements both the alloc and initmethods so that classes can create instances of themselves. So this is why every class can call these methods!

Notice that classes progress down the class hierarchy, they have all the behavior of their parent and more- that is they only gain functionality. For example, an NSMutableArray is an NSArray.. and more!

06:39

Now that we have created a Puppy class, we can add behavior to it that is particular to a puppy:

-(void)givePuppyEyes;

A puppy is a dog, and therefore can do anything a dog can do. However, the reverse is not true. A dog is not always a puppy! Giving puppy eyes is behavior exclusive to a puppy.

Because a puppy is a subclass of a dog, it inherits all the functionality of a dog and can add to it. Thus, a puppy also has a name, breed, and the other properties declared in our MBFDog class.

littlePuppy.name = @"Bo O.";
littlePuppy.breed = @"Portuguese Water Dog";
littlePuppy.image = [UIImage imageNamed:@"Bo.jpg"];

Since a puppy is a dog, it can be used anywhere a dog is used. Thus, there is no restriction in adding our puppy to our myDogs array.

[myDogs addObject:littlePuppy];

If you have never dealt with inheritance before, it can certainly be a little tricky! Don't worry if you are struggling with the concept now, we will encounter inheritance countless times throughout the course so there is plenty of time for it to sink in.

02:17

While class inherit functionality from their parents, there are certainly times where a subclass will want to simply act differently. That is, it won't share the exact functionality of its parent. To accomplish this, a class can override a method declared in its superclass in order to change its behavior.

A puppy inherits the method bark from its superclass, a dog. However, a puppy doesn't quite bark like a dog. In this case, the puppy needs to override the bark method.

- (void)bark

{

NSLog(@"Whimper Whimper");

}

Thus whenever the method bark is called on a puppy object, it will respond as a puppy would with a whimper!

You should note that a subclass inherits ALL of its superclass' behavior, whether public or private. However, in order for Xcode to help with the autocomplete, the superclass' properties and methods must be declared in the header file. ALthough it is possible to override a method declared only in a superclass' implementation file (and thus private), this is strange and usually frowned upon.

01:27

In the previous section we learned that it is possible to override a method defined in our superclass (the class we inherit from) and implement custom functionality for a method. It is also possible to simply extend the functionality of a method. In short, for a method defined in our super class we can gain access to all of its' functionality and then add our own on top.

To accomplish this we use the super keyword. We've briefly caught a glimpse of this in the ViewController.m file we saw [super viewDidLoad];. In English this means, do everything that my superclass does in this method!

As a parallel, in our MBFPuppy class, we can call our MBFDog's implementation of bark, and then add our own behavior if we would like.

[super bark];

// Do more stuff!

It is quite common to have a subclass implement its superclass' implementation of a method, and in turn that superclass implement its own superclass' implementation. With this, a sort of "chain" occurs up the hierarchy with a method implementing behavior from numerous ancestors.

Section 16: Object Continued
02:42

The stack and the heap are two main ways in which data is stored in Objective-C. We need memory to store our variables and information, so that we can pass this information around.

The stack is memory primarily reserved for local variables that exist within the scope of a function. Primatives such as floats or BOOLs are stored in the stack.

The heap is where objects live. Objects can be variable in size, and thus it is more efficient to access them through an address rather than directly. Each object has a memory address which variable can "point" to. The * when declaring an NSString for example (NSString *myString = @"Hello";), designates that myString holds a memory address where the object @"Hello" lives.

Confusing? Well, right now it might be but the key takeaway is that objects and primatives are stored in memory differently. Objects, being variable in size, are stored in the heap while primatives are stored in the stack.

04:14

NSString, similarly to our MBFDog, is simply an object. You call alloc and init on the class to create a new one, and the variable holds a pointer to a string object.

Many of the objects we will use have NS in front of them like NSString, NSMutableArray and NSArray. NS is representative of NextStep libraries. Notice that these two letters are simply there for the same reason we added a Class prefix to our classes, to avoid collisions!

Now that we have been exposed to objects, we are able to demystify the strange @”My String” syntax. NSStrings are used frequently and thus Apple has created shorthand or a literal syntax to make code easier to write and read. Every time you have seen @””, it was simply shorthand for allocating and initializing a NSString object.

Thus creating an NSString using a literal syntax:

NSString *myString = @”The NewFoundland dog breed has webbed feet which aids in its swimming prowess!”

Achieves the same effect as using the traditional alloc and init method calls:

NSString *myString = [[NSString alloc] initWithString:@”The NewFoundland dog breed has webbed feet which aids in its swimming prowess!”];

Because NSString is used so frequently, it is advised that you check out the documentation in detail. There are many powerful methods that have already been written. For example, we can separate the words in this sentence using the method componentsSeperatedByString:. This method returns an NSArray of strings.

NSArray *wordsInSentence = [[myString componentsSeperatedByString: @” ”]];

There is no harm in playing around with these methods and seeing what they do!

06:43

Lets make sure we understand each line of the code.

NSMutableArray *capitalizedWords = [[NSMutableArray alloc] init];

for (int word = 0; word < [wordsInSentence count]; word++) {

NSString *uncapitalizedWord = [wordsInSentence objectAtIndex:word];

NSString *capitalizedWord = [uncapitalizedWord capitalizedString];

[capitolizedWords addObject: capitalizedWord];

}

Notice once again that our index word starts at 0 and not 1. This is a consequence of our array starting at index 0. Next, our upper limit is less than but not equal to the number of words in sentence. If we go over, we will get an error.

In our original for loop we assume that all objects in the wordsInSentence array are strings. However, if we had added any type of object other than NSString to our array when we attempt to call a string method on the object our application would crash. I urge you to try this for yourself!

Since iterating through the objects of an array is such a popular task, a quicker shorthand method is available known as "fast enumeration" (If you haven't been paying attention: Popular --> Shorthand).

The Fast Enumeration Way

NSMutableArray *capitalizedWords = [[NSMutableArray alloc] init];

for (NSString *word in wordsInSentence) {

NSString *capitalizedWord = [word capitalizedString];

[capitolizedWords addObject: capitalizedWord];

}

07:00

When you write an @property statement, you are actually implementing two methods and declaring an instance variable to store information behind the scenes - you do not see this code in the implementation file!

In our previous MBFDog class, we declared an NSString property referred to as 'name'. This NSString is stored as an "instance variable" under the variable name '_name'. (The underscore is an adopted convention when naming instance variables).

With this _name available to us, we are able to both write this variable (or set it) and read it (or get it). The automatically included "setter" and "getter" methods that have been written when you declare a property are:

-(void)setName:(NSString *)name;
-(NSString *)name;

Their corresponding implemenations are as follows:

-(void)setName:(NSString *)name

{

_name = name;

}

-(NSString *)name

{

return _name;

}

The setName: method will allow us to change the value of the instance variable. The name method will return the current value of the instance variable.

The last component is what we are actually reading or writing, the instance variable itself. In code, the declaration of an instance variable looks like:

@interface MBFDog : NSObject{ NSString *_name; }

Notice that if you have included all the code written above, your code is now synonymous with your @property declaration... meaning you can get rid of it! However, obviously declaring @property is a much cleaner approach to accomplishing what is above.

In summary, dot notation is simply a replacement or short hand for a method call. When we use the dot notation on the right side of an equal sign, we are implementing the getter or the -(NSString *)name method. When we use dot notation on the left side of an equal sign we are setting the value of an instance variable, or using -(void)setName:.

Section 17: Pirate Adventure Assignment: Prereq's
04:37

NSArray is a container that we can use to hold objects. A NSArray holds these objects as an ordered list of pointers or references to our objects stored in the heap. It is also immutable, meaning that once we create our array object we will not be able to add or remove objects from it.

When creating an NSArray we can use the custom initializer initWithObjects: to instantiate our object with a set of objects. This is really handy since it saves us from having to create an NSMutableArray and then add 1 object at a time. NSArray also has a performance advantage over NSMutableArray since they are simpler objects. Look below for an example of our custom initalizer.

NSString *firstString = @”Hello”;

NSString *secondString = @”

NSArray *myArray = [[NSArray alloc] initWithObjects:firstString, secondString,nil];

Notice that the last item we added in our initializer was nil. This tells the computer program that we are done adding objects. Why do we have to do this? Without nil our NSArray doesn’t know we are done adding objects and our computer program breaks.

Since a NSArray or NSMutableArray can both accept any type of object for storage we can actually have an array inside of an array. This is known as an embedded array and is actually very common in computer programming.

02:19

CGPoint is an example of a struct, a data type inherited from the C programming language. In its’ simplest form, a struct holds or groups related primitives (ie. integers, floats, and BOOLs) under one name. To create a CGPoint we can use the following syntax:

CGPoint point = CGPointMake(0,0);

Notice the absence of the * notoriously seen with objects. A struct is not an object.

To access the primitives within a struct, we can use dot notation. For example, the x coordinate of the CGPoint point can be retrieved by writing point.x. To access the second value, or y coordinate, we write similarly point.y. It is also important to remember that we can use a CGPoint as a type for a property the same way we declared properties to be of type int.

@property (nonatomic) CGPoint currentPoint;

Once again, notice that we do not use either strong or weak since this a primitive not an object!

01:46

It is possible to nest if statements within other if statements. This is very common when you want some logic to conditionally evaluate, as you would imagine, only when the outer comparison is true.

However, nesting multiple if statements quickly leads to code that is very difficult to read. Generally try to joining comparisons with && or || to create legible code.

04:30

It is possible to update a button using the method setTitle:forControlState. We will cover UIControlState in depth in a future video series. For now stick with UIControlStateNormal. Using this option will allow you to easily update your button’s title in code. For example:

Class.h

@property (strong, nonatomic) IBOutlet UIButton *myButton;

And we could update my method in the class.m file in viewDidLoad with the following bit of code.

Class.m

[self.myButton setTitle:@”New Title” forControlState:UIControlStateNormal];

We can also dynamically hide the button from the user using the hidden property. If we set the hidden property to YES, the button will become "hidden" from the user. This means that not only can the user not see the button, but they cannot interact with it as well. Setting the property back to NO reveals the button once more.

myButton.hidden = YES;

We can also create UIAlertView’s as a way of notifying users, or for lack of a better word, showing them an alert message. To create an instance of UIAlertView look through the following code. For now set the delegate to nil and the otherButtonTitles to nil as well. We’ll learn about delegation in the upcoming week.

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert!" message:@"You trigged the alert" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];

[alertView show];

Notice that in order to have the alert view display on the screen, the method "show" must be called on the alert view object.

01:45

If we want to declare a property of a given class in our header file, we must first import that class into our headerfile (.h). This stands in contrast to our previous imports that occurred mostly in the implementation file (.m).

It is important to note that you want to import into header files sparingly and only when necessary. Importing willy nilly bloats your code (there is more to compile and run then there needs to be) and is not a good design decision. This will become clearer as we begin to discuss popular design patterns in iOS development.

01:32

nil refers to pointer to nothing or no object. At this point in the course, we commonly pass nil in as a parameter to a method meaning that we don't wish to pass in any optional objects.

Furthermore, in Objective-C, it is perfectly legal to send methods to nil although they will not do anything. If you are coming from programming in another language, this might sound strange as sending messages to nil frequently raises exceptions, but in Objective-C, this is not the case. It is perfectly legal, and sometimes quite convienient, to send messages to nil.

Section 18: Pirate Adventure Assignment
Pirate Assignment
Text
13:17
Objective:

This project will be the most comprehensive assignment to-date. At the end of this assignment, you should have acquired a formidable understanding of each of the major concepts we’ve touched upon in our first two weeks. While it might appear intimidating at first, successful completion of the assignment should help you grasp key concepts in object-oriented programming, a foundational pillar for the rest of our class together.

Let me state emphatically that this is meant to be a challenge. But, if you break this up and solve it in chunks, this puzzle is solvable. Building something of this length will allow you to put many of the concepts we've learned so far in an appropriate context.

When approaching this project, we STRONGLY recommend working on one part at a time. As such, we have broken this assignment into multiple parts.

Furthermore, you are highly encouraged to customize your application and attempt the problems on your own before viewing the solution videos. The solutions provided do not constitute the only way to complete this assignment. If your application meets the specified requirements, then you have solved that problem. What is offered is concise and clean code that may prove to be a helpful comparison as you work through the assignment. Finally, this assignment is meant to take some time to complete.

Project Requirements:

The application, at its heart, is a game. The application should have a coordinate system. We recommend starting with a 4 by 3 rectangular coordinate system. Users should be able to navigate to different “tiles” by pressing one of 4 directional arrows. Tiles are objects which will package the information required to update our view. When a valid movement is not possible the buttons should be inactive or hidden.

Use a Tile object to package the information. This means creating a class called Tile that will have properties that we can use to update our view ie. a story, a background etc. You can declare these properties in its' header file. Then when you create instances of your tile object you can set these properties and group information for your view together.

The game should also include a character object. It should have health, damage, weapon and armor stat. The first two properties may be integers but the last two should be a Class that you create. This means you will have to create a Armor and Weapon class. Both of these classes should have a name and damage or a health bonus where appropriate.

The view should contain at least 1 label that should display a story for our game. There should be at least 1 button that allows the user to do a specific action based on the current tile. There should also be an area to display your character’s stats including its' health amount, damage amount, weapon name and armor name.

To create the tiles, you should implement a Factory class. This sounds complex, but in reality it is pretty straight forward. The Factory class will serve as an intermediary between our models and our View Controller. We should define a method that returns an NSArray of Tile objects. Within this method we can create 12 instance of our Tile class and set properties for our tile here. While not required, it is certainly recommended that you create 4 arrays that contain 3 tile objects. We then recommend wrapping all 4 arrays into a single array and returning it from your method. This is called an embedded method and was discussed in the Pirate Adventure Prereq videos.

When users tap on the directional buttons, the application should be able to determine which tile to make active. Your application should also update the information on the view appropriately. Users should also be able to interact with the story with the action button (we included this in the actions UIView). Suggested interactions could include: picking up an additional weapon, armor or some health effect either negative or positive.

There should be only 1 character object in the application at a given time and that character should only have 1 weapon and 1 armor. Therefore, if an action changes the weapon you will have to determine how to remove the old weapon and/or armor and its’ effect before adding the new armor and weapon. This updated information should be displayed in the character stats UIVIew.

To finish the application you will need to create a Boss class. Like the character, the Boss object should have a health stat so that we know when we’ve defeated the boss. Users should be able to fight the boss on one of the tiles. Every time an action occurs that may reduce our characters health, we should check to see if our current health is 0. During the fight with the boss we should check to see if the bosses health is 0. If our boss dies before we lose all of our health, we should alert the user they have won. If we die at any point in the application we should be alerted that we lost the game.

Finally, the user should have a way to start over. Add a button to your application and title it reset. When the user presses this button reset the character’s stats to their initial values, set the starting point back to 0,0 and reload the view.

Extra Credit

We will include additional tasks for those students that want to push forward and attempt some problems on their own. These are only recommendations and are not core to our curriculum. Let me stress that these are meant to be very challenging. In many cases you will need to come up with inventive solutions or do a bit of online research. Best of luck!

Randomize tiles 2-12 so that your game is more dynamic. You always start at the same place but the location of the boss and everything else is left to chance.

Right now if a user doesn’t want to complete an action they can simply navigate to a new tile. Disable the navigation buttons for certain tiles so the user must complete an action before they can proceed. For the final boss fight lock the user in so they can not retreat until they have gotten attacked at least once by the boss.

Add additional UIAlertViews to tell a better story and make it more interactive. For example once a user picks up a sword put up an alert that says user takes sword.

Add an additional class for our character, perhaps an item class.

Do some balancing with your damage and health numbers so that it is possible for your user to lose if they take the wrong path, but also possible for them to win if they take the correct path through your game.

RECOMMENDED STEPS AND HINTS:

Part 1: Setting up the storyboard, a basic Tile object and a Factory.

Part 2: Navigating between tiles, adding a background image and upgrading the story.

Part 3: Adding additional objects: Weapon and Armor and Character: adding their effects to our project.

Part 4: Adding a actions to our story

Part 5: Final boss and Reset

Note

The recommended steps below are not the only way to solve this assignment. As much as you can try and solve the assignment based on the requirements and use this section when you get stuck or are unsure of how to proceed.

Part 1: Setting up the storyboard, a basic Tile object and a Factory

The first thing we need to do is setup our view. Setting up our view will give us an idea of where this project is headed and will hopefully get us thinking about how our viewcontroller interacts with our view.

Take a look at the assignment video for inspiration (although feel free to take some artistic liberty!). The background is a UIImageView and as a nice touch, I set my container UIView objects to be partially transparent. I set the "alpha" property on them to induce transparency. Alpha may be found in the attributes inspector and has a value between 0 and 1.

Although our tile object will eventually be used to update our entire view, we recommend you start with a basic story until you can get the tiles updating properly as you navigate on your coordinate system.

Finally, you should create your factory class. The method declaration should look something like this:

-(NSArray *)tiles;

I recommend creating 4 arrays that each have 3 tile objects. Something like this:

NSArray *column1Array = [[NSArray alloc] initWithObjects:tile1, tile2, tile3];

NSArray *column2Array = [[NSArray alloc] initWithObjects:tile1, tile2, tile3];

NSArray *column3Array = [[NSArray alloc] initWithObjects:tile1, tile2, tile3];

NSArray *column4Array = [[NSArray alloc] initWithObjects:tile1, tile2, tile3];

Then create an array to hold each column:

NSArray *tilesArray = [[NSArray alloc] initWithObjects:column1Array, column2Array, column3Array, column4Array];

Part 2. Navigating between tiles, adding a background image and upgrading the story.

Now that we have a factory setup we should use it to create our tiles array in our view Controller. We also need to setup an initial point for our user to start at in our coordinate system. I recommend using a property for both in the CCViewController.h headerfile. This way will be able to access your current point in all methods as well as your tiles.

Don’t forget to create a CGPoint we use the syntax CGPointMake(x,y).

Each time we set a new tile as our active tile we need to hide buttons that are invalid. To do this we can use the hidden property for UIButton that will hide the button on the screen. This property can be set to a BOOL value ie. YES or NO. I recommend putting this into a method so that we can reuse this functionality throughout our application.

We should call this method in viewDidLoad so that when our initial view is setup our west and south buttons will be hidden.

We should run a test on all 4 buttons to determine if they are valid. This can be accomplished by simply taking our current point and either adding 1 to x, adding 1 to y, subtracting 1 from x or subtracting 1 from y. On this new point we have to perform 4 tests. If the point passes all 4 tests it is a valid or possible. If it fails any of them the tile does not exist. We should check to make sure that our y point is greater than or equal to 0 and that our x point is greater than or equal to 0 to confirm that our point is above our lower bounds. To test our upper bounds we should check to make sure that our x point is less than the count of our tiles array. We should also check to make sure that our y point is less than the tiles array container. We can access this tiles array through: [self.tiles objectAtIndex:point.x].

Now that you are able to dynamically hide your buttons you need to actually implement the functionality for each of your IBActions connected to the arrow buttons. If for example the user presses the north button update the current point with something like: self.currentPoint = CGPointMake(self.currentPoint.x, self.currentPoint.y+1);

Finally, once you have the navigation between tiles working which you should be able to confirm visually on your storyboard as your story should change from reading story 1 to story + 2-12. It’s time to update you factory. Add a background image to your tile object and make your story more explicit. Then using that information update your view.

Part 3: Adding additional objects: Weapon and Armor and Character: adding their effects to our project.

It is important to learn about creating many classes and one of your classes as a property in another class.

First create a Weapon and Armor class. The weapon class should have properties of damage and name of type int and NSString respectively. The Character class should have properties of health and name of type int and NSString respectively.

Now you can create a character class. A weapon, armor, damage and health. In order to create a property of type Weapon and Armor you will need to import both the Weapon class and Armor class into your header file, not your implementation file.

Next create an instance of character in your factory. You should setup some initial settings. Perhaps your character starts with a weapon or armor. You should give your character an initial amount of health and you can choose to give you character damage. The factory will have to import character into its’ header file. Your method might look something like this:

-(CCCharacter *)character;

Notice that we are returning a character instance from this method, hence the need to import our character class into our header file.

Finally, in your ViewController.h file create a property so you will be able to access its’ value throughout your class. Then create your character in viewDidLoad. You should finish by updating your characters information onto the view.

Part 4: Adding a actions to our story

Now that we have a character inside of our application and we can navigate through our application its’ time to add actions to our application.

Start by updating your tile. For brevity your tile’s header file should now have a story, a background image, an actionbutton title, a weapon, armor and health effect.

Now in our factory we can setup our tile to include all of these attributes. For example a tile in our factory might now look like this:

Tile *tile1 = [[Tile alloc] init];

tile1.story = @”In the stone you see a gilded sword that glimmers in the sunlight”

tile1.backgroundImage = [UIImage imageNamed:@”GlimmeringSword.jpg”];

tile1.actionButtonTitle = @”Take sword”;

Weapon *sword = [[Weapon alloc] init];

sword.name = @”Glimmer sword”;

sword.damage = 20;

tile1.weapon = sword;

Now our tile knows that its’ action is related to a specific weapon or armor or health effect. Update all your tiles so that they have an actionButtonName so that we can update our actionButton in our storyboard. Also add Armor a weapon or a health effect.

When thinking about where to implement this functionality remember that we have an IBAction called actionButtonPressed. It would make sense here to test if the current tile has either a weapon, armor or a health effect associated with it here. Using an if, else if and else statement we should be able to test which variation our tile object has. For example:


if (tile.armor != nil)

{

self.character.health = self.character.health - self.character.armor.health + tile.armor.health;

self.character.armor = tile.armor;

}

Notice that we first update our characters health by removing the old armor before adding our new armor’s health benefit. Then we update our current character’s armor to the tiles armor.

Part 5: Final boss and reset

Create a Boss class it should have a health. Depending on your implementation it may also do damage or you may include damage as a health effect as part of the boss story. Create a method in your factory that returns one boss object:

-(Boss *)boss;

As we did with our character object I would recommend only having one boss in our class. We will need to track its’ health stat for the entire life cycle of our view Controller so it would be prudent to make our boss a property. You can use your factory to setup your boss in the viewDidLoad method.

Every time you do an action you should test if your health is less than 0. Now that you have a boss you should also do an if statement to test if the bosses health is less than 0. Finally, it would be great if the user were alerted if their health falls below 0 in which case they lose or if the bosses health dips below 0 in which case they can claim victory. I would recommend using a UIAlertView:

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Death" message:@"You have died restart the game!" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];

[alertView show];

If you aren’t sure how to do this check out the video and you can see it done by hand!

Section 19: Pirate Adventure Solutions: Parts 1 & 2
14:46

In order to get our application working we need to setup our storyboard:

  • Add a UIImageView object onto our view this will serve as the background for our application.
  • Drag in 3 UIViews onto our of our UIImageView, these will make up our sections. We will be adding objects ontop of these views. We say that each of these views is a subview of our Imageview which is also a subview of the view that the viewcontroller manages. Later we will add View Objects like buttons and labels onto each of these subviews. We can say that each of these ViewObjects a subview of our subview.

Now we should adjust the backgrounds for each of our UIViews:

  • The top UIView will hold our Character stats. Change its' background color to yellow and set the alpha to .6.
  • The middle UIView will hold our Actions area. Change its' the background color to red and set the alpha to .6.
  • The bottom UIView will hold our Story area. Change the background color to white and set the alpha to .6.

Next we will update our views, we will start with the Character Stats UIView.

  • Add a UILabel and name it Character Stats. Set its’ font to Zapfino with a size of 17.0 and align the label to the right.
  • Add 8 additional labels with 2 labels side by side in 4 rows. Change the labels font to Marker Felt Thin and change it's font size to 15.0.
  • The Labels names should be: Weapon, WeaponName, Armor, ArmorName, Health, HealthValue, Damage, DamageValue

Note: we will be updating the right column of labels so you can name these any description that is helpful to you.

The next todo is to update the Actions UIView.

  • Add a UILabel and name it Actions. Set its’ font to Zapfino with a size of 17.0 and align the label to the right.
  • Add a button to the view. Change the button’s font to Noteworthy Light with a size of 15.0.

The final UIView we need to update is the Story UIVIew.

  • Add a UILabel to the upper right hand corner of our story view. Change the first label's name toStory. Set its’ font to Zapfino with a size of 17.0 and align the label to the right.
  • Add another label to the middle of our story view and make this label large. Set the label's font to Marker Felt Wide and adjust its' size to 14.0. Also set the number of lines to 0 in the attributes inspector.

Now lets add 4 buttons that will serve as our compass points. Make sure to add these onto of the UIImageView but below the Story UIView.

  • Drag 4 UIButtons into our project. Name the buttons N, S, E, W. I also adjusted my buttons to have a background color of yellow and a font color of white.
05:04

Hook up all of your view elements to your header file. For organization I recommend keeping all of your properties/IBOutlets together and the methods/IBActions together.

03:26

We will use our tile object to update our view's objects. We will start by adding two properties.

@property NSString *story;

@property UIImage *backgroundImage;

@property NSString *actionButtonName;

We won't be using the actionButtonName for quite a while but this will hopefully be a hint as to the view objects that we will need to update dynmically. By packaging this information together we will be able to access one tile object to update our story, backgroundImage and actionButton's title at the same time.

10:19

We will be using a factory to create our tile objects. There are a variety of reasons to create a factory but in laymans terms it lets us keep the tile creation in another class outside of the ViewController. In short our VIewController will have less code and will be free to do its' primary task of managing the view.

In the CCFactory.h file create a method that returns an array of our tile objects

-(NSArray *)tiles;

To represent the 12 tiles that will make up our game I create 12 tile objects. For now we'll leave the background image and the actionButton's name blank. However, to allow us to test and make sure that our tiles are updating we will use a default story with its' tile number. We will group the tiles into containers or arrays. Each container will serve as a column in our coordinate system. We can group all of these containers together so that the number of containers we add to our array will be equal to the number of columns in our coordinate system.

We also use a little shorthand here for our final array. Instead of creating an NSMutableArray and adding objects after the fact, we create an NSArray and initalize it with objects. The method initWithObjects: is a custom initializer that allows us to create the tiles array with all of the containers. We can then return this tiles array from our method. Now when we create an instance of CCFactory and call the method tiles on that instance we get an array of containers back.

In the CCFactory.m implement the method tiles.

-(NSArray *)tiles

{

CCTile *tile1 = [[CCTile alloc] init];

tile1.story = @"story 1";

CCTile *tile2 = [[CCTile alloc] init];

tile2.story = @"story 2";

CCTile *tile3 = [[CCTile alloc] init];

tile3.story = @"story 3";

NSMutableArray *firstColumn = [[NSMutableArray alloc] init];

[firstColumn addObject:tile1];

[firstColumn addObject:tile2];

[firstColumn addObject:tile3];

CCTile *tile4 = [[CCTile alloc] init];

tile4.story = @"story 4";

CCTile *tile5 = [[CCTile alloc] init];

tile5.story = @"story 5";

CCTile *tile6 = [[CCTile alloc] init];

tile6.story = @"story 6";

NSMutableArray *secondColumn = [[NSMutableArray alloc] init];

[secondColumn addObject:tile4];

[secondColumn addObject:tile5];

[secondColumn addObject:tile6];

CCTile *tile7 = [[CCTile alloc] init];

tile7.story = @"story 7";

CCTile *tile8 = [[CCTile alloc] init];

tile8.story = @"story 8";

CCTile *tile9 = [[CCTile alloc] init];

tile9.story = @"story 9";

NSMutableArray *thirdColumn = [[NSMutableArray alloc] init];

[thirdColumn addObject:tile7];

[thirdColumn addObject:tile8];

[thirdColumn addObject:tile9];

CCTile *tile10 = [[CCTile alloc] init];

tile10.story = @"story 10";

CCTile *tile11 = [[CCTile alloc] init];

tile11.story = @"story 11";

CCTile *tile12 = [[CCTile alloc] init];

tile12.story = @"story 12";

NSMutableArray *fourthColumn = [[NSMutableArray alloc] init];

[fourthColumn addObject:tile10];

[fourthColumn addObject:tile11];

[fourthColumn addObject:tile12];

NSArray *tiles = [[NSArray alloc] initWithObjects:firstColumn, secondColumn, thirdColumn, fourthColumn, nil];

return tiles;

}

To read more about the factory design pattern check out: http://en.wikipedia.org/wiki/Factory_method_pattern

Factory Explained
04:03
08:05

In CCVIewController.h we'll create two properties. The first one will be a CGPoint that will keep track of our current location in our coordinate system. We also will create an NSArray property to store our tiles array.

@property (nonatomic, readwrite) CGPoint currentPoint;

@property (strong, nonatomic) NSArray *tiles;

In CCViewController.m we will setup our properties initial values. We will first set our current point to a CGPoint at 0,0. Meaning that when the user starts our game they will begin at the lower left hand corner of our coordinate system. We use the function CGPointMake which accepts two floats. However, we want to use whole numbers for our coordinate system so you can enter whole numbers into the function as well. Next we will create our CCFactory object and call the method tiles on it. It returns an NSArray that we can set equal to our tiles property.

self.currentPoint = CGPointMake(0,0);

CCFactory *factory = [[CCFactory alloc] init];

self.tiles = [factory tiles];

Now we can create a helper method to update our view. Since we now have a current point with two integers we can index into our tiles array which returns a container/array of tiles. Then we can index into the returned array and get a tile. We set the returned CCTile object to a variable tileModel. Then we can use the tileModel to update our UI. We access the tile model's story property and set it equal to our storyLabel's text property.

-(void)updateTile

{

CCTile *tileModel = [[self.tiles objectAtIndex:self.currentPoint.x] objectAtIndex:self.currentPoint.y];

self.storyLabel.text = tileModel.story;

}

Finally, we need to use our helper method. Let's update our tile by calling the method in viewDidLoad. Make sure to call the method after self.tiles = [factory tiles];. If we attempted to call the method before hand the method would not work properly since the self.tiles propety has not yet been set and/or the currentPoint does not yet exist.

[self updateTile];

10:48

We need to create two methods. The first method will accept a CGPoint and tell you if a tile exists at that point. The method will return a BOOL which will decide whether or not we should hide the button. If the method returns NO the button should not be hidden. If the button is currently hidden unhide it. If our method returns YES we should hide the button. Our if statement will test to confirm that the CGPoint's x and y values are greater than 0. This will confirm that the tested point does not go below our lower bounds. To test our upper bounds we will confirm that the count of the total number of arrays in our tiles array is greater than our x point. We also need to confirm that for the chosen array inside of our tiles array that its' count is greater than the y point. If all of these conditions are true than the tile exists and we return NO. Otherwise the tile does not exist and we return YES.

- (BOOL)tileExistsAtPoint:(CGPoint)point

{

if(point.y >= 0 && point.x >= 0 && point.x < [self.tiles count] && point.y < [[self.tiles objectAtIndex:point.x] count]){

return NO;

}

else {

return YES;

}

}

Next we need to create a method called updateButtons. We will test each button to see if it should be hidden or not. The method tileExistsAtPoint returns a BOOL value as to whether or not we should set the hidden property of our buttons to YES or NO. The CGPoint we pass in should test the current point if a tile exists to the North, South, East or West of our current point.

-(void)updateButtons

{

self.westButton.hidden = [self tileExistsAtPoint:CGPointMake(self.currentPoint.x - 1, self.currentPoint.y)];

self.eastButton.hidden = [self tileExistsAtPoint:CGPointMake(self.currentPoint.x + 1, self.currentPoint.y)];

self.northButton.hidden = [self tileExistsAtPoint:CGPointMake(self.currentPoint.x, self.currentPoint.y + 1)];

self.southButton.hidden = [self tileExistsAtPoint:CGPointMake(self.currentPoint.x, self.currentPoint.y - 1)];

}

Finally, our initial view at 0,0 should only allow the user to go north and east. Lets use our method updateButtons to hide the west and south buttons. Call the method updateButtons in viewDidLoad at the bottom of the method.

[self updateButtons];

03:59

If the user pressed a valid navigation button we need to update our current point, valid buttons and the information on our view.

First we update our current point. If we press the north button for example our y point increases by 1. Now that our current point is at a new location we need to update which buttons are valid from this location. Call the method updateButtons to unhide or hide based on need. Finally, we can update our view with the new tile. Since the updateTile method finds the current tile based on the current point it is important that we update our current point before using this functionality.

- (IBAction)northButtonPressed:(UIButton *)sender

{

self.currentPoint = CGPointMake(self.currentPoint.x, self.currentPoint.y +1);

[self updateButtons];

[self updateTile];

}

- (IBAction)eastButtonPressed:(UIButton *)sender

{

self.currentPoint = CGPointMake(self.currentPoint.x +1, self.currentPoint.y);

[self updateButtons];

[self updateTile];

}

- (IBAction)southButtonPressed:(UIButton *)sender

{

self.currentPoint = CGPointMake(self.currentPoint.x, self.currentPoint.y -1);

[self updateButtons];

[self updateTile];

}

- (IBAction)westButtonPressed:(UIButton *)sender

{

self.currentPoint = CGPointMake(self.currentPoint.x -1, self.currentPoint.y);

[self updateButtons];

[self updateTile];

}

13:12

In CCFactory.m lets update our tile objects. First add the images to your project. Make sure that the project target is selected. Next update the story property since story 1, story 2, etc. is pretty boring.

tile1.story = @"1 Captain, we need a fearless leader such as you to undertake a voyage. You must stop the evil pirate Boss before he steals any more plunder. Would you like a blunted sword to get started?";

tile1.backgroundImage = [UIImage imageNamed:@"PirateStart.png"];

tile2.story = @"2 You have come across an armory. Would you like to upgrade your armor to steel armor?";

tile2.backgroundImage = [UIImage imageNamed:@"PirateBlacksmith.png"];

tile3.story = @"3 A mysterious dock appears on the horizon. Should we stop and ask for directions?";

tile3.backgroundImage = [UIImage imageNamed:@"PirateFriendlyDock.jpg"];

tile4.story = @"4 You have found a parrot can be used in your armor slot! Parrots are a great defender and are fiercly loyal to their captain.";

tile4.backgroundImage = [UIImage imageNamed:@"PirateParrot.jpg"];

tile5.story = @"5 You have stumbled upon a cache of pirate weapons. Would you like to upgrade to a pistol?";

tile5.backgroundImage = [UIImage imageNamed:@"PirateWeapons.jpg"]

tile6.story = @"6 You have been captured by pirates and are ordered to walk the plank";

tile6.backgroundImage = [UIImage imageNamed:@"PiratePlank.jpg"];

tile7.story = @"7 You sight a pirate battle off the coast";

tile7.backgroundImage = [UIImage imageNamed:@"PirateShipBattle.jpg"];

tile8.story = @"8 The legend of the deep, the mighty kraken appears";

tile8.backgroundImage = [UIImage imageNamed:@"PirateOctopusAttack.jpg"];

tile9.story = @"9 You stumble upon a hidden cave of pirate treasurer";

tile9.backgroundImage = [UIImage imageNamed:@"PirateTreasurer.jpg"];

tile10.story = @"10 A group of pirates attempts to board your ship";

tile10.backgroundImage = [UIImage imageNamed:@"PirateAttack.jpg"];

tile11.story = @"11 In the deep of the sea many things live and many things can be found. Will the fortune bring help or ruin?";

tile11.backgroundImage = [UIImage imageNamed:@"PirateTreasurer2.jpg"];

tile12.story = @"12 Your final faceoff with the fearsome pirate boss";

tile12.backgroundImage = [UIImage imageNamed:@"PirateBoss.jpg"];

Now that our tile objects have been updated lets update them in our view. In our updateTile method add the following line of code at the bottom:

self.backgroundImageView.image = tileModel.backgroundImage;

Section 20: A Review
Review (week2 wrap)
08:47
You did it!
Text
Section 21: Pirate Adventure Solutions: Part 3
02:17

We need to create both a weapon and an armor class. We will use these classes to create objects that will have both a name as well as a damage and health effect for weapon and armor respectively. We start with these classes since we will be creating a character in our next video. The character will have a property of weapon and armor allowing it to encapsulate these properties.

For both Weapon and Armor make sure to subclass NSObject. The header files should have the following properties added:

CCWeapon.h

@property (strong, nonatomic) NSString *name;

@property (nonatomic) int damage;

CCArmor.h

@property (strong, nonatomic) NSString *name;

@property (nonatomic) int health;

03:23

Now that we have a Weapon and Armor class we can create a Character class. We will use an instance of this class to store the players information. This will include a weapon, armor, health and damage.

Make a new Character class that is a subclass of NSObject.

The first thing we need to do is import both CCWeapon and CCArmor into our headerfile. In the past we have imported in the implementation file and created instances of classes as needed. In this case we want to create properties that are of class Weapon and Armor. In order for our header file to be aware of these files we need to import them into our Character.h file. Add the following imports into your Character.h file:

#import "CCArmor.h"

#import "CCWeapon.h"

Now lets setup the properties for our Character class.

@property (nonatomic) int damage;

@property (nonatomic) int health;

@property (strong, nonatomic) CCArmor *armor;

@property (strong, nonatomic) CCWeapon *weapon;

04:56

We could create our character instance directly in the ViewController.m file. However, in order to stick with the factory design pattern we've been using so far lets create our Character instance in the factory. Since we'll be returning an instance of our CCCharacter from a method we need to import our Character class.

CCFactory.h

#import "CCCharacter.h"

-(CCCharacter *)character;

Now that we have our method definition setup we need to implement our method. First we create an instance of our CCCharacter class. Then we setup initial properties for our character. These will be the attributes our player will start with at the beginning of our game. We setup our characters initial health to 100. Next we need to create an armor object. Create an instance of our Armor class and assign a name and a health stat. Since the Character class has a property of armor we can set our character instance's armor property to the armor object we created. We can do the same for our weapon property by creating an instance of our Weapon class.

CCFactory.m

-(CCCharacter *)character

{

CCCharacter *character = [[CCCharacter alloc] init];

character.health = 100;

CCArmor *cloakArmor = [[CCArmor alloc] init];

cloakArmor.name = @"Cloak";

cloakArmor.health = 5;

character.armor = cloakArmor;

CCWeapon *fistWeapon = [[CCWeapon alloc] init];

fistWeapon.name = @"Fists of Fury";

fistWeapon.damage = 10;

character.weapon = fistWeapon;

return character;

}

03:50

Since we only want one character object in our class at a time and we want to be able to access this character instance inside all of our methods, it is prudent to make our character a property. Since we will be creating this property in our header file we will need to import our Character class in our headerfile.

CCViewController.h

#import "CCCharacter.h"

@property (strong, nonatomic) CCCharacter *character;

Now that we have a property of class CCCharacter we need to set it up or give it an initial value. A great place to setup properties is viewDidLoad. We know our character object will be avaliable since all other methods in this class will be called after viewDidLoad. We created a method in our Factory class to return a Character object. We setup this method to give our character initial properties such as armor and damage. Since we used our factory earlier to create our tile object we do not need to create another factory instance. In the viewDidLoad add the following line of code after the creation of our factory object.

self.character = [factory character];

Next we need to update the updateTileMethod so that our view can now show our character's initial health, damage, armor and weapon. Add the following lines of code:

self.healthLabel.text = [NSString stringWithFormat:@"%i", self.character.health];

self.damageLabel.text = [NSString stringWithFormat:@"%i", self.character.damage];

self.armorLabel.text = self.character.armor.name;

self.weaponLabel.text = self.character.weapon.name;

Section 22: Pirate Adventure Solutions: Part 4
11:00

In order to add Weapons, Armor and health effects to our story we need to update our tile objects. Encapsulating the data in our Tile Class means that tile object will have properties of Weapon, Armor and/or a Health effect. When our user presses the action button we can determine from our current tile what effect should be applied to the character. We will use these properties to update the armor, weapon or simply changing the character'health.

We need to update the Tile Model's header file to include these new properties. Don't forget to import both the Weapon and Armor classes since we'll be creating properties with these classes.

CCTile.h

#import "CCWeapon.h"

#import "CCArmor.h"

@property CCWeapon *weapon;

@property CCArmor *armor;

@property (nonatomic) int healthEffect

Now that our Tile object has additional properties we need to update our Factory class. The Factory class is responsible for creating our Tile objects. In the following examples we add a weapon, armor or a health effect to each of the tile instances.

CCFactory.h

tile1.buttonName = @"Take the sword";

CCWeapon *bluntedSword = [[CCWeapon alloc] init];

bluntedSword.name = @"Blunted Sword";

bluntedSword.damage = 7;

tile1.weapon = bluntedSword;

tile2.actionbuttonName = @"Take steel armor";

CCArmor *steelArmor = [[CCArmor alloc] init];

steelArmor.name = @"Steel Armor";

steelArmor.health = 7;

tile2.armor = steelArmor;

tile3.actionButtonName = @"Stop at the Dock";

tile3.healthEffect = 17;

tile4.actionButtonName = @"Adopt Parrot";

CCArmor *parrotArmor = [[CCArmor alloc] init];

parrotArmor.health = 20;

parrotArmor.name = @"Parrot Armor";

tile4.armor = parrotArmor;

tile5.actionButtonName = @"Take pistol";

CCWeapon *pistolWeapon = [[CCWeapon alloc] init];

weapon.name = @"Pistol";

weapon.damage = 12;

tile5.weapon = weapon;

tile6.actionButtonName = @"Show no fear!";

tile6.healthEffect = -22;

tile7.actionButtonName = @"Fight those scum!";

tile7..healthEffect = -15;

tile8.actionButtonName = @"Abandon Ship";

tile8.healthEffect = -46;

tile9.actionButtonName = @"Take Treasurer";

tile9.healthEffect = 20;

tile10.buttonName = @"Repel the invaders";

tile10.healthEffect = 15;

tile11.actionButtonName = @"Swim deeper";

tile11.healthEffect = -7;

tile12.actionButtonName = @"Fight!";

tile12.healthEffect = -15;

06:02

Now we can apply the changes that we made to our tiles in the last section. A good first step would be to update the actionButton's title. We created both an IBAction and an IBOutlet for our action button. Therefore, we can use our IBOutlet for our action button to update the title of our button. At the end of our updateTile method add the following line of code:

CCViewController.m

[self.actionButton setTitle:tileModel.buttonName forState:UIControlStateNormal];

In order to update our button's title we use the method setTitle:forState. This method accepts 2 parameters. The first one is an NSString which we set dynamically using our Tile's actionButtonName property. The second argument expects a control state. We will learn about alternative control states in the future. For now use UIControlStateNormal.

Our button's title should now update properly. The next change to our Tile class that we need to implement is the weapon, armor or health effect. Lets create a method that accepts 3 parameters including: armor, weapon and healthEffect. Inside of this method we will use if statements to test if a valid object or number is being passed into our method. If it is, then we adjust our characters attributes appropriately.

Why do we have to test if the object exists. When we updated our Tile object we were not required to add a weapon, armor or health effect. For all of our tiles we simply added one of these. However, we don't want our method to update all of the tile's properties. We only want update character's attributes for the valid property.

We can use nil as a comparision to test if an object exists. It is a pointer to "no object" or nothing at all. In effect, by saying object == nil, we test is the object exists. Since our health effect is an integer we test if it is equal to 0 instead of nil. We only use nil to test if objects exist. Now we add an else statement at the end of our method in the event that everything is nil or 0. This is the case when we first run our application since the user has not pressed the action button. However, we want to setup our character's initial attributes by factoring in the effects of the weapon and armor currently configured for our character.

To accomplish all of these items we can add a helper method inside of the viewController.m file.

-(void)updateCharacterStatsForArmor:(CCArmor *)armor withWeapon:(CCWeapon *)weapon withHealthEffect:(int)healthEffect

{

if (armor != nil){

self.character.health = self.character.health - self.character.armor.health + armor.health;

self.character.armor = armor;

}

else if (weapon != nil){

self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;

self.character.weapon = weapon;

}

else if (healthEffect != 0){

self.character.health = self.character.health + healthEffect;

}

else {

self.character.health = self.character.health + self.character.armor.health;

self.character.damage = self.character.damage + self.character.weapon.damage;

}

}

03:22

Now we have a method that will use our Tile's properties. There are two locations we should apply this method. The first is in viewDidLoad so when our application first runs our character's armor and weapon stats are accounted for. In viewDidLoad add the following line of code:

[self updateCharacterStatsForArmor:nil withWeapons:nil withHealthEffect:0];

Notice that we pass in the variable arguments of nil, nil and 0. As a result our else statement will trigger.

We also want to call this method when the user presses the action button. In this case we should use the Armor, Weapon or Health effect we added to our current Tile object. This should be a hint that we will first have to figure out what our current Tile object is. Luckily we have a property of tiles that we setup in viewDidLoad. We can access this using the syntax self.tiles and index into this array using the method objectAtIndex:. We use our current point to access the proper tile. Finally, we'll use the returned tile's properties as the arguments for the method:

updateCharacterStatsForArmor:withWeapons:withHealthEffect

Add the following code in the IBAction method named actionButtonPressed:

CCTile *tile = [[self.tilesobjectAtIndex:self.currentPoint.x] objectAtIndex:self.currentPoint.y];

[self updateCharacterStatsForArmor:tile.armor withWeapons:tile.weapon withHealthEffect:tile.healthEffect];

01:30

In order to properly implement our final fight with the evil pirate boss we need to create a class to model it. Create a class that is a subclass of NSObject named Boss. Once it is created add a property of type in that has a variable name health.

@property (nonatomic) int health;

Now that we have a Boss class lets setup the initial properties in our Factory. Since our method will return an instance of our Boss class be sure to import the Boss class in our factories header file.

CCFactory.h

#import "CCBoss.h"


-(CCBoss *)boss;

CCFactory.m

-(CCBoss *)boss

{

CCBoss *boss = [[CCBoss alloc] init];

boss.health = 65;

return boss;

}

02:09

We want to setup our Boss in the same way we setup our Character instance in our ViewController class. We only want 1 boss in our application at a time and we want to be able to access that instance in all of our methods inside of the ViewController class. As a result we should create a property of our Boss class in our header file and than we can initialize our Boss instance in the viewDidLoad method.

CCViewController.h

@property (strong, nonatomic) CCBoss *boss;

CCViewController.m

self.boss = [factory boss];

Now that we have a Boss instance we need to update it's health during our final fight. In the method actionButtonPressed we will first test if we are on the pirate battle tile. A simple solution to figure this out would be to check if the tile's health effect is -15. If it is then we know we are in the final battle since that boss does 15 damage to us every time we attack him. I will note that this is far from a perfect solution to check which tile we are on. If another tile had a health effect of -15 we could confuse our computer program into thinking we were fighting the boss when we were really on another Tile. However, this solution is pretty fast and continues to cement if statements so we'll continue with it. Once we confirm that we are on the final Tile we update the bosses health by subtracting character's damage from it.

if (tileModel.healthEffect == -15) {

self.boss.health = self.boss.health - self.character.damage;

}

04:01

Now that we have our boss fight properly setup lets alert the user if they die or if they defeat the boss. We will use an UIAlertView object. We use the custom initializer initWithTitle which accepts a few parameters. For now we will use NSStrings for all of these parameters. The first one is a title which will appear at the top of our AlertView. Next we will send a message to the user. We won't be using a delegate for now since we have not learned about them yet so set it equal to nil. We need to also give a way for the user to close the alertView which is known as the cancel button. This button needs a title which we set using a string. Finally, we will not have any other button titles so we set this option equal to nil.

Once we have our alertView object properly setup we need to call the method show on the instance so that it will appear on our screen.

if (self.character.health <= 0) {

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Death" message:@"You have died restart the game!" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];

[alertView show];

}

else if (self.boss.health <= 0) {

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Victory"message:@"You killed the evil pirate boss!" delegate:Nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];

[alertView show];

}

03:20

The last step of our assignment is to create a reset button for our application. Add a UIButton to your storyboard and hook it up as an action to ViewController.h. Inside of this method add the following code to reset our game:

self.character = nil;

self.boss = nil;

[self viewDidLoad];

Another adjustment we can make to clean up our project is to group like methods together in the implementation file. Using pragma marks we can keep our code organized and easier to explore.

#pragma mark - group

Section 23: Pirate Adventure Wrap Up
Pirate Assignment Solution
Text
Section 24: Terminal and Git
06:10

Terminal allows us to type in commands into our shell and interact with our computer. This is a percise way to navigate through our file structure and enter in git commands.

Common terminal commands:

ls - lists all visible files and directories in the current directory.

cd Directory\ Name\ With\ Spaces/- change directory to Directory Name With Spaces. Remember that if your directory has spaces like Directory Name With Spaces make sure to use the proper forward and backslashes.

mkdir projects - makes a directory called projects

touch Test - creates an empty file named Test

To see these files we use:

ls -a - ls allows us to list contents of a file. The addition of the -a flag that tells the list to print out all files and directories even the hidden ones.

cd .. - allows us to navigate to the directory above the current directory.

control + c - to abort a long running command entered in terminal.

cd - by itself will take you back to the home directory.

rm fileName - removes the file named fileName. Be careful with this since it won't move our file to the trash. It will permenantely delete it!

08:53

To setup git for our XCode project, make sure to initialize your project with version control.

Create a remote repository on github. If you wish to keep your code private make sure to select this option. In order to have a private repository you must sign up for a paid account.

To use git navigate to the proper directory where you have your project stored.

git add . - stages your changes for the next commit.

git commit -m "messageName" - commit the staged files to the the repository with the message: messageName.

git remote add origin https://github.com/userName/nameOfRepository - Sets up our local repository to be pushed to our github repository. We set our remote name to origin and a repository URL after.

git push -u origin master - The push command tells git where to put our commited files. Origin is the name of our remote and the default branch we'll be using is master. The -u tells git to remember the parameters.

Now our code is on github!

04:12

After we've made changes to our project we want to be able to push additional changes to github. Make sure you are in your projects directory. Like our initial git process we need to type a few git commands in:

git add .

git commit -m "second commit"

git push origin master

This process is very similiar to our initial process but since we setup some parameters we don't have to do every step from before.

In order to download projects we can download the zip and extract it to our desktop. We can also do this in terminal using the command git clone. Make sure that you are in the proper directory where you want to download the project to.

Git clone https://github.com/userName/repositoryName

Section 25: Introduction to MVC
02:48

MVC is a incredibly popular (if not uniformly used) design pattern used to make iPhone applications. The acronym stands for Model, View and Controller. Adhering to the MVC design pattern gives a structure to code that limits strong dependencies and allows related code to be moved around easily- we call this "modular code."

The Model in MVC is the data or concepts behind your application. This is not necessarily what the user sees, but it is the information governing your application. In a game, this would be the score, rules, and number of levels.

The View, on the other hand, is strictly what the user sees and interacts with. You have dragged and dropped many premade view objects into your storyboard already!

The Controller is usually a ViewController and is in charge of linking or managing communication between the model and view. It's the middleman.

In this design pattern, the model and the view should never communicate directly with each other. In other words, it is our controller's responsibility to have our views display what is in our model.

This structure allows the model and views to be independent and thus can move around freely. You have seen this already! Notice how many applications use the code for a UIButton or UILabel - no dependence!

03:08

The controller has complete access and can communicate freely with both the Model and View.

We've seen the controller update the view in our previous demos. Take the Man's Best Friend application for example. The controller had a handle on the views (the UIImageView and UILabels) as well as the model (the MBFDog class). It was the controller's responsibility to dynamically update the UIImageView and UILabel objects on our view corresponding to our model. Once again, the controller is the middleman!

How did the controller communicate with both camps? Well, first, the controller imported the BMFDog class allowing it to access methods and properties freely. Second, the controller imports UIKit (go ahead, check the top of your ViewController's .h file!) , the framework containing the logic behind UIButton, UILabel, etc.

Once again, the controller has open access to, and knows about, both the model and the view!

06:05

How does our View let our Controller know something has occurred on the screen? For example, when a button is tapped?

This communication is a little subtle. Views are not supposed to know (or import) anything about their controller. Thus, communication in this instance between a view and a controller is blind between the objects. Currently in the course, we will discuss two ways in which this blind type of communication occurs.

The first is known as target-action. When we hooked up our button via control-drag to our viewcontroller, we created an IBAction where a "target" was placed on our viewcontroller. Anytime the button was tapped, it shot a message, or "arrow" at the target. Again, the important aspect of this communication is that the sender (the button for example), does not know exactly what it is sending its message to.

Why is this important? Well, adhering to this blind communication to avoid dependencies allows a UIButton to function properly with numerous other classes. Don't worry if this isn't sinking in, only with examples will the purpose of this type of communication become clear... although it's certainly good to be thinking about now!

The second type of communication is known as delegation. An object, such as a UIView, can "delegate" (hence the name) responsibility to another object, such as a UIViewController. Thus, when a view needs to know something, it will ask it's delegate for relevant information. This process is also blind - the UIView in our case has no idea what kind of Class its delegate is. This type of communication will be a key focus in our next application, where we will use the UITableView class extensively.

Furthermore, Models can also talk to the controller in a blind fashion. We will circle back to this later, but in case you are interested right now and would like to do some independent research, this is achieved through the NSNotificationCenter and a process called Key-Value Observing. Check them out if you are curious!

Section 26: Introduction to UITableView
02:38

What is a UITableView? It is simply a table composed of a single column with any number of rows. Although it sounds simple, it might be the most important class used to display information to our users. So Popular

If you open an app right now from your iPhone, chances are good you will see one! Not only is is incredibly useful, but it is a textbook example used to illustrate delegation and View to Controller communication.

How does a UITableView work?

UITableView is simply a view object responsible for organizing and showing data. It "blindly" asks our ViewController what to display, and in turn, our ViewController freely interrogates our Model. Let's get to it and see something concrete instead of all this jabber.

07:39

There are two ways we can add a UITableView to our application using the interface builder. The first and easiest way is by simply adding a UITableViewController to our storyboard file. An alternative method that we will see later, is a little more illustrative and involves adding a UITableView object ontop of our UIViewController. This involves hooking up our viewcontroller as our UITableView's delegate manually, and requires a bit more work than using our out-of-the-box ready-to-go UITableViewController.

Remember! As soon as you subclass a UIViewController (we created a OWOuterSpaceTableViewController in this instance), return to the storyboard file. Select the UITableViewController in the scene outline and find the identity inspector. Change the ViewController in your storyboard's class to match your newly minted subclass (again, OWOuterSpaceTableViewController in this tutorial).

The UITableViewController.m file defines quite a few methods. Chief among these methods are the data source methods. The data source, which is our ViewController in this case, is responsible for telling our TableView how many cells to display, and what those cells should look like.

The three methods briefly touched on above inform our UITableView the number of cells in each section to display, the number of sections, and what to display in each row.

Instructor Biography

John Nichols , Designer, developer, teacher

John was the lead iOS developer at Fast Society and Cameo until he started BitFountain in 2012. The apps that John has contributed to have appeared in TechCrunch, Mashable and the New York Times. At BitFountain, John oversees all projects from a technical and strategic perspective. Before becoming a techie John was a student at Boston College and a researcher in Biophysics at Harvard.

Instructor Biography

Eliot Arntz , iOS Developer and Teacher

Eliot regularly teaches iOS development classes and workshops at General Assembly and guest lectures for companies and development boot camps around NYC. He also taught the inaugural class for Coalition for Queens which focused on increasing diversity in iOS development. He also coaches students in a one-on-one environment with a focus on transitioning to full time development. Eliot cofounded and organizes the iOS Office Hours meetup NYC.

In his free time he works as a contractor for startups focusing on agile development.

Find me on twitter @EliotArntz - I check my direct messages quite frequently.

Reviews

Average Rating
4.7
Details
  1. 5 Stars
    179
  2. 4 Stars
    12
  3. 3 Stars
    2
  4. 2 Stars
    6
  5. 1 Stars
    7
    • Samrat Sen

    Best Course in Udemy

    Fantastic work, this is the best coverage of objective C fundamentals and details with integration with real world frameworks and projects. Requesting to add some fundamentals of using Instruments to make it complete.

    • Amir

    Awesome Course!

    Easy to follow! Lots of cool things to learn!

    • Yousheng

    This is a great course for someone new to IOS and object-c

    I am coming from the enterprise Java side and have lots years' experiences on JAVA and related technology. However I have zero experiences on IOS. This course gave me a great leap on that. After taking it, I feel much confident to develop app in IOS. Thanks a lot. Hopefully if you could provide some tutorial to integrate many internet service such youtube into the IOS app.

    • Tim Herden

    Videos don't work anymore

    It's a good course but it seems that after a longer break the videos won't play anymore. Maybe the fault is on my side but I can't figure out. Help appreciated.

    • Hector Rios

    Finally! I'm learning iOS

    Learning to code for iOS is no small feat. Learning Objective-C and can be daunting and I've several people who've given up trying to learn because Objective-C seemed to hard. I'm a software developer and even I thought that Objective-C looked weird but I decided to give it a shot via this course and I am sooo glad I did. The course starts off nice and slow and explains the complicated bits in a way that make it easy to understand. As you progress through the course you'll feel your level of comfort improve with iOS and as a bonus you'll have an archive of all the projects you've created so that you can refer back to when you decide to really branch out and write your own App.

Show more reviews

What you get with this course

30 day money back guarantee

Lifetime access

Available on desktop, iOS and Android

Certificate of completion

Join the biggest student community

5,400,000

Hours of video content

21,000,000

Course enrollment

6,300,000

Students

Ready to start learning?
Preview this course