Tutorial 7 – Using AutoLayout in xCode 5 (Final UIKit Menu Tutorial)

This tutorial will pick up with our project that we have been working on since Tutorial 5. By the end of this tutorial, you will have a working menu system you can move into any iOS project you want. If you want to start at the beginning, here are the links to the other tutorials in this series:

Tutorial 5:

https://richardyeates.com/2014/04/12/tutorial-5-how-to-use-view-controller-based-navigation-in-uikit/

Tutorial 6:

https://richardyeates.com/2014/04/12/tutorial-6-how-to-create-a-scrolling-selection-menu-of-buttons-in-uikit-with-peaking/

For those of you tired of code, Congrats! This tutorial will be done completely in Interface Builder!

Now we will be working on making our UIKit scrolling menu work for both screen sizes of the iPhone; the 3.5 inch (iPhone 4, 4s) and the 4 inch (iPhone 5 and newer). Our approach will be to use the auto layout features in Xcode’s interface builder to allow our menu to automatically position itself based on the device’s frame. Let’s get started.

By now you should have a working scrolling menu like we saw in our last project. When you build and run, you should see this:

Now, change the project to run on the 3.5 inch simulator and you will see this:

Well, that doesn’t look to good. What is happening here? Well, when you build a project graphically, it is the same as inputting hard code values for positions. If you remember from our last tutorial, we decided that was a bad thing. And here is a perfect example of why. When you hard code in values, it makes your code anti-universal. I just made that term up, but it fits. Your code isn’t flexible, so other devices and projects will have a hard time using your code, because it isn’t tailored to fit all situations. Hence the really long values of self.frame.size.width instead of 480 (see Tutorial 5).

Now, because Interface Builder works so well for certain situations (like building a scrolling menu), we have a method provided to us to make our projects adjust to multiple device sizes, and that is auto-laout. Introduced in iOS 6 and Xcode 4, it has seen some major improvements in iOS 7 and Xcode 5.

Open our project and go to the storyboard.

Screen Shot 2014-04-14 at 9.57.42 AM

 

We wil start by adjusting the constraints in Auto-Layout for our StartScreenViewController. As always, there are multiple ways to do this. In the bottom right of the screen, there are a bunch of icon’s:

Screen Shot 2014-04-14 at 10.00.43 AM

These are your constraint and layout controls. Click the one with the solid circle in-between two lines to see your reset and auto-controls.

Screen Shot 2014-04-14 at 10.03.17 AM

Likewise, check out the two buttons to the left of this one:

Screen Shot 2014-04-14 at 10.03.29 AM Screen Shot 2014-04-14 at 10.03.36 AM

Finally, the button on the far left allows you to switch the view between the 4 inch and the 3.5 inch screen sizes. From left to right these are called the Form, Align, Pin, and Resolve buttons. By selecting the object you want to affect and then clicking these buttons, you can add constraints to them. Alternatively, you can control-drag from the object to another object or to empty space in the Controller to make individual alterations also. When a constraint has been created, you can click on it to alter it the same as an object.

Let’s start by clicking the Resolve -> Clear All Constraints in our StartViewController. We will be using a control-drag mechanism to assign some parameters to our label and button. Control-drag from the label to the button, then click “vertical spacing” from the available options.

Screen Shot 2014-04-14 at 10.17.52 AM

This will add a constraint the will keep the two buttons the same distance apart regardless of screen-dimensions. Now, select both of the buttons and the background image and click the Align button at the bottom. Now select the “Horizontal Center in Container” option and click “Add 3 constraints”.

Screen Shot 2014-04-14 at 10.34.39 AM

Now, these items will all always align with the horizontal centre-point of the screen. The constrains are all orange. This means that there is ambiguity in the settings. This is ok, but it’s always best to make things perfect if we can. Control-drag from our label to just above it and release. Pick “vertical spacing” from the options. Now, the label (and via our other constraints the button) will always be that distance from the top. And finally, select the image, click the align button and select the “Vertical Centre in Container” option, click “Add 1 Constraint”. Now all the constraints turn blue, telling you that there is no longer any ambiguity. Click Resolve -> Update all Frames to see you objects in their true positions. Now, give the Form button a press and see how your app automatically resizes based on the device’s screen size.

Good work! Now we will move on to the more complicated example. Select our MainMenuView Controller. Click on the Image View, then use the align button to set constraints to centre the object both vertically and horizontally. Likewise, do the same for both the scroll view and the ScrollViewContainer objects. Then, highlight the Page Outlet object, and set a constraint to the bottom of the frame (via control dragging down at an angle, so that you end your drag not on the scroll view) and align itself Horizontally to Centre as the others do.

Run the project, and you will see it works. But we are still showing errors and our layout constraints are still orange. Why? Well, we have shown AutoLayout where to position our objects, but we have given them no sizing constraints. When we use the Align tool, and input no true constraints with the constraint option, AutoLayout has no idea if it needs to resize anything, and if it should, what priority to assign those sizes. These values are called “Content Hugging” and “Content Resize Resistance”. They can be found and adjusted in the Inspector window when you have a constrained object selected.
Screen Shot 2014-04-14 at 11.40.02 AM

To remove the remaining errors, highlight each of the ScrollViewController, the Image View and the Scroll View, click the Pin Button and set each to have Height and Width constraints of their current values. The only remaining errors should be of some misplaced views, now click Resolve -> Update All Frames, and behold your masterpiece.

Run the project in the 3.5 inch iOS simulator to see that your menu resizes appropriately now.

Over the past 3 tutorials, you have managed to build a menu system that you can use in any app you make. The menu will automatically adjust based on your users device. Thanks for following along. If you end up using any of this information in an App you build, let me know about it! I’d love to see your projects. Speaking of which, here’s a look at this menu in action in my app! See with a few graphics and a small animation it can take a whole new look?

Tutorial 6 – How to create a Scrolling Selection Menu of Buttons in UIKit (with peaking)

This tutorial will pick up with the project we left off with at the end of Tutorial 5.

http://richardyeates.com/2014/04/12/tutorial-5-how-to-use-view-controller-based-navigation-in-uikit/

We have a backbone of 3 view controllers embedded in a navigation controller. The structure of the project is as follows:

1. Navigation controller with Start Screen Controller embedded

2. Start Screen Controller with a button that pushes the Main Menu

3. Main Menu View Controller with some stubbed out properties

4. View Controller that was created at the creation of the project, this view controller houses our SKScene (for our awesome-to-be game!)

This tutorial is going to focus pretty much exclusively on the Main Menu View Controller, because their is a lot to do. We will be creating part of our structure in Interface Builder and some in code, to once more demonstrate that there is always more than one way to do things. Let’s get started.

Ok, we will start by dragging some elements into our View Controller in storyboard. Grab an image view, a scroll view and a page control element object from the objects menu, and drag them into our Main Menu View Controller (remember to select the controller first). Set the UIImage up with the dimensions of the screen, give it the image of our background image and put the page control down near the bottom, centred on the x-axis. Now for the interesting part, the scroll view controller. Our target audience is going to be toddlers, who don’t necessarily understand that when they see a page control, that they can swipe to see more material. We want to be able to visually see that their is another element to this menu. You can see this in action on the appStore when you are viewing screenshots of apps.

We accomplish this by understanding a bit more about Scrollview Controllers. A ScrollView Controller is designed to allow a user to see more content than they otherwise could by dragging their finger around the screen and having the image follow that movement. When we turn on a “paging” flag, this tells the scroll view to automatically pan one width of itself to see the next element or set of elements within that space. We will use that here to create our “peaking” effect. Typical scrollViews would be set to encompass the whole screen like we have been doing for our image views. Instead, we are going to make this one have the size of the screen, and centre it, do this now in Interface Builder. I have found the best way to make this correct is to move the scroll view element into a corner, and then click and drag the re-size objects and use the smart guides to make sure you are half the size, then drag it over to centre it. You should end up with a view controller that looks like this. Make sure that your document outline looks like mine. You want the elements to be children of the view, not of each other. Click in the document outline and drag them around until they look like mine.

Screen Shot 2014-04-12 at 9.40.53 AM

 

Alright, now, select the scroll View element and click on its attributes inspector. Now, turn on “paging enabled” and turn off “clip subviews”. Also, turn off the “Shows Horizontal” and “Shows Vertical” indicators off.

Now, let’s move to MainMenuViewController.m and lets get coding. We are going to create our buttons programmatically, and have them move us into our game Scene (ViewController). Add an import to the top of MainMenuViewController.m:


#import "ViewController.h"

This should be starting to make sense now. In order to create a segue into another view controller, we have to know about it in our current one. Likewise, if we were to create a “Back Button” to get to our last controller, we would have to import the StartScreenViewController.h also. With that, let’s create a new method to perform this action:

-(void)goToLevel{
    ViewController *gameViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
    [self.navigationController pushViewController:gameViewController animated:YES];
}

Now, we need to add our buttons. We will do this in the viewDidLoad method. Change the current stub to look like this:


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.pageControl.numberOfPages = 4;

    CGFloat screenWidth = self.scrollView.bounds.size.width;
    CGFloat screenHeight = self.scrollView.bounds.size.height;

    self.scrollView.contentSize = CGSizeMake(screenWidth * 4, self.scrollView.bounds.size.height);

    // button 1 @ center of scroll view

    self.button1 = [UIButton buttonWithType:UIButtonTypeCustom];
    UIImage *buttonImage = [UIImage imageNamed:@"button.png" ];
    [self.button1 setImage:buttonImage forState:UIControlStateNormal];
    CGFloat xValue = (screenWidth/2)-(buttonImage.size.width/2);
    CGRect rect = CGRectMake(xValue, (screenHeight/2)-(buttonImage.size.height/2), buttonImage.size.width, buttonImage.size.height);
    self.button1.frame = rect;
    [self.button1 addTarget:self
                     action:@selector(goToLevel)
           forControlEvents:UIControlEventTouchUpInside];

    [self.scrollView addSubview:self.button1];

    //button 2 peaking

    self.button2 = [UIButton buttonWithType:UIButtonTypeCustom];
    buttonImage = [UIImage imageNamed:@"button.png" ];
    [self.button2 setImage:buttonImage forState:UIControlStateNormal];
    xValue =xValue + screenWidth;
    rect = CGRectMake(xValue, (screenHeight/2)-(buttonImage.size.height/2), buttonImage.size.width, buttonImage.size.height);
    self.button2.frame = rect;
    [self.button2 addTarget:self
                     action:@selector(goToLevel)
           forControlEvents:UIControlEventTouchUpInside];

    [self.scrollView addSubview:self.button2];

    //button 3 peaking

    self.button3 = [UIButton buttonWithType:UIButtonTypeCustom];
    buttonImage = [UIImage imageNamed:@"button.png" ];
    [self.button3 setImage:buttonImage forState:UIControlStateNormal];
    xValue =xValue + screenWidth;
    rect = CGRectMake(xValue, (screenHeight/2)-(buttonImage.size.height/2), buttonImage.size.width, buttonImage.size.height);
    self.button3.frame = rect;
    [self.button3 addTarget:self
                     action:@selector(goToLevel)
           forControlEvents:UIControlEventTouchUpInside];

    [self.scrollView addSubview:self.button3];

    //button 4 peaking

    self.button4 = [UIButton buttonWithType:UIButtonTypeCustom];
    buttonImage = [UIImage imageNamed:@"button.png" ];
    [self.button4 setImage:buttonImage forState:UIControlStateNormal];
    xValue =xValue + screenWidth;
    rect = CGRectMake(xValue, (screenHeight/2)-(buttonImage.size.height/2), buttonImage.size.width, buttonImage.size.height);
    self.button4.frame = rect;
    [self.button4 addTarget:self
                     action:@selector(goToLevel)
           forControlEvents:UIControlEventTouchUpInside];

    [self.scrollView addSubview:self.button4];
}

What have we done here? We have created 4 buttons, each with the image “button”, the first at the centre of the scrollView, and each of the following is the width of the scrollview away from the first. All the buttons currently call the same method, -(void)goToLevel. We are using variables for screenWidth and buttonImage.size.width so that no matter what images we add, it will always work. Coding like this may look more complicated that just putting a hard value like 60, but it will make it so that in the future, you can just copy your already existing code into a new project and not have to make any alterations for it to just work.

Now  we need to link up our outlets. Back to Interface Builder, click on our Main Menu View Controller and link the page control object to it’s outlet , and also the ScrollView to it’s element (I used the assistant editor for this). Now, for the scroll view, we earlier (let tutorial) told the program that our MainMenuViewController was going to be a delegate of our Scroll View (remember, a delegate means that it needs to expect certain method messages), so we need to wire that up also. Control-drag from the scroll view to the Yellow view controller box in interface builder, you will see this:

Screen Shot 2014-04-12 at 10.00.52 AM

Select the delegate option in the pop-up menu and you are done! Hooray, now run the project in the 4-inch iOS simulator to see you work in action, and drag around to see the paging effect in action.

Looks good, but the paging object isn’t doing anything, back in MainMenuViewController.m, add the following delegate method:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    self.pageControl.currentPage = (NSInteger)(scrollView.contentOffset.x / self.scrollView.frame.size.width + 0.5);
}

This method tells our paging object object to move with our pages. Build, run and check it out.

After playing with our menu, you may notice a problem. Because we made the Scroll View object half the size of the screen, when you drag from a spot on either side of the Scroll View, it doesn’t move our buttons. Again, because our target audience is 2 years old, we want to make this experience as seamless as possible. So, what we are going to do is “wrap” the scroll view in a container object, and this will make it so that user can touch anywhere on the screen to drag our menu around. Go to File -> New -> File and add an objective-c object class of type UIView. Call it ScrollViewContainer and click add.

In ScrollViewContainer.h, add the following outlet:

@property (nonatomic, strong) IBOutlet UIScrollView *scrollView;

And then in ScrollViewContainer.m, add this method:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event {
    UIView *view = [super hitTest:point withEvent:event];
    if (view == self) {
        return _scrollView;
    }
    return view;
}

And that is all the additional code we need. (special thanks for this tid-bit to raywenderlich.com) Move over to Interface Builder, and click on the Scroll View object. Now, click Editor -> Embed In -> View.  Highlight the newly created view and drag it so that it is the size of the iOS screen. Then, click in the identity inspector and change  it’s class to our ScrollViewContainer class. Open the document outline, and drag the elements around so that the hierarchy looks like mine:

Screen Shot 2014-04-12 at 10.35.43 AM

We want the parent-child relationship of these objects to allow for everything to be seen properly.

Finally, all that is left is to wire up our last outlet property, open up the assistant editor, grab the scroll view container object and drag its outlet property to link it to the scroll view in our scene.

And there we have it. Build and run to see your awesome peaking, scrolling, full engage-able menu. Click (or touch) anywhere on the screen and you will be able to pan the menu. Next time, we’ll look at making it so that the menu will automatically adjust when you use a phone of a different size (try the current project on the 3.5 inch simulator to see what I mean).

See a video of the project in action:

To learn more about scroll-views, check out this great tutorial on Ray’s site:

http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content

The next tutorial in this series is available here, in it we will complete our menu by making it automatically adjust to our users screen size:

http://richardyeates.com/2014/04/14/tutorial-7-using-autolayout-in-xcode-5-final-uikit-menu-tutorial/

 

 

Tutorial 5 – How to use View Controller Based Navigation in UIKit

This will be the first in a series of tutorials that we will begin to work on the basis for an actual app that once completed, will be submitted for download to the appStore for free download. We will be working on a sequel to my first App, Pre-tots.

In this tutorial, we are going to get started making the menu for our App. We are going to start to build a framework, and to help us get familiar with all aspects of Xcode, we will be building part of it in interface builder, and part via code. This should help to demonstrate the fact that in programming there is always more than one way to do something. Let’s get started.

-Note- there are other tutorials on the web that cover some aspects of what we will be doing here today. This is designed to get someone rocking with a working menu right now, so with that, be sure to check out the raywenderlich.com site for some of the base ideas in this tutorial with paging scroll views.

Alright, let’s begin. Start a new project in Xcode by going to file -> New -> Project

Screen Shot 2014-04-11 at 12.21.41 AM

 

Then choose a sprite kit based project and click next:

Screen Shot 2014-04-11 at 12.22.06 AM

 

And finally give it a name and save it somewhere appropriate. Make sure “save local git repository” is unchecked.

Screen Shot 2014-04-11 at 12.22.41 AM

Make sure under deployment info, that you uncheck “Portrait” (this will be a landscape based menu)

Screen Shot 2014-04-11 at 12.30.40 AM

Now, for something that I have taken to doing. I hate that stupid status bar at the top of the iOS screen. It refuses to stay away when you tell it to via code. What I have taken to doing lately is to actually turn it off in the App’s info.plist property list file. Locate it in the left file hierarchy (it is under the Supporting Files Group titled YourApp-info.plist). Now click on the lower most entry in the property list to bring up a little +/- symbol beside the “type” entry. Click the plus to add an entry to the list.

Screen Shot 2014-04-11 at 12.37.05 AM

Begin typing the following: View controller-based status bar appearance (it should auto-populate) which is a BOOLEAN type, and set it to NO.

Screen Shot 2014-04-11 at 12.39.40 AM

Now we have no more status bar ever, and we don’t need to KO it for each individual view controller. Sweet!

Now, we are going to lay down the framework for our App. We will have a start screen with a button, that will move us to a Scrolling View Menu with 4 buttons that will access individual games. We will use place holder graphics for now. Lets start by creating our view controller files in Xcode. Click File -> New -> File. Choose “Objective C Class” and click next. Name this file StartScreenViewController, make sure it is a subclass of UIViewController and click next and then Create. Follow these same steps to make a file titled “MainMenuViewController”.

Now, go to StartScreenViewController.m and add the following method:


-(IBAction)startButtonPressed:(id)sender {

MainMenuViewController *menuViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MainMenuViewController"];
[self.navigationController pushViewController:menuViewController animated:YES];
}

What are we doing here? We have declared an action to be linked to a button in interface builder. We have said that we will be using a storyboard identifier and a navigation controller. Ok, not too bad so far. The only issue we have now, is that the StartMenuViewController class has no idea what the MainMenuViewController class is, because we haven’t told it where to look. Add an import statement to the top of the file:

#import MainMenuViewController.h

This will clear away the error and tell our ViewController where to look. On to MainMenuViewController.h; make the following alteration:

#import <UIKit/UIKit.h>

@interface MainMenuViewController : UIViewController <UIScrollViewDelegate> 

@end

Here we are telling the compiler that this class will be a delegate of UIScrollView, simply meaning that the compiler should expect us to implement certain methods in the implementation file. Speaking of which, lets head there now. In MainMenuViewController.m add the following to the @interface:

@interface MainMenuViewController ()

@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@property (weak, nonatomic) UIButton *button1;
@property (weak, nonatomic) UIButton *button2;
@property (weak, nonatomic) UIButton *button3;
@property (weak, nonatomic) UIButton *button4;

@end

Here, we are declaring a bunch of variables for our upcoming code and to link up to our GUI that we will make in interface builder. At this time, I am going to drag my images into my project. the easiest way to do this is to literally drag them into the project hierarchy on the left side of your Xcode interface.Screen Shot 2014-04-11 at 1.12.25 AM

And then make sure that if the files you drag in exist somewhere else on your computer and not in the actual file of your project, that you copy them into it like so:

Screen Shot 2014-04-11 at 1.12.37 AM

 

I have added three placeholder images to the App, just to demonstrate how our menu will work. We have a background image that is the size of the iPhone 5’s pixel-map (1136×640) and two images for buttons (button@2x.png @ 323×323 px and button.png @ 161×161 px). Why two button images and why label them like that? Remember, at one point iPhone’s had both a retina and a non-retina counterpart. That is where this nomenclature comes from. The image is labeled as normal, with the pixels relating to the points on the screen, and the retina image is labeled with a @2x to show that it is twice the pixel density; however the image still inhabits the original’s points when actually presented on the screen.

Now, we can move to interface builder and set up our visual interface. Click on Main.storyboard in the class hierarchy to load up the storyboard screen in interface builder. Now’s a good time to get used to the interface so poke around a bit. Look for a button in the bottom left corner of the view, “show document outline”, and click it. I like to use this outline panel to organize my view controllers and the hierarchy of elements within each controller. Alright, let’s make some magic happen. Click on the “ViewController” element in interface builder for the only view controller currently in our scene. (either click the yellow shaped box or click it in the document outline). On the right hand tab, click on the identity inspector tab. It should look like this:

Screen Shot 2014-04-11 at 4.16.09 PM

Under identity, add the text “ViewController” to the storyboard ID field. This will allow us to programmatically call this viewController when we want to move to it via a button in our menu. Next, click the attributes inspector tab (one more to the right), and change the orientation option to Landscape. This app is going to be Landscape only, and this will help our storyboard reflect that.

Next, in the object library on the bottom right, find a view controller object and drag it into the screen to the left of the existing view controller. With your new controller highlighted, change its orientation also to Landscape in the attributes tab, and in that same tab click the box marked “is initial view controller”. Head back to the identity inspector, and click the pull down for the class type at the top. Set this View controller as the StartScreenViewController and set its storyboard ID to StartScreenViewController.

Screen Shot 2014-04-11 at 4.23.45 PM

Now, that’s a boring start screen. Let’s spruce it up with a background image, a button and a label. Start by grabbing an image view object from the library and dragging it onto the Start Screen View Controller. Hover above the view controller so that the UIImage automatically sizes itself to the controller’s size. If this isn’t working for you, you likely do not have the view controller you are currently working on selected. Double click on the controller in interface builder to select it. Once you have the image on the screen and selected, click the attributes inspector, and set the image to our background.png image.

Screen Shot 2014-04-11 at 4.28.21 PM

Isn’t it purdy? What a nicely drawn blue box if I do say so myself. Now, let’s add a label and a button from the object library onto the scene. Just click and drag as before. I centred my objects on the screen, but you can put them anywhere. Double click the label to change its text, and do the same for the button. Our background colour makes it kinda hard to see the button doesn’t it? Wait, was that on purpose? Perhaps to show you how to change text colours? Go to its attributes inspector and find the text colour option. Set it to anything you want that shows up. You should have something similar to this:

Screen Shot 2014-04-11 at 4.33.40 PM

Now to link this View controller to our already written code. This part can get a little funky if you have never linked outlets and actions before, so we’ll go bit by bit for this one, so that when we jump into our scrolling menu, you’ll know what to do when i say “wire up your code”.  There are so many ways to link up code, it truly comes down to a personal preference. I will show you the two ways that I typically do it.

1) Assistant editor. There is a button on the top right of Xcode that looks like a butler with a tie on, click it. You should get a screen like the following:

Screen Shot 2014-04-11 at 4.40.05 PM

This is the assistant editor. It is basically two windows, one with your code, and the other with the storyboard. You can navigate the right hand window using the pull down buttons above it. Make sure it is set on StartScreenViewController.m Beside the IBAction we wrote earlier, is a small grey circle, if you click and drag from that circle, you will see a line, and if you pull that line over to our button in our storyboard file and let go, then congrats, you have linked that button graphically to your code. You have assigned an “action” to that button. You can drag in the other direction as well, but you have to hold down the “control” button as you do this. This is called control-drag by most users. You actually don’t even have to have the code written previously to control drag, you can do this to an empty section within your code, and Xcode will automatically fill in a method stub for you. I like to have things organized before i get to this step for how i want things to behave.

2) An alternative to using the assistant editor is to have your code stubbed out before you build the GUI in interface builder, and then control drag from the object to the yellow button on the view controller tab. This will bring up the following dialogue box, and if your code is ready, you will see you declared outlets and actions show up here.

Screen Shot 2014-04-11 at 4.46.30 PM

Alright, the button is linked, so when we press it, we are ready to move to our next view controller. So we should probably add it to the scene now. Grab another view controller, throw it into our scene, and give it the class and storyboard ID MainMenuViewController (under identity inspector). Next, change its orientation to Landscape (under attributes inspector) like we had done before, but do NOT set this one as the initial view controller. Alright, now that we have all our different controllers on screen, we need some way to navigate between them. This is surprisingly simple, highlight our start screen’s View Controller click Editor ->Embed In -> Navigation Controller.

Screen Shot 2014-04-12 at 9.11.00 AM

Now, let’s run the App in the simulator, just to make sure that we have everything right so far. Select the iPhone 4-inch simulator and give it a go, you should see your start screen controller what you start up, and when you press the button it should move to your menu screen. Now, at this point, there is a navigation tab on the top with a back button. That doesn’t look to good for a game does it. Let’s remove that by highlighting the Navigation Controller in the storyboard and clicking the attributes inspector, and deselect the box beside “show navigation bar”.

Alright, with things working so far, its time to get into the UIScrollView portion, let’s look at that in the next tutorial. (Tutorial 6)

https://richardyeates.com/2014/04/12/tutorial-6-how-to-create-a-scrolling-selection-menu-of-buttons-in-uikit-with-peaking/

Tutorial 4 – Objective C – Rich’s Summary for Game Dev

The 4th tutorial in this series is dedicated as a summary of terminology and structure of Objective C and xCode. It is for use by inexperienced programmers in order to dive into this environment and start coding immediately. Keep this one bookmarked, as I will likely be adding to it throughout the next sequence of tutorials as we come across new topics along the way.

Classes

MyClass.h
MyClass.m

#import <UIKit/UIKit.h>
#import "AnotherClass.h"

Classes are organized into “header” and “implementation” files. Header files contain variables and methods that you want other classes to be able to access. You need to import one class into another to be able to access its variables and/or methods. Apple’s provided frameworks are denoted with angle brackets.

Variables

int myInt = 0;
float myFloat = 1.3;
BOOL isThisABool = YES;
NSString *myString = @"Hello World";
NSArray *myArray = [[NSArray alloc]init];

Variables are data or objects that contain information that can be passed around in your program. There are lots of different data-types. Some require pointers to the object that is housing the data, others can be referenced directly. A pointer is shown as an asterisk before the variable name.

Loops

if (myInt = anotherInt) {
//do something
} else {
//do something else
}

for (int i = 0, i < 3, i++) {
//do something while this is true
}

for (UITouch *touch in touches){
//do something based upon a touch input
}

The above are examples of loops. Loops allow you to test conditions and perform actions based upon those conditions. Other loops exist (Switch, do/while, etc), but you can do almost anything just by knowing about both the if/else loop and the for loop.

Methods

-(void)aMethod{
//do something, but return no value
}
-(BOOL)aReturnMethod{
BOOL aBOOL;
//do something to figure out what aBOOL should be
return aBOOL;
}
-(void)aMethodWithParameter:(int)parameter{
int aInt = parameter;
//do something with this variable that you can access via the reference
}

Methods are chunks of code that you write that will do something for your program. They can take parameters and spit out data, or they can do something simply because they are called upon.

Messages

[self aMethod];
[mySprite runAction:theAction];

Messaging is the act of calling upon one of your methods to run. It is typically done using square bracket notation, although some setters/getters are run using the dot notation syntax.

Properties

//setting a property
@property (nonatomic, assign) int myScore;
@property (nonatomic, assign) BOOL isSoundOn;

//accessing a property
self.aProperty = propertyValue;

Properties are a very useful way of representing data to be accessed by either the current Class (self) or other classes. They can be either public or private, and are accessed via dot notation.

Instance and The Stack

An instance of an object or a class occurs anytime that item has been allocated a position in memory. The stack is the representation of that object on the memory “heap”. When you release that object from memory, it can no longer be accessed, or it is out of scope. In most cases, you can have a single class or object initialized many times over, except in the case of a singleton. A singleton class is initialized only once. Some great examples of a singleton are classes called “helpers” and gameData classes.

Property Lists

Screen Shot 2014-03-31 at 3.48.27 PM

A Property List is a file that contains a list of data to be accessed within the program. Property Lists can be mutable or immutable, you can save data to them from within your program or make them read-only. They are a great way to structure data for levels (time to complete, starting lives, number of heroes, etc)

Interface Builder

Screen Shot 2014-03-31 at 4.17.42 PM

 

Interface builder is a visual method of creating user interfaces. It uses a drag and drop method of designing the interface. Be careful with it, as it uses some tools to allow for multiple screen sizes that aren’t always intuitive or leave you with your desired results.

Actions and Outlets

-(IBAction)buttonOneWasPressed :(UIButton *)sender{
//do something because a button was just pressed
}

//in the Header or Interface Section you can add an outlet reference
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@property (weak, nonatomic) IBOutlet UILabel *myLabel;

Actions and outlets are the way to link your program to a user interface you have constructed in interface builder. You do not need to build something in interface builder in order to see it onscreen. You can design entire games and menus programmatically, it would just take longer. There is always more than one way to do something. You link code and Interface Builder elements via a “control-drag” mechanism.

Tutorial 3 – Objective C and a First Look At Sprite Kit

It is time. No longer can we avoid discussions of the language that our devices speak, Objective C. The quickest thing to do is have a look at some code. Lets pull some out of the base Sprite Kit project we created in Tutorial 2. Note, this tutorial assumes some remedial understanding of how programming works, and is looking to familiarize you with how objective C is structured. Lets Start with MyScene.h

//
//  MyScene.h
//  testGame
//

//  Copyright (c) 2014 Richard Yeates. All rights reserved.
//

#import <SpriteKit/SpriteKit.h>

@interface MyScene : SKScene

@end

So, what is happening here? And why are there two files with the same name? The two files marked .m and .h make up an objective C class. The .h file is called the header file, it contains variables, method stubs, and properties that you want other classes in your code to be able to access. The .m file is the implementation file, and this is where your workhorse code will actually lie. This is where things happen.

So why separate it? What is actually happening here, and what is a method, property and variable?

Let’s take a step back and look at a concept a bit larger than objective C, and that is object-oriented-programming, or OOP. OOP is based on the idea of encapsulation and inheritance. The idea being that you can write code in self contained chunks, ask that chunk a question or to do something, and have it either answer you or perform that function without having to bug any other section of your code or the end user. You ask a question, it returns to you an answer. The goal is to create re-usable generic code that you never have to write again. Inheritance is best described via an analogy. You have a generic base class, lets say a vehicle. A vehicle’s properties are that it can move. Now, you move down the tree to types of vehicles, a car and a bike. The properties of a car are that it has 4 wheels, and that of a bike is that it base 2 wheels. Both of the classes “bike” and “car” can use the same code for moving, but they need separate code for how many tires are touching the road. Make sense?

Ok, so, the main take away from our MyScene.h code: We use the .h file to declare values that we want accessible elsewhere in our code.
Lets modify the code like so:


@interface MyScene : SKScene {
    
    int myInt;
    
}

@end

Here, we have modified the header file, and included a iVar (instance variable) for use within the class. It’s now helpful to talk briefly about the nomenclature of objective C.

Variables are data types. Integers, floats, strings, arrays, dictionaries; these are all data types. Some data types hold a value (integer, a number without decimal places) and some hold a list of values (arrays, dictionaries). All are simply data structures. In objective C, you declare a variable by writing the variable type, and then its’ name. Here i have declared an integer myInt. It is typical in objective C to have very long and descriptive variable names, and to use capital letters to show the start of the next “word” in the name. Also note, that all lines of code where we are declaring something end with a semicolon.

@interface and @end. Don’t worry to much about these for now. Know that they are declaring the interface for your class and showing where it ends. These are used in runtime. The takeaway is the SKScene value after the @interface MyScene: – this is showing that you are declaring your class to be of the type SKScene, which is a class defined by Apple. This lets you call upon some pre-determined code (via inheritance).

The // notations shows that this is a comment. The compiler knows to ignore this code and move on, It has no effect on any actual operations.

Finally, what about that #import statement at the top? Whenever you are going to ask another class a question, you need to tell the compiler where to look to find that class, so you #import it. In this case, we need to know about SKScenes, so we have to import SpriteKit so the compiler knows what we’re talking about.

Now, on to the implementation file and the fun stuff.


#import "MyScene.h"

@implementation MyScene

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */
        
        self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
        
        SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
        
        myLabel.text = @"Hello, World!";
        myLabel.fontSize = 30;
        myLabel.position = CGPointMake(CGRectGetMidX(self.frame),
                                       CGRectGetMidY(self.frame));
        
        [self addChild:myLabel];
        
        NSLog(@"Hello World");
    }
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    
    for (UITouch *touch in touches) {
        CGPoint location = [touch locationInNode:self];
        
        SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
        
        sprite.position = location;
        
        SKAction *action = [SKAction rotateByAngle:M_PI duration:1];
        
        [sprite runAction:[SKAction repeatActionForever:action]];
        
        [self addChild:sprite];
    }
}

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
}

@end

Yikes. Lets break it down a bit.

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */
}
return self;
}

Alright, you can almost always just go ahead and leave this section of the block alone. Trying to understand this is a bit tedious right now. Just know that this is boilerplate code that is necessary to initialize your instance. At the very end of it, you return self to the query from the initialize statement. So, that leads naturally into a discussion of the concept of “self”.

Self is the idea that whatever class you are in can refer to itself. This is frowned upon in some other languages, but in objective C it’s commonplace. You can run code and call methods upon self, and in most cases it is preferred.

So, what is with that -(id) thing? -(id)initWithSize:(CGSize)size is a method. A method is also called a function in a lot of other languages. A method is a snippet of code that does something. you write a method in the following structure:

-(type)myMethod {

}

-(type)myMethodWithParameter:theParameter {

}

-(id) is a placeholder “type” of method. By declaring a type, we can tell the compiler what to expect to be spit out by the method. For instance, if you ask the method for a YES or NO answer to a question, you would expect it to return a BOOLEAN variable (Which is a simple variable that holds a YES or NO answer, 1 or 0). If you are expecting the method to just do something, but return no value, you would give it a “void” type, which you will see in a moment. A parameter is a value you pass into a method to have it worked upon; i.e. here is an orange: myOrange, please peel it.

Now to the code within the -init statement.

self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
        
        SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
        
        myLabel.text = @"Hello, World!";
        myLabel.fontSize = 30;
        myLabel.position = CGPointMake(CGRectGetMidX(self.frame),
                                       CGRectGetMidY(self.frame));
        
        [self addChild:myLabel];
        
        NSLog(@"Hello World");

Now, lets start getting into some interesting stuff, self.backgroundColor. We are using a syntax called “dot notation” here to access a property on self. Remember, that in the header file we told the compiler that this class was going to represent an instance of SKScene, which has been declared somewhere else to have the property backgroundColor. Here we are setting that property to be a value by using the = sign. Note that in programming, = and == are not the same thing. One is used to assign a value, and the latter is used to test equality.

SKLabelNode brings two new things to discuss, nodes and pointers, both of which are incredibly hefty topics. Lets make things as simple and quick as possible. Sprite Kit is based on the concept of a node structure. A node is simply the parent class of an inheritance tree. A node is something with properties that can be given a size, shape, potentially an image, can display that on the screen and can have actions run upon it. This is the power of Sprite Kit and Cocos2d before it. The simplest way to describe a pointer is like this, if a variable is too complex to be represented by a simple data structure (like an int, BOOL, float, CGRect, etc) then it is wrapped in an object, and the declaration of the variable is actually a declaration of location in memory where that object is stored. This is represented in code by a * sign before the variable name when it is declared. General rule, if a variable type has a prefix (SK, NS, etc), it needs a pointer (but not the prefix CG). There is a difference between data Structures (like CGPoints) and Objects (like NSObject). xCode will tell you when you’ve done something wrong. It’s good like that.

//declaration of the variable "my label
SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
        //setting properties on the label using dot notation
        myLabel.text = @"Hello, World!";
        myLabel.fontSize = 30;
        myLabel.position = CGPointMake(CGRectGetMidX(self.frame),
                                       CGRectGetMidY(self.frame));
        //adding the cild to the scene hierarchy
        [self addChild:myLabel];

CGPointMake is a helper function that allowed the programmer to define a two dimensional point in space, to put the label. The last line in this sequence of code is asking the instance of “self” (remember that is the scene) to add a child to itself, the previously defined myLabel. So, what does this mean? It means that any Node can have children, and this is pretty cool. Because all Sprite Kit objects inherit from SKNode, that means all objects can have children. So if I have a warrior running around my game, and I need something to be attached to him, I can simply add it as a child of him, and it will stay glued to him like my kid is glued to his iPod. That is powerful.

I also mentioned that all nodes can have actions run upon them. Well, what does this mean? Apple has felt generous enough to add an example of that as well, and we will end this tutorial with a look at it. The last section of code states:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    
    for (UITouch *touch in touches) {
        CGPoint location = [touch locationInNode:self];
        
        SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
        
        sprite.position = location;
        
        SKAction *action = [SKAction rotateByAngle:M_PI duration:1];
        
        [sprite runAction:[SKAction repeatActionForever:action]];
        
        [self addChild:sprite];
    }
}

Lets’ boil this down. This is another method call, that returns no value but does some pretty cool things when it is called upon. Apple has written a ton of pre-defined methods, this one is used to register when a user begins to touch the screen. the code then iterates through a “for” loop, looking for all the touches, creating a UITouch object and then looking though the NSSet of touches for a hit. When this happens, the code within the brackets is performed.

As an aside, brackets are used in objective C to define scope. Scope is used in a multitude of ways, but there are some interesting things to consider. In a loop situation (if, for, etc) the brackets define what to do under what condition. The trick is that any variable that is defined while in that scope, can only be referred to within that same scope.

What this mean for the case above, is that if you decided to write another method and asked for “sprite”, you’d throw an exception (bad) because the compiler would have no idea what you are talking about. This doesn’t mean that the child no longer exists outside of the scope, it means you can’t refer to him as “sprite”. There are ways around this by naming your children in Sprite Kit, but thats for another tutorial.

The new code here is the SKAction declaration, and the method call to run it upon the child “sprite”. There are a ton of actions available in sprite kit, and I would invite you to play around with the auto fill and look at a bunch. You can Scale, Change the Alpha value, Move by, Move To, change the colour, etc, etc. Have a peak, run an action on the label as well. Change the size of the spaceship, alter it’s properties.

I hope this helps to explain what is happening in the base Sprite Kit scene and some of the basics of objective C. This is by no means a comprehensive guide to all things objective C, but it should be a good springboard to help get you being able to have something displayed on a screen and running around.

We’ll look at sequences and creating some more complex behaviours in a future tutorial. Thanks and I hope you enjoyed. As a bonus, have a look at the last method stub provided by Apple. This is a call to update, and like the comment says, it is a method that is called before each frame of the scene is rendered. That means that in a 60 fps game, that method is called 60 times within a second. You can probably do some pretty cool things in there.

Until next time.