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

RWDevCon Inspiration Talk – Teamwork

$
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 first talk – on Teamwork, by myself – I hope you enjoy!


Transcript

Where were you when the Apollo 11 landed on the moon?

Where were you when the Apollo 11 landed on the moon?

People who are born before the 1960s or so commonly ask each other, “Where were you when the Apollo 11 landed on the moon?”

However, we, as iPhone developers have a different question. “Where were you when you got your first iPhone?”

I vividly remember when I first got my iPhone and I’m sure all of you do as well. It was a magical experience. Once we realized that we could make apps for this and show them off to our friends and have anyone across the world download it, we were hooked.

A Feeling of Excitement in the Air

For many of us, this was around the year of 2009. At that time, apps look like this:

Keynote-1

And code looked like this:

Keynote-4

The App Store was only one year old and we were in the middle of the great App Store gold rush. It seemed like everybody had the next great app idea.

Believe it or not, the guy that made this fat app made millions and we all wanted to be just like him.

Keynote-3

There was this feeling of excitement in the air that inspired many of us to become full time iOS developers.

One of the first books on iPhone programming, Beginning iPhone Development by Dave Mark and Jeff Lamarche, summed up this feeling of excitement in the air really well. In its preface, it said:

“I haven’t been this excited about a programming platform since the first time I laid eyes on a Mac. The world is just beginning to open up.”

–Dave Mark and Jeff LaMarche

Who here remembers that feeling when your first app was accepted on to the App Store? Wasn’t that an incredible feeling of accomplishment?

It was addicting and so we kept making apps. Our iOS community continued to grow, and before long, many of us started to make a full time living as indie iPhone developers making our own apps.

The Indiepocalypse

Fast forward to 2015. There aren’t that many indies left anymore. We call this the indiepocalypse and there’s been a lot of discussion about this from all of us on the iOS community over the last few months.

It all started when Jared Sinclair, a well known indie iPhone developer, released the sales numbers for his most recent app which were well below his expectations.

UnreadSales

Soon, others started releasing the sales numbers for their apps and they were equally disappointing. The sense of doom and gloom started coming over the community. We started asking ourselves, “What happened? Where’d all the indies go?”

What happened is as the App Store has matured over the years, developers have started shifting from individuals to teams. By nature, teams can accomplish a lot more than individuals which makes it very hard for an individual to compete.

  • Logically, we know, in order to compete in such a market, we be best served by either joining or making teams of our own.
  • However, emotionally, it’s not that easy, because we have these feelings and fears standing in our way.

Feelings and Fears

First, there’s feelings. As developers, we’re used to working alone and we like it that way. We sometimes think, “I can do it best. I want to do all the work so it’s done right. I want things my way. I want all the credit and I want all the rewards. Mine, mine, mine.” Not very admirable is it, but it’s true. We’ve all felt that way sometimes.

Second, there’s fears. Sometimes, we’re afraid to be a part of a team. We sometimes think, “I’m afraid my teammates won’t work as hard as me. Or I’m afraid my teammates will mess up the vision I have for this project. Or I’m afraid of being a small cog in a grand machine.” I think these feelings and fears, we can’t let them paralyze us, because if we do, we can miss out on a great opportunity.

An Indie Story

Consider for a moment the story of an indie iPhone developer who almost missed out on the greatest opportunity of his entire life.

Typical business plan in 2009.

Typical business plan in 2009.

It all started back in that magical time we were talking about of the 2009. This developer decided to quit his job and become an iPhone developer. He was convinced he had the next great App Store idea and was going to become the next App Store millionaire.

Here’s what the app looked like:

Keynote-5

I think I just heard Jony Ive cry. It looked pretty terrible. There wasn’t much to it and sadly it did not earn this developer his million dollars.

But he learned a lot doing it, he had a lot all along the way and he kept making apps. He was on the right place at the right time, so after about a year of doing this, he was lucky enough to be making a full time living as an indie iPhone developer.

About the same time, this developer started a blog, and the blog started to become popular. He realized he needed some help to take this to the next level, but this guy was one of those darned introverts I was telling you about.

What is an introvert to do?

What is an introvert to do?

Every time he would think about getting some help, he would make a million excuses as to why that was a horrible idea.

He would say, “No, I should just do it myself and that way it will be done right. Or, no, I’ll never be able to find anyone to help. Or, no, I can’t afford it.” Or a million other excuses. If this developer had it his way, it would still be that little blog that it was back then.

But luckily, this developer had a wife who is much smarter than he was and one day she sat him down and said:

“Listen, you need to either get some help or you need to shut down this blog.”

–A smart wife

Luckily, this guy was just smart enough to listen to his wife, so he did. He started looking for some people to work with and he found these incredible team and together they were able to take things much further than he ever could have on his own.

More importantly, he stopped thinking of himself as an indie iPhone developer and instead, he started thinking about himself as part of a great team.

Now, I’m sure many of you have guessed that this former indie iPhone developer I’m talking about is me:

App Store Income, 2009.

App Store Income, 2009.

I remember those $6 fondly. I think that was my entire income of 2009!

But that means that the great team I’m talking about is the raywenderlich.com team. By being a part of this great team, it has changed my life and ways I never would have imagined. I’ve gotten so many more benefits from being a part of this great time than I ever could have gotten as an individual.

Being a Part of a Great Team: 3 Benefits

Today, I like to share with you three of the benefits that you can get by being a part of a great team.

  1. First, when you’re part of a great team, we have this incredible feeling of camaraderie and fun. When we’re part of a great team, we get to hang out with our teammates, talk about geeky stuff, ask questions about bugs we’re working on, even Photoshop each other’s faces on silly pictures.
    The Backstreet Coders!

    The Backstreet Coders!

    It really makes you feel connected, appreciated and part of a tight-knit crew. Recognize any of these guys? They’re here.

  2. Second, just like we have our own personal reputations, teams have reputations too. By being a part of a great team, we can benefit from that reputation. Great teams have reputation for doing something really well whether it’s making great apps, making great open source software, or making great tutorials.


    Great teams hold each other to this high quality standard by giving each other feedback both in terms of what we did well and what we can improve upon in the future. This helps us improve both our personal and our team reputation.

  3. Third, and this one is the most important to me. Teamwork lets you dream bigger. As individuals, we thought in terms of making apps. As a team, we think in terms of making businesses. As individuals, we thought in terms of hosting meetups. As a team, we think in terms of hosting conferences. Teamwork expands the scope of what’s possible. Teamwork lets you dream bigger.

What Does This Mean to You?

What does this mean to all of you right now?

Indie Developers

I know there’s a few of you in this room who are currently indie iPhone developers or independent contractors. By indie, I mean one person, totally on your own. Can I have the indies in the room raise your hand? Okay, fair amount.

First of all, congratulations. It is not easy doing what you’re doing especially in this market and not a lot of people can do what you’re doing, but just because you can be successful all on your own, doesn’t necessarily mean that’s the best thing for you.

I encourage all the indies out there to at least consider teaming up with somebody else on a future project of yours, somebody who’s just as passionate about what you’re working on. Somebody who brings just as many skills to the table. Who knows what you might be able to accomplish together.

Those who are Happy with their Team

Most of us in this room are already part of a team, but there’s two cases, right? Either we’re happy with our team and we’re getting some of the benefits that we’ve just talked about or we’re not so happy with our team. So let’s talk about both of these cases.

Say you’re happy with your team. I encourage you to just take a moment and appreciate what you have, because I don’t want us to just have being an indie iPhone developer as the only thing we have up here on this pedestal as the one thing that we all look up to and admire and wish we could be and as the one benchmark we have for our success.

I also want us to put being a part of a great team right up there with them, because it’s just as challenging. It’s just as important, and you get just as many benefits, if not more so.

2 Pillars for Success

2 Pillars for Success

Take a moment and appreciate the great things you’re able to accomplish with a group of people working together toward a common goal. Also think to yourself how can you take that great team and make it even greater.

Those Who Are Not Happy with their Team

What about those of you who weren’t so happy with your team? For those of you, I encourage you to think how can you make your team into what it can be and what it should be. How can you build that sense of belongingness. How can you improve your team’s reputation. How can you begin to dream bigger.

Now, I know what some of you were thinking. You’re thinking, “Ray, you just don’t understand, okay? My boss is an idiot. My clients are clueless. The guy next to me all he knows is Fortran.” I know that some teams are going to be more challenging than others, but I would argue they’re still a lot you can do.

Let me share with you a few ideas just off the top of my head.

Do something silly!

Do something silly!

  • You could try to convince your team to code according to a common style guide.
  • You can start code reviews on your team if you’re not doing that already.
  • You could do something silly like Nerf gun wars or singing a silly iPhone Christmas song or anything to build that sense of camaraderie across your team.
  • You could start some periodic tech talks with your team to share some knowledge, maybe at lunch time.
  • You could start a team chat room so you can, hang out, ask questions and have fun.
  • You can start a board game group at lunch time.
  • You could appreciate your team when they do something well.
  • You can listen to your team. They often have the very best ideas.

These are just the few of the ideas I have. I’m sure you could come up with much better ones. You’re also going to get a lot more ideas from the inspiration talks at this conference.

The important thing isn’t necessarily what idea you choose, is that you try to do something. You see how it goes, you use that feedback to rinse and repeat. That is the power of iteration.

As you do this, this is going to become contagious. Your teammates will see you doing this and they’re going to start using the power of iteration too. Before long, you will go from an okay team to a great team. I truly believe no matter what our situation, we have the power to transform our teams into something incredible. Let’s make the most of it.

One More Team

Aside from our day jobs, there’s one more team that all of us here are a part of today; the iOS community. As iOS developers, we are extremely lucky because we are a part of the best community of developers that has ever existed. Before I go any further, could I just get a round of applause for the iOS community? That’s all of you guys.

We are a part of a great team and as a great team, we have a great reputation that we all benefit from of being incredibly open, supportive of each other, sharing of our hard one knowledge. We all contribute to this community in different ways.

Different Ways to Contribute

Different Ways to Contribute

Some of us write open source code. Some of us go to local meetups. Some of us answer questions on Stack Overflow. Some of us go to podcasts and some of us write blog posts.

Some of us are beginners and we’re not doing this yet, but that’s okay, because we will. As we improve our knowledge and skills, we will naturally find ourselves contributing back later. That is what the iOS community is all about and that is why I feel so lucky to be a part of this community.

Don’t Miss it All

Back in 2009 when I was an indie iPhone developer, I never would have imagined that I’d be here with the iOS community, with all of you making this conference happen today.

If I continued walking on that road that I was walking alone, I would have missed it all. Don’t fall into the same trap I almost did of being left alone on a side of the road with your feelings and your fears.

Instead, I encourage you to consider. What are the teams you could join or the teams you could make? What are the great things you could create together and how could you change your life and the lives of others?

As you begin to do this and you begin to make your wildest dreams become a reality just like in the preface of Dave and Jeff’s programming book, you’ll feel the world begin to open up.

It’s 2015 and to me, there’s still this feeling of excitement in the air more so than ever, because I truly believe with a spirit of friendship and cooperation, we can do anything.

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 – Teamwork is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk – Teamwork appeared first on Ray Wenderlich.


Video Tutorial: Custom Collection View Layouts Part 0: Introduction

Video Tutorial: Custom Collection View Layouts Part 1: Pinterest – Basic Layout

Reminder: Free Live Tech Talk (View Debugging with Xcode and Reveal) Tomorrow (Tuesday)!

$
0
0
Free live tech talk (View Debugging with Xcode and Reveal) tomorrow!

Free live tech talk (View Debugging with Xcode and Reveal) tomorrow!

This is a reminder that we are having a free live tech talk on View Debugging with Xcode and Reveal tomorrow (Tuesday Mar 17, and you’re all invited! Here are the details:

  • When: Tuesday, Mar 17 at 2:00 PM EST – 3:00 PM EST
  • What: View Debugging w/ Xcode and Reveal followed by live Q&A (come w/ questions!)
  • Who: Tech Editors and Tutorial Team Members Scott Berrevoets and Erik Kerber
  • Where: Google Hangouts Event Page
  • Why: For learning and fun!
  • How: Visit the event page and a video URL should be posted. Follow the instructions there to submit your Q&A (via text) as the talk runs.

We hope to see some of you at the tech talk, and we hope you enjoy!

Reminder: Free Live Tech Talk (View Debugging with Xcode and Reveal) Tomorrow (Tuesday)! is a post from: Ray Wenderlich

The post Reminder: Free Live Tech Talk (View Debugging with Xcode and Reveal) Tomorrow (Tuesday)! appeared first on Ray Wenderlich.

Developing for Android with Darryl Bayliss – Podcast S03 E09

$
0
0
Learn about developing for OS X with Mike Daley!

Learn about developing for OS X with Mike Daley!

Welcome back to season 3 of the raywenderlich.com podcast!

In this episode, we’ll chat with tutorial team member Darryl Bayliss about developing for Android.

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

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

Links and References

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. Stay tuned for a new episode 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 in future episodes. Feel free to drop a comment here, or email us anytime at podcast@raywenderlich.com!

Developing for Android with Darryl Bayliss – Podcast S03 E09 is a post from: Ray Wenderlich

The post Developing for Android with Darryl Bayliss – Podcast S03 E09 appeared first on Ray Wenderlich.

View Debugging with Xcode and Reveal Tech Talk: Rescheduled

Video Tutorial: Custom Collection View Layouts Part 2: Pinterest – Layout Attributes

Introduction to MapKit in Swift Tutorial

$
0
0
Plot Honolulu public artwork data using MapKit!

Plot Honolulu public artwork data using MapKit!

Update note: Audrey Tam updated this tutorial to Swift and iOS 8. Original post by Ray Wenderlich. Ray’s original tutorial queried and retrieved data from the Baltimore web service but the code broke when the web service made minor changes, so this update uses a static JSON file downloaded from the Honolulu data portal.

MapKit is a really neat API available on iOS devices that makes it easy to display maps, jump to coordinates, plot locations, and even draw routes and other shapes on top.

This update uses public artworks data from Honolulu, where I was born and raised. It’s no longer my hometown but the names and places bring back memories. If you’re not lucky enough to live there, I hope you’ll enjoy imagining yourself being there!

In this tutorial, you’re going to make an app that zooms into a location in Honolulu, and you’ll plot one of the artworks on the map. Just for fun, you’ll implement the pin’s callout detail button to launch the Maps app, with driving/walking directions to the artwork. Your app will then parse a JSON file from a Honolulu data portal, find the public artworks around that area, and plot them on the map.

In the process, you’ll learn how to add a MapKit map to your app, zoom to a particular location, parse government data that uses the Socrata Framework, create custom map annotations, and more!

This tutorial assumes some familiarity with Swift and iOS programming. If you are a complete beginner, you may wish to check out some of the other tutorials on this site.

Without further ado, let’s get mapping!

Getting Started

In Xcode, go to File\New\New Project, select iOS\Application\Single View Application, and click Next. Then type HonoluluArt as the project name. Set Language to Swift and select iPhone for the Devices option. Make sure that Use Core Data is unchecked, then click Next, and choose a directory to save your project in to finish.

Open Main.storyboard and, from the Object library, drag a Toolbar to the bottom of the screen, and a MapKit View above the Toolbar. In the Attributes Inspector, change the Toolbar Item‘s Identifier to Refresh, as shown in the screenshot below – the Item will become a Refresh button.

storyboardLayout

When you select the Toolbar Item, be careful not to select its Title by double-clicking on it, or you’ll only change its Title and not its Identifier.

Note: It’s important to add the Toolbar first and then the MapKit View, because if you do it that way ’round you’ll notice that the MapKit View automagically takes up the remaining space. It’s as if Xcode is reading your mind!

To set the constraints to pin all the edges to the superview, so that your layout works for all the different screen sizes, click on the view controller icon then select Resolve Autolayout Issues\Reset to Suggested Contstraints from the lower All Views in View Controller section:

storyboardConstraints

Before you can run your code, you need to create an outlet for the map view in ViewController.swift, or else it will crash on startup!

The outlet’s type will be MKMapView, so you first need to add the MapKit framework to your project.

Open the Assistant editor: it should display ViewController.swift. Just below the import UIKit statement, add this line:

import MapKit

To create the outlet, click the Map View in Main.storyboard and control-drag from it into the space just inside the ViewController class definition: Xcode should prompt you to Insert Outlet or Outlet Collection. Release the drag and, in the pop-up window, name the outlet mapView:

storyboardOutlet

Xcode adds a mapView property to the ViewController class – you’ll use this to control what the map view displays.

While you’re here, delete the didReceiveMemoryWarning method; you won’t be needing it.

Build and run your project, and you’ll have a fully zoomable and pannable map showing the continent of your current location, using Apple Maps!

run1

So far so good, eh? But you don’t want the map to start looking at the entire world – you want to take a look at a particular area!

Setting Visible Area

In ViewController.swift, add the following property to the class:

let searchRadius: CLLocationDistance = 1000

This simply creates a constant for the search radius that you’ll be using later: 1000 meters (1 kilometer), which is a little more than half a mile.

Next, find viewDidLoad and add the following to the end of the method:

// set initial location in Honolulu
let initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)

This will set the the starting coordinates of the map view to a point in Honolulu.

When you are trying to tell the map what to display, you can’t just give a latitude and longitude. That’s enough to center the map, but you need to specify the rectangular region to display to get a correct zoom level too.

Add the following helper method to the class:

func centerMapOnLocation(location: CLLocation) {
  let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 
    searchRadius * 2.0, searchRadius * 2.0)
  mapView.setRegion(coordinateRegion, animated: true)
}

The location argument is the center point. The region will be have north-south and east-west spans based on a distance of searchRadius. You use searchRadius * 2.0 here, because that works well for plotting the public artwork data in the JSON file.

setRegion tells the mapView to display the region. The map view automatically transitions the current view to the desired region with a neat zoom animation, with no extra code required!

Back in viewDidLoad, add the following line to the end of the method:

centerMapOnLocation(initialLocation)

This will call the helper method to zoom into initialLocation on startup.

Build and run the app, and now it should zoom in to the heart of Waikiki :]

run2

Obtaining Public Artworks Data

The next step is to plot some interesting data around the current location. But where in the heck can we get such stuff?

Well, it depends on your current location. Honolulu, like many cities, has an Open Data Portal to improve public access to government data. Like many cities, Honolulu’s data portal is “Powered by Socrata“, an open data framework which provides a rich set of developer tools for accessing Socrata-based data. After you finish this tutorial, maybe look around to see if a nearby city has an alternate dataset you can use?

For this tutorial, you’ll be using the Honolulu Public Art dataset. To keep things simple, I have already downloaded this data from the portal for you – download the HonoluluArtResources.zip file here. Unzip it to find two files: PublicArt.json and JSON.swift. You’ll use JSON.swift later in this tutorial, to parse PublicArt.json.

When you have the PublicArt.json file, drag it into your HonoluluArt\Supporting Files group, make sure Destination: Copy items if needed and Add to targets: HonoluluArt are selected, and click Finish.

To get a feeling for the items in this dataset, open PublicArt.json in the Xcode editor and scroll down to line 1180 (or use ⌘ + L for Jump to Line), which begins with "data" followed by an array of arrays – one array for each artwork. For this tutorial, you’ll use only a few properties from each array: the artwork’s location name, discipline, title, latitude and longitude. For example, for the first data item:

  • location name: Lester McCoy Pavilion
  • discipline: Mural
  • title: The Makahiki Festival – The Makai Mural
  • latitude: 21.290824
  • longitude: -157.85131

Later in this tutorial, you’ll parse this dataset to create an array of Artworks but first, to jump straight into the MapKit fun, you’ll just plot one of the artworks on the map.

Showing an Artwork on the Map

In PublicArt.json, scroll down further to item 55 at line 1233 (or use ⌘ + L for Jump to Line) – it’s a bronze statue of King David Kalakaua in Waikiki Gateway Park – ah, can you hear the tradewinds sighing through the palm trees?

KingKalakaua

Photo of King David Kalakaua statue, by Wally Gobetz

The properties for this item are:

  • location name: Waikiki Gateway Park
  • discipline: Sculpture
  • title: King David Kalakaua
  • latitude: 21.283921
  • longitude: -157.831661

To show this on the map view, you must create a map annotation. In the context of MapKit, annotations are small pieces of information tied to a particular location and are most often represented as the little pins that show up in the Maps app.

Creating your own annotations is easy. All you need is a class that conforms to MKAnnotation, add the annotation to the map, and inform the map how the annotation should be displayed.

Begin with step 1: create an Artwork class in a new Swift file. To specify the new file’s position in the Project Navigator, select ViewController.swift, so the new file will appear below this. Next, go to File\New\New File, choose iOS\Source\Swift File, and click Next. Set the Save As field to Artwork.swift and click Create.

Open Artwork.swift in the editor and add the following, below import Foundation:

import MapKit
 
class Artwork: NSObject, MKAnnotation {
  let title: String
  let locationName: String
  let discipline: String
  let coordinate: CLLocationCoordinate2D
 
  init(title: String, locationName: String, discipline: String, coordinate: CLLocationCoordinate2D) {
    self.title = title
    self.locationName = locationName
    self.discipline = discipline
    self.coordinate = coordinate
 
    super.init()
  }
 
  var subtitle: String {
    return locationName
  }
}

This is a plain old NSObject with a special initializer. Note it marks itself as implementing the MKAnnotation protocol. This means that the coordinate property is required. If you want the annotation view to display a title and subtitle when the user selects a pin, the class also needs properties named title and subtitle.

It’s perfectly sensible for the Artwork class to have stored properties named title and coordinate but none of the PublicArt.json properties maps naturally to the idea of “subtitle”. To conform to the MKAnnotation protocol, subtitle is a computed property that returns locationName.

OK, so the title, locationName and coordinate properties will be used for the MKAnnotation object, but what’s the discipline property for? You’ll find out later in this tutorial ;]

On to step 2 – add an instance of the Artwork class for every artwork you want to plot. You’re adding only one artwork to the map so add the following lines to the end of viewDidLoad in ViewController.swift:

// show artwork on map
let artwork = Artwork(title: "King David Kalakaua",
  locationName: "Waikiki Gateway Park", 
  discipline: "Sculpture",
  coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
 
mapView.addAnnotation(artwork)

This creates a new Artwork object and adds it as an annotation to the map view. The MKMapView class also has an addAnnotations method, which you’ll use later in this tutorial, when you have an array of annotations to add to the map view.

OK, on to the third and final step: providing the map with the information it needs to display the annotation! To do so, the map view will call its viewForAnnotation delegate method. Your job in this delegate method is to return an instance of MKPinAnnotationView to present as a visual indicator of the annotation.

In this case, your ViewController will be the delegate for the map view. To avoid clutter and improve readability, you’ll create an extension of ViewController in a separate file.

Create a new Swift file: go to File\New\New File, choose iOS\Source\Swift File, and click Next. Set the Save As field to VCMapView.swift and click Create. Then add the following, below import Foundation:

import MapKit
 
extension ViewController: MKMapViewDelegate {
 
  // 1
  func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
    if let annotation = annotation as? Artwork {
      let identifier = "pin"
      var view: MKPinAnnotationView
      if let dequeuedView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
        as? MKPinAnnotationView { // 2
        dequeuedView.annotation = annotation
        view = dequeuedView
      } else {
        // 3
        view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        view.canShowCallout = true
        view.calloutOffset = CGPoint(x: -5, y: 5)
        view.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as UIView
      }
      return view
    }
    return nil
  }
}

This code isn’t too complicated, but here’s a quick breakdown:

  1. mapView(_:viewForAnnotation:) is the method that gets called for every annotation you add to the map (kind of like tableView(_:cellForRowAtIndexPath:) when working with table views), to return the view for each annotation.
  2. Also similarly to tableView(_:cellForRowAtIndexPath:), map views are set up to reuse annotation views when some are no longer visible. So the code first checks to see if a reusable annotation view is available before creating a new one.
  3. Here you use the plain vanilla MKAnnotationView class if an annotation view could not be dequeued. It uses the title and subtitle properties of your Artwork class to determine what to show in the callout – the little bubble that pops up when the user taps on the pin.

Note: One extra thing to point out about this, suggested by Kalgar, when you dequeue a reusable annotation, you give it an identifier. If you have multiple styles of annotations, be sure to have a unique identifier for each one, otherwise you might mistakenly dequeue an identifier of a different type, and have unexpected behavior in your app. It’s basically the same idea behind a cell identifier in tableView(_:cellForRowAtIndexPath:).

All that’s left is setting ViewController as the delegate of the map view. You can do this in Main.storyboard, but I prefer to do it in code, where it’s more visible. In ViewController.swift, add this line to viewDidLoad, before the statement that creates artwork:

mapView.delegate = self

And that’s it! Build and run your project, and now you should see where King David Kalakaua’s statue is, at the gateway to Waikiki!

run3

mapView(_:viewForAnnotation:) configures the callout to include a detail disclosure info button on the right side but tapping that button doesn’t do anything yet. You could implement it to show an alert with more info, or to open a detail view controller. In Swift By Tutorials, the TreasureHunt app in Chapter 3 shows an alert, and the CafeHunter app in Chapter 8 opens a detail view controller.

Here’s a neat third option: when the user taps the info button, your app will launch the Maps app, complete with driving/walking directions to get from the simulated user location to the artwork!

Launching the Maps App

To provide this great user experience, open Artwork.swift and add this import statement, below the other two import statements:

import AddressBook

This adds the AddressBook framework. What does the address book framework have to do with maps, you might ask? Well, it contains some dictionary key constants such as kABPersonAddressStreetKey for when you need to set the address or city or state fields of a location.

Next, add the following helper method to the class:

// annotation callout info button opens this mapItem in Maps app
func mapItem() -> MKMapItem {
  let addressDictionary = [String(kABPersonAddressStreetKey): subtitle]
  let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: addressDictionary)
 
  let mapItem = MKMapItem(placemark: placemark)
  mapItem.name = title
 
  return mapItem
}

Here you create an MKMapItem from an MKPlacemark. The Maps app is able to read this MKMapItem and display the right thing.

Next, you have to tell MapKit what to do when the callout button is tapped. To do so, open VCMapView.swift and add this method to the MKMapViewDelegate extension:

func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, 
    calloutAccessoryControlTapped control: UIControl!) {
  let location = view.annotation as Artwork
  let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
  location.mapItem().openInMapsWithLaunchOptions(launchOptions)
}

When the user taps a map annotation pin, the callout shows an info button. If the user taps this info button, the mapView(_:annotationView:calloutAccessoryControlTapped:) method is called.

In this method, you grab the Artwork object that this tap refers to and then launch the Maps app by creating an associated MKMapItem and calling openInMapsWithLaunchOptions on the map item.

Notice you’re passing a dictionary to this method. This allows you to specify a few different options; here the DirectionModeKeys is set to Driving. This will make the Maps app try to show driving directions from the user’s current location to this pin. Neat!

I suggest you take a look at the various different options you can pass in the launch options dictionary. Also take a look at the MKMapItem class method that allows you to pass multiple MKMapItem objects at the same time.

Before you build and run, it is a good idea to simulate your location to Honolulu. In Xcode, go to Product\Scheme\Edit Scheme… and select Run from the left menu, then select the Options tab. Check Core Location: Allow Location Simulation and select Honolulu, HI, USA as the Default Location. Then click the Close button:

defaultUserLocation

Build and run the app and you’ll see the map zoom in on Waikiki:

run4a

Note: The glowing user location dot might not appear until you stop and run your app again, or you might need to give it a nudge by selecting Apple from the simulator‘s Debug\Location menu, then stopping and running your app again.

Now tap on the pin, then tap the info button in the callout and watch it launch the Maps app to show the statue’s location, with driving directions to it. Click on the service station icon just to the left of your pin: Aloha!

run4b

This calls for a celebration – treat yourself to your favorite tropical drink!

Parsing JSON Data into Artwork Objects

Now that you know how to show one artwork on the map and how to launch the Maps app from the pin’s callout info button, it’s time to parse the dataset into an array of Artwork objects. Then you can search this array for objects that are in the current map region, and show them on the map.

First, find the JSON.swift file that was in the resources zip file along with PublicArt.json. JSON.swift contains a wonderful enumeration that makes JSON parsing a piece of cake. You can read all about it in Chapter 6 of Swift By Tutorials but basically, it provides a case for each type of JSON value, and a library of computed properties to extract the various values.

Add JSON.swift to the HonoluluArt group in the Project Navigator, then add this method to Artwork.swift, below the initializer:

class func fromJSON(json: [JSONValue]) -> Artwork? {
  // 1
  var title: String
  if let titleOrNil = json[16].string {
    title = titleOrNil
  } else {
    title = ""
  }
  let locationName = json[12].string
  let discipline = json[15].string
 
  // 2
  let latitude = (json[18].string! as NSString).doubleValue
  let longitude = (json[19].string! as NSString).doubleValue
  let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
 
  // 3
  return Artwork(title: title, locationName: locationName!, discipline: discipline!, coordinate: coordinate)
}

Just a few notes about this code:

  1. fromJSON‘s json argument will be one of the arrays that represent an artwork – an array of JSONValue objects. If you count through an array’s elements, you’ll see that the title, locationName etc. are at the indexes specified in this method. The title for some of the artworks is null so you test for this when setting the title value.
  2. This converts the string latitude and longitudes to NSString objects so you can then use the handy doubleValue to convert them to doubles.
  3. The computed string property from JSON.swift returns an optional string for locationName and discipline, which must be implicitly unwrapped when passing them to the Artwork initializer

In other words, the fromJSON method converts an array like this:

[ 55, "8492E480-43E9-4683-927F-0E82F3E1A024", 55, 1340413921, "436621", 1340413921, "436621", "{\n}", "Sean Browne",
"Gift of the Oahu Kanyaku Imin Centennial Committee", "1989", "Large than life-size bronze figure of King David Kalakaua
mounted on a granite pedestal. Located at Waikiki Gateway Park.", "Waikiki Gateway Park", 
"http://hiculturearts.pastperfect-online.com/34250images/002/199103-3.JPG", "1991.03", "Sculpture", "King David 
Kalakaua", "Full", "21.283921", "-157.831661", [ null, "21.283921", "-157.831661", null, false ], null ]

into an Artwork object like the one you created before:

  • locationName: “Waikiki Gateway Park”
  • discipline: “Sculpture”
  • title: “King David Kalakaua”
  • coordinate with latitude: 21.283921 longitude: -157.831661

To use the fromJSON method, open ViewController.swift and add the following properties to the class:

var artworks = [Artwork]()
var visibleArtworks = [Artwork]()

This will hold the Artwork objects from the JSON, as well as just the visible ones.

Next, add the following helper method to the class:

func loadInitialData() {
  // 1
  let fileName = NSBundle.mainBundle().pathForResource("PublicArt", ofType: "json");
  var readError : NSError?
  var data: NSData = NSData(contentsOfFile: fileName!, options: NSDataReadingOptions(0),
    error: &readError)!
 
  // 2
  var error: NSError?
  let jsonObject: AnyObject! = NSJSONSerialization.JSONObjectWithData(data, 
    options: NSJSONReadingOptions(0), error: &error)
 
  // 3
  if let jsonObject = jsonObject as? [String: AnyObject] {
    if error == nil {
      // 4
      if let jsonData = JSONValue.fromObject(jsonObject)?["data"]?.array {
        for artworkJSON in jsonData {
          if let artworkJSON = artworkJSON.array {
            // 5
            if let artwork = Artwork.fromJSON(artworkJSON) {
              artworks.append(artwork)
            }
          }
        }
      }
    }
  }
}

Here’s a run-down of what you’re doing in this code:

  1. Read the PublicArt.json file into an NSData object
  2. Use NSJSONSerialization to obtain a JSON object
  3. Check that the JSON object is a dictionary where the keys are Strings and the values can be AnyObject
  4. You’re only interested in the JSON object whose key is "data" and you loop through that array of arrays, checking that each element is an array
  5. Pass each artwork’s array to the fromJSON method that you just added to the Artwork class. If it returns a valid Artwork object, you append it to the artworks array.

Plotting the Visible Artworks

You now have an array of all the public artworks in the dataset but not all of them are located within searchRadius meters of the map view’s center location. You’ll add another helper method next to filter the full list of artworks to just the ones that are within the visible part of the map. In ViewController.swift, add the following method:

func fetchArtAroundLocation(location: CLLocation) {
  // 1
  var artworksHere = [Artwork]()
  // 2
  for artwork in artworks {
    let artworkLocation = CLLocation(latitude: artwork.coordinate.latitude, 
      longitude: artwork.coordinate.longitude)
    if  location.distanceFromLocation(artworkLocation) <= searchRadius {
      artworksHere.append(artwork)
    }
  }
  // 3
  mapView.removeAnnotations(visibleArtworks)
  visibleArtworks = artworksHere
  mapView.addAnnotations(visibleArtworks)
}

Let’s look at what you’re doing here:

  1. Create an initially empty working array artworksHere to keep track of artworks located within the search radius. At the end of this method, artworksHere is copied to visibleArtworks.
  2. Loop through the artworks array, looking for those that are located within the search radius and appending them to the working array artworksHere
  3. Remove the current annotations in visibleArtworks from the map view, copy the working array artworks to visibleArtworks, and add these annotations to the map view.

Soon, you’ll implement the Refresh button but for now, you’ll make a few changes so you can see fetchArtAroundLocation in action.

Under the lines in viewDidLoad that create initialLocation and center the map view there, add calls to loadInitialData and fetchArtAroundLocation:

loadInitialData()
fetchArtAroundLocation(initialLocation)

Comment out or delete the lines that create the single “King David Kalakaua” map annotation – you don’t need them, now that loadInitialData creates the artworks array:

//    let artwork = Artwork(title: "King David Kalakaua", locationName: "Waikiki Gateway Park",
//      discipline: "Sculpture", coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
//    mapView.addAnnotation(artwork)

Build and run your app and check out all the pins!

run5

Tap a pin to open its callout bubble, then tap its info button to launch the Maps app – yes, everything you did with the King Kalakaua statue works with all these new artworks!

The User Moves the Map…

With your app running, move the map around – there aren’t any pins outside of the initial map region, but I can assure you that there are artworks there. What you need is a way to tell the app to recalculate the visible artworks array and update the map view – that’s what the Refresh button is for.

You need to set up the Refresh button on the toolbar to call a method, so you know when it’s tapped and can search for the artworks around the new current location.

To do this, open Main.storyboard and the Assistant editor, select the Refresh button, and control drag from the button to ViewController.swift, to the line right after the fetchArtAroundLocation method – Xcode should prompt you to Insert Outlet, Action, or Outlet Collection.

Release the drag, change the Connection type to Action, the Name to refreshTapped, keep the Type as AnyObject, and click Connect. Xcode will automatically create the method for you:

@IBAction func refreshTapped(sender: AnyObject) {
}

All you’re going to do in refreshTapped is call centerMapOnLocation and fetchArtAroundLocation, just as you did with the initialLocation – but … what’s the new location?

MKMapViewDelegate to the rescue! First, create a new optional property in the ViewController class to store the currentLocation – just below the searchRadius declaration is a good place to put it:

var currentLocation: CLLocation?

It’s declared as an optional property because you won’t set its initial value until viewDidLoad to – what else? – initialLocation. Do this anywhere in viewDidLoad, after you’ve created initialLocation:

currentLocation = initialLocation

Now add this delegate method to the MKMapViewDelegate extension in VCMapView.swift:

func mapView(mapView: MKMapView!, regionDidChangeAnimated animated: Bool) {
  currentLocation = CLLocation(latitude: mapView.region.center.latitude, longitude: mapView.region.center.longitude)
}

Note that mapView(_:regionDidChangeAnimated:) is called continuously when the user is moving the map – it needs to be as lightweight as possible so it doesn’t slow down the map scrolling.

When the user moves the map view, it wil notify its delegate via this method, so you implement it to update currentLocation. Back in ViewController.swift, implement refreshTapped with the following code:

@IBAction func refreshTapped(sender: AnyObject) {
if let location = currentLocation {
    centerMapOnLocation(location)
    fetchArtAroundLocation(location)
  } else {
    let alert = UIAlertController(title: "Error", message: "No location yet!", preferredStyle: .Alert)
    alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
    presentViewController(alert, animated: true, completion: nil)
  }
}

In refreshTapped, you check that currentLocation has a value: if it does, then you center the map and fetch the artworks; if it doesn’t, you pop up an alert.

Build and run your app. Move the map away from where all the pins are, then tap the Refresh button – new pins appear!

run6

And that’s it! You’ve built an app that parses a JSON file into an array of artworks, calculates which ones are visible in the current map region, displays them as annotation pins, with a callout info button that launches the Maps app – celebrate with a hula dance around your desk :]

But wait, there’s one little bit of bling that I saved for last…

Color-Coded Pins

Remember the discipline property in the Artwork class? Its values are things like “Sculpture” and “Mural” – in fact, the most numerous disciplines are Sculpture, Plaque, Mural and Monument. It’s easy to color-code the pins so that Sculptures and Plaques have red pins and Murals and Monuments have purple pins, with green pins for all the other disciplines.

In Artwork.swift, add this method:

// pinColor for disciplines: Sculpture, Plaque, Mural, Monument, other
func pinColor() -> MKPinAnnotationColor  {
  switch discipline {
  case "Sculpture", "Plaque":
    return .Red
  case "Mural", "Monument":
    return .Purple
  default:
    return .Green
  }
}

Then, in VCMapView.swift, specify the pinColor in mapView(_:viewForAnnotation:) by adding this line after the else closure:

view.pinColor = annotation.pinColor()

The color needs to be reset every time the view is being reused, since the pin view could previously have been of a different discipline.

Build and run your app to see the different colored pins:

run7

You’re restricted to three pin colors because MKPinAnnotationColor only has those ones defined. Another option for customization is to use images instead of colors. You could replace the pinColor method with a pinImage method in Artwork.swift and set view.image instead of view.pinColor in ViewController.swift.

Bonus Topic: User Location Authorization

This app doesn’t need to ask the user for authorization to access their location but it’s something you might want to include in your other MapKit-based apps. Apple’s phrase is “to use location services” – as of iOS 8, this requires some extra steps, beyond checking a checkbox in the map view’s Attributes pane.

In ViewController.swift, add the following lines:

// MARK: - location manager to authorize user location for Maps app
var locationManager = CLLocationManager()
func checkLocationAuthorizationStatus() {
  if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
    mapView.showsUserLocation = true
  } else {
    locationManager.requestWhenInUseAuthorization()
  }
}
 
override func viewDidAppear(animated: Bool) {
  super.viewDidAppear(animated)
  checkLocationAuthorizationStatus()
}

This code creates a CLLocationManager object, which keeps track of your app’s authorization status for accessing the user’s location. The checkLocationAuthorizationStatus method checks your app’s status: if your app is authorized, then it effectively checks the map view’s Shows-User-Location checkbox; otherwise, it gets the locationManager to request authorization from the user.

Note: The locationManager can make two kinds of authorization requests: requestWhenInUseAuthorization or requestAlwaysAuthorization. The first lets your app use location services while it is in the foreground; the second authorizes your app whenever it is running. Apple’s documentation discourages the use of “Always”:

Requesting “Always” authorization is discouraged because of the potential negative impacts to user privacy. You should request this level of authorization only when doing so offers a genuine benefit to the user.

Info.plist item: important but easy to overlook!

There’s just one more authorization-related task you need to do – if you don’t, your app won’t crash but the locationManager’s request won’t appear. To get the request to work, you must add an item named NSLocationWhenInUseUsageDescription to your app’s Information Property List, and set its Type to String and its Value to a message that explains to the user why they should allow your app to access their location.

Open Info.plist and, if it’s closed, open the Information Property List. Hover your cursor over the up-down arrows, or click on any item in the list, to display the + and – symbols, then click the + symbol to create a new item. Name it NSLocationWhenInUseUsageDescription, check that its Type is String, then set its Value to something like To show you cool things nearby:

Infoplist

With a usage description like that, who wouldn’t allow access? ;]

Where To Go From Here?

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

Now you know the basics of using MapKit, but there’s a lot more you can do from here, including geocoding, adding custom map overlays, and more. A great place to go to for additional information is Apple’s Location Awareness Programming Guide.

To take this app further you may want to look into the MKMapItem class method I hinted at for opening the Maps app with multiple items. Perhaps add a button to the toolbar that opens the Maps app with all of the artworks currently shown. Also, why not take a look at the other launch dictionary options to control what happens when Maps opens.

If you want to learn more about MapKit features in iOS 6 and iOS 7, including registering your app as a routing provider, you should check out our books iOS 6 By Tutorials and iOS 7 By Tutorials. Fully updated for iOS 8 and Xcode 6, each book contains a chapter on MapKit. The iOS 6 chapter covers how you can launch Maps with various options, and how you can register your own app as a routing provider to give directions to users! The iOS 7 chapter covers Flyover, overlays, and the Directions, Snapshots and Cameras APIs.

If you have any questions as you use MapKit in your apps, hints for other MapKit users, or are interested in using government data in your apps, please join in the forum discussion below!

Introduction to MapKit in Swift Tutorial is a post from: Ray Wenderlich

The post Introduction to MapKit in Swift Tutorial appeared first on Ray Wenderlich.


Video Tutorial: Custom Collection View Layouts Part 3: Pinterest – Cell Content

View Debugging with Xcode and Reveal Tech Talk Video

$
0
0

Each month, one of the members of the team gives a Tech Talk, and by popular request we also stream these live.

Today in our March Tech Talk, we had a special 4-in-1 tech talk!

  1. Scott Berrevoets covered view debugging with Xcode.
  2. Erik Kerber covered view debugging your own apps with Reveal.
  3. Derek Selander covered view debugging third party apps with Reveal.
  4. Oliver Jones covered the history of Reveal and helped with Q&A.

Here’s the video for anyone who didn’t get a chance to attend live!

Helpful Links

Here are some handy links related to the talk:

Where To Go From Here?

Thanks again to Scott, Erik, Derek, and Oliver for giving a great talk and Q&A, having the guts to present to a live audience :]

And thank you to everyone who attended – we hope you enjoyed it!

View Debugging with Xcode and Reveal Tech Talk Video is a post from: Ray Wenderlich

The post View Debugging with Xcode and Reveal Tech Talk Video appeared first on Ray Wenderlich.

iOS Animations by Tutorials: Bonus Chapters Now Available!

$
0
0
3 New Bonus Chapters for iOS Animations by Tutorials Now Available!

3 New Bonus Chapters for iOS Animations by Tutorials Now Available!

iOS Animations by Tutorials is the gift that keeps on giving!

Marin Todorov has just released a brand new version of his book, that includes three free new bonus chapters covering Facebook’s popular Pop animation library:

  • Chapter 22, Getting Started with Pop: In this chapter, you’ll learn how to install Pop and take it for a quick test drive by creating a few simple animations.
  • Chapter 23, Decay Animations with Pop: Learn about a new kind of animation where instead of setting start and end points, you set an initial velocity vector and deceleration rate, and Pop takes care of the rest.
  • Chapter 24, Spring Animations with Pop: Learn how to make your animations look a bit snappier with one of Pop’s best feeling features – spring animations!

He’s also checked and updated the sample projects as needed so everything is up-to-date with the latest release of Xcode 6.2.

Wondering how to get these cool new chapters?

  • PDF customers: You can download the new version (v1.3) that includes the bonus chapters immediately on your My Loot page.
  • Print customers: Check the introduction in the book for instructions on how to download the bonus chapters.
  • Don’t have the book yet?: Be sure to grab your copy!

Marin and I hope you enjoy these free bonus chapters of iOS Animations by Tutorials – happy animating! :]

iOS Animations by Tutorials: Bonus Chapters Now Available! is a post from: Ray Wenderlich

The post iOS Animations by Tutorials: Bonus Chapters Now Available! appeared first on Ray Wenderlich.

Video Tutorial: Custom Collection View Layouts Part 4: DIY – Stretchy Headers

RWDevCon Inspiration Talk – Math Isn’t Scary

$
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 second talk – Math Isn’t Scary, by Matthijs Hollemans – I hope you enjoy!


Transcript

I would like to start with a show of hands. Who here understands this?

func countOccurrences(value: Int, array: [Int]) -> Int {
  var count = 0
  for element in array {
    if element == value {
      ++count
    }
  }
  return count
}
 
let array = [100, 28, 999, 43, 62, 999, 77, 35, 999]
let value = 999
let count = countOccurrences(value, array)
 
println("\(value) appears \(count) times")

I was hoping for more hands :]

OK, this is a piece of source code, right? There’s a for loop, an if statement; it’s a pretty basic algorithm for counting how often something appears in an array. This should be a piece of cake for most of you.

Now, raise your hands if you understand this… don’t be shy!

PieceOfMath

As you probably guessed, this is a piece of math.

In case you did not recognize this, this is the explicit formula for the prime counting function. I have to admit that I don’t completely understand it myself, I just Googled for “difficult math equation” and this is what came up.

I saw some people raise their hands, so if you’re really curious, if you really want to know what this means, I’m sure they’ll be happy to explain it to you afterwards.

I get the sense that what I’m showing in this slide is a lot more intimidating to you guys than the source code. I’m sure some people here went like, “Ugh, math.”

Math has a pretty bad reputation, not just among normal people but also among us software developers.

Let’s Turn That Frown Upside Down

happy-big-smile-l

The point I want to make in this talk is:

  • Math is actually pretty cool
  • It can even be a lot of fun
  • It’s not really that different from software development
  • And most importantly, I want to convince everyone here that they are already a lot better at math than they may think.

Let’s get started!

Why Math is Reviled

How Vladimir Putin Feels about Math

How Vladimir Putin Feels about Math

Let’s start with why math is so reviled.

  • If you don’t like math at all…
  • If the thought of doing math gives you hives…
  • If you have nightmares of doing multiplication tables or trigonometry…

…then you, poor listener, may suffer from what’s known as mathophobia, or math anxiety!

Where did you pick up this nasty-sounding affliction? Well, believe it or not, it’s been claimed that math anxiety is a disease caused by school.

Think about that for a second. The reason why math gives you the heebie-jeebies is the way it is taught in the traditional classroom. If you’re terrified of doing math, then you have this. It’s a very real thing, and it affects almost every one of us.

Except, of course, for that lucky handful of people who actually enjoy doing math. Even for them, it’s been suggested that they only managed to succeed in learning mathematics was despite what they were taught in school.

Math and Piano Lessons

I have this book, it’s called How to Play the Piano Despite Years of Lessons:

MathBook

I only started to play the piano in my late twenties, because for years I had this limiting belief that if you wanted to become good at the piano, it was impossible unless you started to play the piano when you were five years old.

It turns out that a lot of the kids who take piano lessons actually end up hating the piano just about as much as they hate math, and for pretty much the same reasons, too.

Now, for those of you who did not take piano lessons, the way the piano is usually taught is pretty similar to the way math is taught. You have to memorize a lot of facts, and you have to do practice drills over and over and over and over. There’s not much room for creativity, or for having fun.

I mean, it’s got playing the piano, right? You have to be able to play, you have to be able to enjoy it, you have to be able to mess around with the piano.

Well, try telling that to your drill instructor!

Mechanical Process vs True Understanding

There’s no deeper understanding of music with those traditional piano lessons. It’s just this mechanical process for playing the right notes, and the playing the right time.

The same thing is true for high school mathematics. You don’t really learn the deeper understanding of what mathematics is all about in school; all you learn is this mechanical process for doing calculations. I’ve got a computer who can do calculations much better than I can.

There’s no reason why an adult, or even a child, would have to do long division by hand. That’s something that computers are good at. School doesn’t tell you why you want to do long division in the first place.

Now, the full story goes something like this, and I quote:

“As a kid, I heard some tunes on the radio, and I liked to pick them out on my piano. Then my parents heard this and they thought I was super-talented, and they made me take piano lessons, but my piano teacher was this horrible witch, and I dreaded going. I couldn’t stand the thought of playing the piano for years.”

How sad is that? Taking music lessons, taking piano lessons, actually ruins music for a lot of kids. How familiar does that sound to math?

I really wish that this book existed: How to Play Math Despite Years of Lessons.

MathBook2

Play is also the right verb here, because doing math should really be like playing a game or solving a puzzle.

If you feel like you were no good at math, it’s not really your fault. You’re not defective. You just weren’t taught properly. Math anxiety is the result of bad teaching. That’s all there is to it.

Are we all irreparably damaged by our failed educations? Well, no, I don’t think so. You’ve suffered some minor setbacks, but that’s no reason to give up on math. Math is too beautiful for that.

Math Can Be Fun!

Now, I know these last couple minutes have been a bit of a downer, so in order to cheer you up I have a photo of people having a good time.

Celebrate

Attribution: lo-ny

I think they just solved some math problems, so now they’re out celebrating.

I said that math can be fun, something that you can really enjoy doing, like these people. I suspect that some of you might be a bit skeptical about this, so I’m going to back up my claim with the following piece of evidence.

Attribution: flickr.com/photos/hippie/2465105227

Attribution: Philippa Willitts

I probably don’t have to explain to you what this is. It’s a Sudoku, right?

These things are super popular, they’re played by millions of people around the world. Does anybody here like doing Sudokus? That’s what I thought.

Now, you’re going to say, “That’s not math, it’s a puzzle,” which is true. It’s a puzzle with numbers.

Well, a lot of mathematics is puzzles with numbers. Solving puzzles is what human beings love to do. We just can’t resist it. It’s how our brains are wired. That’s why kids love games, because a lot of games are about puzzle solving.

Whether you like it or not, this is math; you just don’t think about it that way. I hope I just didn’t ruin Sudokus for you, but a lot of the math that we learn in school, or are supposed to learn in school, isn’t really much harder than this. In both cases, your brain does exactly the same things.

My girlfriend, Deanna, her brain freezes up just at the thought of having to do math; but for some reason, she really likes this game:

Rummukub

For those of you who don’t know this, this is Rummikub. You have numbers, you arrange those numbers in certain patterns, and then you rearrange them. The first one to get rid of their numbers wins.

This game really exercises your math muscles. You have to do pattern-based thinking, pattern matching, you have to think steps ahead. She doesn’t think about it as math. It doesn’t trigger the bad memories she has of school, and how she used to get upset at her math homework. She also beats me way too often at this game.

Another game she likes is blackjack:

Attribution: Images Money

Attribution: Images Money

Now, to win at blackjack, you have to know all about odds and probabilities; or you have to learn card counting, but the same thing goes here. It’s all mathematics. That’s true for bridge or poker or any other game, or lots of games.

Many of the games you play are fundamentally mathematical in nature, but we don’t mind it because it’s not like doing the math that we used to do in school. It’s not really math that we dislike, it’s just our school experiences that we don’t like. The math itself can be pretty awesome.

I’m sorry to break it to you, but if you’re the kind of person who likes puzzles and games, then you’re probably a closet mathematician.

Learning Math is Like Learning a Programming Language

Let’s say five years ago, or two years ago, or however long ago you first started programming, and they showed you this, it probably wouldn’t have made much sense to you.

func countOccurrences(value: Int, array: [Int]) -> Int {
  var count = 0
  for element in array {
    if element == value {
      ++count
    }
  }
  return count
}
 
let array = [100, 28, 999, 43, 62, 999, 77, 35, 999]
let value = 999
let count = countOccurrences(value, array)
 
println("\(value) appears \(count) times")

You first had to learn the language – not Swift, but the language of computers and programming.

How does a compiler work? What’s a variable, what’s a function, and a thousand other things.

It was probably pretty hard to learn, in the beginning, anyway, but eventually you figured it out, and now you speak Objective-C or Swift, or whatever language. You speak it fluently.

If we show this to someone who just starts programming, or who hasn’t done any programming at all, it probably looks like a bunch of gobbledygook. Just like this looks like a bunch of gobbledygook to someone who doesn’t speak the language of math.

PieceOfMath

The point I’m trying to make here is that you’re all smart people. You’re very intelligent people. You’re software developers. You do difficult stuff all day long.

Math isn’t any harder than what you already do in your daily development jobs. If you were able to learn programming, I’d say you’re pretty much able to learn anything, even math.

What you do on a daily basis is the same thing that a professional mathematician does on a daily basis:

  • You build these elaborate thought structures in your head
  • You think through problems
  • You solve puzzles
  • You think creatively

You already act like a mathematician; you just don’t speak the language yet.

Why Bother?

Okay, fine. Let’s say I’m right, developers are like mathematicians. So what? Why should we bother learning about calculus or statistics or algebra? What do we need that kind of math for, anyway?

Well, I’d say if you want to create any piece of software that’s remotely interesting, you could use some mathematics.

For example, games. If you want to make games, even simple 2D games, it’s really helpful to know something about trigonometry.

Trigonometry is important for games!

Trigonometry is important for games!

All of the hot areas in software development of today — machine learning, big data, computer vision — all require solid math skills.

I have an interest in audio programming and digital signal processing, and that requires knowledge of things like complex numbers, fourier analysis, and when I didn’t know the math, it was very hard to do all this stuff. As I started studying the math behind it all, it made a lot more sense to me.

If you want to get ahead in your field, if you want to stay relevant, even, it’s really helpful to know a bit more about mathematics. Besides, knowing math will make you a better programmer, and better programmers make more money.

A developer who knows math

A developer who knows math

Just in case you need some extra motivation!

How To Learn?

Let’s say I’ve convinced you to give math a second chance; how would you go about it?

Well, the book I mentioned, How to do Math Despite Years of Lessons, it does exist, sort of. This book’s called Math Overboard.

MathOverboard

I used it to brush up on my high school mathematics a little while ago. It’s not perfect, but it’s a lot more accessible than standard textbooks, and it’s written for adults, so this is a pretty good place to start.

There’s also Khan Academy. These guys have a ton of free videos on math and lots of other subjects. Essentially, all the math that you need to know as a software developer, you can learn here.

Also, lots of universities are putting out their courses online for free, but if you want an easy place to start, then Khan Academy is a good place.

Now, if you just want to get your feet wet and explore some mathematical ideas without too much commitment, then why not read popular science books, such as this one, called 50 Mathematical Ideas You Really Need to Know:

50MathIdeas

Or, listen to a podcast such as this one. It’s from the BBC; it’s called A Brief History of Mathematics:

HistoryOfMath

There are a lot of entertaining stories about math, and the people who used to practice math throughout the ages. There’s lots of intrigue, there’s lots of drama, but these stories can also give you an appreciation for the art of mathematics, and how fascinating it can be.

You can’t really learn math just by reading about it. You also have to put it into practice. That means you have to do some hard thinking from time to time. These are math puzzle books, and these math puzzle books are a great way to get a feel for what it is to think through mathematical problems.

PuzzleBooks

If you like to do puzzles, if you like to do Sudokus, then these can be a lot of fun. They sell them at any bookstore, they sell them at airports, so you might pick one up on your way home.

If you’re ready for a real challenge, then give Project Euler a try:

ProjectEuler

This is a website that has lots of mathematical challenges, but the interesting thing is that you often have to write a short program to solve those puzzles. This tests your math skills, it also tests your programming skills.

Start Small

cat_collider_small

My advice is that you start easy, that you get over this limiting belief that math is somehow this horrible thing. There are recent stories about mathematical discoveries, and learn to see the beauty of mathematical ideas.

By the way, I said mathematical ideas can be beautiful a few times now, so what do I mean by that?

Well, you’re coders. You probably know beautiful code when you see it, right It’s basically the same thing. A beautiful mathematical idea, or a beautiful piece of code, is a thought or idea that’s expressed in an elegant way. It’s like the opposite of a hack.

I’m pretty sure beauty in mathematics, that you’ll recognize it when you see it. If you want to get serious, brush up on your basics first, basically learn all the high school stuff, but in a nice way this time. Get something, the books like Math Overboard, or Khan Academy.

Then from then on, it really depends on what you want to do. Math is this huge field. You can’t possibly learn it all, so pick something from areas that interest you. For example:

  • If you want to get into audio processing or video processing, learn about complex numbers and fourier analysis.
  • If you want to do 3D games, learn about linear algebra.

You can pick, just a topic here, topic there. There’s lots to explore, lots to learn, and you’ll never run out of stuff to learn for the rest of your life.

Math Isn’t Scary, but Can Be Hard

Now, I won’t lie to you; on your schedules, it actually said the talk is called “Math Isn’t Hard,” which is my mistake. It should have said “Math Isn’t Scary,” because math can definitely be hard.

It can be hard, it can be frustrating, and it’s very much an uphill climb. I get stuck all the time, but it doesn’t matter, because learning anything new is always hard. Finding bugs is hard, fixing bugs is hard; but it’s also half the fun of programming, right? I mean, I think it’s half the fun of programming.

It’s okay to be confused when you’re learning math, it’s okay to be wrong. It’s okay to struggle. Even professional mathematicians are in a state of constant confusion. It’s no big deal; the only thing that really matters is that you’re thinking about this stuff, because the thinking is what literally makes you smarter.

Attribution

Attribution: _Untitled-1

Math isn’t really that scary. It’s only as scary as learning to program is for a newbie. You’ve all been there.

You’ve all had to learn programming at some point, and you stuck with it, and now here you are. You’ve been able to learn programming; I’m pretty sure you’re all able to learn mathematics.

I hope I’ve inspired you a little to give math another go. Play around with it, explore some of those mathematical ideas, such as how does Pythagoras work, where does pi come from, why are prime numbers such a big deal. What’s the point of negative numbers, anyway? It’s these simple ideas, simple thoughts, but they get you thinking about math, and you take it from there.

I wish you all a safe and happy journey through the land of mathematical ideas!

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 – Math Isn’t Scary is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk – Math Isn’t Scary appeared first on Ray Wenderlich.

Readers’ App Reviews – March 2015

$
0
0
Apps from readers like you!

Apps from readers like you!

March is here, and so are your latest app reviews!

As expected, you guys filled up my inbox with great app submissions, so I’ve been busy playing with all your apps. There are some really cool ones this month.

This month we’ve got:

  • A party game to call out your friends
  • A powerful 2D animation tool
  • A math game that will test your mind
  • And naturally, much more!

Read on to see some fun, unique, and powerful apps made by readers like you.

Lastronaut

lastronaut
Lastronaut is one of the last humans on earth, running for their life to board the final rocket leaving the planet. And its simply beautiful.

Running in an adrenaline fueled haze with rockets and shotguns abound, you’ve got to dodge everything the sentinel army can throw at you. New weapons fall from the sky as gifts from the heavens to help you fight your way to the last rocket.

Controls are simple: jump and shoot with simple taps. GameCenter integrations makes sure you can brag to your friends as you expect. And there are an array of achievements to keep your running after your life is safe.

Creature

Creature
Creature is a new tool made by professional animator with experience animating hit movies such as Wall-e, Up, TS3, Brave.

Creature is designed to make complex and gorgeous animations out of static 2D images.

Creature has a ton of tricks. With skeletal animations you can give your character life and generate an entire range of movement. With physics simulations those skeletons become even more real as your tails bounce and your arms swing.

Creature also overs a variety of mesh deformations allowing even static images to flex and breath. As if you didn’t have enough at your fingertips, Creature supports motion capture from your camera to allow you to record your own movements and mimic them in your character animations!

Creature supports plenty of formats such as videos, gifs, sprite sheets, and image frames. It even has built in support for a number of popular game engines including Cocos2D, Unity, and more.

Cozy City

CozyCity
Cozy City is a unique puzzle game that leaves your planning a neighborhood with a variety of predetermined tiles.

The game begins by giving you a blueprint of tiles required for your city. You must use them in order on the grid below to build a city that satisfies the blueprint. No road can simply end cut off, it must end with a house or grass. Forks in the road must be managed carefully as they immediately send you down interesting paths.

Cozy City doesn’t always have one right answer, instead you’re left to solve the puzzle in your own way. Even how you pay can be up to you whether its careful upfront planning or a see as you go style. 50 levels should keep you busy as you decide if your next career will be city planner.

Schemes

schemes
Schemes is an enormously powerful URL builder that takes advantage of iOS URL-Schemes to build unique and customizable workflows between applications.

Schemes can open other apps, take data from one app and send it to another. Really the sky is the limit as each app can supply its own actions and data that other apps can use. Schemes acts as the middle man by organizing those actions and allowing you to chain them into workflows.

Since any app can open up a URL-Scheme to enable communication between itself and other apps, Schemes will continue to expand as more and more apps take advantage of this powerful library.

Makan Kaki

makanKaki
How many times have you and a few friends tried to setup an outing and simply can’t agree on a place or a time? If you’re like me, it’s many many times.

Makan Kaki is designed to solve that problem. The app allows you to create an event and invite your friends. Then everyone can suggest and vote on venues and times. The venues are sorted by votes and also offer reviews, directions, and a gallery of photos. Suggested a date makes it easy for friends to decide if they have the day available and vote accordingly.

You can login using Facebook to invite your friends, but you can also roll without an account. Makan Kaki will generate a URL for you share with friends as you please. When they open the URL they’ll be prompted for the app if they don’t have it, and if they do they’ll be taken to the event without the need to login either.

Push notifications will keep you updated on your friends updates as you finally manage to plan a painfree outing.

Dice Mogul

Dicemogurl
Dice Mogul is a fun twist on a real estate board game.

Dice Mogul lets you build a proper empire as you circle the board a few times. As you circle you have the chance to buy properties. Once you own a property you can of course upgrade it to increase the damages when an opponent lands on it.

A large variety of powerups bring extra excitement and often mean flipping the tables on your opponents repeatedly. The available powerups include stealing a property, upgrading your properties, shielding from payments, and more.

Dice Mogul brings memories of monopoly nights with my family. Here’s to hoping a GameCenter multiplayer update lurks around the corner. ;]

Pivots

pivots
Pivots is a new puzzle game with a dash a math.

Before I send you running for the hills, the math isn’t that complicated – and remember math isn’t scary!

With a grid of numbers, when a row totals 15, its eliminated then your timer and score are increased.

You play by rotating, or pivoting (get it?!?), numbers in groups of four. Simple drag your finger starting on one number and create a square of four numbers. They will rearrange allowing you to position numbers as you please.

You only get 60 seconds to best your highscore. Pivots without a row of 15 will cost you time. Each removed row gets you some extra time. As you advance the game will get faster and you’ll get score multipliers to take you to new heights.

Pin Circle

pincircle
Pin Circle is a delightfully simple timing based game made for casual play.

The premise is simple. There is a circle spinning in the middle of the screen that has a few pins in it. You’ll have a number of pins to add. Simply tap and the pin will hit the circle at the current location. Your mission is to get all the pins stuck to the circle without any overlapping pins.

The game will change directions, speed up, adjust patterns, and more to complicate the game. With over 400 levels you shouldn’t have a problem staying busy a while.

WeathAR

weathAR
WeathAR is perhaps the most unique weather app yet.

WeathAR doesn’t simply have a list of locations with cute icons. No, that wasn’t good enough for WeathAR.

Instead, after entering a few locations you frequently want the weather for, you can simply point your iPhone in that direction and WeathAR will use your GPS and compass to choose which city to tell you the weather for.

WeathAR is a delight to use with its playful animations and unique Augmented Reality interface. You’ve certainly never checked the weather like this.

WeathAR uses date from Forecast.io so you should find it helpfully accurate and up-to-date.

Files Board

filesboard
Files Board is a powerful file browser and organizer for your iPhone and iPad.

Files Board will let you browse, organize, and store files on your iOS device covering photos, documents, videos, music, etc. It checks all the important features like folders, filtering, searching, favorites, copying, etc. It also supports zip files as well as uncompressing them, even encrypted.

Files Board as has a really cool pro feature that turns your iOS device into a local webserver for your network and allows you to update files over the air from your Mac. A must have for anyone transferring files from their Mac to their iPad for presentations and such.

Callouts

Callouts
Callouts is a party game you and your friends will love.

Callouts is simple: you and your friends join a local game, then questions are asked to the group. They’re simple questions always about the group of people playing. So it could be something like “Who’s the goofball?” Everyone picks their answer and then the game reveals to everyone who was the most selected.

The covered answers that lead up to the big reveal lend to the tension in the room as everyone chuckles to themselves about the question. Careful with all that chuckling though because the next question could be about you. >;]



Honorable Mentions

Every month I get more submissions than I can handle. I give every app a shot, but I can’t write about them all. These are still great apps made by readers like you. Its no a popularity contest or even a favorite picking contest. I just try to get a glimpse of what the community is working on through your submissions. Take a moment and checkout these other great apps I didn’t have time to showcase properly.

Flight Tracker
shapesly
Greenchick 2
Matching Shapes
RainMM
Boob-Tube
Coubbles
First Draw
Coloria
Angle Clash
Kill Sector
FaceDash
Magic Wanda
Pregnancy Recorder Pro
Color-Pong
Know – Social Proximity



Where To Go From Here?

Each month, I really enjoy seeing what our community of readers comes up with. The apps you build are the reason we keep writing tutorials. Make sure you tell me about your next one, submit here!

If you saw an app your liked, hop to the App Store and leave a review! A good review always makes a dev’s day. And make sure you tell them you’re from raywenderlich.com; this is a community of makers!

If you’ve never made an app, this is the month! Check out our free tutorials to become an iOS star. What are you waiting for – I want to see your app next month!

Readers’ App Reviews – March 2015 is a post from: Ray Wenderlich

The post Readers’ App Reviews – March 2015 appeared first on Ray Wenderlich.

App Architecture with Matthijs Hollemans – Podcast S03 E10

$
0
0
Learn about app architecture with Matthijs Hollemans!

Learn about app architecture with Matthijs Hollemans!

Welcome to the final episode of season 3 of the raywenderlich.com podcast!

In this episode, we’ll chat with tutorial team member Matthijs Hollemans about app architecture.

After this episode we’ll be taking a break, and then we’ll be back for season 4.

If you have any ideas for things to improve in season 4, now’s your chance to let us know!

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

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

Links and References

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. Stay tuned for season 4, after a short break! :]

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!

App Architecture with Matthijs Hollemans – Podcast S03 E10 is a post from: Ray Wenderlich

The post App Architecture with Matthijs Hollemans – Podcast S03 E10 appeared first on Ray Wenderlich.


Video Tutorial: Custom Collection View Layouts Part 5: DIY – Adding Depth

Unreal Engine Tutorial for Beginners: Part 1

$
0
0
BlueprintMan: The hero of your game.

BlueprintMan: The hero of your game.

Unreal Engine (also known as the Unreal Development Kit, or UDK) is a favorite platform of AAA game studios and is the magic behind many blockbuster games such as Unreal Tournament, Gears of War on consoles and desktops and Infinity Blade and XCom: Enemy Within on mobile devices.

If you’ve spent any time in the above games, you know that Unity Engine can help create games that look amazing and are a joy to play. But did you know you can use the visual scripting system of Unreal to create a complete game, without writing any code? And best of all, Unreal changed the licensing model of Unreal Engine so it’s free to start without any upfront charges; you only pay 5% of gross revenue per product created with Unreal Engine, and only if the product earns $3,000 or more.

This combination of popularity, power, ease-of-use, and low cost makes Unreal Engine a great option for indie developers; it’s right up there with Unity 5 and the upcoming Source 2 engine.

So it’s high time for an Unreal Engine tutorial on raywenderlich.com! In this tutorial, you’ll create a side-scrolling 2D-platformer named BlueprintMan, in honor of the iconic Schwarzenegger flick Running Man.

Time to get (un)real! :]

Getting Started

Unreal Engine is built upon three principal modules:

  • Epic Games Launcher: This lets you log in to Unreal, search for and view content and tutorials and download the engine.
  • Unreal Engine: This is the actual game engine. You won’t normally work with this code directly as it’s the behind-the-scenes SDK code.
  • Unreal Editor: This the IDE editor you’ll use to develop Unreal Engine games; it’s much like using Xcode to develop iOS or Mac apps.

Download the Epic Games Launcher here; in order to download the engine you’ll need to sign up for a free Epic Games account first. Create an account, then download the engine using the links presented when you sign in.

Download and install Unreal Engine, and then continue when you’re ready.

Creating a New Project

Now that you have Unreal Engine installed, open it and the following window will appear:

Screen Shot 2015-03-07 at 2.50.43 PM

Enter the email and password that you used to sign up for Unreal Engine. Click Sign In and the launcher will sign you in and open a larger window like so:

Screen Shot 2015-03-07 at 2.54.43 PM

Take a moment to scroll through the stack of content that Epic Games has generously provided: tutorials, videos and more. It’s quite a list!

To download the Unreal Engine and Unreal Editor, click the yellow Launch Unreal Engine 4.7.2 button at the top left; your version might be slightly different but that won’t affect your progress in this tutorial. The editor will open once the download has completed with the following splash screen:

Screen Shot 2015-03-07 at 2.59.23 PM

Once the editor opens, you’ll see a project organizer similar to the one pictured below, although your list of projects will be initially empty:

Screen Shot 2015-03-07 at 3.00.09 PM

Click on the New Project tab at the top to reveal the following:

Screen Shot 2015-03-07 at 3.00.16 PM

About Blueprints

You can take one of two approaches when developing with Unreal Engine:

  • C++: Choosing C++ gives you the raw performance and power of C++, but you also assume the responsibility of memory management — without ARC or Garbage Collection, might I add — along with having to manage the overhead of C++’s complex syntax.
  • Blueprints: Choosing Blueprints gives you a powerful visual programming editor; simply drag and drop game elements onto a graph and connect them together to control the logic and actions in your game.

A Blueprint is to Unreal Engine what Interface Builder is to iOS; it supports the WYSIWYG construction of game logic just as Interface Builder supports the WYSIWYG construction of the user interface. However, the best way to understand Blueprints is to see them in context. For example, the Blueprint below makes the character in your game jump:

A Blueprint to control your character's jumps.

A Blueprint to control your character’s jumps.

A Blueprint looks suspiciously like a flowchart; not a boring business flowchart, mind you, but an awesome flowchart that could chart the flow of monsters, explosions and loot drops in your game.

As an added bonus, if you’re working with a game designer or artist, the visual simplicity of Blueprints makes your game logic accessible and lets the designers tweak your game directly without any programming knowledge.

Now I know what you may be thinking: “That’s too easy; I want to do things the hardcore way with C++!” Well, even if you know C++ really well, it’s often best to use Blueprints as it saves time, reduces lines of code and as you know, less lines of code == less bugs! :] Therefore, in this tutorial, you’ll be developing the entire game with Blueprints.

Time to get started!

Creating Your First Project

There are two tabs that let you determine which language to use in your new project: Blueprint and C++. Select the Blueprint tab and click the 2D Side Scroller icon:

Screen Shot 2015-03-10 at 9.19.06 PM

Selecting 2D Side Scroller instructs the Unreal Editor to populate your new project with a handy shell of a 2D side scroller game that you can fill in with your own art assets, sound effects and logic. It’s much like Xcode’s “New project” template.

Make certain that the Settings section is set to Desktop/Console, Maximum Quality and No Starter Content as shown above; this ensures your game will be playable on your Mac, with crisp graphics, and won’t be filled with hundreds of megabytes of starter textures, assets and other cruft that you won’t need to build your game.

All that remains is to name your new, epic project. In the Name textfield at the bottom type in BlueprintMan:

Screen Shot 2015-03-10 at 9.20.32 PM

Then click Create Project; you may see the following splash screen for a moment while the Unreal Editor goes about the busy work of creating your project:

Screen Shot 2015-03-07 at 3.03.35 PM

Once your project is ready, The Unreal Editor will open like so:

Screen Shot 2015-03-07 at 3.06.22 PM

This is the main editor window; it’s a good idea to get familiar with it since you’ll spend most of your Unreal Engine development time in this window with its various tabs and views.

Understanding the Unreal Editor

Note: When you start Unreal Editor for the first time, you’ll see a prompt to start a tutorial in the upper right of the window. Take a moment to work through the tour of the Unreal Editor UI, then continue on with this tutorial once you’re done.

The Unreal Editor has the following views:

EditorInitialAnnotated

  1. Modes View: This is where you select objects to drop into your scene and access tools, such as brushes, to modify your scene.
  2. World Outliner: This lists all of the Blueprints in your game. Click the Ledge_12 line in the World Outliner to highlight the Ledge_12 line; the Details View will populate with the respective object’s details.
  3. Details View: This shows you the details of list entries like Ledge_12 from the World Outliner. You can set things such as the transform of the ledge to control its geometry and placement in the scene; the object’s sprite to control its appearance in the scene; and a myriad of other properties.
  4. Content Browser: This lists all the content in your game, neatly organized into folders by content type.
  5. Toolbar: This gives you access to various functions in the game, such as playing your game or building it.
  6. Viewport: This is your view into the game; you can drag and drop elements into your scene and move them around as necessary.

ragecomic_whendoigettoplaysomegames

Okay, enough background information – it’s time to have some fun! Click the Play button in the Toolbar at the top to begin playing your game in its current state.

Playing Your Game

Your game is configured to use traditional movement controls:

  • A: move left
  • D: move right
  • Space: jump

Press and hold the A key to move left, hit space to jump off your current ledge and land on the ledge below:

FirstPlay30v2

Move your mouse up to the Stop button and click it to stop the game:

StopButton

Note: You can also exit the game by pressing the Esc key.

Editing Your Game’s Blueprints

Okay, so you’ve seen your basic game in action. Now you get to peek behind the curtain to see how Blueprints drive the gameplay.

Blueprints are typically short, focused groupings of game logic that fulfill a single cohesive purpose. For example, you can create a character Blueprint to represent your player’s character or a monster Blueprint to represent the enemies in your game.

Select the Blueprints folder in the Content Browser like so:

BlueprintsFolder

Double click on it to open the folder:
BlueprintsFolderOpen

Select the 2DSideScrollerCharacter Blueprint as follows:

BlueprintsCharacterSelected

This is your player, the blue humanoid that moves around your game. Look: it’s a bird, it’s a plane, it’s BlueprintMan! :]

Double click on the 2DSideScrollerCharacter Blueprint to launch the Blueprint Editor:

Screen Shot 2015-03-07 at 3.32.10 PM

Take note of the following key views of the Editor:

  1. Components View: This is where you add components to your Blueprint. Unreal Engine, like many game engines, uses a form of Entity Component System (ECS) that favors composition over inheritance. For example, a player “has-a sprite” instead of “is-a sprite”.
  2. MyBlueprint: This is the “class view” of your Blueprint where you can add variables, functions and other elements.
  3. Details: This is where you can view and edit details of your Blueprint.
  4. EventGraph: This is the meat of a Blueprint; it displays the graph of objects, events and actions that make up your game logic.
  5. Toolbar: This provides you with various tools to perform actions on your Blueprint.

The EventGraph is central to your Blueprint, so take a moment to examine it in detail:

A Blueprint to control your character's jumps.

A Blueprint to control your character’s jumps.

What you’re seeing here is the logic that causes your player to jump when you press the spacebar. The two red rectangles and the two blue rectangles are nodes in your graph. Nodes can represent entities (objects) in your game such as other Blueprints, events (where something happened) or functions (where you do something).

Consider InputActionJump. The red colored top portion of the node indicates that this is an event; it’s a placeholder for the event “the jump input action occurred.”

Okay, but since your player jumps when you press the spacebar, wouldn’t it be more clear if the node was named “SpacebarPressed”?

Well, Unreal Engine uses abstract input mappings: the event InputActionJump represents the generic event “a jump happened” — independent of which key (or joystick) action triggered the jump. This seems a bit indirect at first, but that’s precisely the point: input mappings let you change which key controls the jumping action — without having to change your node graph.

EventGraph nodes are wired together by the white curvy lines between them, known as links. Links are attached to points on the nodes named pins.

Check out the right-facing white triangles on the InputActionJump node:

JumpCloseup copy

These are exec pins. For events, they’re placeholders for the action to take when the event occurs. Output exec pins are on the right of a node, while input exec pins are on the left.

Exec pins don’t actually do anything until you connect them to other nodes. In this case, the Pressed output exec pin of InputActionJump node is linked to the input exec pin of the Jump node. The input exec pin of a function node such as Jump means “call this function.” Therefore, the above connection calls the Jump function when the InputActionJump is Pressed.

Similarly, see how the Released output exec pin of the InputActionJump node is connected to the StopJumping node’s input exec pin:

JumpCloseup copy 2

What does this mean in terms of your gameplay? You guessed it: when you release InputActionJump, the player will stop jumping.

Finally, take a look at the InputTouch node and see if you can figure out what task it performs:

JumpCloseup copy 3

This represents the input mapping on a touch device like an iPhone. It has Pressed and Unpressed output exec pins just like the Mac input mapping InputActionJump. InputTouch represents the event “player wants to jump” on your iPhone or iPad.

Getting Closer: Zooming In

Place your mouse cursor in the middle view (2DSideScrollerCharacter > EventGraph), hold down the right mouse button and drag to scroll around the EventGraph:

PanEventGraph

You’ll see there are other node mappings in the graph but it’s hard to see them all at once. Fortunately, it’s easy to zoom to see them all. Left-click on the top menu View\Zoom to Graph Extents:

ZoomToGraphExtents

Then release your mouse button to zoom out show the entire extent of the graph:

Screen Shot 2015-03-07 at 3.48.59 PM

Now you can see the big picture!

But, wait, how do you zoom in to a specific area of the graph? Scroll up to the Event Begin Play node and left-click to select it:

SetIsReplicatedSelected

Then left-click the View\Zoom to Selection menu item:

ZoomToSelection

This will zoom in to the Event Begin Play node you selected earlier:

Screen Shot 2015-03-07 at 3.52.51 PM

You’ve zoomed in on the Event Begin Play area of the EventGraph in this particular example, but you can zoom in on any node using this technique.

Enough Talk: Adding Actions to your Game

You’ve been incredibly patient to this point; your patience is about to be rewarded by implementing some action in your game. At the moment, your game character is the strong, silent type; he doesn’t say much. Your task is to bring him out of his shell and make him talk.

ragecomic_makemyday

Use your mouse to scroll the graph area around as shown below and left-click outside of the Event Begin Play node to unselect it:

Screen Shot 2015-03-07 at 4.03.20 PM

Right-click on the blank grid in the EventGraph to the right of the Event Begin Play node. This summons the context menu which you’ll use to add nodes. Press t in the white search box; the context menu will highlight the T row with what looks like a keyboard beside it. Left-click on the highlighted row or press Enter to add the T key event to your node graph like so:

LetterTContextMenu

Note: Sometimes the context menu is a bit finicky. If the T key doesn’t show up for some reason, try unchecking the Context Sensitive checkbox in the top right corner of the context menu.

If you can’t mouse scroll in the menu’s list of choices, you can always use your up and down arrow keys to scroll with your keyboard instead.

Things will be a bit easier if you focus in on the T key event without being distracted by other nearby nodes. Use your mouse to scroll around the EventGraph until it looks roughly like the screenshot below:

Screen Shot 2015-03-07 at 4.09.39 PM

Now you have some room to work!

Hover your mouse over the Pressed exec pin of the T key event. A tooltip will appear with Pressed Exec to remind you that this is the exec pin activates when you press the T key:

PressedExec

Left-click on the Pressed exec pin, drag to the right outside the T node and release your left mouse button. You’ll see a white link line and the popup context menu. Unreal Editor recognizes the action of dragging a pin from a node and releasing outside the node as “hey, I want to connect this pin to a new node” so it will pop up the context menu to assist you.

Type print string in the white search box; the words Print String with an italicized f are highlighted; this represents the Print String function (f stands for function). Press Return or Enter, or alternately left-click on Print String to create a Print String function node like so:

LetterTDragOutPressed

Hover your mouse over the pink In String pin on your Print String node:

InString

The Print String function prints the value of this input pin; note that the pin is a circle to indicate that it’s a data pin. Exec pins are “filled in white triangles” and represent actions, while data pins are circles and represent data, such as strings or numbers that are consumed (via input data pins) or produced (via output data pins) by functions or actions.

You could fill the In String input data pin with the output of another function or variable, but for now you’ll simply use a constant string. Click in the text field next to In String and type Say hello to my little friend!:

SayHelloToMyLittleFriend

Solution Inside: For movie buffs: Which movie is this line from? SelectShow>

You’re almost ready to unleash your Al Pacino-quoting character in your game, but there’s one last thing to take care of. Notice how the Compile button has a question mark over it:

NeedsCompile

This indicates Your node graph is “dirty”; in other words, it has uncompiled changes. You’ll need to compile these changes before you can play it.

Left-click Compile to compile your graph and after a second or two you’ll see the following:

GoodToGo

The green checkmark indicates that the compile succeeded. As an added convenience, you can run your Blueprint graph directly from the current Blueprint Editor: left-click Play as shown below:

BlueprintEditorPlayButton

When your game launches you’ll see your scene as below:

SayHelloWindow

Press T to make your character talk:

SayHelloV5Talking

The text will disappear from the screen after a few seconds. Using the Print String function like this is a good way to prototype interactions with your character, or to log visible messages to your game screen during gameplay. Press the Esc key to exit gameplay.

Though your character may be prone to uttering some questionable movie lines, he is nonetheless polite. As a challenge, make your character say Goodbye… when the T key is Released. You should end up with a graph as follows:

HelloGoodbyeGraph

If you get stuck, try to repeat the sequence of steps you used for the T key Pressed event.

Left-click Compile; once the graph is compiled the Compile button will display a green checkmark. Left-click Play to play your game. Once your game is running, press T then release. You should see the following:

SayHelloGoodbyeV5Talking

Not only have you made your character a bit more polite, you’ve learned something valuable: events and actions often come in pairs. In the case of the T key, there’s corresponding T Pressed and T Released actions. In other cases, you might encounter pairs of events like “collision began” and “collision ended”.

Keeping Your Event Graph Clean and Tidy

Just like flossing, good EventGraph hygiene is a healthy habit to practice right from the start. You’re going to cleanup your new talk nodes so that they’re easier to recognize as a group of related functionality.

ragecomic_cantgoout

Use your mouse to select the three nodes you just added: first left-click the T node, then hold down the Command key and left-click the two Print String nodes; the command key lets you select multiple nodes. Right click somewhere inside the canvas to bring up the context menu and click the Create Comment from Selection option.

This will group your three nodes into a comment group. Left-click in the text field that contains Comment and replace that text with Talk: Hello and Goodbye. Press Return or Enter and take a look at your well-commented, neatly grouped set of nodes:

EventGraphHygiene

EventGraph Comments like these are similar to pragma marks in Objective-C, or block comments in Swift. They add no real computational value, but they are excellent organizational tools that help you keep your EventGraph clean and readable, just like you keep your code classes nice and tidy. Believe me, when you come back to this EventGraph months from now, you’ll appreciate those comments! :]

Where to Go From Here?

You can download the completed example project for the first part of this tutorial.

You’ve covered quite a bit in this tutorial, from setting up Unreal to learning how to work inside Unreal Editor to modifying Blueprints to create a small working 2D game.

Keep reading the second part of this tutorial series, which will show you how to create and spawn loot for your player to collect.

If you have any questions or comments, feel free to join the discussion below!

Unreal Engine Tutorial for Beginners: Part 1 is a post from: Ray Wenderlich

The post Unreal Engine Tutorial for Beginners: Part 1 appeared first on Ray Wenderlich.

Unreal Engine Tutorial for Beginners: Part 2

$
0
0
BlueprintMan: The hero of your game.

BlueprintMan: The hero of your game.

Welcome to the second part of this two-part tutorial series on Unreal Engine!

In the first part of this series, you learned the basics of Unreal Editor and the Blueprints visual scripting language. In this second and final part of the series, you’ll learn how to add loot and randomly spawn it in your game.

Getting Started

If you completed the previous part of this tutorial series, you can pick up where you left off. If you just want to get right into it, or want to start afresh, you can download the completed project from Part 1 and pick up from there.

Open your project in Unreal Editor; you’ll most likely see the following screen, depending on where you left off from Part 1 of the series:

Part2FirstLaunch

Click the 2DSideScrollerMap tab at the top left to navigate back to the main editor view:

Part2BackOnMainEditorScreen

Now you’re in position to start adding some loot to your game.

Creating and Animating Loot

As any good game designer knows, loot is an essential part of a 2D side-scrolling platformer. Otherwise, what’s the point of all that running and jumping around?

ragecomic_piratelootkpi

Yes, as any Pirate knows, the best loot of all is gold coins. Before you add the loot to your game, you’ll need some art assets to represent the loot in your game. Download the art assets file GoldCoins.zip generously donated by GameArtGuppy.com, and extract it to a convenient location.

In the content browser, navigate to the Sprites folder by right-clicking on the arrow between 2DSideScrollerBP and Blueprints, like so:

GoingToSprites

Left-click on Add New\New Folder to add a new folder:

CreateNewFolderSmall

Click on the new folder and edit its name to be Coins:

CoinsFolderSelectedSmall

Double-click Coins to navigate to the folder:

CoinsReadyToAdd

Right-click where it says Drop files here or right click to create content and click on the Import to /Game/… menu item:

CoinImagesImportMenu

This presents the import file dialog. Navigate to the GoldCoins directory you downloaded earlier, select all six coins as below, then click Open:

CoinImagesOpenSelected

You’ll probably see the warning shown below about non-powers of two; you can ignore this for now and simply click Yes:

CoinWarningCloseup

Once your import completes, you’ll see the six coin images inserted into your Coins folder and highlighted as below:

CoinImagesAdded

With the six coin images still selected, right-click on any of the images and choose Sprite Actions\Create Sprite:

CoinSpritesCreateFromImagesSmall

This creates coin sprites from each of the six coin images:

CoinSpritesAdded

Your coin sprites can now be drawn on-screen in your game. Much like Sprite Kit, Cocos2D and Unity, Unreal uses sprites to draw 2D images.

Look closely at the six sprites and observe how they appear to be drawn at different angles and in different states. That’s intentional: these sprites make up six different frames of a spinning coin animation. In order to create the animation, you need to place the sprites inside a Flipbook, which plays a sequence of sprites one after another.

With the six coin sprites still selected, right-click on any of them and select Create Flipbook:

CoinFlipbookCreateFromSpritesSmall

Click on your new flipbook and edit its name to be CoinFlipbook:

CoinFlipbookNaming

Double-click on CoinFlipbook to open the flipbook editor:

CoinFlipbookAt15fps

You’ll see your coin spinning smoothly around like so:

CoinsToFast

Congratulations: you’ve created your first Unreal animation! However, it would look a little better if the coin spun a little more slowly. Right now, the coin spins at the default animation rate of 15 fps. Edit Frames Per Second and reduce its value to 6 as shown below:

CoinFlipbookAt6fpsSmallWithLoupe

Check out the resulting slower animation:

CoinsToBetterSpeed

That looks a little less frantic.

Return to the 2DSideScrollerMap by clicking the tab at the top left. Then click the arrow between 2DSideScrollerBP and Sprites and select the Blueprints menu item:

CoinFlipbookGoingToBlueprintsFolder

If you were in Sprite Kit, you might add a Coin Class to model your coin loot in the game world. However, in Unreal, you’ll add a Coin Blueprint to model your coin. Click Add New\Blueprint Class to create a new Blueprint:

CoinBPAddBPMenuSmall

Next, click on Actor:

CoinBPMakeItAnActor

As the description says, an Actor is an object that can be placed and spawned in your game world. Your BlueprintMan character is an actor and your coins are also going to be actors.

Click on the Blueprint you just added:

CoinBPAdding

Edit its name to be CoinBP:

CoinBPAddedAndSelected

Note: It’s common convention in Unreal to name your Blueprints ending in BP as in CoinBP (or BP_Coin according to the Unreal Assets Naming Convention).

Double-click on CoinBP to launch the Blueprint editor for your coin:

CoinBPEditor

Click Add Component, type “flipbook” then press the down arrow and hit Enter to create your flipbook:

CoinBPAddingFlipbookComponentWithMisdrawnMenuSmall

Note:The Add Component menu seems to have some rendering bugs on OS X so you may see a blurry image like above.

You can leave the name as its default, PaperFlipbook:

CoinBPAddingFlipbookComponentSmall

Left-click on Sprite\Source Flipbook and select the CoinFlipbook you just created:

CoinBPSelectingFlipbookSmall

This will produce a sprite flipbook as shown below:

CoinFlipbookAddedToBP

Click Play and play your game; hey, weren’t you promised loot in your game? Oh right — you have to add your gold coin actors to the game first! Whoops. :]

Click Stop and return to the 2DSideScrollerExampleMap tab like so:

ReturnToMainEditorMap

The act of creating an instance of a Blueprint and adding it to the game world is called spawning. In Sprite Kit, you’d construct an instance of your Coin Class and add it to your game’s scene; the process in Unreal is somewhat similar.

Spawn Points: Make Your Loot Appear

You know what you want to spawn: your CoinBP Blueprint. Now you need to specify where you want to spawn it. These locations are called Spawn Points or Target Points.

One of the really neat things about Unreal is that you can edit your game world using drag-and-drop actions. In order to create a spawn point, there’s no need to calculate x and y coordinates; you simply create a spawn point by clicking on the desired location with your mouse.

In the Modes view, type target into the search box:

TargetPointModes

Target Point is Unreal’s name for Spawn Point; you’ll see then used interchangeably in the Unreal development universe.

Use your mouse to drag and drop the Target Point from the Modes view to the center viewport and place it as shown below:

SpawnPoint1TargetAdded

That was easy — you’ve created your first Spawn Point!

Note: Your CoinBP is an example of a Class Blueprint: a tightly-focused chunk of game logic that represents a single piece of functionality in your game — in this case, loot.

The other major kind of Blueprint in Unreal is known as the Level Blueprint. This is a Blueprint that controls high-level logic across the entire game level itself, and typically holds the spawn logic of your game.

Left-click Blueprints\Open Level Blueprint to open the Level Blueprint editor:

OpenLevelBlueprint

You’re going to create a function to spawn coins. Even though Blueprints is a visual scripting language, it uses familiar concepts like functions to organize bits of related logic just like lower-level code SDKs do.

Left-click the + in Functions under My Blueprint and set the name to SpawnCoin:

SpawnCoinAddedNewFunction

Your goal is to have SpawnCoin call a built-in event to spawn an actor (the coin) at a certain point (the target point you added earlier). For this to work, you need to add a reference to the target point you added earlier in your graph.

To do this, click on 2DSideScrollerExampleMap to bring up the main editor view and ensure that TargetPoint is selected in the World Outliner:

SpawnCoinWorldOutlinerTargetPointSelectedSmall

Click on your level blueprint editor again to return to it.

Note: You’ll see two tabs labelled 2DSideScrollerExampleMap: one is the actual level map and one is the level Blueprint editor.

Hover your mouse over the tabs and the tooltip will tell you which is the level Blueprint editor: it should say 2DSideScrollerExampleMap – Level Blueprint Editor.

Right-click on the graph and the context menu should appear as below:

SpawnCoinTargetPointReferenceContextMenuSmall

If, for some reason, the Create a Reference to TargetPoint doesn’t appear, make sure the Context Sensitive checkbox is checked; also check to make sure you selected TargetPoint in the World Outliner above.

Click Create a Reference to TargetPoint to add the reference point:

SpawnCoinTargetPointReferenceAddedSmall

Now you’ve created a placeholder for your Target Point that you can use within this graph’s logic.

Left-click on the Target Point node’s right output pin, drag out into the graph and release. Type get actor transform into the search box and press Enter:

SpawnCoinGetActorTransformSmall

You should see the following appear in your graph:

SpawnCoinGetActorTransformAddedSmall

You’re probably wondering “What’s an Actor Transform?”

The Actor is the object in this case — your target point — and the Actor Transform is your Actor’s set of 3D geometric properties: location, rotation and scale. Your Get Actor Transform node spawns your coin at the transform of your TargetPoint.

Left-drag from the right orange Return Value pin of the of the Get Actor Transform node into your graph. Type spawn in the resulting search box:

SpawnCoinSpawnActorFromClassContextMenuSmall

Select Spawn Actor from Class to create a new node:

SpawnCoinSpawnActorFromClassAddedSmall

Note that the Spawn Transform input pin of SpawnActor NONE is connected to the Return Value output pin of Get Actor Transform. You’ve created a piece of logic that says “use the location of the target point to set the location of the actor I’m spawning.” Now you just need to tell Unreal what to spawn at that location.

Click in the purple Class pin on the left of SpawnActor NONE and scroll down to CoinBP:

SpawnCoinSpawnActorFromClassSelectClassSmall

Release your mouse to set the class as follows:

SpawnCoinSpawnActorFromClassClassSelectedSmall

Note that the Class is now CoinBP and SpawnActor NONE is now SpawnActor CoinBP, indicating that the SpawnActor node is configured to spawn a CoinBP actor.

There’s one step left to complete your function: to trigger the spawn event when the function executes. Left-drag from the SpawnCoin output exec pin to the input exec pin of SpawnActor CoinBP, which will produce the following in your graph:

SpawnCoinFunctionHookedUpToSpawnActorFromClassSmall

That’s it — you’ve created your first Blueprint function. Well done! :] Now you need to wire up your function so you can invoke it during gameplay.

The wiring happens in your Level Blueprint’s EventGraph, since this is where the magic happens for events in your game. Click on the Event Graph tab:

BackToLevelBPEventGraph

You’re going to wire the L key to generate Loot. Right-click in the graph, type L into the search box and press Enter to create an L key event. Left-drag from the Pressed output pin and release in the graph. Type function in the search box and select Spawn Coin as shown below:

SpawnCoinConnectToLKeySmall

This produces the following:

LToSpawn

As a reward for all your hard work, you are now at a spot where you can test out your loot generation! Click the Play button and move your BlueprintMan so that he drops down to the lower left ledge near your target point. Press the L key to make a coin appear at the target point:

CoinAlwaysSpawnedAtFirstTarget

Cha-ching — show me the money! :] When you’re done admiring your shiny new loot, click the Stop button or press Esc to stop the gameplay.

Randomness: More Fun and More Repeat Plays

Your game would a lot more fun — and challenging — if your loot appeared randomly throughout your game world. There’s a term for this: variable ratio rewards, which means “when stuff happens randomly, it’s more fun and encourages repeat play of your game.” It turns out random generation like this is quite easy to achieve in Unreal.

Go back to the 2DSideScrollerExampleMap tab, drag another Target Point onto your viewport and drop it on the ledge just to the right of your first target point. This new target point will automatically be named TargetPoint2.

Return to the Level Blueprint, right-click in the graph and select Create a Reference to TargetPoint2.

Return to 2DSideScrollerExampleMap and add a third target point on the ledge just to the right of TargetPoint2, like so:

ThreeSpawnPointsAddedSmall

Unreal will automatically name this TargetPoint3.

Return to the Level Blueprint editor and add a reference to TargetPoint3. Your graph should now look like the following:

SpawnCoinTargetPoint2AddedSmall

To make random selection of target points easier, you’re going to add the three points to an array. Once again, Blueprints uses a familiar programming concept — arrays — to help you organize your game logic.

Right-click in the graph and type make array:

SpawnCoinArrayAddContextMenuSmall

Hit Enter to produce the following:

SpawnCoinArrayAddedSmall

Click the white + sign beside Add pin two times to produce a three-element array container:

SpawnCoinArrayPinsAddedSmall

Don’t worry about the red ERROR! message at the bottom of the node: this is just Unreal telling you that it doesn’t yet know what type of object is going to go in the array.

Left-drag from TargetPoint to the Make Array [0] pin; then perform the same action for TargetPoint2 and TargetPoint3 to the [1] and [2] pins respectively.

You’ll now have the following connections in place:

SpawnCoinArrayErrorReasonSmall

The error message is still there; simply click the Compile button to resolve the issues:

SpawnCoinArrayErrorClearedAfterCompileSmall

There, that looks better.

To spawn a coin, you need to randomly pick one element of your array. Right-click to the right of the array node, type array and select Get:

SpawnCoinArrayGetContextMenuSmall

Then left-drag from the left grid-like blue pin of the Get node to the right grid-like blue pin of the Make Array node to produce the following connection:

SpawnCoinIndex0AttachedToArraySmall

Left-drag from the right output blue pin of the Get node to the left input blue Target pin of the Get Actor Transform like so:

HookedUpToTarget

Note that the direct link from Get Actor Transform to TargetPoint has been replaced by this new link to the array, indicating that instead of hard-coding the value to a single spawn point, it should now choose an element from the array.

You’re almost there! Now you need to add some randomness.

ragecomic_dice

Left-drag from the green input pin of the Get node to create a Random Integer node and set its Max value to 3 as shown below:

SpawnCoinCompleteSmall

Since three-sided dice are hard (but not impossible!) to come by, you simply sample a random integer in 0, 1, 2 and use it as the index of the spawn point.

Click Play, drop down onto the lower ledges and press the L key a few times; you should see coins spawn randomly between your three spawn points. Click Stop when you’re done.

Right now, your game lets the player spawn a gold coin whenever they wish — predictable, but boring. It would be far more awesome if you could not only spawn the coins in random places, but at random times as well!

More Challenging Loot

Switch to the Event Graph tab in your Blueprint, right-click on an empty space, type event begin play and select the top match (Event Begin Play):

TimerEventBeginPlayContextMenu

You’ll be rewarded with the following:

TimerEventBeginPlayAddedSmall

EventBeginPlay occurs for any Blueprint when its life begins within the game; think of it as a post-initialization step that you can use to perform further setup tasks for your Blueprint. You’re going to wire up periodic coin spawning to begin when the level starts.

Left-drag from the EventBeginPlay right output pin and release in the graph. Type set timer in the search box:

TimerContextMenuSmall

Hit Enter to produce the following node:

TimerJustAddedSmall

Generating a coins every two seconds sounds just about right. Enter 2 in the Time pin and check the Looping pin to produce the following:

TimerTimeAndLoopingSetSmall

Type SpawnCoin (not that there is no space between “Spawn” and “Coin”) in the Function Name pin:

FunctionNameSet

This instructs Unreal to invoke the SpawnCoin function every two seconds and to continue doing so as long as the game keeps playing.

Click Play and you should see coins randomly spawn at one of the three spawn points, every two seconds, as shown below:

RandomLootSpawning

And there you have it — a solid start to a 2D platformer game — without writing a stitch of code. Neat, eh? :]

Where to Go From Here?

You can download the completed example project for this tutorial series here.

This tutorial has only scratched the surface of what you can do with Unreal; hopefully this series has piqued your interest to explore further.

You can find lots of additional documentation and tutorials on Unreal at the Epic games website; here are a few choice links that will give you some more in-depth information on what you’ve covered in this tutorial series:

If you enjoyed this tutorial and would like to see more Unreal Engine tutorials on this site, or if you have any questions or comments, please let us know in the comments below!

Unreal Engine Tutorial for Beginners: Part 2 is a post from: Ray Wenderlich

The post Unreal Engine Tutorial for Beginners: Part 2 appeared first on Ray Wenderlich.

Video Tutorial: Custom Collection View Layouts Part 6: DIY – Limiting Stretch

Overlay Views with MapKit and Swift Tutorial

$
0
0
Learn how to add an overlay image using MapKit!

Learn how to add an overlay image using MapKit!

Update note: This tutorial was updated for Swift, iOS 8, and Xcode 6.1 by Niv Yahel. Previous updates by Cesare Rocchi, and original post by Chris Wagner.

It’s quite easy to add a map into your app using MapKit. But what if you want to decorate or customize the map provided by Apple with your own annotations and images?

Luckily, Apple provides and easy way to do this with custom overlay views.

In this tutorial, you’ll create an app for the Six Flags Magic Mountain amusement park. If you’re a roller coaster fan in the LA area, you’ll be sure to appreciate this app! :]

Just think about what would interest a visitor to the park that isn’t in the standard satellite or map view. Things like the location of specific attractions, routes to the various rides and roller coasters, and the location of characters around the park are all perfect candidates for custom overlay images – and that’s exactly what you’ll be adding in this tutorial.

Keep reading to add some excitement to these vanilla maps!

Note: You have two options for how to proceed with this tutorial based on your experience level:
  1. Already familiar with MapKit? If you’re already familiar with MapKit and want to dive right into the overlay image code, you can skip (or scan) ahead to the “All About Overlay Views” section – there’s a starter project waiting for you there.
  2. New to MapKit? If you are new to MapKit, keep reading and I’ll walk you through adding map into your app from the very beginning!

Getting Started

To get started, download the starter project which provides you with a basic application for both the iPhone and the iPad, with some rudimentary navigation included – but no maps yet!

The interface provided in the starter app contains a UISegmentedControl to switch between the different map types you will implement, and an action button which presents a table of options to allow you to choose what map features to display. You select or deselect options by tapping them, and tapping the Done button will dismiss the options list.

The class MapOptionsViewController drives the options view, which defines an important enum that you’ll use later on. The rest of the code in this class is outside the scope of this tutorial. However, if you need more information on UITableView, check out one of the many UITableView tutorials to quickly get up to speed.

Open up the starter project in Xcode, and build and run. I bet you didn’t expect that so soon in the tutorial! You’ll see the following:

Park view app screenshots

As advertised, the starter app is pretty basic! If your map application is going to do anything useful, then it’s going to need a map, for starters!

Adding A Map View

To add a MapView to your app, start by opening MainStoryboard_iPhone.storyboard. Select the Park Map View Controller scene, and drop a Map View object on the view. Position the MapView so it fills the entire view, as shown below:

Park view app screenshots

Now open up MainStoryboard_iPad.storyboard, add a MapView as above, and again adjust it so it fills the entire view.

Resist the temptation to build and run the app at this point to see what it looks like with your map added; however, if you did, you would see the following exception and your app will crash:

*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named MKMapView'

This is because you haven’t yet linked the MapKit.framework to your target!

Wiring Up Your MapView

You’ll be writing a whole lot of MapKit code, so the easiest way to get the framework into the build is to reference it from code. Open ParkMapViewController.swift and add the following import to the top of the file:

import MapKit

This will make MapKit available within this source file, and also include it into the project as a whole.

To do anything with a MapView, you need to do two things – associate it with an outlet, and register the view controller as the MapView’s delegate.

Next, open MainStoryboard_iPhone.storyboard and make sure your Assistant Editor is open with ParkMapViewController.swift visible. Then control-drag from the map view to above the first outlet, as shown below:

Add MapView Outlet

In the popup that appears, name the outlet mapView, and click Connect.

Now you need to set the delegate for your map view. To do this, right-click on the map view object to open the context menu, then drag the delegate outlet to Park Map View Controller, as shown below:

Set MapView Delegate

Now perform the same steps for your iPad storyboard — connect the MapView to the mapView outlet (but this time drag on top of the existing outlet rather than creating a new one), and make the view controller the MapView’s delegate.

Now having finished wiring your outlets, you need to indicate that ParkMapViewController conforms to the MKMapViewDelegate protocol. Open ParkMapViewController.swift and add the following to the very end of the file, outside the class declaration curly braces:

// MARK: - Map View delegate
 
extension ParkMapViewController: MKMapViewDelegate {
}

You’ll fill in the delegate methods later. But for now, that’s it for setting your outlets, delegates, and controllers.

Build and run to check out your snazzy new map! It should look like the screenshot below:

Park Map View Map Example

As you can see, it doesn’t take much work to add a map to your app.

As cool as it is to have a map in your application, it would be even cooler if you could actually do something with the map! :] It’s time to start adding some interactions to your map!

Interacting With MKMapView

Although the default view of the map looks nice, it’s a little too broad to be of use since it is the theme park that interests the user, not the entire continent! It would make more sense to center the map view on the park when you launch the app.

There are many ways to provide position information for a specific location; you could fetch it from a web service, or you could simply package it and ship it with the app itself.

To keep things simple, you will include the location information for the park with your app in this tutorial. Download the resources for this project, which contains a file named MagicMountain.plist with the park information:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>midCoord</key>
        <string>{34.4248,-118.5971}</string>
        <key>overlayTopLeftCoord</key>
        <string>{34.4311,-118.6012}</string>
        <key>overlayTopRightCoord</key>
        <string>{34.4311,-118.5912}</string>
        <key>overlayBottomLeftCoord</key>
        <string>{34.4194,-118.6012}</string>
        <key>boundary</key>
        <array>
                <string>{34.4313,-118.59890}</string>
                <string>{34.4274,-118.60246}</string>
                <string>{34.4268,-118.60181}</string>
                <string>{34.4202,-118.6004}</string>
                <string>{34.42013,-118.59239}</string>
                <string>{34.42049,-118.59051}</string>
                <string>{34.42305,-118.59276}</string>
                <string>{34.42557,-118.59289}</string>
                <string>{34.42739,-118.59171}</string>
        </array>
</dict>
</plist>

This file contains the information that you need to center the map on the park, and it also contains boundary information for the park which you’ll use a bit later.

All information in this file is in the form of latitude/longitude coordinates.

Add this file to your project by dragging it to the Park Information group and choosing to copy it to the project.

Now that you have some geographical information about the park, you should model it into a Swift class in order to work with it in your app.

Right-click the Models group, and choose New File… Select the iOS\Source\Swift File template for the file and name it Park.

Once you create the new class, open Park.swift and replace its contents with the following:

import Foundation
import MapKit
 
class Park {
  var boundary: [CLLocationCoordinate2D]
  var boundaryPointsCount: NSInteger
 
  var midCoordinate: CLLocationCoordinate2D
  var overlayTopLeftCoordinate: CLLocationCoordinate2D
  var overlayTopRightCoordinate: CLLocationCoordinate2D
  var overlayBottomLeftCoordinate: CLLocationCoordinate2D
  var overlayBottomRightCoordinate: CLLocationCoordinate2D
 
  var overlayBoundingMapRect: MKMapRect
 
  var name: String?
}

Most of these properties should look familiar, as they have counterparts in the plist file above.

Now, having defined the properties of the class, you need to add an initializer, which will allow you to give the defined properties a value. The initializer, init(filename:), will read all of the information from the plist file into the defined properties. This will be pretty straightforward if you have done any file I/O with property lists.

Add the following code to the Park class:

init(filename: String) {
  let filePath = NSBundle.mainBundle().pathForResource(filename, ofType: "plist")
  let properties = NSDictionary(contentsOfFile: filePath!)
 
  let midPoint = CGPointFromString(properties!["midCoord"] as String)
  midCoordinate = CLLocationCoordinate2DMake(CLLocationDegrees(midPoint.x), CLLocationDegrees(midPoint.y))
 
  let overlayTopLeftPoint = CGPointFromString(properties!["overlayTopLeftCoord"] as String)
  overlayTopLeftCoordinate = CLLocationCoordinate2DMake(CLLocationDegrees(overlayTopLeftPoint.x),
    CLLocationDegrees(overlayTopLeftPoint.y))
 
  let overlayTopRightPoint = CGPointFromString(properties!["overlayTopRightCoord"] as String)
  overlayTopRightCoordinate = CLLocationCoordinate2DMake(CLLocationDegrees(overlayTopRightPoint.x),
    CLLocationDegrees(overlayTopRightPoint.y))
 
  let overlayBottomLeftPoint = CGPointFromString(properties!["overlayBottomLeftCoord"] as String)
  overlayBottomLeftCoordinate = CLLocationCoordinate2DMake(CLLocationDegrees(overlayBottomLeftPoint.x),
      CLLocationDegrees(overlayBottomLeftPoint.y))
 
  let boundaryPoints = properties!["boundary"] as NSArray
 
  boundaryPointsCount = boundaryPoints.count
 
  boundary = []
 
  for i in 0...boundaryPointsCount-1 {
    let p = CGPointFromString(boundaryPoints[i] as String)
    boundary += [CLLocationCoordinate2DMake(CLLocationDegrees(p.x), CLLocationDegrees(p.y))]
  }
}
Note: properties reads the contents of the file as defined by filePath as a NSDictionary. Each element’s type is AnyObject. To convert the values into Strings, you must downcast them by adding as String when accessing the NSDictionary‘s elements.

The code above uses CLLocationCoordinate2DMake() to make a CLLocationCoordinate2D structure using latitude and longitude coordinates. MapKit API’s use CLLocationCoordinate2D structures to represent geographical locations.

This initializer also creates a CLLocationCoordinate2D array that will be used later to display the park boundary.

One property missing from the property list file is overlayBottomRightCoordinate. The plist file provides coordinates for the other three corners (top right, top left, and bottom left), but not the bottom right. Why?

The reason is that you can calculate this final corner of the rectangle based on the other three points — it would be redundant to include this information when you can calculate it.

Replace the current declaration of overlayBottomRightCoordinate inside of Park.swift with the following code in order to implement the calculated bottom right coordinate:

var overlayBottomRightCoordinate: CLLocationCoordinate2D {
  get {
    return CLLocationCoordinate2DMake(overlayBottomLeftCoordinate.latitude,
      overlayTopRightCoordinate.longitude)
  }
}

This getter method generates the bottom right coordinate using the bottom left and top right coordinates.

Finally, you’ll need a method to create a bounding box based on the coordinates read in above.

Replace the definition of overlayBoundingMapRect inside of Park.swift with the following:

var overlayBoundingMapRect: MKMapRect {
  get {
    let topLeft = MKMapPointForCoordinate(overlayTopLeftCoordinate)
    let topRight = MKMapPointForCoordinate(overlayTopRightCoordinate)
    let bottomLeft = MKMapPointForCoordinate(overlayBottomLeftCoordinate)
 
    return MKMapRectMake(topLeft.x,
      topLeft.y,
      fabs(topLeft.x-topRight.x),
      fabs(topLeft.y - bottomLeft.y))
  }
}

This getter method generates an MKMapRect object, which is a bounding rectangle for the park’s boundaries. It’s really just a rectangle that defines how big the park is, based on the provided coordinates, and is centered on the midpoint of the park.

Now it’s time to put this new class to use. Open ParkMapViewController.swift and add the following property to the class:

var park = Park(filename: "MagicMountain")

This will initialize the park property using MagicMountain.plist by default. Then change viewDidLoad as follows:

override func viewDidLoad() {
  super.viewDidLoad()
 
  let latDelta = park.overlayTopLeftCoordinate.latitude -
    park.overlayBottomRightCoordinate.latitude
 
  // think of a span as a tv size, measure from one corner to another
  let span = MKCoordinateSpanMake(fabs(latDelta), 0.0)
 
  let region = MKCoordinateRegionMake(park.midCoordinate, span)
 
  mapView.region = region
}

The code now creates a latitude delta, which is the distance from the top left coordinate of the park’s property to the bottom right coordinate of the park’s property.

You can then use the latitude delta to generate an MKCoordinateSpan struct which defines the area spanned by a map region.

MKCoordinateSpan is then used along with the park’s midCoordinate property (which is just the midpoint of the park’s bounding rectangle) to create an MKCoordinateRegion. This MKCoordinateRegion structure is then used to position the map in the map view using the region property.

Build and run your app. Notice that the app centers the map right on the Six Flags Magic Mountain Park, just as in the image below:

Okay! Now you centered the map on the park, which is great. But the display doesn’t look terribly exciting. It’s just a big beige blank spot with a few streets on the edges.

If you’ve ever played with the Maps app, you know that the satellite imagery looks pretty cool. You can easily leverage the same satellite data in your app to dress it up a little!

Switching The Map Type

In ParkMapViewController.swift, you will find a method at the bottom that looks like the following:

@IBAction func mapTypeChanged(sender: AnyObject) {
  // To be implemented
}

Hmm, that’s a pretty ominous-sounding comment in there! :]

Fortunately, the starter project has much of what you’ll need to flesh out this method. Did you note the segmented control sitting above the map view that seems to be doing a whole lot of nothing?

That segmented control is actually calling mapTypeChanged(_:), but as you can see above, the method does nothing — yet!

Add the following implementation to mapTypeChanged():

let mapType = MapType(rawValue: mapTypeSegmentedControl.selectedSegmentIndex)
switch (mapType!) {
case .Standard:
  mapView.mapType = MKMapType.Standard
case .Hybrid:
  mapView.mapType = MKMapType.Hybrid
case .Satellite:
  mapView.mapType = MKMapType.Satellite
}

Believe it or not, adding standard, satellite, and hybrid map types to your app is as simple as a switch statement on mapTypeSegmentedControl.selectedSegmentIndex, as seen in the code above! Wasn’t that easy?

Build and run your app. Using the segmented control at the top of the screen, you should be able to flip through the map types, as seen below:

Even though the satellite view still is much better than the standard map view, it’s still not very useful to your park visitors. There’s nothing labeled — how will your users find anything in the park?

One obvious way is to drop a UIView on top of the map view, but you can take it a step further and instead leverage the magic of MKOverlayRenderer to do a lot of the work for you!

All About Overlay Views

Note: If you’re skipping ahead from earlier in this tutorial, you can pick up at this point with this starter project. Also, you should download the resources for this project which you’ll be adding in as you go.

Before you start creating your own views, you need to understand the classes that make this all possible – MKOverlay and MKOverlayRenderer.

A MKOverlay is how you tell MapKit where you want the overlays drawn. There are three steps to using the class:

  1. Create your own custom class that implements the MKOverlay protocol, which has two required properties: coordinate and boundingMapRect. These two properties define where the overlay resides on the map, as well as its size.
  2. Create an instance of this class for each area for which you want to display an overlay. For example, in this app, you might create one instance for a rollercoaster overlay, and one for a restaurant overlay.
  3. Finally, add the overlays to your Map View.

Now the Map View knows where it’s supposed to display overlays – but how does it know what to display in each region?

Enter MKOverlayRenderer. You create a subclass of this to set up what you want to display in each spot. For example, in this app you’ll just draw an image of the rollercoaster or restaurant.

A MKOverlayRenderer is really just a special kind of UIView, as it inherits from UIView. However, you don’t add an MKOverlayRenderer directly to the MKMapView. This is an object the MapKit framework expects you to provide. After you give it to MapKit, it will render it as an overlay on top of the map.

Remember how a map view has a delegate – and you set it to your view controller in this tutorial? Well, there’s a delegate method you implement to return an overlay view:

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer!

MapKit will call this method when it realizes there is an MKOverlay object in the region that the map view’s viewport is displaying.

To sum it up, you don’t add MKOverlayRenderer objects directly to the map view; rather, you tell the map about MKOverlay objects to display and return them when the delegate method requests them.

Now that you’ve covered the theory, it’s time to put those concepts to use!

Adding Your Own Information

As you saw earlier, the satellite view still doesn’t provide enough information about the park. Your task is to create an object that represents an overlay for the entire park to dress it up a little.

Select the Overlays group and create a new Swift file named ParkMapOverlay. Then replace ParkMapOverlay.swift with the following:

import UIKit
import MapKit
 
class ParkMapOverlay: NSObject, MKOverlay {
  var coordinate: CLLocationCoordinate2D
  var boundingMapRect: MKMapRect
 
  init(park: Park) {
    boundingMapRect = park.overlayBoundingMapRect
    coordinate = park.midCoordinate
  }
}

In the code above, you import the MapKit header to get those classes in scope. Conforming to the MKOverlay means you also have to inherit from NSObject. Finally, the initializer simply takes the properties from the passed Park object, and sets them to the corresponding MKOverlay properties.

Now you need to create a view class derived from the MKOverlayRenderer class.

Create a new Swift file in the Overlays group called ParkMapOverlayView. Open the file and replace its contents with the following:

import UIKit
import MapKit
 
class ParkMapOverlayView: MKOverlayRenderer {
  var overlayImage: UIImage
 
  init(overlay:MKOverlay, overlayImage:UIImage) {
    self.overlayImage = overlayImage
    super.init(overlay: overlay)
  }
 
  override func drawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale, inContext context: CGContext!) {
    let imageReference = overlayImage.CGImage
 
    let theMapRect = overlay.boundingMapRect
    let theRect = rectForMapRect(theMapRect)
 
    CGContextScaleCTM(context, 1.0, -1.0)
    CGContextTranslateCTM(context, 0.0, -theRect.size.height)
    CGContextDrawImage(context, theRect, imageReference)
  }
}

The implementation here contains two methods and a UIImage property for the overlay image itself.

init(overlay:overlayImage:) effectively overrides the base method init(overlay:) by providing a second argument overlayImage. The passed image is stored in the class extension property that appears in the next method, drawMapRect.

drawMapRect is the real meat of this class; it defines how MapKit should render this view when given a specific MKMapRect, MKZoomScale, and the CGContextRef of the graphic context, with the intent to draw the overlay image onto the context at the appropriate scale.

Details on Core Graphics drawing is quite far out of scope for this tutorial. However, you can see that the code above uses the passed MKMapRect to get a CGRect, in order to determine the location to draw the CGImageRef of the UIImage on the provided context. If you want to learn more about Core Graphics, check out our Core Graphics tutorial series.

Okay! Now that you have both an MKOverlay and MKOverlayRenderer, you can add them to your map view.

In ParkMapViewController.swift, add the following method to the class:

func addOverlay() {
  let overlay = ParkMapOverlay(park: park)
  mapView.addOverlay(overlay)
}

This method will add an MKOverlay to the map view.

If the user should choose to show the map overlay, then loadSelectedOptions() should call addOverlay(). Update loadSelectedOptions() with the following code:

func loadSelectedOptions() {
  mapView.removeAnnotations(mapView.annotations)
  mapView.removeOverlays(mapView.overlays)
 
  for option in selectedOptions {
    switch (option) {
    case .MapOverlay:
      addOverlay()
    default:
      break;
    }
  }
}

Whenever the user dismisses the options selection view, the app calls loadSelectedOptions(), which then determines the selected options, and calls the appropriate methods to render those selections on the map view.

loadSelectedOptions() also removes any annotations and overlays that may be present so that you don’t end up with duplicate renderings. This is not necessarily efficient, but it is a simple approach for the purposes of this tutorial.

To implement the delegate method, add the following method to the MKMapViewDelegate extension at the bottom of the file:

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
  if overlay is ParkMapOverlay {
    let magicMountainImage = UIImage(named: "overlay_park")
    let overlayView = ParkMapOverlayView(overlay: overlay, overlayImage: magicMountainImage!)
 
    return overlayView
  } 
 
  return nil
}

When the app determines that an MKOverlay is in view, the map view calls the above method as the delegate. The method here then returns a MKOverlayRenderer for the matching MKOverlay.

In this case, you check to see if the overlay is of the class type ParkMapOverlay; if so, you load the overlay image, create a ParkMapOverlayView instance with the overlay image, and then return this instance to the caller.

There’s one little piece missing, though — where does that suspicious little overlay_park image come from?

That’s a PNG file whose purpose is to overlay the map view for the defined boundary of the park. The overlay_park image (from the resources for this tutorial you’ve already downloaded) looks like this:

Add both the non-retina and retina images to your project under the Images group.

Build and run, choose the Map Overlay option, and voila! There’s the park overlay drawn on top of your map, just like in the screenshot below:

Zoom in, zoom out, and move around as much as you want — the overlay scales and moves as you would expect. Cool!

Annotations

If you’ve ever searched for a location in the Maps app, then you’ve seen those colored pins that appear on the map. These are known as annotations, which are created with MKAnnotationView. You can use annotations in your own app — and you can use any image you want, not just pins!

Annotations will be useful in your app to help point out specific attractions to the park visitors. Annotation objects work similarly to MKOverlay and MKOverlayRenderer, but instead you will be working with MKAnnotation and MKAnnotationView.

Create a new Swift fise in the Annotations group called AttractionAnnotation and open the new file. Replace its contents with the following:

import UIKit
import MapKit
 
enum AttractionType: Int {
  case AttractionDefault = 0
  case AttractionRide
  case AttractionFood
  case AttractionFirstAid
}
 
class AttractionAnnotation: NSObject, MKAnnotation {
  var coordinate: CLLocationCoordinate2D
  var title: String
  var subtitle: String
  var type: AttractionType
 
  init(coordinate: CLLocationCoordinate2D, title: String, subtitle: String, type: AttractionType) {
    self.coordinate = coordinate
    self.title = title
    self.subtitle = subtitle
    self.type = type
  }
}

Here you first define an enum for AttractionType to help you categorize each attraction into a type. This enum lists four types of annotations: default, rides, foods and first aid.

Next you declare that this class conforms to the MKAnnotation Protocol. Much like MKOverlay, MKAnnotation has a required coordinate property. You define a handful of properties specific to this implementation. Lastly, you define an initializer that allows you to assign values to each of the properties.

Now you need to create a specific instance of MKAnnotation to use for your annotations.

Create another Swift file called AttractionAnnotationView under the Annotations group. Open the file and replace its contents with the following:

import UIKit
import MapKit
 
class AttractionAnnotationView: MKAnnotationView {
  // Required for MKAnnotationView
  required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }
 
  // Called when drawing the AttractionAnnotationView
  override init(frame: CGRect) {
    super.init(frame: frame)
  }
 
  override init(annotation: MKAnnotation, reuseIdentifier: String) {
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
    let attractionAnnotation = self.annotation as AttractionAnnotation
    switch (attractionAnnotation.type) {
    case .AttractionFirstAid:
      image = UIImage(named: "firstaid")
    case .AttractionFood:
      image = UIImage(named: "food")
    case .AttractionRide:
      image = UIImage(named: "ride")
    default:
      image = UIImage(named: "star")
    }
  }
}

MKAnnotationView requires two defined initializers: init(coder:) and init(frame:). Without their definition, errors will prevent you from building and running the app. To prevent this, simply define them and call their superclass initializers. Here, you also override init(annotation:reuseIdentifier:) based on the annotation’s type property, you set a different image on the image property of the annotation.

Great! Now having created the annotation and its associated view, you can start adding them to your map view!

First you’ll first need a few resource files that you referenced in init(annotation:reuseIdentifier:) (included in annotation-images.zip). They’re included in the resources ZIP file you’ve already downloaded; unpack annotation-images.zip and drag the images inside to the images group in your project. Also bring MagicMountainAttractions.plist into the Park Information group in your project in the same way.

For the curious among you, the plist file contains coordinate information and other details about the attractions at the park, such as the following:

<dict>
  <key>name</key>
  <string>Cold Stone</string>
  <key>location</key>
  <string>{34.42401,-118.59495}</string>
  <key>type</key>
  <string>2</string>
  <key>subtitle</key>
  <string>Cost: $</string>
</dict>

Now that you have the above resource files in place, you can leverage your new annotations!

Go back to ParkMapViewController.swift and insert the method below to add the attraction annotations to the map view.

func addAttractionPins() {
  let filePath = NSBundle.mainBundle().pathForResource("MagicMountainAttractions", ofType: "plist")
  let attractions = NSArray(contentsOfFile: filePath!)
  for attraction in attractions! {
    let point = CGPointFromString(attraction["location"] as String)
    let coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(point.x), CLLocationDegrees(point.y))
    let title = attraction["name"] as String
    let typeRawValue = (attraction["type"] as String).toInt()!
    let type = AttractionType(rawValue: typeRawValue)!
    let subtitle = attraction["subtitle"] as String
    let annotation = AttractionAnnotation(coordinate: coordinate, title: title, subtitle: subtitle, type: type)
    mapView.addAnnotation(annotation)
  }
}

This method reads MagicMountainAttractions.plist and enumerates over the array of dictionaries. For each entry, it creates an instance of AttractionAnnotation with the attraction’s information, and then adds each annotation to the map view.

Now you need to update loadSelectedOptions() to accommodate this new option and execute your new method when the user selects it.

Modify loadSelectedOptions() (still in ParkMapViewController.swift) as shown below:

func loadSelectedOptions() {
  mapView.removeAnnotations(mapView.annotations)
  mapView.removeOverlays(mapView.overlays)
 
  for option in selectedOptions {
    switch (option) {
      case .MapOverlay:
        addOverlay()
      case .MapPins:
        addAttractionPins()
      default:
        break;
    }
  }
}

In addition to the overlays, you’re also hiding and showing the pins as required by calling removeOverlays or your new addAttractionPins() method.

You’re almost there! Last but not least, you need to implement another delegate method that provides the MKAnnotationView instances to the map view so that it can render them on itself.

Open ParkMapViewController.swift and add the following method to the MKMapViewDelegate class extension at the bottom of the file:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
  let annotationView = AttractionAnnotationView(annotation: annotation, reuseIdentifier: "Attraction")
  annotationView.canShowCallout = true
  return annotationView
}

This method receives the selected MKAnnotation, and uses it to create the AttractionAnnotationView. The property canShowCallout is set to true so that when the user touches the annotation, a call-out appears with more information. Finally, the method returns the annotation view.

Build and run to see your annotations in action!

Turn on the Attraction Pins to see the result as in the screenshot below:

The Attraction pins are looking rather…sharp at this point! :]

So far you’ve covered a lot of complicated bits of MapKit, including overlays and annotations. But what if you need to use some drawing primitives, like lines, shapes, and circles?

The MapKit framework also gives you the ability to draw directly on a map view! MapKit provides MKPolyline, MKPolygon, and MKCircle for just this purpose.

I Walk The Line – MKPolyline

If you’ve ever been to Magic Mountain, you know that the Goliath hypercoaster is an incredible ride, and some riders like to make a beeline for it once they walk in the gate! :]

To help out these riders, you’ll plot a path from the entrance of the park to the Goliath.

MKPolyline is a great solution for drawing a path that connects multiple points, such as plotting a non-linear route from point A to point B. You’ll use MKPolyline in your app to draw the route that the Goliath fans should follow to ensure they get to the ride as quickly as possible!

To draw a polyline, you need a series of longitude and latitude coordinates in the order that the code should plot them. Order really is important here — otherwise, you’ll have a meandering mess of connected points, which won’t do your riders any good!

The resources for this tutorial contains a file called EntranceToGoliathRoute.plist that contains the path information, so add it to your project.

The plist has an array of coordinates like this:

<string>{34.42367,-118.594836}</string>
<string>{34.423597,-118.595205}</string>
<string>{34.423004,-118.59537}</string>

These are the latitude and longitude coordinates of each of the points in the path.

Now you need a way to read in that plist file and create the route for the riders to follow.

Open ParkMapViewController.swift and add the following method to the class:

func addRoute() {
  let thePath = NSBundle.mainBundle().pathForResource("EntranceToGoliathRoute", ofType: "plist")
  let pointsArray = NSArray(contentsOfFile: thePath!)
 
  let pointsCount = pointsArray!.count
 
  var pointsToUse: [CLLocationCoordinate2D] = []
 
  for i in 0...pointsCount-1 {
    let p = CGPointFromString(pointsArray![i] as String)
    pointsToUse += [CLLocationCoordinate2DMake(CLLocationDegrees(p.x), CLLocationDegrees(p.y))]
  }
 
  let myPolyline = MKPolyline(coordinates: &pointsToUse, count: pointsCount)
 
  mapView.addOverlay(myPolyline)
}

This method reads EntranceToGoliathRoute.plist, and enumerates over the contained array where it converts the individual coordinate strings to CLLocationCoordinate2D structures.

It’s remarkable how simple it is to implement your polyline in your app; you simply create an array containing all of the points, and pass it to MKPolyline! It doesn’t get much easier than that.

Now you need to add an option to allow the user to turn the polyline path on or off.

Update loadSelectedOptions() to match the code below:

func loadSelectedOptions() {
  mapView.removeAnnotations(mapView.annotations)
  mapView.removeOverlays(mapView.overlays)
 
  for option in selectedOptions {
    switch (option) {
      case .MapOverlay:
        addOverlay()
      case .MapPins:
        addAttractionPins()
      case .MapRoute:
        addRoute()
      default:
        break;
    }
  }
}

The new case here adds the .MapRoute value and the addRoute() method you just added.

Finally, to tie it all together, you need to update the delegate method so that it returns the actual view you want to render on the map view.

Update mapView(_:rendererForOverlay) to handle the case of a polyline overview, as follows:

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
  if overlay is ParkMapOverlay {
    let magicMountainImage = UIImage(named: "overlay_park")
    let overlayView = ParkMapOverlayView(overlay: overlay, overlayImage: magicMountainImage!)
 
    return overlayView
  } else if overlay is MKPolyline {
    let lineView = MKPolylineRenderer(overlay: overlay)
    lineView.strokeColor = UIColor.greenColor()
 
    return lineView
  }
 
  return nil
}

The change here is the additional else if branch to look for MKPolyline objects. The process of displaying the polyline view is very similar to previous overlay views. However, in this case, you do not need to create any custom view objects. You simply use the MKPolyLineRenderer framework provided, and initialize a new instance with the overlay.

MKPolyLineRenderer also provides you with the ability to change certain attributes of the polyline. In this case, you’ve modified the stroke color to show as green.

Build and run your app, enable the route option, and it should appear on the screen as in the screenshot below:

Goliath fanatics will now be able to make it to the coaster in record time! :]

It would be nice to show the park patrons where the actual park boundaries are, as the park doesn’t actually occupy the entire space shown on the screen.

Although you could use MKPolyline to draw a shape around the park boundaries, MapKit provides another class that is specifically designed to draw closed polygons: MKPolygon.

Don’t Fence Me In – MKPolygon

MKPolygon is remarkably similar to MKPolyline, except that the first and last points in the set of coordinates are connected to each other to create a closed shape.

You’ll create an MKPolygon as an overlay that will show the park boundaries. The park boundary coordinates are already defined in MagicMountain.plist; go back and look at init(filename:) to see where the boundary points are read in from the plist file.

Add the following method to ParkMapViewController.swift:

func addBoundary() {
  let polygon = MKPolygon(coordinates: &park.boundary, count: park.boundaryPointsCount)
  mapView.addOverlay(polygon)
}

The implementation of addBoundary above is pretty straightforward. Given the boundary array and point count from the park instance, you can quickly and easily create a new MKPolygon instance!

Can you guess the next step here? It’s very similar to what you did for MKPolyline above.

Yep, that’s right — update loadSelectedOptions to handle the new option of showing or hiding the park boundary, as shown below:

func loadSelectedOptions() {
  mapView.removeAnnotations(mapView.annotations)
  mapView.removeOverlays(mapView.overlays)
 
  for option in selectedOptions {
    switch (option) {
      case .MapOverlay:
        addOverlay()
      case .MapPins:
        addAttractionPins()
      case .MapRoute:
        addRoute()
      case .MapBoundary:
        addBoundary()
      default:
        break;
    }
  }
}

Notice the new case for .MapBoundary with the call to your new addBoundary() method.

MKPolygon conforms to MKOverlay just as MKPolyline does, so you need to update the delegate method again.

Update the delegate method in ParkMapViewController.swift as follows:

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
  if overlay is ParkMapOverlay {
    let magicMountainImage = UIImage(named: "overlay_park")
    let overlayView = ParkMapOverlayView(overlay: overlay, overlayImage: magicMountainImage!)
 
    return overlayView
  } else if overlay is MKPolyline {
    let lineView = MKPolylineRenderer(overlay: overlay)
    lineView.strokeColor = UIColor.greenColor()
 
    return lineView
  } else if overlay is MKPolygon {
    let polygonView = MKPolygonRenderer(overlay: overlay)
    polygonView.strokeColor = UIColor.magentaColor()
 
    return polygonView
  }
 
  return nil
}

The update to the delegate method is as straightforward as before. You create an MKOverlayView as an instance of MKPolygonRenderer, and set the stroke color to magenta.

Run the app to see your new boundary in action!

That takes care of polylines and polygons. The last drawing method to cover is drawing circles as an overlay, which is neatly handled by MKCircle.

Circle In The Sand – MKCircle

MKCircle is again very similar to MKPolyline and MKPolygon, except that it draws a circle, given a coordinate point as the center of the circle, and a radius that determines the size of the circle.

You can easily imagine that users would like to mark on the map where they spotted a character in the park, and have that information communicated to other app users in the park. As well, the radius of the circle representing a character could change, depending on how long it has been since that character was last spotted.

You won’t go quite that far in this tutorial, but at the very least, you can load up some sample character coordinate data from a file and draw some circles on the map to simulate the location of those characters.

The MKCircle overlay is a very easy way to implement this functionality.

The resources for this tutorial contains the character location files (character-locations.zip), so make sure you unzip that file and add all the plist files inside to your project.

Each file is an array of a few coordinates where the user spotted characters.

Create a new Swift file under the Models group called Character. Open the new Character.swift and replace its contents with the following code:

import UIKit
import MapKit
 
class Character: MKCircle, MKOverlay {
 
  var name: String?
  var color: UIColor?
}

The new class that you just added conforms to the MKOverlay protocol, and defines two optional properties: name and color. And that’s it for this class — you don’t need anything more.

Now you need a method to add the character based on the data in the plist file. Open ParkMapViewController.swift and add the following method to the class:

func addCharacterLocation() {
  let batmanFilePath = NSBundle.mainBundle().pathForResource("BatmanLocations", ofType: "plist")
  let batmanLocations = NSArray(contentsOfFile: batmanFilePath!)
  let batmanPoint = CGPointFromString(batmanLocations![Int(rand()%4)] as String)
  let batmanCenterCoordinate = CLLocationCoordinate2DMake(CLLocationDegrees(batmanPoint.x), CLLocationDegrees(batmanPoint.y))
  let batmanRadius = CLLocationDistance(max(5, Int(rand()%40)))
  let batman = Character(centerCoordinate:batmanCenterCoordinate, radius:batmanRadius)
  batman.color = UIColor.blueColor()
 
  let tazFilePath = NSBundle.mainBundle().pathForResource("TazLocations", ofType: "plist")
  let tazLocations = NSArray(contentsOfFile: tazFilePath!)
  let tazPoint = CGPointFromString(tazLocations![Int(rand()%4)] as String)
  let tazCenterCoordinate = CLLocationCoordinate2DMake(CLLocationDegrees(tazPoint.x), CLLocationDegrees(tazPoint.y))
  let tazRadius = CLLocationDistance(max(5, Int(rand()%40)))
  let taz = Character(centerCoordinate:tazCenterCoordinate, radius:tazRadius)
  taz.color = UIColor.orangeColor()
 
  let tweetyFilePath = NSBundle.mainBundle().pathForResource("TweetyBirdLocations", ofType: "plist")
  let tweetyLocations = NSArray(contentsOfFile: tweetyFilePath!)
  let tweetyPoint = CGPointFromString(tweetyLocations![Int(rand()%4)] as String)
  let tweetyCenterCoordinate = CLLocationCoordinate2DMake(CLLocationDegrees(tweetyPoint.x), CLLocationDegrees(tweetyPoint.y))
  let tweetyRadius = CLLocationDistance(max(5, Int(rand()%40)))
  let tweety = Character(centerCoordinate:tweetyCenterCoordinate, radius:tweetyRadius)
  tweety.color = UIColor.yellowColor()
 
  mapView.addOverlay(batman)
  mapView.addOverlay(taz)
  mapView.addOverlay(tweety)
}

The method above performs pretty much performs the same operations for each character. First, it reads in the data from the plist file and selects a random location from the four locations in the file. Next, it creates an instance of Character at the previously chosen random location, and sets the radius to a random value to simulate the time variance.

Finally, it assigns each character a color and adds it to the map as an overlay.

You’re almost done — can you recall what the last few steps should be?

Right — you still need to provide the map view with an MKOverlayView, which is done through the delegate method.

Update the delegate method in ParkMapViewController.swift to reflect the following:

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
  if overlay is ParkMapOverlay {
    let magicMountainImage = UIImage(named: "overlay_park")
    let overlayView = ParkMapOverlayView(overlay: overlay, overlayImage: magicMountainImage!)
 
    return overlayView
  } else if overlay is MKPolyline {
    let lineView = MKPolylineRenderer(overlay: overlay)
    lineView.strokeColor = UIColor.greenColor()
 
    return lineView
  } else if overlay is MKPolygon {
    let polygonView = MKPolygonRenderer(overlay: overlay)
    polygonView.strokeColor = UIColor.magentaColor()
 
    return polygonView
  } else if overlay is Character {
    let circleView = MKCircleRenderer(overlay: overlay)
    circleView.strokeColor = (overlay as Character).color
 
    return circleView
  }
 
  return nil
}

And finally, update loadSelectedOptions() to give the user an option to turn the character locations on or off:

func loadSelectedOptions() {
  mapView.removeAnnotations(mapView.annotations)
  mapView.removeOverlays(mapView.overlays)
 
  for option in selectedOptions {
    switch (option) {
      case .MapOverlay:
        addOverlay()
      case .MapPins:
        addAttractionPins()
      case .MapRoute:
        addRoute()
      case .MapBoundary:
        addBoundary()
      case .MapCharacterLocation:
        addCharacterLocation()
    }
  }
}

Build and run the app, and turn on the character overlay to see where everyone is hiding out!

Where to Go From Here?

Congratulations – you’ve worked with some of the most important functionality that MapKit provides. With a few basic functions, you’ve implemented a full-blown and practical mapping application complete with annotations, satellite view, and custom overlays!

Here’s the final example project that you developed in the tutorial.

There are many different ways to generate overlays that range from very easy, to the very complex. The approach in this tutorial that was taken for the overlay_park image provided in this tutorial was the easy — yet tedious — route.

To generate the overlay, you can start with a screenshot of the satellite view of the park. Then in your graphics tool of choice, just draw the roller coasters, building locations, trees, parking lot, and other details onto a new layer. If you know the latitude and longitude of the four corners of your starter screenshot, you can also calculate the coordinates for the park’s property list which the app uses to position the overlay on the map view.

There are much more advanced — and perhaps more efficient — methods to create overlays. A few alternate methods are to use KML files, MapBox tiles, or other 3rd party provided resources.

This tutorial didn’t delve into these overlay types in order to remain focused on the task of demonstrating the MapKit framework and APIs. But if you are serious about developing mapping apps, then you would do well to investigate these other options, and discover how to hook them into your apps!

I hope you enjoyed this tutorial, and I hope to see you use MapKit overlays in your own apps. If you have any questions or comments, please join the forum discussion below!

Overlay Views with MapKit and Swift Tutorial is a post from: Ray Wenderlich

The post Overlay Views with MapKit and Swift Tutorial appeared first on Ray Wenderlich.

Viewing all 4370 articles
Browse latest View live