Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all 4370 articles
Browse latest View live

Video Tutorial: Intermediate Swift Part 11: Wrap Up


Open Call for Authors and Editors: iOS, Android, Unity, and More!

$
0
0
The Tutorial Team: A Happy Cycle!

The Tutorial Team: A Happy Cycle!

The raywenderlich.com Tutorial Team is known for making the highest quality tutorials available online. It’s awesome how far we’ve come, but we think we can do even better!

To help us raise the quality level of our tutorials even further, and expand beyond just iOS tutorials, we are splitting our Tutorial Team into 8 new sub-teams:

  • Swift Language: Tutorials on Swift language concepts (structs, closures, generics, etc – not making apps).
  • iOS: Tutorials on iOS topics in Swift.
  • Android: Tutorials on Android topics in Java.
  • OS X: Tutorials on OS X topics in Swift.
  • Sprite Kit: Tutorials on Sprite Kit topics in Swift.
  • Unity: Tutorials on Unity topics in C#.
  • Unreal Engine: Tutorials on Unreal Engine topics in Blueprints and C++.
  • Articles: Articles (not tutorials) on topics of interest to iOS, Android, OS X, and game developers.

As such, we are looking for great new authors and editors to join our team. Keep reading to find out what’s involved, and how to apply!

Why Join Our Team?

Here are the top 10 reasons to join the Tutorial Team:

  1. Learning. You’ll always be learning something new – and will have fun doing it! You’ll become a better developer, writer, and person, and make a lot of new friends along the way.
  2. Eyeballs. This site gets a lot of traffic – over 3 million pageviews per month and growing. When you publish a tutorial here, it will get read a lot, and people will love you for it.
  3. Tutorial Polish. When you submit a tutorial to raywenderlich.com, we will personally work with you to polish your tutorials to a high level of quality. In the end, your tutorial will look much better than when you first submitted it, making you look really good! :]
  4. Writing Training. When we are done editing your tutorial, we will send you detailed feedback on how you can improve your tutorials in the future. This will help make you a better developer and writer.
  5. Personal Exposure. Your picture and bio will be prominently featured on your tutorials and multiple other places on the site. Many team members have gotten full-time jobs at top-tier companies, in part because of the exposure they got on this site.
  6. Money! Get paid to learn! We offer the highest rates in the industry.
  7. Special Opportunities. Members of the Tutorial Team get access to special opportunities such as contributing to our books and products, speaking at our conference, being a guest on our podcast, working on team projects, and much more.
  8. Contracting Opportunities. Members of the Tutorial Team share contracting opportunities we hear about to the rest of the team – a great way to find out about more work.
  9. You’ll Make a Difference. We get emails every day about how our tutorials help our readers make their first app, get their dream job, or accomplish a lifelong dream of making their own game. This means a lot to us and makes all the hard work worth it!
  10. Free Stuff! And as a final bonus, by joining the Tutorial Team you will get a lot of free stuff! You’ll get a free copy of all of the products we sell on the site – over $1,000 in value!

Aww Yeah!

Requirements and How to Apply

Here are the requirements:

  • You must be an advanced-level developer.
  • You should be a great writer with fluent English writing skills.
  • You should be comfortable learning brand new topics that you have never done before, which are either not documented or poorly documented.
  • You should have a strong work ethic – this will be a significant time commitment and is not easy.

To apply, simply send me an email with the following details:

  • Why do you want to join the Tutorial Team?
  • Which team are you most interested in joining: Swift Language, iOS, Android, OS X, Sprite Kit, Unity, Unreal, or Articles?
  • Please tell me a little bit about yourself and your experience.
  • What is the best app/game you’ve made or worked on, and why are you proud of the work you did on this app/game? [Please include link]
  • Please link to any examples of technical writing you have done in the past.
  • Please include links to: your GitHub account, your StackOverflow account, your Twitter account.

For the applicants that look most promising, we will give you a tryout for the team of your choice. If you pass the tryout, you’re in!

Note: We typically get hundreds of applicants for open positions, so we might not be able to respond to every email.

Now’s The Time

If you’ve ever been thinking about joining the Tutorial Team in the past, this is the best chance there’s ever been:

  • Tons of openings: With this restructuring, we are looking to bring tons of new people to the team, so your chance to get in are higher than ever.
  • Get in on the ground floor: You’ll also be getting in on the ground floor with our brand new teams, which will bring some exciting opportunities to team members.

So don’t delay – apply today – and please help us spread the word about this to others! :]

Open Call for Authors and Editors: iOS, Android, Unity, and More! is a post from: Ray Wenderlich

The post Open Call for Authors and Editors: iOS, Android, Unity, and More! appeared first on Ray Wenderlich.

Split View Controllers Part 1: Getting Started

Season Introduction with Mic and Jake – Podcast S04 E01

$
0
0
Welcome to Season 4!

Welcome to Season 4!

Welcome to the season 4 of the raywenderlich.com podcast!

In this episode, Mic and Jake chat about some changes this season and what’s coming next, and catch up on some of the latest Apple news.

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

Interested in sponsoring a podcast episode? We sell ads via Syndicate Ads, check it out!

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. The first regular episode of season 4 starts next week! :]

Be sure to subscribe in iTunes to get access as soon as it comes out.

We’d love to hear what you think about the podcast, and any suggestions on what you’d like to hear next season. Feel free to drop a comment here, or email us anytime at podcast@raywenderlich.com.

Season Introduction with Mic and Jake – Podcast S04 E01 is a post from: Ray Wenderlich

The post Season Introduction with Mic and Jake – Podcast S04 E01 appeared first on Ray Wenderlich.

iOS 8 by Tutorials Updated for Swift 1.2!

$
0
0

i8t-thumb

Good news – the iOS 8 by Tutorials Team has updated iOS 8 by Tutorials for Swift 1.2!

As you may know, Swift 1.2 introduced some new syntax, such as an improved if let statement, and revised usage of as vs as! vs as?. To learn more about these changes, check out our What’s New in Swift 1.2 overview.

In this update, the team has updated all chapters and sample code to use the new Swift 1.2 syntax, and have also fixed some of the errata reported on the forums.

Here’s how you can get the update:

  • If you’re an iOS 8 by Tutorials PDF customer, you can download the update for free on your My Loot page (version 1.5).
  • If you’re an iOS 8 by Tutorials Print Version customer, you can find the updated source code at the URL given in the introduction of the book.
  • If you don’t have the iOS 8 by Tutorials yet, grab your copy now!

We hope you enjoy this update!

iOS 8 by Tutorials Updated for Swift 1.2! is a post from: Ray Wenderlich

The post iOS 8 by Tutorials Updated for Swift 1.2! appeared first on Ray Wenderlich.

Cocos2d-x Tutorial for Beginners

$
0
0

Learn how to create a simple 2D game in this Cocos2d-x Tutorial!

Cocos2d-x is a fast, powerful, and easy-to-use open source 2D game engine.

It’s is very similar to Apple’s Sprite Kit, but has one key advantage – Cocos2d-x is cross platform.

This means with one set of code, you can make games for iOS, Android, Windows Phone, Mac OS X, Windows Desktop and Linux. This is huge for indie game devs!

In this tutorial, you will learn how to create a simple 2D game in Cocos2d-x with C++. And yes — there will be ninjas! :]

Note: This tutorial assumes you know the basics of C++ development. If you are new to C++, be sure to read a book on the subject first.

Getting Started

Download the latest version of Cocos2d-x at www.cocos2d-x.org/download; this tutorial used version 3.5.

Place the downloaded file wheres you’d like to store your Cocos2d-x installation, such as in your home directory, then unzip it.

Open Terminal and cd into the folder you just extracted. For example, if you placed the project in your home directory, run the following command:

cd ~/cocos2d-x-3.5/

Now run the following command:

python setup.py

This sets up the necessary shell environment variables. When it prompts you to configure the Android-specific variables NDK_ROOT, ANDROID_SDK_ROOT and ANT_ROOT, just press Enter three times to finish the configuration.

Note: Cocos2D requires Python 2.7+ installed on your machine. If you aren’t sure what version of Python you have, type python on the command line and it will display the version (then hit Ctrl-D to exit). If you have an older version of Python, install the latest version of Python at python.org.

As you can see in the following screenshot, the script instructs you to execute another command to complete the setup:

SourceCommand

Note: Depending on which shell you use, you might see some different output. In the above screenshot, the setup package prompts for “source /Users/rwenderlich/bash_profile.” commands since I’m using Bash, but had I been using Zsh, for example, it would have prompted me to run “source /Users/rwenderlich/.zshrc”.

Enter the command as the script’s output instructed. A great timesaving tip: you can use a tilde (~) in place of /Users/your_user_name, so to save keystrokes you could type the following:

source ~/.zshrc  (or source ~/.bash_profile)

The command you entered simply re-processes your shell configuration and gives it access to the new variables. Now you can call the cocos command in Terminal from any directory.

Run the following command to create a C++ game template named SimpleGame:

cocos new -l cpp -d ~/Cocos2d-x-Tutorial SimpleGame

This creates a directory named Cocos2d-x-Tutorial in your home directory, and inside that, a sub-directory named SimpleGame that contains your project’s files.

Note: To learn about the available cocos subcommands, type cocos --help or cocos -h. You can also learn about any subcommand’s options by appending “--help” or “-h”, such as cocos new -h to see the options for the new command.

Double-click ~/Cocos2d-x-Tutorial/SimpleGame/proj.ios_mac/SimpleGame.xcodeproj in Finder to open the project in Xcode.

Once you’re Inside Xcode, ensure that SimpleGame Mac is the active scheme, as shown below:

simplegame

While Cocos2d-x is capable of building games for many platforms, in this tutorial you’ll focus on making an OS X app. Porting this project to other platforms is a trivial (yes, trivial!) matter discussed briefly at the end of this tutorial.

Build and run your app to see the template project in all its glory:

 simplegame

Resolution Setup

By default, Cocos2d-x games are named “MyGame” and have a resolution of 960×640, but those details are easy to change.

Open AppDelegate.cpp and find the following line inside AppDelegate::applicationDidFinishLaunching:

glview = GLViewImpl::create("My Game");

Replace that line with the following code:

glview = GLViewImpl::createWithRect("SimpleGame", Rect(0,0, 480, 320), 1.0);

This changes the app’s name to “SimpleGame” and sets its resolution to 480×320 to match the background art included with the template.

Build and run your app again to see your new, smaller game:

small_cocos2d_run

Notice the third argument you passed to createWithRect1.0. This parameter scales the frame, which is usually \used for testing resolutions larger than your monitor. For example, to test a 1920×1080 resolution on a monitor smaller than 1920×1080, you could pass 0.5 to scale the window to 960×540.

While this call to createWithRect changes the game’s frame on desktops, it doesn’t work this way on iOS devices; instead, the game’s resolution matches the screen size. Here is how it looks on an iPhone 6:

cocos2dx_first_run_iphone

So how do you handle multiple resolutions? In this tutorial, you’ll create a single set of game resources based on a 960×640 resolution, then simply scale the assets up or down as necessary at runtime.

To implement this, add the following code inside AppDelegate::applicationDidFinishLaunching, just above the line that calls setDisplayStats on director:

// 1
Size designSize = Size(480,320);
Size resourceSize = Size(960,640);
// 2
director->setContentScaleFactor(resourceSize.height / designSize.height);
director->getOpenGLView()->setDesignResolutionSize(
  designSize.width, designSize.height, ResolutionPolicy::FIXED_HEIGHT);

Here’s what the code above does:

  1. Here you define designSize – the size you’re using when creating your game logic – and resourceSize – the size on which all your art assets are based.
  2. These lines tell your game’s Director to scale the assets as necessary based on the design and resource sizes you provided.

For a detailed explanation of how Cocos2d-x handles resolutions, please refer to the Cocos2d-x wiki entry on Multi-resolution adaptation.

Adding a Sprite

Next, download the resources file for this project and unzip it to a convenient location.

Select all the files in the SimpleGameResources folder you just extracted and drag them into the Resources group in your Xcode project. In the dialog that appears, be sure to check Copy items if needed, SimpleGame iOS and SimpleGame Mac before clicking Finish:

adding_resources

Next open HelloWorldScene.h add the following line just after the line that includes cocos2d.h:

using namespace cocos2d;

This specifies you’ll be using the cocos2d namespace; this lets you do things like write Sprite* instead of cocos2d::Sprite*. It’s not absolutely necessary, but it certainly makes development more pleasant. :]

Now you’ll need a private member variable to point to your player sprite. Add the following code to the HelloWorld declaration:

private:
  Sprite* _player;

Next, open HelloWorldScene.cpp and replace the contents of the HelloWorld::init method with the following:

// 1
if ( !Layer::init() ) {
  return false;
}
// 2
auto origin = Director::getInstance()->getVisibleOrigin();
auto winSize = Director::getInstance()->getVisibleSize();
// 3
auto background = DrawNode::create();
background->drawSolidRect(origin, winSize, Color4F(0.6,0.6,0.6,1.0));
this->addChild(background);
// 4
_player = Sprite::create("player.png");
_player->setPosition(Vec2(winSize.width * 0.1, winSize.height * 0.5));
this->addChild(_player);
 
return true;

Here’s the play-by-play of this method:

  1. First you call the super class’s init method. Only if this succeeds do you proceed with HelloWorldScene‘s setup.
  2. You then get the window’s bounds using the game’s Director singleton.
  3. You then create a DrawNode to draw a gray rectangle that fills the screen and add it to the scene. This serves as your game’s background.
  4. Finally, you create the player sprite by passing in the image’s name. You position it 10% from the left edge of the screen, centered vertically, and add it to the scene.

Build and run your app; voila, ladies and gentlemen, the ninja has entered the building! :]

005_Ninja

Moving Monsters

Your ninja needs a purpose in life, so you’ll add some monsters to your scene for your ninja to fight. To make things more interesting, you want the monsters to move around – otherwise, it wouldn’t prove to be much of a challenge! You’ll create the monsters slightly off-screen to the right, and set up an action for them telling them to move to the left.

First, open HelloWorldScene.h and add the following method declaration:

void addMonster(float dt);

Then add the following method implementation inside HelloWorldScene.cpp:

void HelloWorld::addMonster(float dt) {
  auto monster = Sprite::create("monster.png");
 
  // 1
  auto monsterContentSize = monster->getContentSize();
  auto selfContentSize = this->getContentSize();
  int minY = monsterContentSize.height/2;
  int maxY = selfContentSize.height - monsterContentSize.height/2;
  int rangeY = maxY - minY;
  int randomY = (rand() % rangeY) + minY;
 
  monster->setPosition(Vec2(selfContentSize.width + monsterContentSize.width/2, randomY));
  this->addChild(monster);
 
  // 2
  int minDuration = 2.0;
  int maxDuration = 4.0;
  int rangeDuration = maxDuration - minDuration;
  int randomDuration = (rand() % rangeDuration) + minDuration;
 
  // 3
  auto actionMove = MoveTo::create(randomDuration, Vec2(-monsterContentSize.width/2, randomY));
  auto actionRemove = RemoveSelf::create();
  monster->runAction(Sequence::create(actionMove,actionRemove, nullptr));
}

It’s relatively straightforward, but here’s what the above code does:

  1. The first part of this method is similar to what you did earlier with the player: it creates a monster sprite and places it just offscreen to the right. It sets its y-position to a random value to keep things interesting.
  2. Next, the method calculates a random duration between two and four seconds for the action it’s about to add to the monster. Each monster will move the same distance across the screen, so varying the duration results in monsters with random speeds.
  3. Finally, the method creates an action that moves the monster across the screen from right to left and instructs the monster to run it. This is explained in more detail below.

Cocos2d-x provides lots of extremely handy built-in actions that help you easily change the state of sprites over time, including move actions, rotate actions, fade actions, animation actions, and more. Here you use three actions on the monster:

  • MoveTo: Moves an object from one point to another over a specific amount of time.
  • RemoveSelf: Removes a node from its parent, effectively “deleting it” from the scene. In this case, you use this action to remove the monster from the scene when it is no longer visible. This is important because otherwise you’d have an endless supply of monsters and would eventually consume all your device’s resources.
  • Sequence: Lets you perform a series of other actions in order, one at a time. This means you can have the monster move across the scene and remove itself from the screen when it reaches its destination.

There’s one last thing to do before you let you ninja go to town — you need to actually call the method to create monsters! Just to make things fun, you’ll create monsters that spawn continuously.

Simply add the following code to the end of HelloWorld::init, just before the return statement:

srand((unsigned int)time(nullptr));
this->schedule(schedule_selector(HelloWorld::addMonster), 1.5);

srand((unsigned int)time(nullptr)); seeds the random number generator. If you didn’t do this, your random numbers would be the same every time you ran the app. That wouldn’t feel very random, would it? :]

You then pass HelloWorld::addMonster into the schedule method, which will call addMonster() every 1.5 seconds.

Here Cocos2d-x takes advantage of C++’s pointers to member functions. If you don’t understand how this works, please refer to ioscpp for more information.

That’s it! Build and run your project; you should now see monsters happily (or angrily, as the case may be!) moving across the screen:

006_Monsters

Shooting Projectiles

Your brave little ninja needs a way to protect himself. There are many ways to implement firepower in a game, but in this project you’ll have the user click or tap the screen to fire a projectile in the direction of the click or tap. Pew-pew! :]

To keep things simple, you’ll implement this with a MoveTo action — but this means you’ll need to do a little math.

The MoveTo action requires a destination for the projectile, but you can’t use the input location directly because that point only represents the direction to shoot relative to the player. You want to keep the bullet moving through that point until the bullet arrives at the final destination off-screen.

Here’s a picture that illustrates the matter:

Projectile Triangle

The x and y offsets from the origin point to the touched location create a small triangle; you just need to make a big triangle with the same ratio – and you know you want one of the endpoints to be off-screen.

Performing these calculations is a snap with Cocos2d-x’s included vector math routines. But before you can calculate where to move, you need to enable input event handling to figure out where the user touched!

Add the following code to the end of HelloWorld::init, just above the return statement:

auto eventListener = EventListenerTouchOneByOne::create();
eventListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(eventListener, _player);

Cocos2d-x versions 3 and up use EventDispatcher to dispatch various events, such as touch, accelerometer and keyboard events.

Note: Throughout this discussion, the term “touch” refers to taps on a touch device as well as clicks on a desktop. Cocos2d-x uses the same methods for handling both types of events.

In order to receive events from the EventDispatcher, you need to register an EventListener. There are two types of touch event listeners:

  • EventListenerTouchOneByOne: This type calls your callback method once for each touch event.
  • EventListenerTouchAllAtOnce: This type calls your callback method once with all of the touch events.

Touch event listeners support four callbacks, but you only need to bind methods for the events you care about.

  • onTouchBegan: Called when your finger first touches the screen. If you are using EventListenerTouchOneByOne, you must return true in order to receive any of the other three touch events.
  • onTouchMoved: Called when your finger, already touching the screen, moves without lifting off the screen.
  • onTouchEnded: Called when your finger lifts off the screen.
  • onTouchCancelled: Called in certain circumstances that stop event handling, like when you are touching the screen and then something like a phone call interrupts the app.

In this game, you really only care about when touches occur. Declare your callback to receive touch notifications in HelloWorldScene.h like so:

bool onTouchBegan(Touch *touch, Event *unused_event);

Then implement your callback in HelloWorldScene.cpp:

bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event) {
  // 1  - Just an example for how to get the  _player object
  //auto node = unused_event->getCurrentTarget();
 
  // 2
  Vec2 touchLocation = touch->getLocation();
  Vec2 offset = touchLocation - _player->getPosition();
 
  // 3
  if (offset.x < 0) {
    return true;
  }
 
  // 4
  auto projectile = Sprite::create("projectile.png");
  projectile->setPosition(_player->getPosition());
  this->addChild(projectile);
 
  // 5
  offset.normalize();
  auto shootAmount = offset * 1000;
 
  // 6
  auto realDest = shootAmount + projectile->getPosition();
 
  // 7
  auto actionMove = MoveTo::create(2.0f, realDest);
  auto actionRemove = RemoveSelf::create();
  projectile->runAction(Sequence::create(actionMove,actionRemove, nullptr));
 
  return true;
}

There’s a lot going on in the method above, so take a moment to review it step by step.

  1. The first line is commented out, but it’s there to show you how you can access the _player object that you passed as the second parameter to addEventListenerWithSceneGraphPriority(eventListener, _player).
  2. Here you get the coordinate of the touch within the scene’s coordinate system and then calculate the offset of this point from the player’s current position. This is one example of vector math in Cocos2d-x.
  3. If offset‘s x value is negative, it means the player is trying to shoot backwards. This is is not allowed in this game (real ninjas never look back!), so simply return without firing a projectile.
  4. Create a projectile at the player’s position and add it to the scene.
  5. You then call normalize() to convert the offset into a unit vector, which is a vector of length 1. Multiplying that by 1000 gives you a vector of length 1000 that points in the direction of the user’s tap. Why 1000? That length should be enough to extend past the edge of your screen at this resolution :]
  6. Adding the vector to the projectile’s position gives you the target position.
  7. Finally, you create an action to move the projectile to the target position over two seconds and then remove itself from the scene.

Build and run your app; touch the screen to make your ninja fire away at the oncoming hordes!

007_Shoot

Collision Detection and Physics

You now have shurikens flying everywhere — but what your ninja really wants to do is to lay some smack down. So you’ll need some code to detect when your projectiles intersect their targets.

One nice thing about Cocos2d-x is it comes with a physics engine built right in! Not only are physics engines great for simulating realistic movement, but they are also great for detecting collisions. You’ll use Cocos2d-x’s physics engine to determine when monsters and projectiles collide.

Start by adding the following code to HelloWorldScene.cpp, just above the implementation of HelloWorld::createScene:

enum class PhysicsCategory {
  None = 0,
  Monster = (1 << 0),    // 1
  Projectile = (1 << 1), // 2
  All = PhysicsCategory::Monster | PhysicsCategory::Projectile // 3
};

These bit masks define the physics categories you’ll need in a bit – no pun intended! :] Here you’ve created two types, Monster and Projectile, along with two special values to specify no type or all types. You’ll use these categories to assign types to your objects, allowing you to specify which types of objects are allowed to collide with each other.

Note: You may be wondering what this fancy syntax is. The category on Cocos2d-x is simply a single 32-bit integer; this syntax sets specific bits in the integer to represent different categories, giving you 32 possible categories max. Here you set the first bit to indicate a monster, the next bit over to represent a projectile, and so on.

Next, replace the first line of HelloWorld::createScene with the following code:

auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setGravity(Vec2(0,0));
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

This creates a Scene with physics enabled. Cocos2d-x uses a PhysicsWorld to control its physics simulation. Here you set the world’s gravity to zero in both directions, which essentially disables gravity, and you enable debug drawing to see your physics bodies. It’s helpful to enable debug drawing while you’re prototyping physics interactions so you can ensure things are working properly.

Inside HelloWorld::addMonster, add the following code right after the first line that creates the monster sprite:

// 1
auto monsterSize = monster->getContentSize();
auto physicsBody = PhysicsBody::createBox(Size(monsterSize.width , monsterSize.height),
                                          PhysicsMaterial(0.1f, 1.0f, 0.0f));
// 2
physicsBody->setDynamic(true);
// 3
physicsBody->setCategoryBitmask((int)PhysicsCategory::Monster);
physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
physicsBody->setContactTestBitmask((int)PhysicsCategory::Projectile);
 
monster->setPhysicsBody(physicsBody);

Here’s what the above code does:

  1. Creates a PhysicsBody for the sprite. Physics bodies represent the object in Cocos2d-x’s physics simulation, and you can define them using any shape. In this case, you use a rectangle of the same size as the sprite as a decent approximation for the monster. You could use a more accurate shape, but simpler shapes are good enough for most games and more performant.
  2. Sets the sprite to be dynamic. This means that the physics engine will not apply forces to the monster. Instead, you’ll control it directly through the MoveTo actions you created earlier.
  3. Here, you set the category, collision and contact test bit masks:

    • Category: defines the object’s type – Monster.
    • Collision: defines what types of objects should physically affect this object during collisions – in this case, None. Because this object is also dynamic, this field has no effect but is included here for the sake of completeness.
    • Contact Test: defines the object types with which collisions should generate notifications – Projectile. You’ll register for and handle these notifications just a bit later in the tutorial.
    • Finally, you assign the physics body to the monster.

Next, add the following code to HelloWorld::onTouchBegan, right after the line that sets projectile‘s position:

auto projectileSize = projectile->getContentSize();
auto physicsBody = PhysicsBody::createCircle(projectileSize.width/2 );
physicsBody->setDynamic(true); 
physicsBody->setCategoryBitmask((int)PhysicsCategory::Projectile);
physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
physicsBody->setContactTestBitmask((int)PhysicsCategory::Monster);
projectile->setPhysicsBody(physicsBody);

This is very similar to the physics setup you performed for the monsters, except it uses a circle instead of a rectangle to define the physics body. Note that it’s not absolutely necessary to set the contact test bit mask because the monsters are already checking for collisions with projectiles, but it helps make your code’s intention more clear.

Build and run your project now; you’ll see red shapes superimposed over your physics bodies, as shown below:

debug_ninjas

Your projectiles are set up to hit monsters, so you need to remove both bodies when they collide.

Remember that physics world from earlier? Well, you can set a contact delegate on it to be notified when two physics bodies collide. There you’ll write some code to examine the categories of the objects, and if they’re the monster and projectile, you’ll make them go boom!

First, add the following method declaration to HelloWorldScene.h:

bool onContactBegan(PhysicsContact &contact);

This is the method you’ll register to receive the contact events.

Next, implement the following method in HelloWorldScene.cpp:

bool HelloWorld::onContactBegan(PhysicsContact &contact) {
  auto nodeA = contact.getShapeA()->getBody()->getNode();
  auto nodeB = contact.getShapeB()->getBody()->getNode();
 
  nodeA->removeFromParent();
  nodeB->removeFromParent();
  return true;
}

The PhysicsContact passed to this method contains information about the collision. In this game, you know that the only objects colliding will be monsters and projectiles. Therefore, you get the nodes involved in the collision and remove them from the scene.

Finally, you need to register to receive contact notifications. Add the following lines to the end of HelloWorld::init, just before the return statement:

auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegan, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contactListener, this);

This creates a contact listener, registers HelloWorld::onContactBegan to receive events and adds the listener to the EventDispatcher. Now, whenever two physics bodies collide and their category bit masks match their contact test bit masks, the EventDispatcher will call onContactBegan.

Build and run your app; now when your projectiles intersect targets they should disappear:

ninja_shooting

Most ninjas are silent, but not this one! Time to add some sound to your game.

Finishing Touches

You’re pretty close to having a workable (but extremely simple) game now. You just need to add some sound effects and music (since what kind of game doesn’t have sound!) and some simple game logic.

Cocos2d-x comes with a simple audio engine called CocosDenshion which you’ll use to play sounds.

Note: Cocos2d-x also includes a second audio engine designed to replace the simple audio engine module. However, it is still experimental and it is not available for all the supported platforms, so you won’t use it here.

The project already contains some cool background music and an awesome “pew-pew” sound effect that you imported earlier. You just need to play them!

To do this, add the following code to the top of HelloWorldScene.cpp, after the other #include statement:

#include "SimpleAudioEngine.h"
using namespace CocosDenshion;

This imports the SimpleAudioEngine module and specifies that you’ll be using the CocosDenshion namespace in this file.

Next, add the following defines to HelloWorldScene.cpp, just above the PhysicsCategory enum:

#define BACKGROUND_MUSIC_SFX  "background-music-aac.mp3"
#define PEW_PEW_SFX           "pew-pew-lei.mp3"

Here you define two string constants: BACKGROUND_MUSIC_SFX and PEW_PEW_SFX. This simply keeps your filenames in a single place, which makes it easier to change them later. Organizing your code like this (or even better, using a completely separate file) makes it easier to support platform-specific changes like using .mp3 files on iPhone and .wav files on Windows Phone.

Now add the following line to the end of HelloWorld::init, just before the return statement:

SimpleAudioEngine::getInstance()->playBackgroundMusic(BACKGROUND_MUSIC_SFX, true);

This starts the background music playing as soon as your scene is set up.

As for the sound effect, add the following line to HelloWorld::onTouchBegan, just above the return statement:

SimpleAudioEngine::getInstance()->playEffect(PEW_PEW_SFX);

This plays a nice “pew-pew” sound effect whenever the ninja attacks. Pretty handy, eh? You can play a sound effect with only a single line of code.

Build and run, and enjoy your groovy tunes!

Where to Go From Here?

Here is the finished example game from the above tutorial.

I hope you enjoyed learning about Cocos2d-x and feel inspired to make your own game! To learn more about Cocos2d-x, check out the Cocos2d-x website for great learning resources.

If you have any questions or comments about this tutorial, please join the discussion below!

Cocos2d-x Tutorial for Beginners is a post from: Ray Wenderlich

The post Cocos2d-x Tutorial for Beginners appeared first on Ray Wenderlich.

Split View Controllers Part 2: Display Modes

RWDevCon Inspiration Talk: raywenderlich.com Folklore by Marin Todorov

$
0
0

Note from Ray: At our recent RWDevCon tutorial conference, in addition to hands-on tutorials, we also had a number of “inspiration talks” – non-technical talks with the goal of giving you a new idea, some battle-won advice, and leaving you excited and energized.

We recorded these talks so that you can enjoy them, even if you didn’t get to attend the conference. Here’s our next talk – raywenderlich.com Folklore by Marin Todorov – I hope you enjoy!


Transcript

I often speak at iOS conferences in Europe and people always ask me:

  • What is it like to write for raywenderlich.com?
  • How many people are on the team?
  • Does Ray actually exist?

I thought it would be cool for my session for RWDevCon to answer all these questions and give you some behind the scenes stories and give you some folklore from the raywenderlich.com team.

Backstreet

If you attended Ray’s Keynote, you know that the site started as Ray’s personal blog and grew to be 100 people plus team, scattered around the world.

In my talk, I’m going to revisit the same timeline, but I’m going to try to highlight some interesting stories along the way and fun moments.

How It All Began

To actually do this, we’re going to going back to the very beginning of time.

cosmos

We’re going to go back to January 24, 2010. This is how it all starts.

This was the very first post on raywenderlich.com. It’s called ‘Drinking from a Fire Hose.’

DrinkingFirehose

It’s still online, you can still go to the website and read through it, but it’s just mostly Ray ranting about how web technology advanced since the 90’s and he has to learn many new stuff to put his blog online. It also features this weird image of bursting water.

After posting this, Ray probably worked very hard throughout the night to make the website work.

On the next day, on the 25th of January, he was like, “Duh, this is not what your blog post should be.” So he posted, “What is this Blog About?” which is good, but the post itself is mostly about how he much he loves C++, and Python. And he used this weird PHP code image on the side.

He just slightly mentions that he also does iPhone apps. It’s really funny; it’s a shaky start at best. But it was 2010, so nobody knew that this was going to be the most popular iOS development blog on the internet.

There was no team behind the launch, there was no product of any kind. It was just Ray in his mother-in-law’s basement.

justRay

He was just there putting what he thought was best online.

Not only that but he wasn’t the best designer either. I’m sure how his website was designed, and particularly how he snipped off the top of his own logo, really sent people around the globe into seizures.

cutoffLogo

Ray Has Fun

Not only this, but he wasn’t really the business type that will have a successful blog. In fact, he was pretty goofy.

You can now call me Ray-droid!

When he first said that he was ditching iOS development for Android, many people didn’t exactly know what to think. He was making some pretty solid points:

  • One app store just isn’t enough
  • Java is the bomb
  • Visual interface design is for pansies

Of course, that was the April Fool’s hoax for April 2011, but it still told a lot who Ray was.

The Team is Formed

Seemingly against all odds, it turned out that content is king and people really liked what Ray was writing. The website started gaining popularity.

In 2011, as Ray mentioned in the keynote, he finally realized that he cannot do it on his own.

He did a call for authors on the website in 2011, so that’s how the tutorial team was born.

teamWelcomeEmail

Fun fact, 30% of the initial 10 people that started are still on the team. That’s me, Matthijs, and Adam.

There’s also many guys that joined in the first couple of months that are still around like Cesare, Felipe, Jake, and actually many more. These are guys that have been together a long, long time.

A Store is Born

With the help of the tutorial team, the website started rolling out products.

The first newsletter came out in August 2011, and also introduced the idea of The iOS Apprentice coming out soon. Another feature that was possible thanks to the tutorial team the same year, a little bit after the newsletter came out was the raywenderlich.com store page.

InitialStore

If you have been recently to the website and have been looking to the store, this old page is hilarious because it has this one single product in the top left, kind of like suggesting there’s going to be more, but actually everything else is just empty.

That image shows the first product for sale, which was the Space Game Starter Kit for the iPhone and iPad.

Matthijs Writes The iOS Apprentice

Speaking about early team members, I want to take a moment to speak about Matthijs Hollemans.

Matthijs

He has been on the team from the very start, and he has a story of one of the early team members.

He quit his job in 2010, and wanted to make it on his own as an iOS indie. In 2011, he joined the team, and shortly afterwards, he wrote the missing book on beginning iOS development: The iOS Apprentice.

For sure, many of you recognize the bull’s eye app, which is the first part of the iOS Apprentice.

bullseye

Many people started developing for the iPhone with exactly this tutorial.

Not only did Matthijs write the book, but he also keeps updating it. He wrote it and released it for iOS 5. Then he updated for iOS 6. Then he updated for iOS 7. Last year, he updated for iOS 8. And because he is just that crazy, he updated all source code to Swift. It’s a thousand page book!

Every year, he says, “No more!” but Apple introduces something and he’s like, “Okay, let’s do it.” This is one of the things people really love about the raywenderlich.com books because they come with free updates each year, just like this one.

This is also great because Matthijs is now making a comfortable living off The iOS Apprentice and his other iOS books of course, but when you give, you also receive the love of everyone.

iOS 5 by Tutorials

Speaking about team, the first team book was iOS 5 by Tutorials. It’s a funny story how it came together.

Let me rewind a little bit. I’m going to go back to June 23, 2010.

There is an email from me in 2010 to Ray. It says, “Just an idea, have you thought about putting together all of your great tutorials like maybe in a downloadable pdf, have some exclusive, extra nice stuff?”

I thought it was a good idea and he was like, “Oh that’s a great idea, definitely something I’ll have to consider.”

So nothing afterwards and now we jump back to 2011, fifteen months later, in a Steve Jobs-like way, he pitches it back to me:

RayPitchesMarin

“Hi guys, we’ve been discussing the idea of joining together to write an eBook about iOS 5. So far there are three of us interested, me, Felipe, and Steve.”

The best thing, I totally bite back, “Hey Ray, that’s the best idea I’ve heard.”

MarinBites

Great stuff.

But seriously, Ray was the one that actually got us together and organized the first iOS Feast, and the launch, and we did the book together.

iOSFeast

He was really the one that started it for all of us iOS book authors. This was fantastic.

Too Much Awesome For One Book

Interesting story, at the time, we made a total rookie mistake. Of course as it was our first book together, we didn’t really have a process.

There was about ten guys around the world. Our plan was:

  • We start writing.
  • In two months, everybody sends in their chapters.
  • Ray puts it together.
  • We put it on the website.

We ended up with so much material that when we had to print the book, we had to do two volumes because the printer couldn’t bind one out of all the content we had.

iOS5volumes

If you ordered the print version of iOS 5 by tutorials, you actually got two volumes because of this.

I don’t know what we were thinking.

Felipe Joins the Team

Speaking of early team, remember how I mentioned that one of the three authors on the original book pitch was Felipe? Well, he is also one of the early members of the team and here’s how he took over the team in one swift motion. :]

That is how August 2011 looked for Felipe.

Screen Shot 2015-04-03 at 4.56.14 PM

August 1st, he’s about to join the team. He’s promised to write a tutorial. In a way, he’s not really a tutorial member. He’s a pending member so to say.

On the 12th, I got an email from a cool company called Lextech. They’re actually one of the conference sponsors. They were like, “Yeah, Marin how about working for us?”

I’m like, “Well, I’m just trying to make it as an indie, maybe later, not right now.”

So I just forward it to guys on the team. Felipe was a pending member so he got the email. Actually, that’s what started for him at Lextech. He still works there this very day.

Then, Felipe was officially announced as a member on the 23rd. Then Ray sent the email I was talking about earlier, and Felipe was one of the three authors that were mentioned on the 25th.

In one month:

  • He got a job.
  • He became an author to-be.
  • He joined the team.

That was only August of the whole year!

It’s not a coincidence because Felipe is adorable and brings a lot humor, passion, and Apple fun into the team.

Screen Shot 2015-04-03 at 4.56.17 PM

A final fun fact about him, there’s a game on the app store called Flappy Felipe. It’s a flappy bird clone with Felipe with a sombrero.

But seriously, Felipe made one very important contribution to the team at about that time. He was the first to go “out of line” from an online acquaintance to a friend.

After we were done with writing on iOS 5 by tutorials, he sent to everybody on the team this email where he shared he needed some guidance and some help about the universe, life, and everything else.

Some authors on the team, we just play along, and shared some of our experience with him and guided him. This is the very first time where we stop being just some guys around the world and we actually became a team. He was the one that made this first step, and it was a very emotional thing for all of us that were there.

The Fun Continues

While the website was rapidly changing and growing. Ray somehow managed to remain goofy and oblivious of all design trends. Not to mention the hilarity of the nerdy Christmas song he posted on the website.

Screen Shot 2015-04-03 at 4.56.23 PM

For the April Fool’s joke for 2012, Ray told people that there was an undocumented thermometer sensor in the iPhone. He put out this post where he said that he figured it out.

Introducing the Thermometer App Starter Kit!

He’s selling a thermometer app starter kit. Using the starter kit, people would develop all kind of applications from thermometer app. Basically you would:

  • Stick your iPhone under your tongue and measure your temperature.
  • Stick the iPhone in the turkey, and the turkey in the oven and the phone would let you know when it’s done.

Quite a lot of people tried to buy this.

iOS 6 by Tutorials

In 2012 we wrote iOS 6 by Tutorials. This time we did it professionally, editors and all.

This is important because the editors at raywenderlich.com are known to be sticklers for detail, and they write pages of feedback. For example, when I had my first feedback about iOS 6 by tutorials, I was in a café. I was about to burst in tears.

Screen Shot 2015-04-03 at 4.56.29 PM

Just to make clear what is here. The black text is my text. Everything else is edited. These are all the edits that’s been done to just these two paragraphs.

Not to mention that this is just my text. Then comes the feedback from the editors. This feedback for a simple tutorial was 2,300 words.

Yeah, but what can you do?

Screen Shot 2015-04-03 at 4.56.32 PM

You buckle up, and you up your game and that’s it.

But let’s not get too emotional.

Brian Joins Razeware

In 2012, Ray figured they needed to make another huge step and hire their first employee who turned out to be Brian Moakley, whose workshops you probably attended today or yesterday, and you probably met him around.

The question is, what made Brian the one?

Screen Shot 2015-04-03 at 4.56.35 PM

Although Brian looks adorable, he’s one tough cookie. Besides being a brilliant iOS developer and web developer, he also has a minor in creative writing. And a high point for Ray, who is a huge Walking Dead fan, Brian has a zombie blog with over 1000 posts.

He had to survive all the interviews, all the many interviews that Ray and Vicki had plotted out for him. The last one of the series of interviews took place in DC in a hotel and lasted five hours. This is the agenda for the interview.

Screen Shot 2015-04-03 at 4.56.39 PM

Brian had to do:

  • iOS programming
  • Editing
  • Algorithm development
  • and more!

All of this was on Brian’s ancient MacBook with missing on the keyboard, and seg faulted every now and then.

But luckily Brian made it, and one of the first things that he took on when he joined the team was integrating the new design for raywenderlich.com. I’m happy to report that somebody else other than Ray was in charge of cutting the logo.

Screen Shot 2015-04-03 at 4.56.41 PM

The Two Book Summer

2013 was the year where the team really came together. This was the summer, when we decided to write two books because we’d already wrote one book per year. Why not do two at the same time?

These two books, iOS 7 by Tutorials and iOS Games by Tutorials, involved more editors and authors than ever. This thing, it really pushed us to the edge. Then some of us, over. But you know what doesn’t kill you makes you stronger, so we did the two books about iOS 7.

Screen Shot 2015-04-03 at 4.56.42 PM

This brings us to the launch day of iOS 7 in 2013. We had the books prepared, everything’s ready to go, we’re just waiting for Apple to actually release it so that the NDA has lifted.

We’re in IRC and we’re all just nervously chatting and waiting for it to go. Greg Heo, one of our editors, sent me this screenshot from our actual conversation that night. It reads:

  • Marin (me): Guys I really need to go to the toilet, but I’m afraid I’ll miss the big moment. Can you hold the release another ten minutes please?
  • Ray: Haha
  • Felipe: Marin, take us with you, you’ve got WiFi.
  • Greg: No! Do not take us with you.
  • Mic: Marin isn’t really to the loo, he’s actually the chap at Apple responsible for flipping the switch.
  • Greg: In that case, hurry to the “toilet” and “flush” iOS 7 already.

You see when there’s enough editors in the chat room, every line is a pun.

As soon as I was off my laptop, of course, iOS 7 came out. It was Greg actually who was screaming, “Marin come back.” I came back and the launch was awesome.

Christmas 2013

This brings us to Christmas time 2013.

Screen Shot 2015-04-03 at 4.56.45 PM

Let’s go to November 18th. A message comes around to a secret team from Marin, me, called Xmas surprise for Ray. Read inside and keep quiet about it. It reads: DO NOT TELL RAY UNDER ANY CIRCUMSTANCES. It’s in caps and it has umbrellas on the sides, it’s top secret.

Screen Shot 2015-04-03 at 4.56.46 PM

It reads further, “I thought it would be funny if a number of us send a Xmas care package to Ray and Vicki so that everyday they will have a new present on the door and so forth.” I thought it was fun. On the next day, I had 10 people participating so we set this conspiracy in motion.

Let’s jump to December 2nd. I was at the post. I sent my package and I thought I’ll write to the guys to remind them. Here’s what I wrote, “I sent mine today, and the not-so-nice lady at the post said it’s gonna be there in about ten days.”

Screen Shot 2015-04-03 at 4.56.48 PM

While we were basically chatting about it and planning how we’re going to send our packages and things like that, then Matthijs comes on December 6th with this, “Okay, Ray got my package. It’s for the Sinterklaas holiday which we celebrate in the Netherlands. It’s on the 5th of December, not the 25th. So he got it right on time.”

Yeah well, everybody else sent it for 20 days later, it still worked. :]

As each package arrived to Ray’s home, Ray sent back a thank you Xmas card. It was at the time when he had bought his green screen as you can see:

Screen Shot 2015-04-03 at 4.56.51 PM

Screen Shot 2015-04-03 at 4.56.56 PM

Screen Shot 2015-04-03 at 4.56.59 PM

It was a great Christmas!

A More Diverse Group

This brings us to the present day. Do you remember how we all started? It was Ray in his mother-in-law’s basement. Now it looks pretty much like this:

Screen Shot 2015-04-03 at 4.57.02 PM

We have all kinds of bright people joining in, all kinds of skills. If you’re interested in joining the team, ping Ray. He’ll tell you if you’d be a good fit or not.

It’s really a community effort, so everybody joins and brings something to the team. We’re open to folks from all backgrounds.

For example, Darryl Bayliss is one of our most recent team members and he’s our resident Android correspondent.

Screen Shot 2015-04-03 at 4.57.03 PM

He had one thing to tell us iOS devs, “I hope you enjoy AutoLayout. We’ve dealt with this pain for years. :]”

Is Ray Even Real?

At last, let’s bring this right around and look into does Ray exist? and what is he like?

It was last Autumn when Ray and I, after four years of working together, met for the first time, to record the iOS Animations video tutorial series.

We decided to meet in the middle between where he lives and I live. We met in a beach house in Portugal. We would combine recording videos throughout the day and hitting the beach later on.

Screen Shot 2015-04-03 at 4.57.07 PM

For me, it was an emotional event. I was one of the first people on the team, and yet I hadn’t met Ray at all.

He existed and he was still a down to earth guy. It was also a lot of fun. We

  • played board games
  • drank wine
  • rode around in a car

It was really awesome.

Screen Shot 2015-04-03 at 4.57.09 PM

Since I probably really don’t have so much time left, I’m just going to tell you a quick story from this time we spent together in Portugal.

We were coming back from lunch, and we were almost through recording the videos and it was the very first time that we spoke about the book that you saw earlier yesterday, the iOS Animations by Tutorials book.

That was just an idea back then. I felt really overwhelmed. I said, “Thank you Ray. Without the team, and the editors, and your leverage, this would never have happened to me.”

He said, “That’s one of my goals for raywenderlich.com: to empower developers like you, and to help them grow and make a living doing what they love to do.”

He said it very simply and honestly as it was like really nothing. You could never imagine this guy has built and run a 100 plus team that is spread around the world.

Screen Shot 2015-04-03 at 4.57.13 PM

RWDevCon

After Portugal, we started preparing for RWDevCon, of course, but I don’t really need to tell you about RWDevCon, right? You’ve been here the whole time, you’ve experienced it yourselves.

Screen Shot 2015-04-03 at 4.57.15 PM

What do you think? Our hope was that it would be very memorable and it will add a lot of stories to our raywenderlich.com folklore, even for the years to come.

Join A Team And Join In On The Fun

Just to wrap up, the whole point of this talk is:

  • not to brag about our accomplishments
  • not to make fun of Ray’s design skills

Instead, it was just to show you that if you team up with friends, if you work towards a common goal, then:

  • you build up experience together
  • you have fun
  • you dream bigger
  • you achieve more

Just reach out to your local community, or Stack Overflow. Get up! Team up with friends. :]

Screen Shot 2015-04-03 at 4.57.16 PM

When you work enough time together, when you make a team of friends, then you will also build up your own folklore and one day you can share it with everyone like we did here today.

Note from Ray: Did you enjoy this inspiration talk? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2016 tickets go on sale!

RWDevCon Inspiration Talk: raywenderlich.com Folklore by Marin Todorov is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk: raywenderlich.com Folklore by Marin Todorov appeared first on Ray Wenderlich.


Split View Controllers Part 3: Collapse Process

Video Tutorial: Monetizing Your App with iAd Part 1: Introduction to iAd

OS X Tutorial: Menus and Popovers in Menu Bar Apps

$
0
0
Learn how to make a menu bar OS X app with a popover!

Learn how to make a menu bar OS X app with a popover!

Menu bar apps have been staple of OS X for along time. Many apps like 1Password and Day One have companion menu bar apps. Others like Fantastical live exclusively in OS X’s menu bar.

In this tutorial, you’ll build a menu bar app that shows inspirational quotes in a popover. While you do this, you’ll learn:

  • How to create a menu bar icon
  • How to make the app live exclusively in the menu bar
  • How to add a menu for the user
  • How to make a popover that shows on demand and hides when the user moves on — aka Event Monitoring
  • How to add essential UI
Note: This tutorial assumes you’re familiar with Swift and OS X. If you need a refresher, start with our Getting Started With OS X and Swift tutorial for a great introduction.

Getting Started

Fire up Xcode. Go to File/New/Project… then select the OS X/Application/Cocoa Application template and click Next.

On the next screen, enter Quotes as the Product Name, choose your desired Organization Name and Organization Identifier. Then make sure that Swift is selected as the language, and uncheck Use Storyboards, Create Document-Based Application and Use Core Data.

QuotesOptions

Finally, click Next again, choose a place to save the project and click Create.

Once the new project is set up, open AppDelegate.swift and add the following property to the class:

let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-2)

This creates a Status Item — aka application icon — in the menu bar with a fixed length that the user will see and use.

Note: At the time of writing, there is a bug in Xcode that prevents it from recognizing NSSquareStatusItemLength, but since it’s just a constant that’s defined as -2, you just use -2 in it’s place.

Next, you’ll need to associate an image to the status item to make your app recognizable in the menu bar.

Go to Images.xcassets. Then download this image StatusBarButtonImage@2x.png and drag it into the asset catalog.

Select the image and open the attributes inspector. Set Devices to Device Specific, and then make sure the Mac option is checked. Change the Render As option to Template Image.

StatusBarButtonImage-3

If you use your own custom image, make sure that the image is black and white and configured as a template image so the Status Item looks great against both light and dark menu bars.

Back in AppDelegate.swift, add the following code to applicationDidFinishLaunching(_:):

if let button = statusItem.button {
  button.image = NSImage(named: "StatusBarButtonImage")
  button.action = Selector("printQuote:")
}

This will configure the status item with an icon of the image you just added, and an action for when you click on the item.

Before you get to test the app, you’ll need to add that button action method. Add the following method to the class:

func printQuote(sender: AnyObject) {
  let quoteText = "Never put off until tomorrow what you can do the day after tomorrow."
  let quoteAuthor = "Mark Twain"
 
  println("\(quoteText) — \(quoteAuthor)")
}

This method will simply log out a nice Mark Twain quote to the console.

Build and run the app, and you should see a new menu bar app available. You did it!

Note: If you have too many menu bar apps, you might not be able to see your button. Switch to an app with fewer menus than Xcode (like Finder) and you should be able to see it.

Every time you click on the menu bar icon, you’ll see the quote printed out in the Xcode console.

Hiding the Dock Icon and Main Window

There are still two small things to do before you have a functional menu bar app: hide the dock icon and kill off the main window.

To disable the dock icon, open Info.plist. Add a new key Application is agent (UIElement) and set its value to YES.

Note: If you’re an expert plist editor, feel free to set this manually with the key LSUIElement.

Now it’s time to handle the main window. Open MainMenu.xib and select the window object. Then, in the attributes inspector, set the window so it’s not visible at launch.

Build and run. You’ll see the app has no main window, no pesky dock icon and only a tidy status item in the menu bar!

Adding a Menu to the Status Item

Usually, a measly single action on click is not enough for a menu bar app. The easiest way to add more functionality to your app is to add a menu. Add the following code to the end of applicationDidFinishLaunching(_:):

let menu = NSMenu()
 
menu.addItem(NSMenuItem(title: "Print Quote", action: Selector("printQuote:"), keyEquivalent: "P"))
menu.addItem(NSMenuItem.separatorItem())
menu.addItem(NSMenuItem(title: "Quit Quotes", action: Selector("terminate:"), keyEquivalent: "q"))
 
statusItem.menu = menu

Here you create an NSMenu, add multiple instances of NSMenuItem to it, and then set the status item’s menu to that new menu.

A few things to note here:

  • The title of a menu item is clear; it’s just the text that appears on the menu item.
  • The action, like the action of a button or any control, is the method that gets called when you click the menu item.
  • The KeyEquivalent is a keyboard shortcut that you can use to activate the menu item. A lowercase letter uses Cmd as the modifier key and an uppercase letter uses Cmd+Shift. This keyboard shortcut only works if the application is front-most and active. So, in this case, the menu or any other window needs to be visible, since the app has no dock icon.
  • A separatorItem is an inactive menu item that appears as a simple gray line between other menu items. Use it to group functionality in the menu.
  • The printQuote: action is the method you already defined in AppDelegate. On the other hand, terminate: is an action method defined in the shared application instance. Because you don’t implement it, the action gets sent up the responder chain until it arrives at the shared application, in which case the application quits.

Build and run, and you should see a menu when clicking on the status item. Progress!

Try out your options – selecting Print Quote will display the quote in the Xcode console, while Quit Quotes will quit the app.

Adding a Popover to the Status Item

You’ve seen how easy it is to set up a menu from code, but showing the quote in the Xcode console won’t cut it for your end users. The next step is to replace the menu with a simple view controller to show a quote right in place.

Go to File/New/File…, select the OS X/Source/Cocoa Class template and click Next.

Name the class QuotesViewController, make it a subclass of NSViewController, check the option Also create XIB file for user interface, and set the language to Swift.

Finally, click Next again, choose a place to save the file (In the Quotes subfolder of the project folder is a good place) and click Create.

Now, leave the new files alone and go back to AppDelegate.swift. Start by adding a new property declaration to the class:

let popover = NSPopover()

Next, replace applicationDidFinishLaunching(_:) with the following:

func applicationDidFinishLaunching(notification: NSNotification) {
  if let button = statusItem.button {
    button.image = NSImage(named: "StatusBarButtonImage")
    button.action = Selector("togglePopover:")
  }
 
  popover.contentViewController = QuotesViewController(nibName: "QuotesViewController", bundle: nil)
}

You’ve changed the button action to togglePopover: which you’ll implement next. Also, rather than set up a menu, you’re setting up the popover to show whatever’s in QuotesViewController.

Finally, remove printQuote(), and add the following three methods in its place:

func showPopover(sender: AnyObject?) {
  if let button = statusItem.button {
    popover.showRelativeToRect(button.bounds, ofView: button, preferredEdge: NSMinYEdge)
  }
}
 
func closePopover(sender: AnyObject?) {
  popover.performClose(sender)
}
 
func togglePopover(sender: AnyObject?) {
  if popover.shown {
    closePopover(sender)
  } else {
    showPopover(sender)
  }
}

showPopover() displays the popover to the user. Similar to popovers on iOS, you just need to supply a source rect and OS X will position the popover and arrow so it looks like it’s coming out of the menu bar icon.

closePopover() simply closes the popover, and togglePopover() is the action method that will either open or close the popover depending on its current state.

Build and run, and then click on the menu bar icon to check that it shows and then hides an empty popover.

Your popover works great, but where’s all the inspiration? All you see is an empty view and no quotes. Guess what you’ll fix next?

Implementing the Quote View Controller

First, you’ll need model to store the quotes and attributions. Go to File/New/File… and select the OS X/Source/Swift File template, then click Next. Name the file Quote and click Create.

Open Quote.swift and add the following code to the file:

struct Quote {
  let text: String
  let author: String
 
  static let all: [Quote] = [
    Quote(text: "Never put off until tomorrow what you can do the day after tomorrow.", author: "Mark Twain"),
    Quote(text: "Efficiency is doing better what is already being done.", author: "Peter Drucker"),
    Quote(text: "To infinity and beyond!", author: "Buzz Lightyear"),
    Quote(text: "May the Force be with you.", author: "Han Solo"),
    Quote(text: "Simplicity is the ultimate sophistication", author: "Leonardo da Vinci"),
    Quote(text: "It’s not just what it looks like and feels like. Design is how it works.", author: "Steve Jobs")
  ]
}
 
// MARK: - Printable
 
extension Quote: Printable {
  var description: String {
    return "\"\(text)\"\(author)"
  }
}

This defines a simple quote structure and a static property that returns all the quotes. Since you also make Quote conform to Printable, you can easily get a nice formatted string.

You’re making progress, but you still need some more function in the UI. How about some wrapping and auto constraints to make it pretty?

Open QuotesViewController.xib and drag two bevel button instances, a label and a push button into the custom view.

Set the first bevel button’s image to NSGoLeftTemplate and the second button’s image to NSGoRightTemplate, set the label’s text alignment to Center and its line break mode to Word Wrap. Finally, set the title of the push button to Quit Quotes.

Here’s what the final layout should look like:

Can you add the auto layout constraints to make the user interface match? Give it a few good attempts before you open the spoiler below. If you get it right, skip the spoiler and give yourself a gold star.

Solution Inside SelectShow>

After you’ve perfected the constraints, select Update Constraints by selecting Resolve Auto Layout Issues in the bottom-right corner of the canvas.

Now open QuotesViewController.swift and replace the file contents with the following:

import Cocoa
 
class QuotesViewController: NSViewController {
  @IBOutlet var textLabel: NSTextField!
}
 
// MARK: Actions
 
extension QuotesViewController {
  @IBAction func goLeft(sender: NSButton) {
  }
 
  @IBAction func goRight(sender: NSButton) {
  }
 
  @IBAction func quit(sender: NSButton) {
  }
}

This starter implementation is for a standard NSViewController instance. There’s one outlet for the text label, which you’ll need to update with the inspirational quote. The three actions are for the three buttons.

Then go back to QuotesViewController.xib and connect the outlet to the text label by control-dragging from File’s Owner to the label. Connect the actions by contro-dragging from each button to File’s Owner.

Note: If you have trouble with any of the above steps, refer to our library of OS X tutorials, where you’ll find introductory tutorials that will walk you through many aspects of OS X development, including adding views/constraints in interface builder and connecting outlets and actions.

Stand up, stretch and maybe do a quick victory lap around your desk because you just flew through a bunch of interface builder work.

Build and run, and your popover should look like this now:

The interface is finished, but you’re not done yet. Those buttons are waiting on you to know what to do when the user clicks them — don’t leave them hanging.

Open QuotesViewController.swift and add the following properties to the class:

let quotes = Quote.all
 
var currentQuoteIndex: Int = 0 {
  didSet {
    updateQuote()
  }
}

The first property holds all the quotes, and the second holds the index of the current quote. currentQuoteIndex also has a property observer to update the text label string with the new quote when the index changes.

Next, add the following methods to the class:

override func viewWillAppear() {
  super.viewWillAppear()
 
  currentQuoteIndex = 0
}
 
func updateQuote() {
  textLabel.stringValue = toString(quotes[currentQuoteIndex])
}

When the view appears, you set the current quote index to 0, which in turn updates the user interface. updateQuote() simply updates the text label to show whichever quote is currently selected according to currentQuoteIndex.

To tie it all together, implement the three action methods as follows;

@IBAction func goLeft(sender: NSButton) {
  currentQuoteIndex = (currentQuoteIndex - 1 + quotes.count) % quotes.count
}
 
@IBAction func goRight(sender: NSButton) {
  currentQuoteIndex = (currentQuoteIndex + 1) % quotes.count
}
 
@IBAction func quit(sender: NSButton) {
  NSApplication.sharedApplication().terminate(sender)
}

In goLeft() and goRight(), you cycle through the all the quotes and wrap around when you reach the ends of the array. quit() terminates the app as explained before.

Build and run again, and now you can see all the quotes and quit the app!

Event Monitoring

There is one feature you’ll want in your unobtrusive, small menu bar app, and it’s when you click anywhere outside the app, the popover automatically closes.

Menu bar apps should open the popover on click or hover, and then disappear once the user moves onto the next thing. For that, you need an OS X global event monitor.

Here’s where you’ll take the concept to the next level. You’ll make the event monitor reusable in all your projects, and to keep the example app modular, you’ll define a Swift wrapper class and then use it when showing the popover.

Bet you’re feeling smarter already!

I feel S-M-R-T!

I feel S-M-R-T!

Create a new Swift File and name it EventMonitor, and then replace its contents with the following class definition:

import Cocoa
 
public class EventMonitor {
  private var monitor: AnyObject?
  private let mask: NSEventMask
  private let handler: NSEvent? -> ()
 
  public init(mask: NSEventMask, handler: NSEvent? -> ()) {
    self.mask = mask
    self.handler = handler
  }
 
  deinit {
    stop()
  }
 
  public func start() {
    monitor = NSEvent.addGlobalMonitorForEventsMatchingMask(mask, handler: handler)
  }
 
  public func stop() {
    if monitor != nil {
      NSEvent.removeMonitor(monitor!)
      monitor = nil
    }
  }
}

You initialize an instance of this class by passing in a mask of events to listen for – things like key down, scroll wheel moved, left mouse button click, etc – and an event handler.

When you’re ready to start listening, start() calls addGlobalMonitorForEventsMatchingMask(_:handler:), which returns an object for you to hold on to. Any time the event specified in the mask occurs, the system calls your handler.

To remove the global event monitor, you call removeMonitor() in stop() and delete the returned object by setting it to nil.

All that’s left is calling start() and stop() when needed. How easy is that? The class also calls stop() for you in the deinitializer, to clean up after itself.

Open AppDelegate.swift one last time, and add a new property declaration to the class:

var eventMonitor: EventMonitor?

Next, add the code to configure the event monitor at the end of applicationDidFinishLaunching(_:):

eventMonitor = EventMonitor(mask: .LeftMouseDownMask | .RightMouseDownMask) { [unowned self] event in
  if self.popover.shown {
    self.closePopover(event)
  }
}
eventMonitor?.start()

This notifies your app of any left or right mouse down event and closes the popover when the system event occurs.

Add the following code to the end of showPopover(_:):

eventMonitor?.start()

This will start the event monitor when the popover appears.

Then, you’ll need to add the following code to the end of closePopover(_:):

eventMonitor?.stop()

This will stop the event monitor when the popover closes.

All done! Build and run the app one more time. Click on the menu bar icon to show the popover, and then click anywhere else and the popover closes. Awesome!

Where To Go From Here?

Here is the downloadable final project with all of the code you’ve developed in the above tutorial.

You’ve seen how to set up both menus and popovers in your menu bar status items – why not keep experimenting with showing a randomized quote, connecting to a web backend to pull new quotes, or even some kind of “pro” version to open the door to monetization?

A good place to look for other possibilities is reading the official documentation for NSMenu, NSPopover and NSStatusItem.

Pro tip: Be careful with the NSStatusItem documentation. The API changes significantly in Yosemite, and sadly, the documentation marks all old methods as deprecated, but doesn’t document the new alternative methods. For that, you need to command click on NSStatusItem in Xcode to look at the generated Swift header. There are only a few methods now and all the functionality is inside an NSButton, so it’s pretty easy to comprehend.

Thanks for taking the time to learn how to make a cool popover menu app for OS X. For now, it’s pretty simple, but you can see that the concepts you’ve learned here are an excellent foundation for a variety of apps.

If you have any questions, awesome discoveries or ideas you’d like to bounce off others as you configure status items, menus or popovers in your apps, please let me know in the forum discussion below! :]

OS X Tutorial: Menus and Popovers in Menu Bar Apps is a post from: Ray Wenderlich

The post OS X Tutorial: Menus and Popovers in Menu Bar Apps appeared first on Ray Wenderlich.

UISplitViewController Tutorial: Getting Started

$
0
0
Get started with UISplitViewController for your master-detail style apps!

Get started with UISplitViewController for your master-detail style apps!

Update note: This tutorial was updated for Swift and iOS 8 by Brad Johnson. Original post by Ray Wenderlich with updates by Ellen Shapiro.

On an app running on the iPad, it would rarely make sense to have a full-screen table view like you do so often on iPhone – there’s just too much space. To make better use of that space, the UISplitViewContoller comes to the rescue.

The split view lets you carve up the screen into two sections and display a view controller on each side. It’s typically used to display navigation on the left hand side, and a detail view on the right hand side. The best part is, iOS 8 introduces the new universal split view controller, which now works on both iPad and iPhone. The future is truly awesome.

In this tutorial, you’ll make a Universal app from scratch that makes use of a split view controller to display a list of monsters from Math Ninja, one of the games developed by the team here at Razeware. You’ll use a split view controller to handle the navigation and display, which will adapt to work on both iPhone and iPad.

catbot

This tutorial focuses on split view controllers; you should already be familiar with the basics of auto layout and storyboards before continuing.

Note: We recently came out with a video tutorial series on the same subject. If you’d prefer to learn this via video tutorials, check it out!

Getting Started

Create a new Project in Xcode, and choose the iOS\Application\Single View Application template.

SwiftSplitView1

Name the project MathMonsters. Choose Swift for Language and Universal in the Devices dropdown. Leave Use Core Data unchecked, and finish creating the project.

Although you could use the “Master-Detail Application” template as a starting point, you’re going to start from scratch with the “Single View Application” template. This is so you can get a better understanding of exactly how the UISplitViewController works. This knowledge will be helpful as you continue to use it in future projects (even if you choose the Master-Detail template in the future to save time!)

Open Main.storyboard, delete the initial view controller that is placed there by default, and drag a Split View Controller into the now empty storyboard:

SwiftSplitView2

This will add several elements to your storyboard:

  • A Split View Controller. This is the root view of your application – the split view that will contain the entire rest of the app.
  • A Navigation Controller. This represents the UINavigationController that will be the root view of your Master View Controller (ie, the left pane of the split view when on iPad or Landscape iPhone 6 Plus). If you look in the Split View Controller, you’ll see the navigation controller has a Relationship Segue of “master view controller”. This allows you to create an entire navigation hierarchy in the Master View Controller without needing to affect the Detail View Controller at all.
  • A View Controller. This will eventually display all the details of the monsters. If you look in the Split View Controller, you’ll see the View Controller has a Relationship Segue of “detail view controller”:

SplitView3

  • A Table View Controller. This is the root view controller of the master UINavigationController. This will eventually display the list of monsters.

Since you deleted the default initial view controller from the storyboard, you need to tell the storyboard that you want your split view controller to be the initial view controller. Select the Split View Controller and open the Attributes inspector. Check the Is Initial View Controller option.

SwiftSplitView4

You will see an arrow to the left of the Split View Controller, which tells you it is the initial view controller of this storyboard. Build and run the app on an iPad simulator, and rotate your simulator to landscape. You should see an empty split view controller:

SwiftSplitView5

Now run it on an iPhone simulator (any of them except the iPhone 6 plus, which is large enough that it will act just like the iPad version) and you will it starts off showing the detail view in full screen, and allows you to tap the back button on the navigation bar to pop back to the master view controller:

Screen Shot 2015-01-31 at 11.21.06 AM

On iPhones besides iPhone 6 Plus, the iOS 8 version of Split View Controller will act just like a traditional master detail app with a navigation controller pushing and popping back and forth. This functionality is built-in and requires very little extra configuration from you, the developer. Hooray iOS 8!

You’re going to want to have your own view controllers shown instead of these default ones, so let’s get started creating those.

Creating Custom View Controllers

The storyboard has the view controller hierarchy set up — split view controller with its master and detail view controllers. Now you’ll need to implement the code side of things to get some data to show up.

Go to File\New\File… and choose the iOS\Source\Cocoa Touch Class template. Name the class MasterViewController, make it a subclass of UITableViewController, and make sure the XIB checkbox is unchecked and Language is set to Swift. Click Next and then Create.

Open MasterViewController.swift, scroll down to numberOfSectionsInTableView(_:) and replace the implementation as follows:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
  // Return the number of sections.
  return 1
}

Next, find tableView(_:numberOfRowsInSection:) and replace the implementation with the following:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  // Return the number of rows in the section.
  return 10
}

Finally, uncomment tableView(_:cellForRowAtIndexPath:) and replace its implementation with the following:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
 
  // Configure the cell...
 
  return cell
}

This way, you’ll just have 10 empty rows to look at when you test this thing out later.

Open Main.storyboard and select the Root Table View Controller. Change the Class under Custom Class to MasterViewController using the Identity Inspector (3rd tab):

In addition, you need to make sure the Prototype Cell in the Table View is given a reuse identifier, or it will cause a crash when the Storyboard tries to load. Within the Master View Controller, select the Prototype Cell and then change the Identifier to “Cell” (which is already set as the default for UITableViewController subclasses in code), and the cell Style to “Basic”.

SwiftSplitView7

Now, you’ll create the View Controller for the detail side. Go to File\New\File… and choose the iOS\Source\Cocoa Touch Class template. Name the class DetailViewController, make it a subclass of UIViewController, and make sure the XIB checkbox is unchecked and Language is set to Swift. Click Next and then Create.

Open Main.storyboard, and select the view controller on the bottom detail half. Change the Class under Custom Class to DetailViewController:

Then drag a label into the middle, and pin it to the Horizontal and Vertical centers of the container with Auto layout.

SwiftSplitView9

Double-click the label to change its text to say “Hello, World!” so you know it’s working when you test it out later.

Build and run to try this out, and at this point you should see your custom view controllers. On iPad:

SwiftSplitView10and on iPhone:

SwiftSplitView11

Making Your Model

The next thing you need to do is define a model for the data you want to display. You don’t want to complicate things while learning the basics of split view controllers, so you’re going with a simple model with no data persistence.

First, make a class representing the Monsters you want to display. Go to File\New\File…, select the iOS\Source\Swift File template, and click Next. Name the file Monster and click Create.

You’re just going to create a simple class with some instance variables with attributes about each Monster you want to display, and a couple of methods for creating new monsters and accessing the image for the weapon each monster has. Replace the contents of Monster.swift with the following:

import UIKit
 
//an enum that defines a number of weapon options
enum Weapon {
  case Blowgun, NinjaStar, Fire, Sword, Smoke
}
 
class Monster {
  let name: String
  let description: String
  let iconName: String
  let weapon: Weapon
 
  // designated initializer for a Monster
  init(name: String, description: String, iconName: String, weapon: Weapon) {
    self.name = name
    self.description = description
    self.iconName = iconName
    self.weapon = weapon
  }
 
  // Convenience method for fetching a monster's weapon image
  func weaponImage() -> UIImage? {
    switch self.weapon {
    case .Blowgun:
      return UIImage(named: "blowgun.png")
    case .Fire:
      return UIImage(named: "fire.png")
    case .NinjaStar:
      return UIImage(named: "ninjastar.png")
    case .Smoke:
      return UIImage(named: "smoke.png")
    case .Sword:
      return UIImage(named: "sword.png")
    }
  }
}

This file defines an enumeration to track the different kinds of weapons, and then a class to hold the Monster information. There’s a simple initializer to create Monster instances, and a convenience method to get an image corresponding to the monster’s weapon.

That’s it for defining the model – so let’s hook it up to your master view!

Displaying the Monster List

Open up MasterViewController.swift and add a new property to the class:

var monsters = [Monster]()

This will hold an array of monsters to populate the table view.

Find tableView(_:numberOfRowsInSection:) and replace the return statement with the following:

return self.monsters.count

This will return the number of monsters based on the size of the array.

Next, find tableView(_:cellForRowAtIndexPath:) and add the following code before the final return statement:

let monster = self.monsters[indexPath.row]
cell.textLabel?.text = monster.name

This will configure the cell based on the correct monster. That’s it for the table view, which will simply show each monster’s name.

The array of monsters is still empty, so you won’t see any data or fancy weapon details yet. Download and unzip this art pack and drag the folder containing those images into Images.xcassets in Xcode.

After you add the images, open MasterViewController.swift and add the following initializer:

required init(coder aDecoder: NSCoder) {
  super.init(coder: aDecoder)
 
  self.monsters.append(Monster(name: "Cat-Bot", description: "MEE-OW",
    iconName: "meetcatbot.png", weapon: Weapon.Sword))
  self.monsters.append(Monster(name: "Dog-Bot", description: "BOW-WOW",
    iconName: "meetdogbot.png", weapon: Weapon.Blowgun))
  self.monsters.append(Monster(name: "Explode-Bot", description: "BOOM!",
    iconName: "meetexplodebot.png", weapon: Weapon.Smoke))
  self.monsters.append(Monster(name: "Fire-Bot", description: "Will Make You Stamed",
    iconName: "meetfirebot.png", weapon: Weapon.NinjaStar))
  self.monsters.append(Monster(name: "Ice-Bot", description: "Has A Chilling Effect",
    iconName: "meeticebot.png", weapon: Weapon.Fire))
  self.monsters.append(Monster(name: "Mini-Tomato-Bot", description: "Extremely Handsome",
    iconName: "meetminitomatobot.png", weapon: Weapon.NinjaStar))
}

This initializer will set up the array of monsters. Note that you are implementing init(coder:) because this class is being loaded from a storyboard.

Build and run the app, and if all goes well you should now see the list of monster bots on the left hand side on landscape iPad:

SwiftSplitView12

and iPhone:

SwiftSplitView13

Remember that on compact-width iPhone, you start one level deep already in the navigation stack on the detail screen. You can tap the Back button to see the table view.

Displaying Bot Details

Now that the table view is showing the list of monsters, it’s time to get the detail view in order.

Open Main.storyboard, go to the Detail View Controller and delete the placeholder label you put down earlier.

Using the screenshot below as a guide, drag the following controls into the DetailViewController’s view:

SwiftSplitView14

  1. A 95×95 image view for displaying the Monster’s image in the upper left hand corner.
  2. A label aligned with the top of the image view with font System Bold, size 30, and with the text “Monster Name”
  3. Two labels underneath, with font System, size 24. One label should be bottom aligned with the image view; the other label should be below the first label. They should have their left edges aligned, and titles “Description” and “Preferred Way To Kill”
  4. A 70×70 image view for displaying the weapon image, horizontally center aligned with the “Preferred way to Kill” label.

Need some more hints? Open the spoilers below for the set of constraints I used to make the layout.

Solution Inside SelectShow>

Getting auto layout to use the proper constraints is especially important since this app is universal, and auto layout is what ensures the layout adapts well to both iPad and iPhone.

Note: Auto Layout can be a slippery devil! I highly recommend you check out our Beginning Auto Layout tutorial series if you run into any trouble.

That’s it for auto layout for now. Next you’ll need to hook these views up to some outlets. Open DetailViewController.swift and add the following properties to the class:

@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var iconImageView: UIImageView!
@IBOutlet weak var weaponImageView: UIImageView!
 
var monster: Monster! {
  didSet (newMonster) {
    self.refreshUI()
  }
}

Here you added properties for the various UI elements you just added which need to dynamically change. You also added a property for the Monster object this view controller should display.

Next, add the following helper method to the class:

func refreshUI() {
  nameLabel?.text = monster.name
  descriptionLabel?.text = monster.description
  iconImageView?.image = UIImage(named: monster.iconName)
  weaponImageView?.image = monster.weaponImage()
}

Whenever you switch the monster, you’ll want the UI to refresh itself and update the details displayed in the outlets. Note that refreshUI() uses optional chaining even though the properties are implicitly-unwrapped optionals. It’s possible that you’ll change monster and trigger the method even before the view has loaded, so you need to be sure to check that the outlets are connected first.

Finally, find viewDidLoad() and add the following line of code to the end of that method:

refreshUI()

This will trigger the UI refresh when the view first loads.

Now, go back Main.storyboard, right-click the Detail View Controller object to display the list of outlets, then drag from the circle at the right of each item to the view to hook up the outlets.

SwiftSplitView17

Remember, the icon image view is the big image view in the top left, while the weapon image view is the smaller one underneath the “Preferred Way To Kill” label.

Go to to AppDelegate.swift and replace the implementation of application(_:didFinishLaunchingWithOptions:) with the following:

let splitViewController = self.window!.rootViewController as! UISplitViewController
let leftNavController = splitViewController.viewControllers.first as! UINavigationController
let masterViewController = leftNavController.topViewController as! MasterViewController
let detailViewController = splitViewController.viewControllers.last as! DetailViewController
 
let firstMonster = masterViewController.monsters.first
detailViewController.monster = firstMonster
 
return true

A split view controller has an array property viewControllers that has the master and detail view controllers inside. The master view controller in your case is actually a navigation controller, so you get the top view controller from that to get your MasterViewController instance. From there, you can set the current monster to the first one in the list.

Build and run the app, and if all goes well you should see some monster details on the right. On iPad Landscape:

SwiftSplitView18

and iPhone:

SwiftSplitView19

Note that selecting a monster on the MasterViewController does nothing yet and you’re stuck with Cat-Bot forever. That’s what you’ll work on next!

Hooking Up The Master With the Detail

There are many different strategies for how to best communicate between these two view controllers. In the Master-Detail Application template, the master view controller has a reference to the detail view controller. That means the master view controller can set a property on the detail view controller when a row gets selected.

That works fine for simple applications where you only ever have one view controller in the right pane, but you’re going to follow the approach suggested in the UISplitViewController class reference for more complex apps and use a delegate.

Open MasterViewController.swift and add the following protocol definition above the MasterViewController class definition:

protocol MonsterSelectionDelegate: class {
  func monsterSelected(newMonster: Monster)
}

This defines a protocol with a single method, monsterSelected(_:). The detail view controller side will implement this method, and the master view controller will accept a delegate of an object which wants to know about this.

Then, update MasterViewController to add a property for an object conforming to the delegate protocol:

weak var delegate: MonsterSelectionDelegate?

Basically, this means that the delegate property is required to be an object that has selectedMonster(_:) implemented. That object will be responsible for handling what needs to happen within its view after the monster was selected.

Note: You need to mark the delegate as weak to avoid a retain cycle. To learn more about retain cycles in Swift, check out the Memory Management video in our Intermediate Swift video tutorial series.

Since you want DetailViewController to update when the monster is selected, you need to implement the delegate. Open DetailViewController.swift and add a class extension to the very end of the file:

extension DetailViewController: MonsterSelectionDelegate {
  func monsterSelected(newMonster: Monster) {
    monster = newMonster
  }
}

Class extensions are great for separating out delegate protocols and grouping the methods together. Here, you’re saying DetailViewController conforms to MonsterSelectionDelegate and then you implement the one required method.

Now that the delegate method is ready, you need to call through to it from the master side. Open MasterViewController.swift and add the following method:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  let selectedMonster = self.monsters[indexPath.row]
  self.delegate?.monsterSelected(selectedMonster)
}

Implementing tableView(_:didSelectRowAtIndexPath:) means you’ll be notified whenever the user selects a row in the table view. All you need to do is notify the Monster selection delegate of the new monster.

Finally, open AppDelegate.swift. In application(_:didFinishLaunchingWithOptions:), add the following code just before the final return statement:

masterViewController.delegate = detailViewController

That’s the final connection between the two view controllers. Build and run the app on iPad, and you now should be able to select between the monsters like the following:

SwiftSplitView18

So far so good with split views! Except there’s one problem left – if you run it on iPhone, selecting monsters from the table view does not show the detail view controller. You now need add make a few small modifications to make sure the split view works on iPhone, in addition to iPad.

You only need to make one small modification in MasterViewController.swift. Find tableView(_:didSelectRowAtIndexPath:) and add the following to the end of the method:

if let detailViewController = self.delegate as? DetailViewController {
  splitViewController?.showDetailViewController(DetailViewController, sender: nil)
}

First, you need to make sure the delegate is set and that it’s a DetailViewController instance as you expect. You then call showDetailViewController(_:sender:) on the split view controller and pass in the detail view controller. Every subclass of UIViewController has an inherited property splitViewController, which will refer to the split view controller the view controller is in, if one exists.

This new code only changes the behavior of the app on iPhone, causing the navigation controller to push the detail controller onto the stack when you select a new monster. It does not alter the behavior of the iPad implementation, since on iPad the detail view controller is always visible.

After making this change, run it on iPhone and it should now behave properly. Adding just a few lines of code got you a fully functioning split view controller on both iPad and iPhone. Not bad!

SwifthSplitView23

Split View Controller in iPad portrait

Run the app in iPad in portrait mode. At first it appears there is no way to get to the left menu, but try swiping from the left side of the screen. Pretty cool huh? Tap anywhere outside of the menu to hide it.

That built in swipe functionality is pretty cool, but what if you want to have a nav bar up top with a button that will display the menu, similar to how it behaves on iPhone. To do that, you will need to make a few more small modifications to the app.

First, open Main.storyboard and embed the Detail View Controller into a Navigation Controller by selecting the Detail View Controller, hitting Editor/Embed In/Navigation Controller. Your storyboard will now look like this:

SwiftSplitView20

Now open MasterViewController.swift and find tableView(_:didSelectRowAtIndexPath:). Change the line with the call to showDetailViewController(_:sender:) with the following:

splitViewController?.showDetailViewController(detailViewController.navigationController, sender: nil)

Instead of showing the detail view controller, you’re now showing the detail view controller’s navigation controller. The navigation controller’s root is the detail view controller anyway, so you’ll still see the same content as before, just wrapped in a navigation controller.

There are two final changes to make before you run the app. First, in AppDelegate.swift update application(_:didFinishLaunchingWithOptions:) by replacing the single line initializing detailViewController with the following two lines:

let rightNavController = splitViewController.viewControllers.last as! UINavigationController
let detailViewController = rightNavController.topViewController as! DetailViewController

Since the detail view controller is wrapped in a navigation controller, there are now two steps to access it.

Finally, add the following lines just before the final return statement:

detailViewController.navigationItem.leftItemsSupplementBackButton = true
detailViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()

This tells the detail view controller to replace its left navigation item with a button that will toggle the display mode of the split view controller. It won’t change anything when running on iPhone, but on iPad you will get a button in the top left to toggle the table view display. Run the app on iPad portrait and check it out:

SwiftSplitView22

Where To Go From Here?

Here’s an archive of the final project with all of the code you’ve developed so far.

For new apps, you’re likely to just use the Master-Detail template to save time, which gives you a split view controller to start. But now you’ve seen how to use UISplitViewController from the ground up and have a much better idea of how it works. Now that you’ve seen how easy it is to get the master-detail pattern into your universal apps, go forth and apply what you’ve learned!

Check out our short video tutorial series on split view controllers if you’re interested in some more details on split view controllers across devices, including the iPhone 6 Plus.

If you have any questions or comments, please join the forum discussion below!

UISplitViewController Tutorial: Getting Started is a post from: Ray Wenderlich

The post UISplitViewController Tutorial: Getting Started appeared first on Ray Wenderlich.

Video Tutorial: Monetizing Your App with iAd Part 2: Intermediate iAd

Introducing RWDevCon 2016!

$
0
0
RWDevCon 2016 is on!

RWDevCon 2016 is on!

At the end of RWDevCon 2015, everybody kept asking me “Are you going to run this again next year?”

At the time, my answer was “I don’t know.” It takes an incredible amount of work to run a conference – especially the way we run RWDevCon, with huge speaker preparation, multiple rounds of practice, and coordinated content.

But as we reviewed all of the amazing feedback we got from attendees and speakers, we realized the hard work was totally worth it. Everybody had a great time and learned a ton – and we had so much fun hanging out with this amazing community.

So today, I’m happy to announce that RWDevCon 2016 is officially on!

Keep reading to learn more about RWDevCon and when tickets will become available.

What is RWDevCon?

RWDevCon is not your normal conference. It’s organized across four main principles:

  • Hands-on Experience: We believe the best way to learn a subject is through hands-on experience. At RWDevCon, you’ll learn by doing.
  • Team Communication: RWDevCon is coordinated as a team – we make sure we cover the right topics, and make each tutorial shine.
  • Inspiration: There’s more than just tutorials – we also have inspiration talks to leave you with new ideas and energy.
  • Friendship: We believe the best part about going to a conference is the people – so get ready to party and play!

To learn more, check out our quick video here:


Where To Go From Here?

Ticket sales will be available on the conference site sometime after WWDC, after we have a better sense of the new/cool stuff we’ll be covering in the conference, etc.

RWDevCon sold out within a month last year. If you’d like to be notified when tickets become available so you don’t miss your chance to get a ticket, sign up to our mailing list below!

Get Notified When RWDevCon Ticket Sales Open!

* indicates required




Introducing RWDevCon 2016! is a post from: Ray Wenderlich

The post Introducing RWDevCon 2016! appeared first on Ray Wenderlich.

Video Tutorial: Monetizing Your App with iAd Part 3: Ad Mediation with Google AdMob


WatchKit by Tutorials Updated for Swift 1.2 and Print Version Released!

$
0
0

AWT-Thumb

Good news – the WatchKit by Tutorials Team has updated WatchKit by Tutorials for Swift 1.2!

As you may know, Swift 1.2 introduced some new syntax, such as an improved if let statement, and revised usage of as vs as! vs as?. To learn more about these changes, check out our What’s New in Swift 1.2 overview.

In this update, the team has updated all chapters and sample code to use the new Swift 1.2 syntax, and have also fixed some of the errata reported on the forums.

If you’re an WatchKit by Tutorials PDF customer, you can download the update for free on your My Loot page (version 1.3).

Print Version

More good news – we are happy to announce the print version is now available too!

AWT-Print

Here’s how you can get the print version:

  • If you preordered the print version of the book, we will be shipping the books out within the next few days. Please then allow time for delivery.
  • If you don’t have the WatchKit by Tutorials yet, grab your copy now!

We hope you enjoy the update and the print version!

WatchKit by Tutorials Updated for Swift 1.2 and Print Version Released! is a post from: Ray Wenderlich

The post WatchKit by Tutorials Updated for Swift 1.2 and Print Version Released! appeared first on Ray Wenderlich.

RWDevCon Inspiration Talk – Craftsmanship by Chris Wagner

$
0
0

At our recent RWDevCon tutorial conference, in addition to hands-on tutorials, we also had a number of “inspiration talks” – non-technical talks with the goal of giving you a new idea, some battle-won advice, and leaving you excited and energized.

We recorded these talks so that you can enjoy them, even if you didn’t get to attend the conference. Here’s our next talk – Craftsmanship, by Chris Wagner – I hope you enjoy!


Transcript

Craftsmanship. What do you think of when you hear that word?

Maybe what an artisan or an artist does, or maybe a skill in any craft? If that’s what you were thinking, then you were spot on with the definition according to some.

If you’re like me, you’re not very good at precise definitions. Maybe you’ve pictured an image in your mind instead. When I think of craftsmanship, I envision:

Clean lines

Screen Shot 2015-04-17 at 5.53.34 PM

Attention to detail

One Helluva pumpkin!

Things created with passion

Screen Shot 2015-04-17 at 5.53.38 PM

I want to tell a story about the first time that I recall noticing craftsmanship with regard to computers.

When I was a teenager, I started building computers and I would piece together different parts that I could afford or things my Dad had lying around the house, and it was fun. I was proud of what I was doing. It was rewarding.

I became pretty good at what I was doing, at least others assured me that I was, and it wasn’t long until people started asking me for help with their computer problems. One time my Dad came to me and he said that his friend needed help with his computer.

Screen Shot 2015-04-17 at 5.53.47 PM

Mind you, most of what I had learned at that point was from my Dad, so in hindsight, there was no reason he needed me to help him. He could probably do it on his own. This was probably one of those fatherly lessons you don’t realize occurred until later in life.

Anyhow, his friend had just bought a top tier Alienware computer.

Screen Shot 2015-04-17 at 5.53.52 PM

Now this was late 90s or early 2000s, so it was a big deal. These things were expensive.

What he needed help with was transferring the files from his old computer to the new one.

My Dad and I decided we’d pull out the old hard drive, put it in the new computer and do the transfer that way. Not many people had networks back then and they were pretty slow to be honest.

We cracked open that old computer. I can’t remember what it was, maybe a Packard Bell or a Compaq, and it was a mess.

Screen Shot 2015-04-17 at 5.53.55 PM

Not just a dusty mess, but the wiring inside looked no better than something that I had built before myself, but that was normal, right?

We got the drive out and it was time to open up the Alienware tower. We weren’t prepared for what we were about to behold.

In Awe Of The Alien

We didn’t even need a screwdriver. It had thumb screws on the back. Pretty neat. No more stripped screws. The side panel just slid right off, revealed the components that you needed access to. Wow!

After carefully removing the side panel and revealing the internals, I’m pretty sure we both gasped.

Holy Craftsmanship Batman!

Holy Craftsmanship Batman!

It was gorgeous. At first glance, I don’t think we even saw a cable. Everything was cleanly routed and zip-tied in place.

It was very clear that somebody had made a deliberate decision that these computers would be built with craftsmanship.

It’s Hard To Find the Time

This brings me back to my part about this computer being expensive. Things of high craftsmanship intrinsically cost more to make.

To make great things, you must have great skill and a great amount of time.

hourglass

Today, I’m here to inspire you to continue or to start practicing and exuding craftsmanship.

In almost every case, when we start a new project, we set out to do the right things or fully unit test or just not that again. We have green pastures, the sun is bright, and the world’s our oyster.

green_pasture

Then comes crunch time. It’s time to ship, the deadline’s approaching, your significant other has told you for the last time it’s time to leave, they’re pulling out the driveway, and you’re frantically typing that last line of code.

Whatever it may be, oftentimes we forget about what we set out to do. We get overwhelmed and we rush ourselves.

Then, we let the cows into our green pastures, they eat all the grass and shit everywhere.

cows

But you’ll clean it up later, right? Right?

Yeah, I didn’t think so.

As programmers, it’s easy for us to let our code get sloppy because the end user will never see that source code anyway. As far as they know, the code is a bunch of incoherent symbols and squiggly lines.

I would argue that this is the driving factor for the level of apathy that I’ve witnessed when it comes to writing beautiful code.

Finding The Time Is Worth It!

There’s a biography that came out about four years ago called Steve Jobs and I’m sure most of you are familiar with Steve.

steve_jobs_cover

He had an unwavering stance on quality and craftsmanship, and in the biography he attributes that to his adoptive father. He says:

“He loved doing things right. He even cared about the look of the parts you couldn’t see.”

–Steve Jobs

The parts you couldn’t see. Sounds like our jobs, right? We’re constantly working on the parts that nobody’s going to see.

The people that built that Alienware computer were working on the parts that most people wouldn’t see.

Do you know what happens when you focus so much energy on the parts that no one sees?

That energy is amplified on the parts they will see.

Screen Shot 2015-04-17 at 5.54.23 PM

Your pride for the resulting product is also amplified. You’ll be proud to show people what you’ve done and you’ll be confident in what you’ve done.

Have You Experienced Bad Code?

Some of you may be indie, you aren’t working on a team, or have an inherited project before, but for most I suspect that you have. You’ve walked into somebody else’s code before and you probably looked at it and asked yourself, “What the heck?”

Let’s enjoy this one for a little bit.

for (NSInteger i = 0; i < 3; i++) {
  switch(i){
  case 0:
    label0.text = title0:
    break;
  case 1: 
    label1.text = title1;
    break;
  case 2: 
    label2.test = title2;
    break;
  }
}

It’s a for switch loop. Makes sense, right? :P

Sometimes you’ve inherited a project that won’t even run without some voodoo scripts you had to find yourself, or some tribal knowledge that you had to hunt around the office for.

How many times have you run across a class with a single method, it’s 200 lines long and it’s 200 columns wide, you know the ones that look they’re playing Flappy Bird if you turned it on its side?

flappy_felipe

The people that wrote those things are by no means dumb. We’ve all been there. You’re quickly prototyping something and you try new things until it works. I don’t’ see anything wrong with that.

Where things go wrong is when you don’t go back and clean up what you’ve created and encapsulate that logic into small, easy to consume pieces that you can test.

How Good Code Can Happen

I like this quote by Ken Auer that describes the three phrases that you should take when crafting software,

“Make it run. Make it right, and make it fast.”

–Ken Auer

  • Make it run is a stage where you’re trying things out. You’re just hacking away, you’re not quite sure what you’re doing. You’re just playing around and you’ve got things commented out, all jammed into one method.
  • Make it right is where you take what you’ve learned, encapsulate that into small methods, classes, using architecture and make it easy to read for “future you” whether future you is actually you or your replacement.
  • Make it fast is where you worry about performance. Now that all your routines are neatly packed away, you can profile them and use instruments like a true craftsman, and you can make isolated changes without breaking things.

Oftentimes we stop after make it run. I think it’s time to stop stopping.

Find Balance By Setting Clear Expectations

Now you may complain there’s no way that I can make it right and make it fast. My boss is nagging me, deadline’s approaching, or if I spend all of my time making it right and making it fast, that’s going to take up too much time.

You expect what now?

You expect what now?

Time is money, and I get it. I’ve been there. We all have.

Craftsmanship’s not just about creating great things. It’s about knowing your craft and its limits so that you can clearly understand what can and cannot be done.

Set expectations with:

  • yourself
  • your peers
  • your boss
  • your client or customer

That’s all part of the craft.

No one’s going to be happy when you ship something and it falls on its face. Be clear with everyone involved about what can and can’t actually be done, and if anything changes in the process, make everyone aware.

Craftsmanship Is Appreciated

Let’s take a moment to step outside of the computer programming world and talk about consumer retail space. Now over the past few years, I’ve noticed a trend.

Now this may vary depending on where you’re from, but what I’ve noticed here in the States is people are starting to appreciate handcrafted goods.

  • Craft beer brewing has exploded. The mass beer producers are being hit hard as consumers prefer local brews.
  • Alternate coffee brewing methods are becoming popular.
  • Etsy.com, a website for handmade and vintage goods, reported over $1 billion in sales in 2013.

People are flocking to handcrafted merchandise and they’re staying away from the big box stores.

The prices for goods on Etsy are nowhere near as competitive as the big box stores. Coffee typically is 2 times as expensive, and maybe upwards of 10 times as expensive for those special beans.

The craft beers are typically 2 to 4 times as expensive as the mass-produced competitors.

beers

People appreciate craftsmanship and people pay a premium for craftsmanship.

If John Lennon Wrote Code

Let’s think about this for a moment. What would a world of craftsmanship as far as programming goes look like?

Consider every library on GitHub that’s reached it’s self-proclaimed Version 1.0.

Imagine a world where all of those libraries are fully unit tested, a world where 90% of their methods are less than 15 lines of code. Every public API is well-documented, and there’s a clear readme with a getting started tutorial.

Imagine a world where the difficult questions on Stack Overflow are answered rather than the simple ones being cherry-picked by point seekers.

Imagine all the coders sharing all the world

Imagine all the coders sharing all the world. You-ooooo-oo-oo-oooo…

Imagine a world where you start at a company and you check out the source code, and you can build and run with a couple of commands.

Imagine a world where every developer on the team consciously respects and follows the style guide.

Imagine a world where craftsmanship programmers are the norm. They

  • Are appreciated by their employers
  • Are paid well
  • Can survive the app store

This is a good world. I like this world and I think you would too.

The Trap Of Thinking Craftsmanship is Optional

Well-crafted things are often considered a luxury and I’ll agree with that. What I won’t agree with, though, is that shoddy software is acceptable.

Prototype’s fine, I won’t argue there. Proving a point, again, hack away, but when you’re shipping a product that people depend on, give them your best.

I would wager that the reason people are apprehensive to buy apps on the apps store is they’re not confident in the developer or the company behind them. They don’t know if what they’re getting is built with craftsmanship or that it’s high quality.

Maybe we can change that perception.

Screen Shot 2015-04-26 at 7.49.26 PM

You may be working on products that have a short life span or have a small amount of users, and you might think it’s okay to cut some corners here or there.

But remember that when you do anything, you’re building up tolerance and you’re creating habits. Eventually you’ll have cut that corner 5 times and it went all right so why not just keep doing so?

Our Responsibility as Software Architects

How would you feel if a civil engineer thought that way when they were designing a bridge that you drive your family across?

bridge

How would you feel if corners were cut by an aerospace engineer designing a commercial airliner that your parents might use to fly to you for the holidays?

Engineering is a huge responsibility. Society depends on engineers to do the right thing and to do it well.

As software engineers, we may not building applications that can directly harm somebody or maybe we never will, but we’re constantly working with other software engineers that we influence, and someday they might.

As we move further into the future, software is arguably becoming the crux of how our world operates. Just some examples:

  • Robotics are beginning to take over jobs that humans used to do.
  • Cars are starting to drive themselves.

google_car

Engineers of all disciplines are using software to design bridges, buildings, vehicles, what have you. There are so many lives that depend on software now and even more that will in the future.

Software architects are designing and building the pillars for which our society stands on.

pillars

From now on, when you’re writing code, I hope that you think of it in terms of craftsmanship.

Whether you’re heading down the road, starting a new project, or working on an existing one, take pride in what you’re doing. Don’t skimp on the parts that you think nobody’s going to see.

You’ll never know who’s going to crack open that Alienware box of your code and walk away inspired.

Note from Ray: Did you enjoy this inspiration talk? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2016 tickets go on sale!

RWDevCon Inspiration Talk – Craftsmanship by Chris Wagner is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk – Craftsmanship by Chris Wagner appeared first on Ray Wenderlich.

Core Data by Tutorials Updated for Swift 1.2!

$
0
0

CDT-Thumb

Good news – the Core Data by Tutorials Team has updated Core Data by Tutorials for Swift 1.2!

As you may know, Swift 1.2 introduced some new syntax, such as an improved if let statement, revised usage of as vs as! vs as?, and a native Set type. To learn more about these changes, check out our What’s New in Swift 1.2 overview.

In this update, the team has updated all chapters and sample code to use the new Swift 1.2 syntax, and have also fixed some of the errata reported on the forums.

Here’s how you can get the update:

  • If you’re a Core Data by Tutorials PDF customer, you can download the 1.2 update for free on your My Loot page.
  • If you’re a Core Data by Tutorials Print Version customer, you can find the updated source code at the URL given in the introduction of the book.
  • If you don’t have the Core Data by Tutorials yet, grab your copy now!

We hope you enjoy this update!

Core Data by Tutorials Updated for Swift 1.2! is a post from: Ray Wenderlich

The post Core Data by Tutorials Updated for Swift 1.2! appeared first on Ray Wenderlich.

Video Tutorial: Unity Basics Part 0: Introduction

Video Tutorial: Unity Basics Part 1: User Interface

Viewing all 4370 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>