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

Video Tutorial: Intermediate Core Graphics Part 6: Conclusion


Video Tutorial: Networking With NSURLSession: Series Introduction

Video Tutorial: Networking With NSURLSession Part 1: NSURLSession And Configuration

Cocoa Bindings on OS X Tutorial

$
0
0

CocoaBindings-featureCocoa bindings have a simple goal: write less code. You’ll discover as you work through this Cocoa Bindings on OS X tutorial that they do indeed live up to this objective.

Cocoa bindings, aka bindings, fulfill a lot of responsibilities. Most importantly, they free you up from having to spend hours writing glue code — i.e. creating links between the model and the view in the controller when using the Model-View-Controller (MVC) pattern.

If you’ve spent time in Cocoa or Cocoa Touch, you’ve no doubt written countless lines of boilerplate code to handle the passing of data between your model and UI layers. You’ve got your delegates, notifications and observers to let you know when a control has been altered, in addition to code that helps with the task of validating and transforming data.

You may have wondered if there’s a better way.

The great news is that there is. Cocoa bindings comprise a set of technologies that makes a lot of the code you’ve previously written, frankly, unnecessary.

In this Cocoa Bindings on OS X tutorial, you’ll learn about how to use Cocoa bindings to:

  • Set the relationship within Interface Builder between a data model property and a UI element, such as a label or a button
  • Set up default values
  • Apply formatting, such as a currency or date format
  • Change the data structure, e.g. when converting a value into a representing color

Once the relationship is set up within Interface Builder, any user-generated changes to your UI are automatically pushed to your data model, and any changes made to the data model are automatically updated in the UI.

Although you won’t have to spend the next several of your hours coding, there’s still a fair amount of work ahead in Interface Builder using Auto Layout, so familiarity with both of these tools is a prerequisite.

cb-rageface1

Getting Started

In this tutorial, you’ll create an app that displays search results from the App Store via the iTunes API.

First, download the starter project here.

Build and run the project. You’ll see that there’s already a nice interface – but no data.

Screen Shot 2016-01-31 at 6.01.30 PM

You’ll also see there are a couple of files to help you along. iTunesRequestManager.swift contains a struct with two static methods. The first sends a query to the iTunes API and downloads a JSON payload that contains iOS apps results for a provided search string, while the second is a helper method to download an image asynchronously.

The second file, iTunesResults.swift, defines a data model class that matches the data downloaded by the iTunes search method.

Note: All variables in the Result class are defined as dynamic. This is because bindings rely on key-value coding, and hence require the Objective-C runtime. Adding the dynamic keyword guarantees that access to that property is always dynamically dispatched using the Objective-C runtime.

Hence, you must remember that bindings rely on key-value coding and need to use the Objective-C runtime in order to work.

The class inherits from NSObject; this is also a requirement for bindings. You’ll discover why a little later, when you add a variable to your view controller class.

Searching via iTunes

First, you’re going to retrieve search results via the iTunes API and add it to an NSArrayController.

Open the storyboard and look at the objects in the View Controller Scene. Note that objects on which you’ll set bindings all have the labels ‘(Bind)’.

Set Up an NSArrayController

NSArrayController is an object that manages the content of an NSTableView. This content often takes the form of an array of model objects.

Note: NSArrayController offers much more than a simple array – including managing object selection, sorting and filtering. Cocoa Bindings make heavy use of this functionality.

Find an NSArrayController object in the Object Library. Drag it into the list of objects under the View Controller Scene grouping in the Document Outline:

add array controller

Next, open the Assistant Editor and make sure ViewController.swift is the file being edited. Control-drag from the Array Controller object in the Storyboard to the ViewController.swift source to add an outlet to it, and name it searchResultsController:

Screen Shot 2016-01-31 at 6.39.36 PM

Add Search Box and Button

Now you’re ready to use the search box and button to get a list of search results and add them to the searchResultsController object.

Control-drag from the search button in the Storyboard to the ViewController.swift source. Select to create an IBAction, call it searchClicked, and then add the following code to the method:

@IBAction func searchClicked(sender: AnyObject!) {
 
  //1
  if (searchTextField.stringValue == "") {
    return
  }
 
  //2
  if let resultsNumber = Int(numberResultsComboBox.stringValue) {
 
    //3
    iTunesRequestManager.getSearchResults(searchTextField.stringValue,
                                results: resultsNumber,
                             langString: "en_us") { (results, error) -> Void in
      //4
      let itunesResults = results.flatMap { $0 as? NSDictionary }
        .map { return Result(dictionary: $0) }
 
      //Deal with rank here later
 
      //5
      dispatch_async(dispatch_get_main_queue()) {
 
        //6
        self.searchResultsController.content = itunesResults
        print(self.searchResultsController.content)
      }
    }
  }
}
 
//7
override func controlTextDidEndEditing(obj: NSNotification) {
  //enter pressed
  searchClicked(searchTextField)
}

Taking each line in turn:

  1. Check the text field, if it’s blank, you don’t send that query to iTunes search API.
  2. Get the value in the dropdown. This is a number passed to the API that controls how many search results it should return. There’s a number of pre-configured options in the dropdown, but you can also type in other numbers — 200 is the maximum.
  3. Make a call to getSearchResults(query:, results:, language:). This passes in the number of results from the combo box and the query string you typed into the text field. It returns, via a completion handler, an array of NSDictionary result objects or an NSError object if there’s a problem completing the query. Note that the method already handles parsing the JSON.
  4. Here you use some swift style array mapping to a) optionally cast the object to a dictionary, and b) pass the dictionary into an initialization method that creates a Result object from it. When that is done, the itunesResults variable contains an array of Result objects.
  5. Before you can set this new data on the searchResultsController, you need to make sure you’re on the main thread, therefore you use dispatch_async to get to the main queue. You haven’t set up any bindings, but once you have, altering the content property on the searchResultsController will update the NSTableView (and potentially other UI elements) on the current thread. Updating UI on a background thread is always a no-no.
  6. Here you set the content property of the NSArrayController. The array controller has a number of different methods to add or remove objects that it manages, but each time you run a search, you want to clear out whatever is there and start over with just the results of the latest query. For now, print the content of searchResultsController to the console to verify that everything is working.
  7. The last thing you’ll do is add a small method that will invoke the searchClicked() method when the user presses enter in addition to clicking the button. This just makes it easier to run a quick search.

Build and run now. Type flappy into the search bar. You will see something like this show up in the console:

console

Your First Bindings

It’s time to get to the meat of this tutorial!

allthethings1

The first step is to bind the array controller to the table view.

Open up Main.storyboard and select the table view titled Search Results Table View (Bind). Open the Bindings Inspector — it’s the second to last icon in the right pane, just before the View Effects Inspector.

  1. Expand the Content option under the Table Contents heading
  2. Check the box next to ‘Bind to ‘ and make sure SearchResultsController is displayed in the dropdown box
  3. Make sure the Controller Key is set to arrangedObjects

Like this:

TableViewBinding

Build and run now. You’ll see at most five results unless you changed the number in the dropdown. However, they all say ‘Table View Cell’.

arrayboundnotitlesintable

Binding Text Fields to Their Properties

You’re getting a bunch of duplicate hits because the text fields in the cells have no idea which properties on the data model they should read.

Expand the objects in the table view until you find the text field named Title TextField (Bind). Select this object and open the Bindings Inspector.

  1. Expand the Value option and bind to the Table Cell View object.
  2. The Model Key Path should be objectValue.trackName.

objectValue is a property on the table cell view that gets set by the NSTableView on each cell view object from its binding to the table.

In other words, objectValue is, in this case, equal to the Result model object for that row.

trackName

Repeat this process for Publisher TextField (Bind) by binding the value of this element to objectValue.artistName.

Build and run now. Look at that – both the title and publisher show themselves.

title and publisher

Adding in Rank

How about that missing rank column? Rank isn’t set on the data model object you get from iTunes. However, the order of the results from iTunes does tell you the order in which they display on a device when searching iTunes.

So, with a little more work you can set the rank value.

Add the following code in ViewController under this comment: //Deal with rank here later.

.enumerate()
.map({ (index, element) -> Result in
  element.rank = index + 1
  return element
})

This code calls enumerate() in order to get the index and the object at the index. Then it calls .map to set the rank value for each object and return an array with that result.

Finally, go back to the Storyboard, select Rank TextField (Bind), open the Bindings Inspector and do the following:

  1. In the Value section, bind to the Table Cell View
  2. Make sure Controller Key is empty
  3. Set Model Key Path to objectValue.rank

Build and run now.

ranktitlepublisher

Binding a Table View’s Selection

Now it’s time to bind the Result object in the table that the user selects to the rest of the UI. Binding to a selection in a table involves two steps:

  1. You first bind the NSArrayController to the table selection
  2. Then you can bind the properties of the selection object in the NSArrayController to the individual labels and other properties.

Select the Search Results Table View (Bind) and open the Bindings Inspector to do the following steps:

  1. Expand the Selection Indexes option in the Table Content section
  2. Check Bind to the SearchResultsController object
  3. Enter selectionIndexes into the Controller Key box. The table has a selectionIndexes property that contains set of indexes that the user has selected in the table. Note that in this case, I’ve set the table view to only allow a single selection, but you could work with more than one selection if needed — think about the finder window and how you can select multiple files at a time.

selectionIndexes

The NSArrayController object has a selection property that returns an array of objects. When you bind the selectionIndexes property from the table view to the array controller, the selection property will be populated with the objects in the array controller that correspond to the indexes selected in the table.

The next step is to bind the labels and other UI elements to the selected object.

Find and select the App Name Label (Bind).

  1. Bind to the SearchResultsController
  2. Controller Key should be selection
  3. Model Key Path should be trackName

mainTrackName

Build and run.

Main Title

Formatting Bound Data

Now you know how easy it is to get data from your model into your UI, but what if the data needs to be formatted in some way, such as currency or a date?

Luckily, there’s a built-in set of objects that make it easy to change the way a specific piece of data is displayed in a label.

Format as Price

Find the label titled Price Label (Bind), setting it up like this:

  1. Bind it to the SearchResultsController object
  2. Make sure Controller Key is selection
  3. Set Model Key Path to price
  4. Next, find a Number Formatter in the Object library. Drag it over to NSTextFieldCell under the Price label.
  5. Select the Number Formatter and open the Attributes Inspector change the Style to Currency.

Like this:

Number Formatter

Build and run.

priceformatted

Note: Number formatters are very powerful – in addition to currencies, you can also control how many digits follow a decimal point, percentages, or have the number spelled out in words.

There are also a bunch of other kinds of formatters. There are formatter objects for dates, for byte counts and several other less common ones.

Format as Bytes

You’ll be using a Byte Count Formatter next.

Find File Size Label (Bind) and set it up like so:

  1. Bind it to the SearchResultsController
  2. Controller Key is selection
  3. Model Key Path is fileSizeInBytes
  4. Then, find a Byte Count Formatter and attach it to the NSTextFieldCell. There’s no need to configure anything here, the default settings on a byte formatter will work.

Like this:

byte count formatter

Build and run now.

byte count final

You now know everything you need to know to bind the remaining labels, so here’s a short list of the keys you need to bind:

All these labels should be bound to the SearchResultsController and the selection controller key.

  • Bind the Artist Label (Bind) to artistName
  • Bind the Publication Date (Bind) to releaseDate
  • Add a Date Formatter, default settings are fine
  • Bind the All Ratings Count (Bind) to userRatingCount
  • Bind the All Ratings (Bind) to averageUserRating
  • Bind the Genre Label (Bind) to primaryGenre

For more precision in your UI, you can also bind the Description Text View (Bind), the Attributed String binding to the itemDescription Model Key Path. Make sure you bind the NSTextField, which is several levels down in the hierarchy, not the NSScrollView which is at the top.

Build and run. You should see now that most of the UI is populated.

mostly populated

Binding Images

The next step is to bind the image for the icon to the Icon Image View. This is a little trickier because what you get from the JSON payload is not the image, but a URL location for the image. Result includes a method to download the image file and make it available as an NSImage on the artworkImage property.

Download the Right Icon at the Right Time

You don’t want to download all the icons at once — just the one for the current selection in the table. You therefore need to invoke the method whenever the selection changes.

Add the following code to ViewController:

//1
func tableViewSelectionDidChange(notification: NSNotification) {
  //2
  if let result = searchResultsController.selectedObjects.first as? Result {
    //3
    result.loadIcon()
  }
}
  1. tableViewSelectionDidChange() gets fired every time the user selects a different row in the table
  2. The array controller has a property, selectedObjects. It returns an array that contains all the objects for the indexes of the rows selected in the table. In your case, the table will only allow a single selection, so this array always contains a single object. You store the object in the result object.
  3. Finally, you call loadIcon(). This method downloads the image on a background thread and then updates the Result objects artworkImage property when the image is downloaded on the main thread.

Binding the Image View

Now that your code is in place, you’re ready to bind the image view. Head back to Main.storyboard, select the Icon Image View (Bind) object and open the Bindings Inspector and set things up:

  1. Bind to the SearchResultsController
  2. Set Controller Key to selection
  3. Set Model Key Path to artworkImage

You may notice that there is a Value Path and a Value URL section. Both of these bindings are intended to be used only with local resources. It is possible to connect them to a network resource, but if you do, the UI thread will be blocked until the resource is downloaded.

Build and run, search for fruit and then select a row. You’ll see the icon image appear once it has downloaded:

icon populated

Populate the Collection View

The collection view beneath the description text view is currently looking a little bare — time to populate that with some screenshots. First you’ll bind the collection view to the screenShots property before ensuring that the screenShots array is correctly populated.

Select the Screen Shot Collection View (Bind). Open the Bindings Inspector and expand the Content binding in the Content group. Set it up thusly:

  1. Bind to the SearchResultsController
  2. Controller Key is selection
  3. Model Key Path is screenShots

The screenShots array starts out empty. There’s a method named loadScreenShots() that is similar to the method that loads the icon. It’ll download the image files and populate the screenShots array with NSImage objects.

Add this line in ViewController.swift, in tableViewSelectionDidChange() right after the result.loadIcon():

result.loadScreenShots()

This will populate the screenshot images and create the right number of views. The next thing you need to do is set the right collection view item prototype.

Normally when you drag a collection view into a storyboard, you automatically create a collection view item and a segue. However, this feature is buggy in the latest Xcode and at the time of writing, it’s not working.

Although the collection view item scene is present in the storyboard, it’s not connected to the collection view. Therefore you’ll have to create this connection in code.

Add the following code to the end of viewDidLoad in ViewController.swift:

let itemPrototype = self.storyboard?.instantiateControllerWithIdentifier("collectionViewItem")
      as! NSCollectionViewItem
collectionView.itemPrototype = itemPrototype

Now that the collection view knows how to create each item (via the prototype) you need to provide the content for each item, via a binding.

Open Main.storyboard and select Screen Shot Image View (Bind) inside the Collection View Item Scene. You’ll find this floating next to the main view controller. Here are the settings for this one:

  1. Bind the Value option to the Collection View Item object.
  2. The controller key should be blank
  3. Model Key Path should be representedObject

The representedObject property represents the object in the collection view array for that item; in this case, it’s an NSImage object.

Build and run now.

screenshots

You can now see the screenshots appearing below the description text — great work! Just a few more features of Cocoa Bindings to cover before wrapping up.

Binding Other Properties

Thus far you’ve seen how you can bind model objects to labels and images for display to the user. However, you can also bind attributes such as fonts, colors, text styles and visibility to data in your model. This allows you to easily control the appearance of your UI directly through the model layer.

Set Up a Progress Spinner

Users don’t like to stare at static screens when something is loading — they tend to think the worst if there’s nothing to tell them something’s happening behind the scenes.

Instead of leaving a static screen, you can show a spinner to the user, indicating that the app is busy working. An easy way to do this is to bind a progress spinner to a new property in the ViewController, so add the following property to ViewController:

dynamic var loading = false

Loading requires two things in order to work correctly. The dynamic keyword and that the parent class is a subclass of NSObject. Bindings relies on KVO (Key Value Observing). A swift class that doesn’t inherit from NSObject wouldn’t be able to use KVO.

Add the following line of code in the function searchClicked() right before the line that executes the call to getSearchResults().

loading = true

Locate the line that sets the content property on searchResultsController (self.searchResultsController.content = itunesResults) and add the following immediately before it:

self.loading = false

Next, select Search Progress Indicator (Bind) in Main.storyboard. You’re going to bind two properties of the progress spinner: hidden and animate.

First, expand the Hidden group, and set it up like so:

  1. Bind to the View Controller
  2. Controller Key should be blank
  3. Model Key Path should be self.loading

In this case you need to do one more thing, when loading is true, you actually want hidden to be false and vice versa. Luckily, there’s an easy way to do that — using NSValueTransformer to flip the value of the boolean.

Choose NSNegateBoolean from the Value Transformer dropdown list.

NSValueTransformer is a class that helps you convert the form or value of data when moving between UI and data model.

You can subclass this object in order to do much more complex conversions, you can learn more about NSValueTransformers in this tutorial: How to Use Cocoa Bindings and Core Data in a Mac App.

Next, bind to the Animate value like this:

  1. Bind it to the View Controller object
  2. Controller Key should be blank.
  3. Model Key Path is self.loading

This boolean doesn’t need to be negated.

Binding animating

Build and run now. You might want to use a larger number of results so that there’s time to watch the spinner do its spin thing while results are retrieved.

Spinner animating

Adding a Little More Spice

Color is the spice of design, and right now things are looking a little drab. You won’t be surprised to learn that you can set color with Cocoa bindings!

In this scenario, you’re dealing with apps that have a larger number of reviews, making them rank higher in the search results. More reviews tends to be a good sign, and users enjoy having a visual indicator of such a thing when they have to scroll through a long list and make split-second decisions.

So, you’ll build out that visual cue.

Create a Ranking Method

First, you need to add a method that calculates the color of each result based on the number of reviews.

Add this code to ViewController inside ViewController.swift:

func setColorsOnData() {
 
  //1
  let allResults = searchResultsController.arrangedObjects
 
  //2
  let sortDescriptor = NSSortDescriptor(key: "userRatingCount", ascending: false)
  let sortedResults = allResults.sortedArrayUsingDescriptors([sortDescriptor]) as NSArray
 
  //3
  for index in 0..<sortedResults.count {
 
    //4
    let red = CGFloat(Float(index) / Float(sortedResults.count))
    let green = CGFloat(1.0 - (Float(index) / Float(sortedResults.count)))
    let color = NSColor(calibratedRed: red, green: green, blue: 0.0, alpha: 1.0)
 
    //5
    if let result = sortedResults.objectAtIndex(index) as? Result {
      result.cellColor = color
    }
  }
}

Here’s what you’re cooking up in there:

  1. Get the array from the array controller
  2. Create a sort descriptor that is based on the ‘userRatingCount’ key. It’s descending so that the largest number of reviews is first in the list. You then create a sortedResults array that contains the sorted list
  3. Iterate through the results
  4. Create a color; the objects at the beginning of the set will be the most green and the values at the end will be the most red
  5. Finally, you set the cellColor

Next, you need to call that new method. Add this line to searchClicked() in ViewController.swift right after this line self.arrayController.content = itunesResults:

self.setColorsOnData()

Bind Font Color

Now, bind the font color of the rank column to that value.

Select the Rank TextField (Bind) object and set it up like this:

  1. Bind to the Text Color value, the Table Cell View object.
  2. Controller Key should be blank
  3. Set Model Key Path to objectValue.cellColor

Build and run.

cell color

You can now see that the rank numbers are color-coded, according to the number of reviews each app has.

Where to Go From Here

That’s the gist of Cocoa Bindings, and you can see just how much easier it makes life when you need to connect data and UI. You learned:

  1. How to use Interface Builder to quickly and easily bind objects to data
  2. How to make keep models and views in sync with the user’s current selection
  3. How to use methods and bindings together to control behaviors and organize data
  4. How to quickly build out UI features like progress spinners

You can download the final project here. Hopefully, you can see how much time and code you can save by adopting this technology.

Each binding has a lot of little settings and options, many of which we didn’t explore. One specific thing to take a look at is this resource provided by Apple. It will cover a lot of the details about what the options in the bindings windows do.

I hope you enjoyed this Cocoa Bindings on OS X tutorial and picked up some new techniques to use to accelerate your development process. You’ve just opened up a whole new universe! Let’s talk about it in the forums — I look forward to your questions, comments and findings.

The post Cocoa Bindings on OS X Tutorial appeared first on Ray Wenderlich.

Video Tutorial: Networking With NSURLSession Part 2: NSURL, NSURLRequest, and NSURLResponse

NSNorth 2016 Conference Highlights

$
0
0

NSNorth

I recently got back from the fourth annual NSNorth, a popular Canadian mobile development conference.

This year the event was held at the the St James Cathedral Centre in Toronto, and organizers Philippe Casgrain and Dan Byers were joined by Adrienne Marshall in presenting another successful conference for designers and developers.

There were 160 attendees registered for the conference, with companion tickets bringing the attendance to over 200. It felt like just the right size for connecting with past acquaintances and making new life long friends.

In this article, I’ll share some of the highlights of the event so you can get a taste of what the event was like, and see if it’s something you might want to attend next year. Let’s dive in!

Note: We will update this post to add video links as they become available.

Tech Workshop – Start Thinking in Swift – Daniel Steinberg

Daniel Steinberg

Author and podcaster Daniel Steinberg kicked off the conference with a day long workshop geared to towards intermediate developers looking to level up their Swift skills.

Daniel walked students though intermediate level Swift concepts, assuming that the basics were covered. For example, he explained how the Swift compiler will treat objects and types, how errors are handled in Swift 2, and how we now have the ability to ask for the “first” element in a collection.

One thing Daniel said in his talk really stood out to me:

“We should pay attention to what Apple tells us at WWDC, because they are telling us about what’s coming without telling us.” – Daniel Steinberg

Consider these examples:

  • Auto Layout led to larger iPhones, size classes and Adaptive Layout.
  • ARC wasn’t just about automatic memory management, rather it was preparing the way for the Swift language.
  • App Thinning was getting our code ready for the Apple TV and Apple Watch.

Daniel’s mix of clear explanations, humor and industry know-how was a great help for budding and experienced developers looking to enhance their understanding of Swift.

Keynote – What Does the Future Look Like – May-Li Khoe

May-Li Khoe, Adrienne Marhsall, Phillipe Casgrian & Dan Byers

May-Li Khoe, Adrienne Marhsall, Phillipe Casgrian & Dan Byers

The keynote for NSNorth was presented on Thursday night. It was followed by a reception sponsored by Shopify.

May-Li Khoe, formerly with Apple, Microsoft and Leapfrog and now with Khan Academy, led off the conference with a talk about reshaping the future. She prompted us to consider the putting the user first when designing our apps, where are they when using the apps, and how they feel about the technology.

“Like a fish in water, we can’t see the water.” – May-Li Khoe

She illustrated her arguments with the story of Antanas Mockus, the mayor of Bogata who shook things up by firing the corrupt police department. He hired mimes to mock litterers and jay walkers. He also gamed the system by instituting white and red cards popular in sports. Like offensive soccer players, bad citizens would get presented red cards by fellow citizens. Good and kind people would get a white card.

She also gave great examples people who successfully shaped the future:

  • Douglas Engelbart gave “the mother of all demos” in 1968, discussing the augmentation of the human mind with technology.
  • Steve Jobs, described the computer as the bicycle for the mind.
  • Grandmaster Flash invented DJing, allowing hip-hop to break out of the debris and poverty of the Bronx.

She left us with an insightful question: “What do you want the future to be?”

Keep Calm and Type Erase On – Gwen Weston

Gwen Weston

Indie developer Gwen Weston gave an interesting talk on type erasure.

She began by asking us to consider what is a “type”. She then went on to explain the differences between concrete and abstract types, the former representing data and the latter representing behavior. With the use of Generics, we use types represented by T or U, we can use type reification to make abstract type concrete.

Protocols present a exception, where we cannot directly instantiate abstract types. In this case we can wrap an abstract type in a concrete type, also know as type erasure.

Gwen took a topic that could have been dry and made it fun by injecting humor: all of her examples were Pokemon based. A great talk all around!

Clean View Layout with iOS9 Features – Ayaka Nonaka

Ayaka Nonaka

The delightful speaker Ayaka Nonaka is looking forward to iOS 10, however she wanted to look back at some new additions to iOS 9 that we may not have implemented yet.

Stating that she preferred to work in code, she likes the new layout tools that empower clean layout:

  • NSLayoutAnchors allow users to create layout settings and constraints with as few as one line of code (which is great compared to the Visual Format Language, which often involves a lengthy set of commands).
  • UILayoutGuides are similar to adding padding in web design – “designers like padding,” she adds. Ayaka showed plenty of code examples during her talk, and noted that Apple had not added UILayoutGuide in storyboards, yet.
  • UIStackViews aren’t just for Interface Builder: they can be used in code too! She also showed a series of slides to demonstrate where stack views are used. “When you start using stack views, everything looks like stack views”, she concluded. For those still supporting iOS 8, Ayaka pointed out TZStackView on GitHub, which is interchangeable with Apple’s UIStackView when developers eventually switch to iOS 9.

If you ever get a chance to see Ayaka Nonaka speak, you won’t be disappointed!

Note: We are quite passionate about Auto Layout, Adaptive Layout, and UIStackView at raywenderlich.com. If you’d like to learn more about these, check out our Auto Layout video tutorials, Adaptive Layout video tutorials, UIStackView video tutorials, or our brand new free tutorial Easier Auto Layout in iOS 9 which covers layout anchors and guides.

Safety, Fun, and Learning – Liz Marley

Liz

Liz Marley likes to play. She’s a heavy duty character in World of Warcraft, taking on all foes while sending instructions to her companions. Putting a twist on the gamer put-down “Learn to Play”, she renamed her clan “Play to Learn”. This positive attitude extends to her work in App Camp For Girls.

Empowering young girls to become developers is the mandate of App Camp For Girls. It provides a safe environment presented by other women, whom the girls can identify with. Praise is not given for appearance or for being smart, but rather for working hard.

Relating her talk to the audience, Liz argued that Apple reset the clock with Swift. All developers started off fresh on the same footing, and they even gave us Playgrounds making it easy to get started and experiment.

Liz wrapped her talk up by saying we are invited to play – so go pick a topic and play!

Note: The app created by the App Camp For Girls attendees is on the App Store: App Camp Quiz Compendium.

Lightning Talks

BonMot-logo

One of the cool features of NSNorth are lightning talks. These are short 15 minute presentations given by attendees, selected from proposals ahead of the conference. They are a great way for new speakers to get experience and for those who want to impart a bite size bit of knowledge.

As an example, one talk I really liked was by Zev Eisenberg, discussing his open source library BonMot, which allows you to take the pain out of attributed strings.

In essence, it allows you to layout type like a typographer. He developed the library out of necessity for some projects he was working on.

BonMot allows for the creation of attributed strings through the use of BonChain arrays, where effects can be applied and the sent to BonText. The resulting output is an attributed string with the format added to each individual BonChain item.

Very slick and worth checking out for your typography needs!

Carving out a Space in the Continuum of App Store Success – Jon Edwards

buddy

Another fascinating talk was given by watchmaker and iOS developer Jon Edwards.

Building on Charles Perry’s talk at NSNorth 2014 on finding your niche in the App Store, Jon started out by reminding us that only 0.01% of app developers are successful and happy with their App Store results.

By analogy, Jon also used the example of the surfing mecca Mavericks, where some of the biggest waves exist. In the movie Chasing Mavericks, the protagonist learns that careful observation can lead you to find the best waves. Rather than fighting things head on, a keen observation of the laws of nature offers better results.

Steve Jobs suggested that one should zoom out and see what is really going on. Jon said that in the world of watchmaking, the ratio of watches to watchmakers is 5000:1. Currently, 50% of watchmakers are of retirement age or close to death. Last year, just around 50 watchmakers graduated from colleges. With that insight, it seems to be no wonder why watchmaking is a lucrative business!

Jon went on to discuss the hedgehog concept, where unlike a fox that knows many things, a hedgehog knows one big thing. The key is to discover your sweet spot. As Jim Collins explains in his book Good to Great, it’s critical to determine what you passionate about.

The takeaway is to find out what you can be the best in the world at, and also find out what can drive your economic engine. The intersection of these is the sweet spot.

Tell Your Story – Jonathan Rhyne

jonathan

Jonathan Rhyne began his talk with a definition of story: an accounting of incidents or events. He explained that one of his favorite films, Forrest Gump is an example of great storytelling. It’s about destiny versus coincidence, and overcoming obstacles.

Jonathan argued that we are all storytellers. We form our identities and understand life through stories. Most of us have vivid memories, and memories are often attached to emotions.

We can remember where we were when significant events happened, but sometimes we remember the emotions at the expense of details. For example during the events on 911 the first plane crash wasn’t broadcast until the next day. Many of us can remember that as if we experienced it live. We have changed our memories with emotion.

We as developers are also in the people and emotion business. He suggested that you don’t just give a feature list: instead, ask many whys. Why can’t I do that, and why does my app do this?

Here are some examples of focusing on the why’s:

  • Toms Shoes donate a pair of shoes to impoverished children with every pair you buy. People embrace that idea.
  • Apple commercials demonstrate how their products are used, rather than discussing the features. They ask us to consider what we will create with them.
  • Lego teaches us that making things is fun.

Get to know your target audience and ask how your product feels. Make people the center of your story and make your app have a supporting role. The take away is to ask yourself: why it is that you do what you do?

The Value of Platform Tourism – Michael Gorbach

26129613504_8b6ef5d9b5_k

Michael Gorbath talk invited the audience to consider where we place our values in the platforms we choose to work with.

Beginning with conference name, NSNorth, he reminded us that the name and many Apple frameworks came from NextStep. Founded by Steve Jobs after he was ousted from Apple 30 years ago, NeXT and values that the company contained still matter today.

He argued that values should be a top priority. NeXT valued well designed UI, ease of use, and power. Values are about the choices we make and many of the NeXT’s values are still with us, especially given that NeXT was the seed that led to OS X and iOS.

Michael worked at Apple for a time and recalled attending C4, an early developer conference. A speaker from Appcelerator gave a talk on using Java instead of Objective-C. Following the talk, the questions from the audience were very negative – Michael being among the naysayers! The C4 conference organizers were very upset because of the attendees xenophobic behavior. The takeaway was that we shouldn’t criticize someone just because they use a different stack.

The reaction was caused by a conflict of values:

  • Appcelerator sought to democratize development. They valued accessibility to tools and reducing time to market.
  • The C4 audience responded negatively because the speaker didn’t belong to their tribe of Objective-C users.

In this talk, Michael invited us to become “xenophilic” – to be more open to ideas and new platforms.

“We need to become Xenophilic.” – Michael Gorbach

For example, recently Micheal was asked to work on Xamarin project, that is built using C#. He found that working with C# had certain advantages over the tools he was familiar with.

Even exploring Android development opened his eyes to some interesting features; such as a built in annotation system, collections of components, different ways to manage resources and animations with built-in tweeting to name a few.

In conclusion, he suggests that we all should become platform tourists and be inspired to explore other mobile stacks.

Journey to the East – Rob Segal

7bfc3760d1de20da86bb0917745085ca_400x400

Rob Segal of Get Set Games, makers of the Mega Jump series of games, was the first game developer to speak at any NSNorth conference.

Get Set is a small company, initially just 2 designers and 2 developers. Mega Jump benefited from early App Store success, often featured by Apple and in the early days was able to sell characters by In App Purchases. They also had come success working with Pixar and Disney with re-skinned versions of their games.

With the assistance of the Canadian Trade Commission, they were able to find more success selling their apps in Asian markets. They were introduced to companies that would take their code and adapt their apps to burgeoning markets, such as India, who are the latest target having just jumped into smart phones.

Working with social networks; Linc, Kakao, WeChat and others also provided larger audiences. In China, working with Tenyu, Yoda1 and Takweb Games they were quite successful. Notably one of their games managed to get 100 million downloads in one day.

The takeaway here is to reach out to other development companies – they can hep you access markets you might not be able to otherwise.

Keynote Karaoke

Janie

One of the most entertaining talks took place during Keynote Karaoke. Organizer Phillipe Casgrain wrote an algorithm that would play 5 slides in random order. Participants were invited onto the stage and given 3 minutes to present their talk on the fly.

Many of the conference speakers took part and some attendees volunteered to be in the spotlight. Once on stage they realized that they had got more than they bargained for!

Notable Karaoke talks were given by Janie Clayton, Paddy O’Brian, Jonathan Rhyne and one of the most entertaining was by Joe Cieplinski of the Release Notes podcast.

Hockey Hall of Fame

Ray Wenderlich team members Janie Clayon, René Cacheaux and Tim Mitra.

Ray Wenderlich team members Janie Clayon, René Cacheaux and Tim Mitra.

Aside from poutine and beaver tails, what would make a Canadian conference more complete that a winter related activity!

In 2015, we were able to experience Curling at rink at the Chateaux Montebello, where the conference was hosted. This year, we had a private night at the Hockey Hall of Fame, just around the corner from St. James Cathedral.

We were able to see exhibits of all the stars of the game, from around the world. We even tried our hand at the interactive exhibits; shoot out and goaltending. Of course we all got to hang out with the Stanley Cup, awarded to the top team in the National Hockey League.

Children’s Coding Workshops

NSNorth has offered companion tickets for designers and developers who wanted to bring their families to attend the events.

This year they took it up a notch and had two tech workshops for kids on Saturday. Toronto’s Ladies Learning Code presented a gaming workshop, and Daniel Steinberg ran an afternoon workshop on for kids on making iOS games with Swift.

Where To Go From Here?

NSNorth is great conference and one of my favorites. I would definitely suggest that you try to attend it in the spring of 2017, where hopefully it will be held in Toronto again.

There are some other great iOS conferences you should consider too:

  • Like to learn via hands-on tutorials?: You should consider RWDevCon 2017 in the DC area early next year. If you’re curious how it went last year, check out our recent post-mortem.
  • Like the idea of NSNorth but in the US?: You should consider 360 iDev – it’s very much like NSNorth but bigger: it has three tracks you can choose from.
  • Want something more business focused, or from an indie perspective?: You should consider the Release Notes conference in Indianapolis or IndieDevStock in Nashville Tennessee.

As a proud Canadian on the raywenderlich.com Team, I hope to see you next year at NSNorth and keep your stick on the ice!

Photo Credits: Martin Reich, Tim Mitra, Lucas Chang, Jacob Gorban, Anluan O’Brien

The post NSNorth 2016 Conference Highlights appeared first on Ray Wenderlich.

Video Tutorial: Networking With NSURLSession Part 3: NSURLSessionTask

Command Line Programs on OS X Tutorial

$
0
0

CommandLinePrograms-featureNot so long ago, before the advent of graphical user interfaces, command-line programs were the primary method for interacting with computers. Despite the prevalence of GUIs, command-line programs still have an important role in today’s computing world. Command-line programs such as ImageMagick or ffmpeg are important in the server world. In fact, the majority of the servers that form the Internet run only command-line programs.

Even Xcode uses command-line programs! When Xcode builds your project, it calls xcodebuild, which does the actual building. If the building process was baked-in to the Xcode product, continuous integration solutions would be hard to achieve — if not impossible!

In this command line programs on OS X tutorial you will write a command-line utilty named Panagram. Depending on the options passed in, it will detect if a given input is a palindrome or anagram. It can be started with arguments or run in interactive mode without arguments.

Getting Started

Swift seems like an odd choice for creating a command-line program, as languages like C, Perl, Ruby or Java are a more traditional choice. But there are some great reasons to choose Swift for your command-line needs:

  • Swift can be used as an interpreted scripting language, as well as a compiled language. This gives you the advantages of scripting languages, such as zero compile times and ease of maintenance, along with the choice of compiling your app to improve execution time or to bundle it for sale to the public.
  • You don’t need to switch languages. Many people say that a programmer should learn one new language every year. This is not a bad idea, but if you are already used to Swift and its standard library, you can reduce the time investment by sticking with Swift.

In this command line programs for OS X tutorial, you’ll create a classic compiled project.

Open Xcode and go to File\New\Project. Find the OS X group, select Application\Command Line Tool and click Next:

Create_command_line_tool

For Product Name, enter Panagram. Make sure that Language is set to Swift, then click Next.

Project_Settings

Choose a location on your disk to save your project and click Create.

Many C-like languages have a main function that serves as the entry point — i.e. the code that the operating system will call when the program is executed. This means the program execution starts with the first line of this function. Swift doesn’t have a main function; instead, it has a main file.

When you run your project, the first line inside that file that isn’t a method or class declaration is the first one to execute. It’s a good idea to keep your main.swift file as clean as possible and put all your classes and structs in their own files. This keeps things streamlined and helps you to understand the main execution path.

Press Cmd + N to create a new file. Under OS X, select Source\Swift File and press Next:

File_selection

Save the file as ConsoleIO.swift and open it. You’ll wrap all the input and output elements in a small, handy class.

Add the following code to ConsoleIO.swift:

class ConsoleIO {
  class func printUsage() {
    let executableName = (Process.arguments[0] as NSString).lastPathComponent
 
    print("usage:")
    print("\(executableName) -a string1 string2")
    print("or")
    print("\(executableName) -p string")
    print("or")
    print("\(executableName) -h to show usage information")
    print("Type \(executableName) without an option to enter interactive mode.")
  }
}

This code creates a class ConsoleIO and a class method that prints usage information to the console. Every time you run a program, the path to the executable is implicitly passed as argument [0] and accessible through the global Process enum. Process is a small wrapper around the argc and argv arguments you may know from C-like languages.

Note: It is common practice to print a usage statement to the console when the user tries to start a command-line program with incorrect arguments.

Create another new Swift file named Panagram.swift and add the following code to it:

class Panagram {
  func staticMode() {
    ConsoleIO.printUsage()
  }
}

This creates a class Panagram that has one method. The class will handle the program logic, with staticMode() representing non-interactive mode — i.e. when you provide all data through command line arguments. For now, it simply prints the usage information.

Now open main.swift and replace the print statement with the following code:

let panagram = Panagram()
panagram.staticMode()

Build and run your project; you’ll see the following output in Xcode’s console:

usage:
Panagram -a string1 string2
or
Panagram -p string
or
Panagram -h to show usage information
Type Panagram without an option to enter interactive mode.
Program ended with exit code: 0

So far, you’ve learned what a command-line tool is, where the execution starts and how you can split your code into logical units to keep main.swift organized.

In the next section, you’ll handle command-line arguments and complete the static mode of Panagram.

Command-Line Arguments

When you start a command-line program, everything you type after the name is passed as an argument to the program. Arguments can be separated with whitespace characters. Usually, you’ll run into two kind of arguments: options and strings.

Options start with a dash followed by a character, or two dashes followed by a word. For example, many programs have the option -h or --help, the first being simply a shortcut for the second. To keep things simple, Panagram will only support the short version of options.

Open ConsoleIO.swift and add the following enum above the ConsoleIO class:

enum OptionType: String {
  case Palindrome = "p"
  case Anagram = "a"
  case Help = "h"
  case Unknown
 
  init(value: String) {
    switch value {
    case "a": self = .Anagram
    case "p": self = .Palindrome
    case "h": self = .Help
    default: self = .Unknown
    }
  }
}

This creates an enum with String as its base type so you can pass the command-line arguments directly to init(_:). Panagram has three options: -p to detect palindromes, -a for anagrams and -h to show the usage information. Everything else will be handled as an error.

Next, add the following method to the ConsoleIO class:

func getOption(option: String) -> (option:OptionType, value: String) {
  return (OptionType(value: option), option)
}

The above method accepts a String as its argument and returns a tuple of OptionType and String.

Open Panagram.swift and add the following property to the class:

let consoleIO = ConsoleIO()

Then replace the content of staticMode() with the following:

//1
let argCount = Process.argc
//2
let argument = Process.arguments[1]
//3
let (option, value) = consoleIO.getOption(argument.substringFromIndex(argument.startIndex.advancedBy(1)))
//4
print("Argument count: \(argCount) Option: \(option) value: \(value)")

Here’s what’s going on in the code above:

  1. You first get the number of arguments passed to the program. Since the executable path is always passed in, this value will always be greater than or equal to 1.
  2. Next, take the first “real” argument from the arguments array.
  3. Then you parse the argument and convert it to an OptionType.
  4. Finally, you log the parsing results to the console.

In main.swift, replace the line panagram.staticMode() with the following:

if Process.argc < 2 {
  //Handle interactive mode
} else {
  panagram.staticMode()
}

If your program is invoked with fewer than 2 arguments, then you’re going to start interactive mode. Otherwise you use the non-interactive static mode.

You now need to figure out how to pass arguments to your command-line tool from within Xcode. To do this, click on the Scheme named Panagram in the Toolbar:

Scheme

Select Edit Scheme… in the popover that appears:

Edit_Scheme

Ensure Run is selected, click the Arguments tab, then click the + sign under Arguments Passed On Launch. Add -p as argument and click Close:

Scheme_Settings

Now run your project, and you’ll see the following output in the console:

Argument count: 2 Option: Palindrome value: p
Program ended with exit code: 0

So far, you’ve added a basic option system to your tool, learned how to handle command-line arguments and how to pass arguments from within Xcode.

Next up, you’ll build up the main functionality of Panagram.

Anagrams and Palindromes

Before you can write any code to detect palindromes or anagrams, you should be clear on what they are!

Palindromes are words or sentences that read the same backwards and forwards. Here are some examples:

  • level
  • noon
  • A man, a plan, a canal – Panama!

As you can see, capitalization and punctuation are often ignored.

Anagrams are words or sentences that are built using the characters of other words or sentences. Some examples are:

  • silent <-> listen
  • Bolivia <-> Lobivia (it’s a cactus from Bolivia)

You’ll encapsulate the detection logic inside a small extension to String.

Create a new file StringExtension.swift and add the following code to it:

extension String {
}

Time for a bit of design work. First, how to detect an anagram:

  1. Ignore capitalization and whitespace for both strings.
  2. Check that both strings contain the same characters, and that all characters appear the same number of times.

Add the following method to the String extension:

func isAnagramOfString(s: String) -> Bool {
  //1
  let lowerSelf = self.lowercaseString.stringByReplacingOccurrencesOfString(" ", withString: "")
  let lowerOther = s.lowercaseString.stringByReplacingOccurrencesOfString(" ", withString: "")
  //2
  return lowerSelf.characters.sort() == lowerOther.characters.sort()
}

Taking a closer look at the algorithm above:

  1. First, you remove capitalization and whitespace from both Strings.
  2. Then you sort and compare the characters.

Detecting palindromes is simple as well:

  1. Ignore all capitalization and whitespace.
  2. Reverse the string and compare; if it’s the same, then you have a palindrome.

Add the following method to detect palindromes:

func isPalindrome() -> Bool {
  //1
  let f = self.lowercaseString.stringByReplacingOccurrencesOfString(" ", withString: "")
  //2
  let s = String(f.characters.reverse())
  //3
  return  f == s
}

The logic here is quite straightforward:

  1. Remove capitalization and whitespace.
  2. Create a second string with the reversed characters.
  3. If they are equal, it is a palindrome.

Time to pull this all together and help Panagram do its job.

Open Panagram.swift and replace the print(_:) statement inside staticMode() with the following:

//1
switch option {
  case .Anagram:
  //2
  if argCount != 4 {
    if argCount > 4 {
      print("Too many arguments for option \(option.rawValue)")
    } else {
      print("Too few arguments for option \(option.rawValue)")
    }
 
    ConsoleIO.printUsage()
  } else {
    //3
    let first = Process.arguments[2]
    let second = Process.arguments[3]
 
    if first.isAnagramOfString(second) {
      print("\(second) is an anagram of \(first)")
    } else {
      print("\(second) is not an anagram of \(first)")
    }
  }
  case .Palindrome:
  //4
  if argCount != 3 {
    if argCount > 3 {
      print("Too many arguments for option \(option.rawValue)")
    } else {
      print("Too few arguments for option \(option.rawValue)")
    }
  } else {
    //5
    let s = Process.arguments[2]
    let isPalindrome = s.isPalindrome()
    print("\(s) is \(isPalindrome ? "" : "not ")a palindrome")
  }
  //6
  case .Help:
  ConsoleIO.printUsage()
  case .Unknown:
  //7
  print("Unknown option \(value)")
  ConsoleIO.printUsage()
}

Going through this step-by-step:

  1. First, switch to see what should be detected.
  2. In the case of an anagram, there must be four command-line arguments passed in. The first is the executable path, the second the a option and finally the two strings to check. If you don’t have four arguments, then print an error message.
  3. If the argument count is good, store the two strings in local variables, check the strings and print the result.
  4. In the case of a palindrome, you must have three arguments.
  5. Check for the palindrome and print the result.
  6. If the -h option was passed in, then print the usage information.
  7. If an unknown option is passed, print the usage to the console.

Run your project with some modified arguments inside the Scheme. For example, you could use the -p option as shown below:

p-option-settings

You have a basic version of Panagram working, but you can make it even more useful by tying in to the input and output streams.

Input and Output

In most command-line programs, you’d like to print some messages for the user. For example, a program that converts video files into different formats could print the current progess or some error messages if something goes wrong.

Unix-based systems such as OS X define two different output streams:

  • The standard output stream (or stdout) is normally attached to the display and should be used to display messages to the user.
  • The standard error stream (or stderr) is normally used to display status and error messages. This is normally attached to the display, but can be redirected to a file.

stderr can be used to log error messages, the internal program state, or any other information the user doesn’t need to see. This can make debugging of a shipped application much easier.

Your next task is to change Panagram to use these different output streams.

First, open ConsoleIO.swift and add the following enum to the top of the file, outside the scope of the Panagram class:

enum OutputType {
  case Error
  case Standard
}

This defines the output method to use when writing messages.

Next add the following function to the ConsoleIO class:

func writeMessage(message: String, to: OutputType = .Standard) {
  switch to {
  case .Standard:
    print("\u{001B}[;m\(message)")
  case .Error:
    fputs("\u{001B}[0;31m\(message)\n", stderr)
  }
}

This function has two parameters; the first is the actual message to print, and the second is where to write it. This defaults to .Standard.

The code for the .Standard option uses print, which by default writes to stdout. The .Error case uses the C function puts to write to stderr, which is a global variable and points to the standard error stream.

What are those cryptic strings, though? These are control characters that cause Terminal to change the color of the following string. In this case you’ll print error messages in red (\u{001B}[0;31m). The sequence \u{001B}[;m used in the standard case resets the terminal color back to the default.

To use this new function, open Panagram.swift and change the print lines in staticMode() to use the new writeMessage(_:to:) method.

The switch statement should now look like the following:

case .Anagram:
  if argCount != 4 {
    if argCount > 4 {
      consoleIO.writeMessage("Too many arguments for option \(option.rawValue)", to: .Error)
    } else {
      consoleIO.writeMessage("too few arguments for option \(option.rawValue)", to: .Error)
    }
    ConsoleIO.printUsage()
  } else {
    let first = Process.arguments[2]
    let second = Process.arguments[3]
 
    if first.isAnagramOfString(second) {
      consoleIO.writeMessage("\(second) is an anagram of \(first)")
    } else {
      consoleIO.writeMessage("\(second) is not an anagram of \(first)")
    }
  }
case .Palindrome:
  if argCount != 3 {
    if argCount > 3 {
      consoleIO.writeMessage("Too many arguments for option \(option.rawValue)", to: .Error)
    } else {
      consoleIO.writeMessage("too few arguments for option \(option.rawValue)", to: .Error)
    }
  } else {
    let s = Process.arguments[2]
    let isPalindrome = s.isPalindrome()
    consoleIO.writeMessage("\(s) is \(isPalindrome ? "" : "not ")a palindrome")
  }
case .Help:
  ConsoleIO.printUsage()
case .Unknown:
  consoleIO.writeMessage("Unkonwn option \(value)", to: .Error)
  ConsoleIO.printUsage()
}

As you see, only error messages need the to: parameter. That’s one of the benefits of Swift’s default values for parameters.

Run your project; you should see something similar to this in the Xcode console. For example, using the arguments a, listen and silent you’ll see the following:

[;mlisten is an anagram of silent

The [;m at the beginning of the output looks a bit awkward. That’s because the Xcode console doesn’t support using control characters to colorize the output. To see this in action, you’ll have to launch Panagram in Terminal:

Colored_Output

Note: The following section walks you how to launch your app in Terminal directly from Xcode. The downside is that you can’t debug your app in Xcode this way; therefore, the next section is optional and you can skip directly to the Handle Input section if you wish.

Launching Outside Xcode

There are different ways to launch your program from inside Terminal. You could find the build product using the Finder and start it directly via Terminal, or you could be lazy and tell Xcode to do this for you. In this section you’ll discover the lazy way.

First, edit your current Scheme and uncheck Debug executable. Now click on the Executable drop down and select Other:

Executable_setting

In the window that appears, go to Applications/Utilities, select Terminal.app, then click Choose:

Choose_Terminal

Now select the Arguments tab, remove all entries under Arguments Passed On Launch, then add one new entry in that section:

${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}

passed_arguments2

Finally, click Close.

This instructs Xcode to open Terminal when you run your project and pass through the path to your program. Terminal will then launch your program as you’d expect.

Handle Input

stdin is attached to the keyboard and is therefore a way for you to collect input from users interactively. When Panagram is started without arguments, it will open in interactive mode and prompt the user for the options it would otherwise have collected from its arguments.

First, you need a way to get input from the keyboard.

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

func getInput() -> String {
 
  // 1
  let keyboard = NSFileHandle.fileHandleWithStandardInput()
 
  // 2
  let inputData = keyboard.availableData
 
  // 3
  let strData = NSString(data: inputData, encoding: NSUTF8StringEncoding)!
 
  // 4
  return strData.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
}

Taking each numbered section in turn:

  1. First, grab a handle to stdin.
  2. Next, read any data on the stream.
  3. Convert the data to a string.
  4. Finally, remove any newline characters and return the string.

Next, open Panagram.swift and create a function interactiveMode() as follows:

func interactiveMode() {
  //1
  consoleIO.writeMessage("Welcome to Panagram. This program checks if an input string is an anagram or palindrome.")
  //2
  var shouldQuit = false
  while !shouldQuit {
    //3
    consoleIO.writeMessage("Type 'a' to check for anagrams or 'p' for palindromes type 'q' to quit.")
    let (option, value) = consoleIO.getOption(consoleIO.getInput())
 
    switch option {
    case .Anagram:
      //4
      consoleIO.writeMessage("Type the first string:")
      let first = consoleIO.getInput()
      consoleIO.writeMessage("Type the second string:")
      let second = consoleIO.getInput()
 
      //5
      if first.isAnagramOfString(second) {
        consoleIO.writeMessage("\(second) is an anagram of \(first)")
      } else {
        consoleIO.writeMessage("\(second) is not an anagram of \(first)")
      }
    case .Palindrome:
      consoleIO.writeMessage("Type a word or sentence:")
      let s = consoleIO.getInput()
      let isPalindrome = s.isPalindrome()
      consoleIO.writeMessage("\(s) is \(isPalindrome ? "" : "not ")a palindrome")
    default:
      //6
      consoleIO.writeMessage("Unknown option \(value)", to: .Error)
    }
  }
}

Taking a look at what’s going on above:

  1. First, print a welcome message.
  2. shouldQuit breaks the infinite loop that is started in the next line.
  3. Prompt the user for input and convert it to one of the two options if possible.
  4. Prompt the user for the two strings to compare.
  5. Write the result out. The same logic flow applies to the palindrome option.
  6. If the user enters an unknown option, print an error and start the loop again.

At the moment, you have no way to interrupt the while loop. To do this, open ConsoleIO.swift again and add the following line to OptionType:

case Quit = "q"

Next, add the following line to to init(_:):

case "q": self = .Quit

Now go back to Panagram.swift and add a .Quit case to the switch statement inside interactiveMode():

case .Quit:
  shouldQuit = true

Then change the .Unknown case definition inside staticMode() as follows:

case .Unknown, .Quit:

Finally, open main.swift and replace the comment //Handle interactive mode with the following:

panagram.interactiveMode()

Run your project and enjoy your finished command-line program!

Finished_Program

Where to Go From Here?

You can download the final project for this command line programs on OS X tutorial
here.

If you want to write more command-line programs in the future, take a look at how to redirect stderr to a log file and also look at ncurses, which is a C library for writing “GUI-style” programs for the terminal.

You can also check out this great article on scripting with Swift.

I hope you enjoyed this command line programs on OS X tutorial; if you have any questions or comments, feel free to join the forum discussion below!

The post Command Line Programs on OS X Tutorial appeared first on Ray Wenderlich.


Video Tutorial: Networking With NSURLSession Part 4: Delegate vs. Closures

In App Purchases Tutorial: Consumables

$
0
0
In App Purchases tutorial

Learn how to implement consumables with this In-App Purchases tutorial!

Update note: This In App Purchases tutorial on consumables was updated for iOS 9 and Swift 2.2 by Nicholas Waynik. The original tutorial was written by site editor-in-chief Ray Wenderlich.

Unlike other types of IAPs, Consumables are things that are only supposed to be used once. Think of extra lives in games, or stickers in a messaging app. Because of the disposable nature of these IAPs you have to consider some new functionality in your app: like keeping count of how many IAPs have been purchased and possibly limitting the number a person can have.

This In App Purchases tutorial picks up where things left things off in the previous In-App Purchases tutorial, so you’ll have to follow that tutorial first before starting this one. As a reminder, in that tutorial an app called “Rage” was created. It allowed customers to purchase rage face comics as non-consumable In-App purchases.

In this tutorial, you will extend the app to add a new consumable In-App Purchase – after all, those are often way more lucrative than non-consumables, since customers can purchase them more than once!

Note: This tutorial (and the previous) are focused on the “simplest and easiest” way to do things, not the most “robust and flexible” way of doing things. For more in-depth coverage, check out In-App Purchase Video Tutorial Series.

So without further ado, let’s dive into learning more about In-App Purchases – you’ll see it’s pretty easy, and there’s no need to rage about it! :]

Getting Started

Start by downloading the starter project for this tutorial.

Note that the starter project is not the same as where we left things off in the last tutorial – a few extra things were added for you. So, open the project in Xcode and have a look around:

  • Added RandomFaceViewController.swift.
  • Setup the UI for RandomFaceViewController in the Storyboard.
  • Added an additional segue to show RandomFaceViewController.
  • Added four random rage face images to the Asset Catalog.

You will have to make a few changes to this project for it to work with your own Apple developer account:

Select Rage in Project Navigator and then select the Rage target. Select the General tab and change the Bundle identifier from “com.razeware.Rage” to the one you used for the previous IAP tutorial.

Open RageProducts.swift and search for “com.razeware.rage” – replace that with your Bundle identifier as well. If you used a different product identifier for GirlfriendOfDrummerRage, then go ahead and change that in RageProducts.swift as well.

Once you’re done, build and run to try out the app on your device. Purchase a comic to make sure the purchase succeeds, and that you can view the comic after you buy it.

In App Purchases tutorial

Setting up IAP Consumables in iTunes Connect

You have an sneaky plan to make money – instead of allowing the user to see cool random rage faces as often as they’d like, instead you’ll add an arbitrary limit to it, and charge users to purchase more, mwuhahaha!

This way, there will be no limit to how much money users can spend on your app. Hopefully the bucks will keep rolling in!

Note: This is just the beginning of ways you can use consumable In-App Purchases to (arguably sneakily) increase your app’s revenue. To learn more, check out the many blogs and talks about freemium game design, gamer psychology, or any games by Zynga ;]

Just like you did with consumable In-App Purchases, the first step to make this all happen is to create a new In-App Purchase entry in iTunes Connect.

So log onto iTunes Connect, and click My Apps. Click your entry for Rage, then click Features, In-App Purchases and +.

In App Purchases tutorial

Underneath the Consumable option, click Select.

In App Purchases tutorial

Fill out the screen that appears as follows (but replace the bundle ID with your own):

  • Reference Name: Random Rage Face
  • Product ID: com.razeware.rage.RandomRageFace (replace italic part with your bundle ID)
  • Cleared for Sale: Yes
  • Price Tier: Tier 1

Finally, scroll down to the Language section and click Add Language. Fill in the dialog that appears as follows:

In App Purchases tutorial

Click Save, then Save again, and you’re done! Time to try this out in your app.

Implementing a Consumable In-App Purchase

To begin, open RageProducts.swift and add a new static variable for the new product identifier you just created. Then modify the `productIdentifiers` set to also include the new variable. It should look similar to the following:

public static let RandomRageFace = Prefix + "RandomRageFace"
 
private static let productIdentifiers: Set<ProductIdentifier> =
  [RageProducts.GirlfriendOfDrummerRage,
   RageProducts.RandomRageFace]

Next, open IAPHelper.swift and replace deliverPurchaseNotificationForIdentifier(_:) with the following:

private func deliverPurchaseNotificationForIdentifier(identifier: String?) {
  guard let identifier = identifier else { return }
 
  purchasedProductIdentifiers.insert(identifier)
 
  if identifier == RageProducts.RandomRageFace {
    let defaults = NSUserDefaults.standardUserDefaults()
    var currentValue = defaults.integerForKey(RageProducts.RandomRageFace)
    currentValue += 5
    defaults.setInteger(currentValue, forKey: RageProducts.RandomRageFace)
  } else {
    NSUserDefaults.standardUserDefaults().setBool(true, forKey: identifier)
  }
 
  NSUserDefaults.standardUserDefaults().synchronize()
  NSNotificationCenter.defaultCenter().postNotificationName(IAPHelper.IAPHelperPurchaseNotification, object: identifier)
}

Here you add a special case behavior for the consumable In-App Purchase. When a customer purchases one, instead of simply setting a flag indicating whether it’s purchased or not, you increment a value that keeps track of how many times the user can see a random rage face.

Note: This works but isn’t the ideal way of doing things, because now your IAPHelper class has hard-coded logic for a particular In-App Purchase. This doesn’t make it so reusable. For a more reusable way of doing things, check out In-App Purchase Video Tutorial Series.

Next open MasterViewController.swift and replace tableView(_:didSelectRowAtIndexPath:) with the following:

override func tableView(tableView: UITableView,
                        didSelectRowAtIndexPath indexPath: NSIndexPath) {
 
  let product = products[indexPath.row]
  if (product.productIdentifier == RageProducts.RandomRageFace) {
    self.performSegueWithIdentifier(showRandomFaceSegueIdentifier, sender: self)
  } else {
    self.performSegueWithIdentifier(showDetailSegueIdentifier, sender: self)
  }
}

Here you added logic to determine if the selected product is the RandomRageFace IAP. If it is then you will show the new RandomFaceViewController, otherwise you’ll perform the segue with the identifier value of showDetail and show the details of a specific rage face.

Go ahead and build and run. The new Random Rage Face consumable In-App purchase is listed in the table view.

In App Purchases tutorial

Now tap on Random Rage Face.

In App Purchases tutorial

You’ll see that the app displays the the view for RandomFaceViewController. Currently, tapping on the Random Rage Face! button does nothing. Quit the simulator so you can fix this.

Open RandomFaceViewController.swift and replace buttonPressed(_:) with the following:

@IBAction func buttonPressed(sender: UIButton) {
  let defaults = NSUserDefaults.standardUserDefaults()
  var currentValue = defaults.integerForKey(RageProducts.RandomRageFace)
 
  if currentValue <= 0 {
    return
  } else {
    currentValue -= 1
    defaults.setInteger(currentValue, forKey: RageProducts.RandomRageFace)
    defaults.synchronize()
 
    refresh()
 
    let randomIdx = (arc4random() % 4) + 1
    let randomName = "random\(randomIdx).png"
    imageView.image = UIImage(named: randomName)
  }
}

This is basic logic to determine if the user has any random rage faces available. If they do, then you will display one of the random four images included in the starter project. There is one problem though: how does the user know if they have any available faces? To fix that, add the following two methods just above buttonPressed(_:):

override func viewWillAppear(animated: Bool) {
  super.viewWillAppear(animated)
 
  refresh()
}
 
func refresh() {
  let defaults = NSUserDefaults.standardUserDefaults()
  let currentValue = defaults.integerForKey(RageProducts.RandomRageFace)
 
  label.text = "Times Remaining: \(currentValue)"
}

When RandomFaceViewController is first presented, you update the label with the current rage face count by calling refresh(). The refresh() method simply retrieves the number of rage faces left to be viewed from NSUserDefaults. Finally, you display that number in a label at the bottom of the view controller.

And that’s it! Build and Run the app and purchase a few more consumables. Then test out your random rage face button and make sure it works as expected!

In App Purchases tutorial

Where To Go From Here?

Here is the final sample project from the In App Purchases tutorial series.

Congrats – you now have implemented both non-consumable and consumable In-App Purchases, and added the ability for users to restore transactions!

This In App Purchases tutorial may provide more than enough functionality for simple apps. But if you want to take things even further and learn how develop a robust and extensible app, check out In-App Purchase Video Tutorial Series!

I hope you enjoyed this In App Purchases tutorial, and wish you best of luck with your consumable In-App Purchases! Just don’t be too sneaky or evil, one Zynga is enough ;]

The post In App Purchases Tutorial: Consumables appeared first on Ray Wenderlich.

Video Tutorial: Networking With NSURLSession Part 5: Threading And Operation Queues

Video Tutorial: Networking With NSURLSession Part 6: Conclusion

Video Tutorial: Collection Views: Introduction

Video Tutorial: Collection Views Part 1: Getting Started

Video Tutorial: Collection Views Part 2: Custom Cells


How to Make a Game Like Bomberman

$
0
0

unity-particle-systemsBlowing stuff up is fun. Blowing stuff up with friends is even funner. Blowing your friends up? We have a winner!

Unfortunately, it’s a little difficult to secure C4 explosives along with some willing buddies willing to explore the afterlife. Thankfully, there are some alternatives.

Enter Bomberman. Bomberman is a game where four players battle it out by strategically placing bombs across the battlefield with the goal being to blow each other up.

Each bomb has a few seconds of delay before it explodes and spews out an inferno in four directions. For additional excitement, explosions can trigger impressive chain reactions.

The original Bomberman came out in the early 80s and spinoffs have been published ever since. It’s a timeless game formula that’s still a lot of fun to play and build.

The original title was 2D, but you’re going to create a basic 3D version inside of Unity.

In this tutorial, you’ll learn the following:

  • Dropping bombs and snapping them to a tile position.
  • Spawning explosions by using raycasts to check for free tiles.
  • Handling explosions colliding with the player.
  • Handling explosions colliding with bombs.
  • Handling player death(s) to determine a win/draw.

Loosen up your wrists and get ready to shout “fire in the hole”. Things are about to get really explody inside of Unity. :]

Note: This tutorial assumes you know your way around the Unity editor and know how to edit code in a text editor. Check out some of our other Unity tutorials first if you’re not confident yet.

Getting Started

Download the bomberman how-to starter project and extract it to a location of your choosing.

Open up the Starter Project in Unity. The assets are sorted inside several folders:

AssetFolders

  • Animation Controllers: Holds the player animation controller, including the logic to animate the players’ limbs when they walk around. If you need to brush up on animation, check out our Introduction to Unity Animation tutorial
  • Materials: Contains the block material for the level
  • Models: Holds the player, level and bomb models, as well as their materials
  • Music: Contains the soundtrack
  • Physics Materials: Holds the physics material of the players — these are special kinds of materials that add physical properties to surfaces. For this tutorial it’s used to allow the players to move effortlessly arund the level without friction.
  • Prefabs: Contains the bomb and explosion prefabs
  • Scenes: Holds the game scene
  • Scripts: Contains the starter scripts; be sure to open them and read through them because they’re heavily commented to make them easier to understand
  • Sound Effects: Holds the sound effects for the bomb and explosion
  • Textures: Contains both player textures

Dropping A Bomb

If it’s not opened yet, open up the Game scene and give it a run.

FirstRun

Both players can walk around the map using either the WASD keys and the arrow keys.

Normally, when player 1 (the red one) presses Space he should place a bomb at his feet, player 2 should be able to do the same thing by pressing Enter/Return.

However, that doesn’t work yet. You need to implement the code for placing bombs first, so open the Player.cs script in your favorite code editor.

This script handles all player movement and animation logic. It also includes a method named DropBomb that simply checks if the bombPrefab GameObject is attached:

private void DropBomb() {
  if (bombPrefab) { //Check if bomb prefab is assigned first
 
  }
}

To make a bomb drop beneath the player, add the following line inside the if statement:

Instantiate(bombPrefab, myTransform.position, bombPrefab.transform.rotation);

This will make a bomb spawn at the player’s feet. Give your scene a run to try it out:

DropBombs

It’s working great!

There’s a small problem with the way the bombs get dropped though, you can drop them wherever you want and this will create some problems when you need to calculate where the explosions should spawn.

You’ll learn the specifics when this tutorial covers how to make the explosions.

Snapping

The next task it to make sure the bombs snap into position when dropped so they align nicely with the grid on the floor. Each tile on this grid is 1×1, so it’s fairly easy to make this change.

In Player.cs, edit Instantiate() like so:

Instantiate(bombPrefab, new Vector3(Mathf.RoundToInt(myTransform.position.x),
  bombPrefab.transform.position.y, Mathf.RoundToInt(myTransform.position.z)),
  bombPrefab.transform.rotation);

Mathf.RoundToInt calls for the x and z values of the player position, rounds off any float to an int value, which then snaps the bombs to the tile positions:

SnappingBombs

Play the scene and run around while dropping some bombs. The bombs will now snap into place:

BombsSnap

Although dropping bombs on the map is pretty fun, you know it’s really all about the explosions! Time to add some firepower to this thing. :]

Creating Explosions

To start off, you’re going to need a new script:

  • Select the Scripts folder in the Project view.
  • Press the Create button.
  • Select C# Script.
  • Name the newly created script Bomb.

MakeBombScript

Now attach the Bomb script to the Bomb prefab:

  • In the Prefabs folder, select the Bomb GameObject.
  • Click the Add Component button.
  • Type bomb in the search box.
  • Select the Bomb script you just made.

Finally, open the Bomb script in your code editor. Inside of Start(), add the following line of code:

Invoke("Explode", 3f);

Invoke() takes 2 parameters, firstly the name of the method you want to be called and secondly, the delay before it gets called. In this case, you want to make the bomb explode in three seconds, so you call Explode() — you’ll add it next.

Add the following under Update():

void Explode() {
 
}

Before you can spawn any Explosion GameObjects, you’ll need a public variable of the type GameObject so you can assign an Explosionprefab in the Editor. Add the following right above Start():

public GameObject explosionPrefab;

Save your file and return to the Editor. Select the Bomb prefab in the Prefabs folder and drag the Explosion prefab to the Explosion Prefab slot:

DragExplosionPrefab

Once you’ve done this, return to the code editor. You finally get to write the code that makes things go boom!

Inside Explode(), add the following lines:

Instantiate(explosionPrefab, transform.position, Quaternion.identity); //1
 
GetComponent<MeshRenderer>().enabled = false; //2
transform.FindChild("Collider").gameObject.SetActive(false); //3
Destroy(gameObject, .3f); //4

This piece of code does the following:

  1. Spawns an explosion at the bomb’s position.
  2. Disables the mesh renderer, making the bomb invisible.
  3. Disables the collider, allowing players to move through and walk into an explosion.
  4. Destroys the bomb after 0.3 seconds; this ensures all explosions will spawn before the GameObject is destroyed.

Save your Bomb script and return to the editor and give your game a play. Put down down some bombs and bask in the fiery goodness as they explode!

Cool guys don't look at explosions!

Cool guys don’t look at explosions!

Bigger! The Explosions Must be Bigger!

The next step is to add the iconic touch of expanding rows of explosions. To do that, you’ll need to create a coroutine.

Note: A coroutine is essentially a function that allows you to pause execution and return control to Unity. At a later point, execution of that function will resume from where it last left off.

People often confuse coroutines with multi-threading. They are not the same: Coroutines run in the same thread and they resume at intermediate points in time.

To learn more about coroutines and how to define them, check out the Unity documentation.

Return to your code editor and edit the Bomb script. Under Explode(), add a new IEnumerator named CreateExplosions:

private IEnumerator CreateExplosions(Vector3 direction) {
  return null // placeholder for now
}

Create the Coroutines

Add the following four lines of code between the Instantiate call and the disabling of the MeshRenderer in Explode():

StartCoroutine(CreateExplosions(Vector3.forward));
StartCoroutine(CreateExplosions(Vector3.right));
StartCoroutine(CreateExplosions(Vector3.back));
StartCoroutine(CreateExplosions(Vector3.left));

The StartCoroutine calls will start up the CreateExplosions IEnumerator once for every direction.

Now comes the interesting part. Inside of CreateExplosions(), add this piece of code:

//1
for (int i = 1; i < 3; i++) {
  //2
  RaycastHit hit;
  //3
  Physics.Raycast(transform.position + new Vector3(0,.5f,0), direction, out hit, i, levelMask);
 
  //4
  if (!hit.collider) {
    Instantiate(explosionPrefab, transform.position + (i * direction),
    //5 
      explosionPrefab.transform.rotation);
    //6
  } else {
    //7
    break;
  }
 
  //8
  yield return new WaitForSeconds(.05f);
}

This looks like quite a complicated code snippet, but it’s actually fairly straightforward. Here’s a section-by-section explanation:

  1. Iterates a for loop for every unit of distance you want the explosions to cover. In this case, the explosion will reach two meters.
  2. A RaycastHit object holds all the information about what and at which position the Raycast hits — or doesn’t hit.
  3. This important line of code sends out a raycast from the center of the bomb towards the direction you passed through the StartCoroutine call. It then outputs the result to the RaycastHit object. The i parameter dictates the distance the ray should travel. Finally, it uses a LayerMask named levelMask to make sure the ray only checks for blocks in the level and ignores the player and other colliders.
  4. If the raycast doesn’t hit anything then it’s a free tile.
  5. Spawns an explosion at the position the raycast checked.
  6. The raycast hits a block.
  7. Once the raycast hits a block, it breaks out of the for loop. This ensures the explosion can’t jump over walls.
  8. Waits for 0.05 seconds before doing the next iteration of the for loop. This makes the explosion more convincing by making it look like it’s expanding outwards.

Here’s how it looks in action:

BombExplosionDiagram

The red line is the raycast. It checks the tiles around the bomb for a free space, and if it finds one then it spawns an explosion. When it hits a block, it doesn’t spawn anything and it stops checking in that direction.

Now you can see the reason why bombs need to be snapped to the center of the tiles. If the bombs could go anywhere, then in some edge cases the raycast will hit a block and not spawn any explosions because it is not aligned properly with the level:

AllignedVsNot

Add a LayerMask

There’s still an error in the Bomb code — the LayerMask doesn’t exist yet. Right under the variable declaration of explosionPrefab, add an extra line to it so it looks like this:

public GameObject explosionPrefab;
public LayerMask levelMask;

A LayerMask selectively filters out certain layers and commonly used with raycasts. In this case, you need to filter out only the blocks so the ray doesn’t hit anything else.

Save your bomb script and return to the Unity Editor. Click the Layers button at the top right and select Edit Layers…

EditLayersButton

Click the text field next to User Layer 8 and type in “Blocks“. This defines a new layer you can use.

BlocksLayer

Inside the hierarchy view, select the Blocks GameObject.

BlocksGameObject

Change the layer to your newly created Blocks layer:

SelectBlocksLayer

When the Change Layer dialog comes up, click the “Yes, change children” button, to apply to all of the yellow blocks scattered across the map.

ChangeLayerDialog

Finally, select the Bomb prefab in the Prefabs folder in the project view, and change the Level Mask to Blocks.

BlocksLevelMask

Run the scene again and drop some bombs. Watch your explosions spread out nicely and go around the blocks:

ExplosionSpread

Congratulations, you’ve just made it through the hardest part of this tutorial!

Go ahead and reward yourself with a refreshing drink or a delicious snack, think about what you just did, and then come back to play around with reactions to explosions!

Chain Reactions

When an explosion from one bomb touches another, the next bomb should explode — this feature makes for a more strategic, exciting and firey game.

Luckily this is quite easy to implement.

Open up the Bomb.cs script in your code editor. Add a new method named OnTriggerEnter below CreateExplosions():

public void OnTriggerEnter(Collider other) {
}

OnTriggerEnter is a pre-defined method in a MonoBehaviour that gets called upon collision of a trigger collider and a rigidbody. The Collider parameter, named other, is the collider of the GameObject that entered the trigger.

In this case, you need to check the colliding object and make the bomb explode when it is an explosion.

First, you need know if the bomb has exploded. The exploded variable will need to be declared first, so add the following right under the levelMask variable declaration:

private bool exploded = false;

Inside OnTriggerEnter(), add this snippet:

if (!exploded && other.CompareTag("Explosion")) { // 1 & 2  
  CancelInvoke("Explode"); // 2
  Explode(); // 3
}

This snippet does three things:

  1. Checks the the bomb hasn’t exploded.
  2. Checks if the trigger collider has the Explosion tag assigned.
  3. Cancel the already called Explode invocation by dropping the bomb — if you don’t do this the bomb might explode twice.
  4. Explode!

Now you have a variable, but it hasn’t been changed anywhere yet. The most logical place to set this is inside Explode(), right after you disable the MeshRenderer component:

...
GetComponent<MeshRenderer>().enabled = false;
exploded = true;
...

Now everything is set up, so save your file and run the scene again. Drop some bombs near each other and watch what happens:

ChainReaction

Now you’ve got some seriously destructive firepower going on. One little explosion can set your little game world on fire by triggering other bombs, allowing for these cool chain reactions!

The last thing to do is to handle players’ reactions to explosions (Hint: they’re not good!) and how the game translates the reaction into a win or draw state.

Player Death And How To Handle It

Open the Player.cs script in your code editor.

Right now, there’s no variable to indicate if the player is dead or alive, so add a boolean variable at the top of the script, right under the canMove variable:

public bool dead = false;

This variable is used to keep track if the player died to an explosion.

Next, add this above all other variable declarations:

public GlobalStateManager GlobalManager;

This is a reference to the GlobalStateManager, a script that is notified of all player deaths and determines which player won.

Inside OnTriggerEnter(), there’s already a check to see if the player was hit by an explosion, but all it does right now is log it in the console window.

Add this snippet under the Debug.Log call:

dead = true; // 1
GlobalManager.PlayerDied(playerNumber); // 2
Destroy(gameObject); // 3

This piece of code does the following things:

  1. Sets the dead variable so you can keep track of the player’s death.
  2. Notifies the global state manager that the player died.
  3. Destroys the player GameObject.

Save this file and return to the Unity editor. You’ll need to link the GlobalStateManager to both players:

  • In the hierarchy window, select both Player GameObjects.
  • Drag the Global State Manager GameObject into their Global Manager slots.

LinkGlobalStateManager

Run the scene again and make sure one of the players is obliterated by an explosion.

HitByExplosion

Every player that gets in the way of an explosion dies instantly.

The game doesn’t know who won though because the GlobalStateManager doesn’t use the information it received yet. Time to change that.

Declare the Winner

Open up GlobalStateManager.cs in your code editor.

For the GlobalStateManager to keep track of what player(s) died, you need two variables. Add these at the top of the script above PlayerDied():

private int deadPlayers = 0;
private int deadPlayerNumber = -1;

First off, deadPlayers will hold the amount of players that died. The deadPlayerNumber is set once the first player dies, and it indicates which one it was.

Now that you have this set up, you can add the actual logic. In PlayerDied(), add this piece of code:

deadPlayers++; // 1
 
if (deadPlayers == 1) { // 2
    deadPlayerNumber = playerNumber; // 3
    Invoke("CheckPlayersDeath", .3f); // 4
}

This snippet does the following:

  1. Adds one dead player.
  2. If this is the first player that died…
  3. It sets the dead player number to the player that died first.
  4. Checks if the other player also died or if just one bit the dust after 0.3 seconds.

That last delay is crucial for allowing a draw check. If you checked right away, you might not see that everybody died. 0.3 seconds is sufficient to determine if everybody died.

Win, Lose or Draw

You’re made it to the very last section! Here you create the logic behind choosing between a win or a draw!

Make a new method named CheckPlayersDeath in the GlobalStateManager script:

void CheckPlayersDeath() {
  // 1
  if (deadPlayers == 1) {
    // 2
    if (deadPlayerNumber == 1) {
      Debug.Log("Player 2 is the winner!");
    // 3
    } else {
      Debug.Log("Player 1 is the winner!");
    }
     // 4
  } else {
    Debug.Log("The game ended in a draw!");
  }
}

This is the logic behind the different if-statements in this method:

  1. A single player died and he’s the loser.
  2. Player 1 died so Player 2 is the winner.
  3. Player 2 died so Player 1 is the winner.
  4. Both players died, so it’s a draw.

Save your code, then give the game a final run and test if the console window reads out what player won or if it ended up as a draw:

FInalRun

And that concludes this tutorial! Now go ask a friend if they want to share in the fun and blow them up when you get the chance. :]

Where To Go From Here?

Download the final project here.

Now you know how to make a basic Bomberman-like game by using Unity.

This tutorial used some particle systems for the bomb and the explosion, if you want to learn more about particle systems, check out my Introduction To Unity: Particle Systems Tutorial.

I highly encourage you to keep working on this game — make it your own by adding new features! Here are some suggestions:

  • Make the bombs “pushable”, so you can escape bombs next to you and push them towards your opponent
  • Limit the amount of bombs that can be dropped
  • Make it easy to quickly restart the game
  • Add breakable blocks that get destroyed by the explosions
  • Create interesting powerups
  • Add lives, or a way to earn them
  • UI elements to indicate what player won
  • Find a way to allow more players

Be sure to share your creations here, I’d love to see what you guys can come up with! As always, I hope you enjoyed this tutorial!

If you have any remarks or questions, you can do so in the Comments section.

The post How to Make a Game Like Bomberman appeared first on Ray Wenderlich.

Video Tutorial: Collection Views Part 3: Multiple Sections

Video Tutorial: Collection Views Part 4: Inserting Cells

Video Tutorial: Collection Views Part 5: Subclassing Layout

Introduction to Unity Sound

$
0
0

game-thumb

Creating the visual elements of a game is only half of the work. Once you have your monsters in place and you have primed all your catapults to fire, a colossal battle may appear underwhelming when the greatest of explosions fail to produce even the tiniest of a whisper.

But when you add sounds to your game – even terrible ones at that, you may be shocked to discover the depth that they provide. Throw in some awesome sounds, and you’ll may discover an entirely new game.

Adding sound via code isn’t difficult, but Unity, which has an easy-to-use visual editor and works with a wide range of audio file formats, makes it even simpler. This tutorial will show you how to add sounds to the game Barn Blaster by using the Unity editor and by adding code, so if you are looking to add sounds to your next game, this tutorial is a great starting point!

In this tutorial, you’ll:

  • learn the difference between AudioClips and AudioSources
  • discover how to configure various properties of 3D sounds
  • programmatically play sounds
  • learn to maybe, just maybe, throw a pig into a barn

This is a beginner level tutorial, but you should be familiar with Unity’s interface. If you are new to Unity or need a refresher on the basic concepts, check out our Introduction to Unity tutorial.

Note: You will need to have Blender installed in order to open the project; get it free here.

Getting Started

First, download the source project: . Open the project in Unity and hit play.

scene

You’ll see a bunch of tractors driving back and forth in front of a red barn. When you hit the space bar, a farm animal launches into the air. The goal of the game is to land the animal in the barn without getting hit by a tractor. If the animal gets hit by a tractor it dies; if it makes it into the barn, it’s a goal!

Right now, of course, it’s totally silent—not a moo to be heard! You’ll bring the game to life with sound.

Adding Your First Sound Effects

The game is set up to launch a random animal: a cow, pig or sheep. Each one will play a different sound, so your first task is add the sound effect of the animal being launched.

The project has already been set up with the prefabs (object templates) for each animal. In the Project tab, click on the Assets/Prefabs folder and select the cow prefab.

Note: Never heard of a prefab? Check out our Introduction to Unity tutorial to get up to speed.

prefabs

The first thing this prefab needs is an AudioSource component to play sound. Click the Add Component button and type in AudioSource, then select the only option that appears.

addAudioSource

The cow prefab can now play audio, but it needs an AudioClip to play. Currently, the AudioClip on the component you added is empty.

emptyAudioClip

Some of you may be wondering: what exactly is an AudioSource? How does it differ from an AudioClip? You can assume the functions by their names, but assuming can be a dangerous thing—especially with flying livestock on the line!—so let’s cover some basics.

How Sound Effects Work in Unity

To play sound in Unity, you use an AudioSource and an AudioClip.

An AudioSource is what will actually play the sound in 2D or 3D space. In 3D space, the sound’s volume can vary based on how far the AudioSource is from the object listening to it (the AudioListener, which in this game is on the camera).

You can set an AudioSource to play sound in 2D space, which means it will play at a consistent volume regardless of the distance from the AudioListener.

The AudioClip is the actual audio file the AudioSource will play.

audiosourcecomponent

One important thing to note is that the AudioSource is a component. That means it’s an object that inherits from Unity’s MonoBehaviour class and can be attached directly to any Unity GameObject.

The AudioClip is a member variable that is found on the AudioSource (i.e. each AudioSource will have one AudioClip). You can attach components through the Unity editor and through code, though this tutorial only uses the editor.

A key part of playing sounds is setting up triggers for AudioSources to play. A trigger is just that: a condition which causes the AudioSource to play.

In this tutorial you will be editing code which has been pre-configured to only need you to code in the audio-playing portions, but behind the scenes is code that uses Unity’s physics engine.

Note: If you are interested in learning how these physics triggers work, check out Unity’s physics system.

Adding AudioClips

Click on the Assets/Sounds folder in the Project view and find the moo sound file. With the cow prefab still highlighted in the Inspector, drag the moo sound file onto the AudioClip.

dragsingleaudioclip

Make sure there is a check mark in the the Play On Awake box.

Screen Shot 2016-03-24 at 3.38.57 PM

This means the sound file will play as soon as the object is created, which is exactly what you want. When the animal is launched toward the barn, it will let out an animal roar—or moo, in this case!

As a challenge, do the same thing for the Sheep and Pig prefabs.

Need help? Just open the spoiler to find out how.

Solution Inside SelectShow>

At this point, all three animal prefabs have their voices added. To test it out, hit play and press the space bar to launch an animal. You should hear each animal playing its respective sound as it flies towards the barn.

moo

Oinks and moos and baas—oh my!

Sound Not Playing?

The AudioSource can play a wide variety of file formats, including the most common mp3 and wav formats. If you ever find that your sound file is not playing, first check here to see if the file format is supported.

Note: When choosing a sound format to use, you should select a lossless format such as ogg or wav.

In some cases, sound files will be encoded into formats such as mp3 to take advantage of certain hardware decoding. In cases where mp3 is used, those mp3 files will be re-encoded, resulting in additional quality loss.

Since this tutorial was prepared ahead of time, the file formats should be fine, so if the sounds aren’t playing check the following:

  1. Is the volume set too low? Check the volume level on each of AudioSources.
  2. volume0

  3. Is the AudioSource component disabled? If the component is disabled, it won’t play the sound.
  4. disabledaudiosource

  5. Is Play On Awake toggled? You won’t always want this on, but if you expect a sound to play as soon as the object is created, check that this is toggled on. It will play at the same frame the object is created.

playOnAwake

Sound Polish

The game is coming along great so far—all the animals are making their sounds as they fly towards the barn. But a few things are still missing:

  • The tractors aren’t making any sound.
  • There’s no success sound when an animal makes it to the barn.
  • There is no death sound if an animal hits a tractor.

Adding these sounds will give this game this game some real polish.

Tractor Sounds

To add a buzzing sound to the tractors as they move back and forth, first hold Control on Windows and Command on Mac and click on all three tractors in the Hierarchy. Batch-add an AudioSource, then add the tractor sound clip just like you did with the animal sounds. Make sure Play On Awake is checked.

addaudiocomponent

With all the tractors hooked up with sound, hit the play button.

loudtractors

Hmmm … it’s great the tractors have sound, but with all three playing at the same time it’s hard to distinguish between them. Plus it’s really loud.

As mentioned earlier, 3D sounds can play with a decrease in volume the further the AudioListener (in this game it’s on the camera) is from the AudioSource. Adding a falloff effect (so that the further the tractors are from the camera, the quieter they are) will make things sound a lot better.

Click on tractor in the Hierarchy; in the Inspector, look at the AudioSource component. There will be a drop down area called 3D Sound Settings. Here you can set the Doppler Level, the Rolloff and the Distance variables.

The Doppler Level is exactly what it sounds like: sound intensity varies to mimic the Doppler effect. The Rolloff Level is how much the volume quiets down the further it is from the AudioListener.

This is the closest tractor to the player, so its sound falloff should be more dramatic than the back two. Set the Volume Rolloff to Linear Rolloff, which will make the effects more pronounced, and set the Min Distance to 1 and the Max Distance to 9. Set the Doppler Level to 0.68.

3DSoundSettings

This will make the front tractor sound loud as it approaches the middle of the screen (as it moves closer to the listener on the camera) and quieter as it moves off screen. Hit play to see this for yourself.

vroom

For the back two tractors, their sounds should be more like background noise; only the front tractor should have the exaggerated sounds.

To turn down the intensity of the back tractors, start by selecting tractor2 in the Hierarchy. Set the Volume Rolloff to Linear Rolloff, then set the Min Distance to 1 and the Max Distance to 30. Set the Doppler Level to 0.68. Next, select tractor3 in the Hierarchy and set the Volume Rolloff to Linear Rolloff. Set the Min Distance to 1 and the Max Distance to 50. Set the Doppler Level to 0.68.

Hit play and listen to the different sound levels of the tractors as they move back and forth.

vroomVroom

The tractors are way too loud, especially with three of them playing at once. Set the Volume slider on their AudioSource to 0.1.

If you play the game for more than 40 seconds, you’ll notice the tractor sounds cut out. That’s because their AudioSource hasn’t been set to loop. To change this, click the Loop box for each tractor’s AudioComponent.

loop

Hit Sounds

When the animals hit a tractor, they unfortunately get clobbered by it. What’s even more unfortunate is that there is currently no sound when that happens! As mentioned earlier, the tractors are using the Unity physics engine and listening for collisions with the animals. When an animal collides with a tractor, it tells the animal to die—that’s when the sound needs to play.

First, you will need to attach an AudioClip of the death sound to the Tractor component. To do this, hold Control on Windows or Command on Mac and click on the three tractors in the Hierarchy. Click on the Sounds folder in Assets and drag the death file to the Death Sound field of the Tractor component:

Adding death audio clip to Tractor component.

To code in the animal death sound, start by double-clicking on the Tractor C# script to open it in your editor. Before the closing brace of the if statement, add the following code:

audioSource.PlayOneShot(deathSound);

The final result should look like this:

void OnCollisionEnter(Collision col) {
  if (col.gameObject.GetComponent<Animal>() && !col.gameObject.GetComponent<Animal>().isDead) {
    Destroy(col.gameObject);
    audioSource.PlayOneShot(deathSound);
  }
}

Hit Control-S on Windows or Command-S on Mac to save the script.

PlayOneShot() plays the sound once. You are passing in the sound you added to the tractor and then playing it once from the tractor. The reason the tractor (rather than the animal) should play the sound is that when the animal is hit by the tractor, the literal GameObject that was the animal is deleted. Since it no longer exists, the animal can’t play a sound. You could turn the mesh off and play the sound from the animal that way, but that is more complicated.

The benefit of using PlayOneShot() is that the sound will play to completion even if PlayOneShot() is called again. If this were not the case, the animal sounds would cut each other off, sounding jerky to user.

Hit play and exercise your darker side by intentionally launching animals into the tractors instead of aiming for the safety of the barn. You should hear a “squish” sound as they collide with the tractor.

squish

Celebration Sounds

The only missing sound at this point is the success sound when an animal makes it to the barn.

To add that, start by clicking on the barn object in the Hierarchy. In the Inspector, add an AudioSource component to it, then drag the win sound from Assets/Sounds to the AudioClip field. This time, make sure Play On Awake is turned off. This sound will only be played if an animal makes to the barn.

Double-click on the Barn script in Assets/Scripts. Underneath the opening brace of the if statement, add the following:

if(col.gameObject.GetComponent<Animal>())

It should look like this:

void OnCollisionEnter(Collision col){
  if(col.gameObject.GetComponent<Animal>()){
    GetComponent<AudioSource>().Play();
    Destroy(col.gameObject);
  }
}

This tells the barn that when an animal collides with it, it should get the AudioSource component and play it. Save your changes, then hit play and launch animals into the barn. A success sound will now play when the animal makes it to the barn.

win

Success!

Finishing Touches: Varying Sound Effects

There’s one last bit of polish you can add for very little effort. Hearing the exact same sound over and over is annoying. To keep sounds fresher and less irritating, code in some variance to the pitch.

Open the Animal in the Scripts folder. Add the following just under public bool isDead = false;

void Start(){
  AudioSource audioSource = GetComponent<AudioSource>();
  audioSource.pitch = Random.Range(0.8f, 1.5f);
  audioSource.Play();
}

This code fetches the AudioSource component and sets the pitch variable to a random value between 0.8 and 1.5. Now hit play and launch the animals. Their animal sounds will vary each time. Pretty cool, right?

sheepLaunch

Where to Go From Here?

Great job adding your first sound effects to a Unity game! Now your animals can happily moo, oink and baa their way into the barn—unless they get hit by a tractor, of course.

If you ran into any issues, download the completed project: Barn Blaster – Complete Project

For more fun, try adding different pitches to each of the tractors, to the success sound that plays when an animal makes it to the barn and to the death sounds. You can also try adding different animal sounds and a unique death sound for each animal (although that will require a little more coding, along with finding more audio files).

To learn more about Unity’s sound engine, check out Unity’s Live Training on Adding Sound Effects to Your Game. Also, check out the AudioSource and AudioClip Unity documentation.

Stay tuned for future Unity tutorials! Feel free to leave comments below, or join the conversation in our forums.

The post Introduction to Unity Sound appeared first on Ray Wenderlich.

Viewing all 4370 articles
Browse latest View live


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