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

Video Tutorial: Introduction to Unity Part 18: Publishing Your Game


Video Tutorial: Introduction to CloudKit Part 1: Series Introduction

Free Live Tech Talk (Swift, Functional Programming, and the Future of Objective-C) Next Week!

$
0
0
Free live tech talk (Facebook Pop Animation Library) tomorrow!

Free live tech talk (Swift, Functional Programming, and the Future of Objective-C) next week!

This is a heads-up that we are having a free live tech talk on “Swift, Functional Programming, and the Future of Objective-C” next Tuesday, November 11, and you’re all invited! Here are the details:

  • When: Tuesday, Nov 11 at 2:00 PM EST – 3:00 PM EST
  • What: Swift, Functional Programming, and the Future of Objective-C (come w/ questions!)
  • Who: Alexis Gallagher (Tech Editor)
  • Where: Google Hangouts Event Page
  • Why: For learning and fun!
  • How: Visit the event page and a video URL should be posted. Follow the instructions there to submit your Q&A (via text) as the talk runs.

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

Free Live Tech Talk (Swift, Functional Programming, and the Future of Objective-C) Next Week! is a post from: Ray Wenderlich

The post Free Live Tech Talk (Swift, Functional Programming, and the Future of Objective-C) Next Week! appeared first on Ray Wenderlich.

Video Tutorial: Introduction to CloudKit Part 2: Containers and Databases

GPUImage with Brad Larson – Podcast S02 E04

$
0
0
Learn about GPUImage with Brad Larson!

Learn about GPUImage with Brad Larson!

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

Remember that among the many changes in this season, we are now moving to a weekly (and shorter) format – so we’re cracking along with episodes (4 already)!

In this episode, we talk with Brad Larson, co-founder of Sonoplot and author of GPUImage, a popular open source image processing library.

In this episode, we take a deep dive into GPUImage and how it makes doing real time image or video processing on a mobile GPU much easier.

[Subscribe in iTunes] [RSS Feed]

Links and References

Contact Us

Where To Go From Here?

We hope you enjoyed this podcast, and the changes we made for season 2.

Remember – we’re now on a weekly format, so stay tuned for a new episode next week! :]

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

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

GPUImage with Brad Larson – Podcast S02 E04 is a post from: Ray Wenderlich

The post GPUImage with Brad Larson – Podcast S02 E04 appeared first on Ray Wenderlich.

Collection Data Structures In Swift

$
0
0
What kind of performance do you want from your data structure?

What kind of performance do you want from your data structure?

Imagine you have an application that needs to work with a lot of data. Where do you put that data? How do you keep it organized and handle it efficiently?

If your program only manages one number, you store it in one variable. If it has two numbers then you’d use two variables.

What if it has 1000 numbers, 10,000 strings or the ultimate library of memes? (Wouldn’t it be nice to be able to find a perfect meme in an instant?) In that case, you’ll need one of the fundamental collection data structures. Fortunately for you, that’s the topic of this tutorial.

Here’s how the tutorial will flow:

  • You’ll review what a data structure is and then you’ll learn about Big-O notation. It’s the standard tool for describing the performance of different data structures.
  • Next up: practicing by measuring the performance of arrays, dictionaries and sets — the most basic data structures available in Cocoa development. This will also double as a rudimentary introduction to performance testing.
  • As you proceed, you’ll compare the performance of mature Cocoa structures with newer, Swift-only counterparts.
  • Finally, you’ll briefly review some related types offered by Cocoa. These are data structures that you might be surprised to learn are already at your fingertips.

Getting Started

Before you dive in and explore the data structures used in iOS, you should review a couple of basic concepts about what they are and how to measure their performance.

There are many types of collection data structures, and each represents a specific way to organize and access a collection of items. One collection type might make some activities especially efficient, such as adding a new item, finding the smallest item or ensuring you’re not adding duplicates.

Without collection data structures, you’d be stuck trying to manage items one by one. A collection allows you to:

  1. Handle all those items as one entity
  2. Imposes some structure on them
  3. Efficiently insert, removing and retrieve items

What is “Big-O” Notation?

Big-O — that’s the letter O, not the number zero — notation is a way of describing the efficiency of an operation on a data structure. There are various kinds of efficiency: you could measure how much memory the data structure consumes, how much time it takes under the worst case scenario, how much time it takes on average and so on and so forth.

In this tutorial, you’ll measure how much time an operation takes, on average.

In general, larger quantities of data don’t make an operation faster. Usually it’s the opposite, but sometimes there is little or no slowdown. Big-O notation is a precise way of describing this. You write an exact functional form that roughly describes how the running time changes based on the number of elements in the structure.

When you see Big-O notation written as O(something-with-n), the n is the number of items in the data structure, and the something-with-n is roughly how long the operation will take.

“Roughly”, ironically enough, has a specific meaning: the behavior of the function at the asymptotic limit of very large n. Imagine n is a really really large number – you’re thinking about how the performance of some operation will change as you go from n to n+1.

Note: This is all a part of algorithmic complexity analysis, and if you wish to explore it deeper then whip out any computer science textbook. There you’ll find mathematical methods for analyzing complexity from scratch, finer distinctions between different kinds of efficiency, more explicit formulations of assumptions about the underlying machine model, and other fun stuff that you may or may not wish you knew.

The most commonly seen Big-O performance measures are as follows, in order from best to worst performance:

  • O(1) (constant time): No matter how many items are in a data structure, this function calls the same number of operations. This is considered ideal performance.
  • O(log n) (logarithmic): The number of operations this function calls grows at the rate of the logarithm of the number of items in the data structure. This is good performance, since it grows considerably slower than the number of items in the data structure.
  • O(n) (linear): The number of operations this function calls will grow linearly with the size of the structure. This is considered decent performance, but it can grind along with larger data collections.
  • O(n (log n)) (“linearitmic”): The number of operations called by this function grow by the logarithm of the number of items in the structure multiplied by the number of items in the structure. Predictably, this is about the lowest level of real-world tolerance for performance. While larger data structures perform more operations, the increase is somewhat reasonable for data structures with small numbers of items.
  • O(n²) (quadratic): The number of operations called by this function grow at a rate that equals the size of the data structure, squared — poor performance at best. It grows quickly enough to become unusably slow even if you’re working with small data structures.
  • O(2^n) (exponential): The number of operations called by this function grow by two to the power of the size of the data structure. This gives very poor performance and becomes intolerably slow almost immediately.
  • O(n!) (factorial): The number of operations called by this function grow by the factorial of the size of the data structure. Essentially, you have the worst case scenario for performance. For example, in a structure with just 100 items, the multiplier of the number of operations is 158 digits long.

Here’s a more visual representation of performance and how it degrades when there are more items in a collection, going from one to 25 items:

Big-O Notation

Did you notice that you can’t even see the green O(log n) line because it is so close to the ideal O(1) at this scale? That’s pretty good! On the other hand, operations that have Big-O notations of O(n!) and O(2^n) degrade so quickly that by the time you have more than 10 items in a collection, the number of operations spikes completely off the chart.

Yikes! As the chart clearly denotes, the more data you handle, the more important it is to choose the right data structure for the job.

Now that you’ve seen how to compare the performance of operations on data structures, it’s time to review the three most common types used in iOS and explore how they perform in theory and in practice.

Common iOS Data Structures

The three most common data structures in iOS are arrays, dictionaries and sets. First consider how they differ in ideal terms, as fundamental abstractions, and then you’ll examine the performance of the actual concrete classes which iOS offers for representing those abstractions.

For arrays and dictionaries, iOS offers multiple concrete classes that work for the same abstraction. In addition to the old Foundation data structures available in Swift and Objective-C, there are new Swift-only versions of data structures that integrate tightly with the language.

Foundation data structures have been around longer and are currently faster to create, even when you’re working with vast quantities of data. Swift data structures, however, can be faster when you need to search through data. Which one to choose depends on the operation you want to perform.

Arrays

Arrays

An array is a group of items placed in a specific order, and you can access each item via an index — a number that indicates its position in the order. When you write the index in brackets after the name of the array variable, this is subscripting.

Swift arrays are immutable if you define them as constants with let, and mutable if you define them as variables with var.

In contrast, a Foundation NSArray is immutable by default. If you want to add, remove or modify items after creating the array, you must use the mutable variant class NSMutableArray.

An NSArray is heterogeneous, meaning that it can contain Cocoa objects of different types. Swift arrays are homogeneous, meaning that each Swift Array is guaranteed to contain only one type of object.

However, you can still define a single Swift Array so it stores various types of Cocoa objects by specifying that the one type is AnyObject, since every Cocoa type is also a subtype of this.

Expected Performance and When to Use Arrays

Order matters, and that is the primary reason to use an array to store variables. Think about those times when you sort contacts by First or Last name, a To-Do list by date, or any other situation when it’s critical to find or display data in a specific way.

Apple’s documentation includes three key expectations for Array performance in the CFArray header:

  1. Accessing any value at a particular index in an array is at worst O(log n), but should usually be O(1).
  2. Searching for an object at an unknown index is at worst O(n (log n)), but will generally be O(n).
  3. Inserting or deleting an object is at worst O(n (log n)) but will often be O(1).

These guarantees subtly deviate from the simple “ideal” array that you might expect from a computer science textbook or the C language, where an array is always a sequence of items laid out contiguously in memory.

Consider it a useful reminder to check the documentation!

In practice, these expectations make sense when you think about them:

  1. If you already know where an item is and need to look it up, then it should be very fast.
  2. If you don’t know where a particular item is, you’ll need to look through the array from beginning to end to find it, and your search will be slower.
  3. If you know where you’re adding or removing an object, it’s not too difficult, although you may need to adjust the rest of the array afterwards, and that is more time-consuming.

How well do these expectations align with reality? Keep reading to find out!

Sample App Testing Results

Download the the sample application for this tutorial and open it in Xcode. There are some testing methods that will create and/or test an array, and then show you the how long it took to perform each task.

One thing to note: In the app, the Debug configuration automatically sets optimization to a level equal to the release configuration — this is so when you test the application you get the same level of optimization you’d see in the real world.

With optimization off, the results for Swift are a lot worse. Feel free to test this on your own, but make sure you’ve got a good book to read while the tests run.

You need a minimum of 1000 items to run tests with the sample app. When you build and run, the slider will be set to 1000. Press the Create Array and Test button, and you’ll be testing in no time:

Swift 1000 Items

Drag the slider over ever so slightly to the first number above 1000 you can reasonably hit (which will probably be somewhere around 100,000), and press Create Array and Test again. This will take…quite a bit longer:

Swift Array 100,000

In this case, which ran on an iPhone 5 running iOS 8 GM, for around 106.5 times the number of items, it took roughly 1,417 times as much time to create the array.

To grow at O(n) in this example, you’d expect the array with 106.5 times the number of items to take around 3.7 seconds. To grow at O(n log n), you’d expect it to take around 33.5 seconds. To grow at O(n²), you’d expect it to take about 395 seconds.

So in this example, the Swift Array creation performance drops somewhere between O(n log n) and O(n²). As you can see, this is not usable once you get beyond a few dozen items.

What about NSMutableArray? You can still call Foundation classes from Swift without having to drop back down to Objective-C, and you’ll notice there is also a Swift class called NSArrayManipulator that conforms to the same protocol, ArrayManipulator.

Because of this, you can easily swap in NSMutableArray for a Swift Array. The project code is simple enough that you can try NSMutableArray with a single line change to compare the performance.

Open ArrayViewController.swift file and change line 27 from:

let arrayManipulator: ArrayManipulator = SwiftArrayManipulator()

To:

let arrayManipulator: ArrayManipulator = NSArrayManipulator()

Build and run again, and press Create Array and Test to test the creation of an NSMutableArray with 1000 items:

NSArray 1,000 Items

Wow, it’s much faster to create an array this way! You’re probably thinking, “Okay, this is clearly much better performance than Swift — why on earth does its name imply speed? More importantly, how fast can this go?”

Slide that slider as far to the right as it will go — to 10,000,000 items — and press Create Array and Test again. Creating an array with 10 *million* items with a Foundation structure is more than three times faster than creating an array with around 100,000 in Swift. Yikes!

NSArray 10M items

However, you only create an array once then you perform other operations on it, like finding, adding, or removing objects.

In more exhaustive testing, like when you’re using some of iOS 8’s performance testing methods to call each of these methods 50 times, patterns emerge:

As you’ve seen, creating an array is much, much faster with Foundation classes than it is with Swift. The time creating NSArray objects grows at about an O(n) rate, while Swift arrays grow between O(n) and O(n²).

The fact that Swift arrays start slower and grow faster means they’re really slow when you create large arrays.

Adding and removing objects to and from an array isn’t quite as big of a difference — while Swift arrays are still slower than NSArray, they don’t grow nearly as quickly. Generally, they grow between O(log n) and O(n).

Looking up items within an array is where Swift justifies its name. Lookups up by index and object grow at very close rates for both Swift arrays and NSArray. When you’re looking up by object, large Swift arrays perform 50 times faster than using comparable NSMutableArray objects.

That’s pretty darn fast!

The types in Swift arrays certainly help for lookups by object; these operate without the overhead an array that could contain any object.

On the other hand, NSArray first has to determine the type of each object, then figure out if it’s equal to the object you seek.

Note: The results of running each method 50 times against the Gold Master versions of Xcode 6 and iOS 8 on an iPhone 5 are available in this iPhone 5 Performance Tests spreadsheet. You can also run the tests included with the application to see how they run on a 10-runs-per-test average, and how they run on your phone.

Dictionaries

Dictionaries

Dictionaries are a way of storing values that don’t need to be in any particular order and are uniquely associated with keys. You use the key to store or look up a value.

Dictionaries also use subscripting syntax, so when you write dictionary["hello"], you’ll get the value associated with the key hello.

Like arrays, Swift dictionaries are constant if you declare them with let and mutable if you declare them with var. Similarly on the Foundation side, there are both NSDictionary and NSMutableDictionary classes for you to use.

Another characteristic that is similar to Swift arrays is that dictionaries are strongly typed, and you must have known key and value types. NSDictionary objects are able to take any NSObject as a key and store any object as a value.

You’ll see this in action when you call a Cocoa API that takes or returns an NSDictionary. From Swift, this type appears as [NSObject: AnyObject]. This indicates that the key must be an NSObject subclass, and the value can be any Swift-compatible object.

When to use Dictionaries

Chaplin

My cat knows when you use dictionaries. Do you?

Dictionaries are best used when there isn’t a particular order to what you need to store, but there is a meaningful association to what you need to store.

To help you examine how dictionaries and other data structures in the rest of this tutorial work, create a Playground by going to File…\New\Playground, and name it DataStructures.

For example, pretend you need to store a data structure of all your friends and their cats’s names, so you can lookup the cat’s name by your friend’s name. This way, you don’t have to remember the cat’s name to stay in your friends’ good graces.

First, you’d want to store the dictionary of people and cats:

let cats = [ "Ellen" : "Chaplin", "Lilia" : "George Michael", "Rose" : "Friend", "Bettina" : "Pai Mei"]

Thanks to Swift type inference, this will be defined as `[String: String]` – a dictionary with string keys and string values.

Now try to access items within it:

cats["Ellen"] //returns Chaplin as an optional
cats["Steve"] //Returns nil

Note that subscripting syntax on dictionaries returns an optional. If the dictionary doesn’t contain a value for a particular key, the optional is nil; if it does contain a value for that key you could get the wrapped value.

Because of that, it’s a good idea to use the if let optional-unwrapping syntax to access values in a dictionary:

if let ellensCat = cats["Ellen"] {
	println("Ellen's cat is named \(ellensCat).")
} else {
	println("Ellen's cat's name not found!")
}

Since there is a value for the key “Ellen”, this will print out “Ellen’s cat is named Chaplin” in your Playground.

Expected Performance

Once again, Apple outlines the expected performance of dictionaries in Cocoa in the CFDictionary.h header file:

  1. The performance degradation of getting a single value is guaranteed to be at worst O(n), but will often be O(1).
  2. Insertion and deletion can be as bad as O(n²), but will much more typically be closer to O(1) because of under-the-hood optimizations.

These aren’t quite as obvious as the array degradations. Due to the more complex nature of storing keys and values versus an ordered list of stuff, the effects can be less predictable.

Sample App Testing Results

DictionaryManipulator is a similar protocol to ArrayManipulator, and it tests dictionaries. With it, you can easily test the same operation using an NSMutableDictionary or a Swift Dictionary.

To compare the Swift and Cocoa dictionaries, you use a similar procedure as you used for the arrays. Build and run the app, and select the Dictionary tab at the bottom. Run a few tests and make a note of the numbers.

Back in Xcode, open DictionaryViewController.swift and find the dictionaryManipulator property:

let dictionaryManipulator: DictionaryManipulator = SwiftDictionaryManipulator()

Replace it with the following:

let dictionaryManipulator: DictionaryManipulator = NSDictionaryManipulator()

Now the app will use NSDictionary under the hood. Build and run the app again, and run a few more tests.

Sad Swift

Once again, creating a Swift Dictionary is slow and more prone to degradation than an NSDictionary. When you create an NSDictionary it degrades at O(n). Swift dictionaries degrade between O(n) and O(n²).

Swift’s performance here doesn’t live up to its name. On an iPhone 5, creating a 25,000-item Swift Dictionary took an average of over four seconds, vs 1/50th of a second for an NSMutableDictionary.

Adding and removing any number of objects in an NSDictionary is highly efficient, and it floats right around the O(1) best-case scenario promised by Apple’s documentation. For Swift dictionaries, adding and removing degradations for any number of objects lands between O(log n) and O(n).

Looking up objects in Swift dictionaries isn’t quite as dramatic an improvement as looking up objects in Swift arrays, but it’s still at least twice as fast to look up an object in a Swift dictionary as in an NSMutableDictionary. The degradation for both lookups is close to O(1).

Sets

Sets

A Set is a data structure that stores unordered, unique values. When you try to add the same item to a set more than once, the item will not be added. “Sameness” here is determined by isEqual().

Sets are also the one major types of data structure in iOS that does not (yet) have a native Swift equivalent to its Foundation API. Therefore, you’ll only be looking at NSSet.

When to use NSSets

Sets are most useful when uniqueness matters, but order doesn’t. For example, what if you wanted to select four random names out of an array of eight names, with no duplicates?

Enter the following into your Playground:

let names = ["John", "Paul", "George", "Ringo", "Mick", "Keith", "Charlie", "Ronnie"]
let mutableSet = NSMutableSet() // 1
var loopsCount = 0 
while mutableSet.count < 4 {
  let randomNumber = arc4random_uniform(UInt32(countElements(names))) //2
  let randomName = names[Int(randomNumber)] //3
  println(randomName) //4
  mutableSet.addObject(randomName) //5
  ++loopsCount //6
}
 
//7
println("Loops: " + loopsCount.description + ", Mutable set contents: " + mutableSet.description)

In this little code snippet, you’re doing the following:

  1. Initialize the set, so you can add objects to it — note that that you must again use a mutable variant of NSSet to be able to add or remove items.
  2. Pick a random number between 0 and the count of names.
  3. Grab the name at the selected index.
  4. Log the selected name to the console.
  5. Add the selected name to the mutable set. Remember, if the name is already in the set the set will stay unchanged since it doesn’t store duplicates.
  6. Increment the loop counter so you can see how many times the loop ran.
  7. Once the loop finishes, print out the loop counter and the contents of the mutable set.

Since this example uses a random number generator, you’ll get a different result every time. Here’s an example of the log one of the times it ran while writing this tutorial:

Ronnie
John
Ringo
Ronnie
Ringo
Mick
Loops: 6, Mutable set contents: {(
    John,
    Ronnie,
    Mick,
    Ringo
)}

Here, the loop ran six times in order to get four unique names. It selected Ronnie and Ringo twice, but only wound up in the set once.

As you’re writing the loop in the Playground, you’ll notice that it runs over and over and over again, and you’ll get a different number of loops each time. It’ll always be at least four loops, since there must always be four items in the set to break out of the loop.

Now that you’ve seen NSSet at work on a small scale, it’s time to examine their performance with a larger batch.

Sample App Testing Results

Apple didn’t outline expectations for set performance as they did for dictionaries and arrays, so in this case you’ll just look at real-world performance. In addition, since there’s no Swift class to compare NSMutableSets to, the test results are quite a bit simpler.

If you’re looking for pure speed, an NSMutableSet probably won’t make you happy. Compare the numbers on NSMutableSet to the numbers for NSMutableArray, and you’ll see set creation is considerably slower — that’s the price you pay for checking if every single item in a data structure is unique.

Creation degrades at a rate of O(n), but operations like adding, removing or looking up increase at O(1). Now you realize the benefits of using a set, since doing anything afterwards is faster than with arrays or dictionaries.

NSMutableSet lookup is considerably faster at looking up objects than NSMutableArray. Sets use hashes to check for equality, and the hashes can be calculated and stored in sorted order. This makes set lookup much faster than array lookup.

Lesser-known Foundation Data Structures

Arrays, dictionaries and sets are the workhorses of data-handling. However, Cocoa offers a number of lesser-known and perhaps under-appreciated collection types. If a dictionary, array or set won’t do the job, it’s worth checking if one of these will work before you create something from scratch.

NSCache

Using NSCache is very similar to using NSMutableDictionary – you just add and retrieve objects by key. The difference is that NSCache is designed for temporary storage for things that you can always recalculate or regenerate. If available memory gets low, NSCache might remove some objects. They are thread-safe, but Apple’s documentation warns:

…The cache may decide to automatically mutate itself asynchronously behind the scenes if it is called to free up memory.

Basically, this means that an NSCache is like an NSMutableDictionary, except that an object can be automatically removed from another thread at any time without your code doing anything. This is good for managing how much memory the cache uses, but can cause issues if you’re trying to use an object that suddenly disappears.

NSCache also stores weak references to keys rather than strong references.

NSCountedSet

NSCountedSet tracks how many times you’ve added an object to a mutable set. It inherits from NSMutableSet, so if you try to add the same object again, it’s only in the set once.

However, in an NSCountedSet, the set tracks how many times that object was added. You can see how many times an object was added with countForObject().

Note that when you call count on an NSCountedSet, it only returns the count of unique objects, not the number of times all objects were added to the set.

For instance, in your Playground, take the array of names you created in your earlier NSMutableSet testing, and add each one to an NSCountedSet twice:

let countedMutable = NSCountedSet()
for name in names {
    countedMutable.addObject(name)
    countedMutable.addObject(name)
}

Then, log out of the set itself and find out how many times “Ringo” was added:

let ringos = countedMutable.countForObject("Ringo")
println("Counted Mutable set: \(countedMutable)) with count for Ringo: \(ringos)")

Your log should read:

Counted Mutable set: {(
    George,
    John,
    Ronnie,
    Mick,
    Keith,
    Charlie,
    Paul,
    Ringo
)}) with count for Ringo: 2

Note that while you may see a different order for the set, you should only see “Ringo” appear in the list of names once, even though you can see that it was added twice.

NSOrderedSet

An NSOrderedSet along with its mutable counterpart, NSMutableOrderedSet, is a data structure that allows you to store a group of distinct objects in a specific order.

“Specific order” — gee, that sounds an awful lot like an array, doesn’t it? Apple succinctly sums up why you’d want to use an NSOrderedSet instead of an array (emphasis mine):

You can use ordered sets as an alternative to arrays when element order matters and performance while testing whether an object is contained in the set is a consideration — testing for membership of an array is slower than testing for membership of a set.

Because of this, the ideal time to use an NSOrderedSet is when you need to store an ordered collection of objects that cannot contain duplicates.

Note: While NSCountedSet inherits from NSMutableSet, NSOrderedSet inherits from NSObject. This is a great example of how Apple names classes based on what they do, but not necessarily how they work under the hood.

NSHashTable and NSMapTable

Map table?

Not this kind of Map Table. (Courtesy the Tennessee Valley Authority(!) via Flickr Creative Commons)

NSHashTable is another data structure that is similar to a set, but with a few key differences from NSMutableSet.

You can set up an NSHashTable using any arbitrary pointers and not just objects, so you can add structures and other non-object items to an NSHashTable. You can also set memory management and equality comparison terms explicitly using NSHashTableOptions enum.

NSMapTable is a dictionary-like data structure, but with similar behaviors to NSHashTable when it comes to memory management.

Like an NSCache, an NSMapTable can hold weak references to keys. However, it can also remove the object related to that key automatically whenever the key is deallocated. These options can be set from the NSMapTableOptions enum.

NSIndexSet

An NSIndexSet is an immutable collection of unique unsigned integers intended to represent indexes of an array.

If you have an NSArray of ten items where you regularly need to access items’ specific positions, you can store an NSIndexSet and use NSArray’s objectsAtIndexes: to pull those objects directly:

let items : NSArray = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
 
let indexSet = NSMutableIndexSet()
indexSet.addIndex(3)
indexSet.addIndex(8)
indexSet.addIndex(9)
 
items.objectsAtIndexes(indexSet) // returns ["four", "nine", "ten"]

You specify that “items” is an NSArray since right now, Swift arrays don’t have an equivalent way to access multiple items using an NSIndexSet or a Swift equivalent.

An NSIndexSet retains the behavior of NSSet that only allows a value to appear once. Hence, you shouldn’t use it to store an arbitrary list of integers unless only a single appearance is a requirement.

With an NSIndexSet, you’re storing indexes as sorted ranges, so it is more efficient than storing an array of integers.

Pop Quiz!

Now that you’ve made it this far, you can test your memory with a quick quiz about what sort of structure you might want to use to store various types of data.

For the purposes of this quiz, assume you have an application where you display information in a library.

Q: What would you use to create a list of every author in the library?

Solution Inside: Unique List of Author Names SelectShow>

Q: How would you store the alphabetically sorted titles of a prolific author’s entire body of work?

Solution Inside: Alphabetically-Sorted Titles SelectShow>

Q: How would you store the most popular book by each author?

Solution Inside: Most Popular Book by each author SelectShow>

Where to Go From Here?

I’d like to give special thanks to my fellow tutorial team member Chris Wagner, who started on an Objective-C version of this article before the SwiftHammer came down upon us all, for passing along his notes and sample project for me to use while pulling this tutorial together.

I’ll also say thanks to the Swift team at Apple — despite the fact that there’s still considerable room for performance improvement in the native data structures, I had an awful lot of fun writing and testing in Swift. I may continue to use the Foundation data structures for a while, but I’m looking forward to porting a few little toys over to Swift. :]

Anyway, if you want to learn more about data structures for iOS, here are a few excellent resources:

If you’d like to dissect the numbers presented in this article further, you can download the numbers spreadsheet used to track all the testing runs and analyze the data yourself.

Got more questions or want to dissect these numbers further? Go nuts in the comments below!

Collection Data Structures In Swift is a post from: Ray Wenderlich

The post Collection Data Structures In Swift appeared first on Ray Wenderlich.

RWDevCon: 4 Tickets Left and 4 New Sponsors

$
0
0
Check out the second round of sponsors for RWDevCon!

Check out the second round of sponsors for RWDevCon!

Ticket sales are going fast for our upcoming conference: RWDevCon: The Tutorial Conference.

In fact, at the time of writing this post, there are only 4 tickets left until we sell out!

The team and I are hard at work planning out the beginner tutorials, advanced tutorials, and inspiration talks that will be part of the conference.

We can’t wait to reveal the full schedule to you – should be out by the end of next week!

I’ll be giving you periodic updates of how things are proceeding with the conference. This week, I’m pleased to announce four new sponsors for the conference!

4 New Sponsors!

Today, we are happy to announce 4 new sponsors for the conference:

sponsors2

  • Savvy Apps (gold sponsor): Savvy Apps is a full-service mobile development company that’s driven by making life better, one app at a time. They have worked on award-winning mobile apps from Homesnap to PBS for iPad to Musx and more.
  • LexTech (silver sponsor): LexTech helps enterprise clients reinvent processes by identifying, designing, and developing suites of custom mobile apps. Several members of the Tutorial Team work here!
  • Crittercism (silver sponsor): Crittercism provides the world’s leading application performance management solution, and enables enterprises to accelerate their mobile business. It is used by major companies like Netflix, Eventbrite, and LinkedIn.
  • AppCode (bronze sponsor): AppCode is an intelligent IDE that helps iOS/OSX developers create outstanding apps with ease and pleasure. Now with basic Swift support!

Huge thanks to Savvy Apps, LexTech, Crittercism, and AppCode for being a part of RWDevCon!

Get Your Ticket!

There are only 4 tickets left, so if you’ve been thinking of attending now’s your last chance. Grab your ticket now!

If you don’t manage to get a ticket to RWDevCon before it sells out, don’t worry – our partner 360iDev just started selling early bird tickets for its August 2015 event, so you can still go there!

The team and I look forward to meeting you at RWDevCon for some tutorials, inspiration, and fun!

RWDevCon: 4 Tickets Left and 4 New Sponsors is a post from: Ray Wenderlich

The post RWDevCon: 4 Tickets Left and 4 New Sponsors appeared first on Ray Wenderlich.

Video Tutorial: Introduction to CloudKit Part 3: Working with Records


RWDevCon Sold Out

$
0
0
RWDevCon is sold out!

RWDevCon is sold out!

This is just a quick update that RWDevCon is now sold out!

I am amazed and overjoyed by the enthusiastic response from the community for this conference, and thank all of you for believing in us.

The team and I are hard at work on the conference – we’ll make this an event to remember!

Again – if you didn’t manage to get a ticket, you should consider signing up for 360iDev, run by our event partner. They just started selling selling early bird tickets for their August 2015 event.

For the attendees and sponsors of RWDevCon – thanks so much for being a part of the conference, and we can’t wait to see you in DC! :]

RWDevCon Sold Out is a post from: Ray Wenderlich

The post RWDevCon Sold Out appeared first on Ray Wenderlich.

How To Make a Letter / Word Game with UIKit and Swift: Part 1/3

$
0
0
Learn how to create a fun anagrams game!

Learn how to create a fun anagrams game!

Update note: This tutorial was updated for Swift and iOS 8 by Caroline Begbie. Original series by Tutorial Team member Marin Todorov.

Are you a seasoned iOS developer who is thinking of creating an iOS game, but have no experience programming games? Maybe learning OpenGL ES makes you uncomfortable, or maybe you’ve just never crossed paths with Cocos2d for iPhone?

Well, good news! UIKit is a power tool for game developers. Its high-end frameworks provide you with the means to create all of your game logic, from creating animations (including frame-animation) to playing audio and video.

This 3-part tutorial series will guide you through the process of building a board game for iPad, where you create words with letters. You’ll also learn about best practices for creating solid, modular iOS apps. And as a bonus, you’ll get a crash course in audio-visual effects with UIKit!

This tutorial series is designed for readers who are already somewhat familiar with Swift, and thus won’t go over details like primitive types or syntax. If your knowledge of Swift is lacking, I recommend checking out our Swift Video Series.

Click through to get your game on!

Getting Started: Introducing Anagrams

The letter / word game with UIKit you will be making in this tutorial is about anagrams.

An anagram is a word or phrase formed by rearranging the letters of another word or phrase. For example, the word cinema can be rearranged into the word iceman. Your game will challenge the player to create anagrams from words and phrases you provide.

The finished game will look something like this:

Final Game

As you can see, there is a row of letter tiles on the lower end of the screen that makes up the initial phrase. In the screenshot above it is the word admirer, minus the M tile, which the player has dragged to the upper row.

The player’s job is to drag the letters from admirer to form a different word, using the same letters.

Can you guess what it is? I’ve already given you a hint… it starts with an M!

Solution Inside: Answer SelectShow>

So anyway, this is the game you will be making. As you build this game, you will learn about the following foundational topics:

  • Proper model-view-controller (MVC) game structure.
  • Loading levels from configuration files.
  • Organizing your game controller logic.
  • Writing a simple audio controller for UIKit with AV Foundation.
  • Using QuartzCore for static visual effects.
  • Using UIAnimation to smooth in-game movements.
  • Using UIKit particles to add visual effects.
  • Building separate layers for the heads-up display (HUD) and the gameplay.
  • Using custom fonts to improve the look and polish.
  • Upgrading default UIKit components to game-like components.
  • Also included: discussion of the software tools I use along the way when I’m creating a game. :]

Oh, and there will be explosions. :] Let’s dig in!

The Starter Project

To get you straight to the good stuff – using UIKit to build an iOS game – this tutorial provides a ZIP file that includes a starter XCode project and all game assets (images, fonts, audio and config files).

Download the Anagrams Part 1 Starter, unzip it and open it up in Xcode.

Have a look at what’s bundled in the starter project. The project file browser on the left should look something like this:

Starter Files

Here’s a quick summary of what you see:

  • Config.swift: Basic top-level configuration.
  • Levels: Folder containing three .plist files to define the game’s three difficulty levels.
  • Classes/Models: Folder for your data models.
  • Classes/Views: Folder for your custom view classes.
  • Classes/Controllers: Folder for your controllers.
  • Assets/Images: Images you’ll use to create the game.
  • Assets/Audio: Creative Commons-licensed audio files.
  • Assets/Particles: Contains a single PNG file to use for particle effects.
  • Assets/Fonts: A custom TTF font for the game HUD.
  • Main.storyboard: Open up the storyboard and you’ll see there’s only one screen with the background set to a faint woodgrain image, which is included in the project assets.
  • Credits.txt: Includes links to the sources of all the assets used in the project.

Poke around, play the sounds and browse the images. Then run the project.

First Run

It’s much better than an empty app window, isn’t it?

In this first part of the series, your goal is to display the initial anagram and target boxes on the screen. In the next parts of this series, you’ll add the ability to drag the tiles and the gameplay logic.

There’s a lot involved to get this first part working. But don’t worry, you’ll break down this epic task into 8 small steps:

  1. Load the level config file.
  2. Create a game controller class.
  3. Create an onscreen view.
  4. Create a tile view.
  5. Deal the tiles on the screen.
  6. Add the letters.
  7. Slightly rotate the letters randomly.
  8. Add the targets.

Let’s go over these one step at a time.

1) Load the Level Config File

Select the level1.plist file in the project file browser. Have a look what’s inside:

Level Config

There are three top-level keys:

  • pointsPerTile: the number of points awarded for each correctly-placed tile.
  • timeToSolve: The number of seconds the player will have to solve the puzzle.
  • anagrams: A list of anagrams. Each anagram contains two items: an initial and a final phrase.

Don’t bother for the moment with the first two and focus on anagrams. It’s an array of array-elements and each element has two string elements. You’re now going to build a data model to load this configuration in Swift.

Right-click (or control-click) on the Anagrams/Classes/Models folder in the project and select New File… to create a new file. Select the iOS\Source\Swift File template and click Next. Name the file Level.swift and click Create.

Open up Level.swift and add the following struct definition:

struct Level {
	let pointsPerTile: Int
	let timeToSolve: Int
	let anagrams: [NSArray]
}

The properties match the structure of the .plist file, so you are simply going to load the data and populate the properties.

Next, add the code to initialize the Level data model inside the struct definition:

init(levelNumber: Int) {
  //1 find .plist file for this level
  let fileName = "level\(levelNumber).plist"
  let levelPath = "\(NSBundle.mainBundle().resourcePath!)/\(fileName)"
 
  //2 load .plist file
  let levelDictionary: NSDictionary? = NSDictionary(contentsOfFile: levelPath)
 
  //3 validation
  assert(levelDictionary != nil, "Level configuration file not found")
 
  //4 initialize the object from the dictionary
  self.pointsPerTile = levelDictionary!["pointsPerTile"] as Int
  self.timeToSolve = levelDictionary!["timeToSolve"] as Int
  self.anagrams = levelDictionary!["anagrams"] as [NSArray]
}

Given a given difficulty level ranging from 1 to 3, the initializer will set up the struct and its properties. There are four small sections in the initializer body:

  1. Determine the path to the appropriate level config file (level1.plist, level2.plist, etc), based on the levelNumber value passed into the method and the bundle path.
  2. Load the file’s contents into an NSDictionary, explicitly defined as optional since the file may not exist if you pass in an invalid level number. Fortunately, the NSDictionary class knows how to parse .plist files!
  3. Validate that there’s something loaded in levelDictionary. I use assert often for errors that should never happen in a shipped app; if they EVER happen during development I want the app to stop and crash, so I can fix it before doing anything else.
  4. Copy the values from the NSDictionary to the Level instance’s properties.

Open up ViewController.swift and at the end of viewDidLoad(), add:

let level1 = Level(levelNumber: 1)
println("anagrams: \(level1.anagrams)")

Build and run, and in the Xcode console you will see the list of anagrams for Level 1. Nice!

Print Anagrams

Now you can remove the println() line from viewDidLoad() to keep the console tidy.

That’s one task knocked down. Ready to move ahead to the next one?

2) Create a Game Controller Class

People who are not experienced with the model-view-controller (MVC) paradigm before jumping into iOS development often confuse a controller and a UIViewController.

  • A controller is simply a class that focuses on some part of your app’s logic, separate from your app’s data and the classes used to display that data.
  • A class that subclasses UIViewController is a controller managing the presentation of a particular UIView. (And UIViews are used to display something on the screen.) You can read up more on the MVC pattern here.

For this tutorial, you are going to create a controller class to manage your game’s logic. Let’s try this out.

Create a new Swift file in the Anagrams/Classes/Controllers folder. Call the new file GameController.

Open GameController.swift and add the following:

import UIKit
 
class GameController {
	var gameView: UIView!
	var level: Level!
 
	init() {
	}
 
	func dealRandomAnagram() {
	}
}

I bet you’ve already spotted the building blocks of your current goal:

  • gameView: The view you’ll use to display game elements on the screen.
  • level: The Level object that stores the anagrams and other settings for the current game level.
  • dealRandomAnagram(): The method you’ll call to display the current anagram on the screen.

The variables are declared as implicitly unwrapped optionals, as they should never be nil, but you will not be creating the instances in the GameController’s initializer.

The code so far is pretty simple. Change dealRandomAnagram() to have this placeholder implementation:

func dealRandomAnagram () {
	//1
	assert(level.anagrams.count > 0, "no level loaded")
 
	//2
  let randomIndex = randomNumber(minX:0, maxX:UInt32(level.anagrams.count-1))
  let anagramPair = level.anagrams[randomIndex]
 
  //3
  let anagram1 = anagramPair[0] as String
  let anagram2 = anagramPair[1] as String
 
  //4
  let anagram1length = countElements(anagram1)
  let anagram2length = countElements(anagram2)
 
  //5
  println("phrase1[\(anagram1length)]: \(anagram1)")
  println("phrase2[\(anagram2length)]: \(anagram2)")
}

This method will fetch a random anagram, deal the letter tiles, and create the targets. Here’s what happening in the code, section by section:

  1. You check to make sure this method is only called after the level property is set and that its Level object contains anagrams.
  2. You generate a random index into the anagram list, then grab the anagram at this index. This randomNumber() function is defined in Config.swift.
  3. You store the two phrases into anagram1 and anagram2.
  4. Then you store the number of characters in each phrase into anagram1length and anagram2length. Even though the letters are the same between anagram1 and anagram2, there can be a different number of spaces so the overall number of characters can be different.
  5. Finally, you print the phrases to the console. This will suffice for testing.

Your app is already set up to load the storyboard Main.storyboard at start up. This storyboard creates a single screen using the ViewController class.

Since your game will only have one screen, you will add all initialization inside the ViewController initializer. For games that include more than one view controller, you may want to do your initialization someplace else, such as the AppDelegate class.

Open up ViewController.swift and add this property inside the ViewController class:

private var controller:GameController

Finally, add a new initializer to the class:

required init(coder aDecoder: NSCoder) {
  controller = GameController()
  super.init(coder: aDecoder)
}

The app will use the init(coder:) initializer automatically when it instantiates a ViewController from the storyboard.

There it is! You’ve created a GameController class and you have an instance of it in your ViewController class, ready to go off and spill some letter tiles on the screen at any moment. :]

3) Create an Onscreen View

The next step is also quite easy: you need to create a view on the screen and connect your GameController to it.

Open up Config.swift and look at the first two constants inside the file: ScreenWidth and ScreenHeight. You are going to use these constants to create your game view.

Switch back to ViewController.swift and add the following code at the end of viewDidLoad():

//add one layer for all game elements
let gameView = UIView(frame: CGRectMake(0, 0, ScreenWidth, ScreenHeight))
self.view.addSubview(gameView)
controller.gameView = gameView

Here, you create a new view with the dimensions of the screen and add it to the ViewController‘s view. Then you assign it to the gameView property of your GameController instance. This way the GameController will use this view for all game elements. You’ll take care of the separate view for the heads-up display (HUD) later.

Having now created your model and controller classes, you’ve come to the point where you need your first custom view class for the Anagrams game to display the tiles.

4) Create a Tile View

In this section, you are going to build a view to show tiles like these:

For now, you’ll focus on just creating the tile squares with the background image. Later, you’ll add the letters on top.

Inside the file group Anagrams/Classes/Views, create a new file called TileView. Add the following to TileView.swift:

import UIKit
 
//1
class TileView:UIImageView {
  //2
  var letter: Character
 
  //3
  var isMatched: Bool = false
 
  //4 this should never be called
  required init(coder aDecoder:NSCoder) {
    fatalError("use init(letter:, sideLength:")
  }
 
  //5 create a new tile for a given letter
  init(letter:Character, sideLength:CGFloat) {
    self.letter = letter
 
    //the tile background
    let image = UIImage(named: "tile")!
 
    //superclass initializer
    //references to superview's "self" must take place after super.init
    super.init(image:image)
 
    //6 resize the tile
    let scale = sideLength / image.size.width
    self.frame = CGRect(x: 0, y: 0, width: image.size.width * scale, height: image.size.height * scale)
 
    //more initialization here
  }
}

There are a few different sections in the code:

  1. Make the class a subclass of UIImageView. The UIImageView class provides you with the means to show an image, so you’ll only need to add a label on top of the image later on.
  2. letter: A property that will hold the letter assigned to the tile.
  3. isMatched: A property, initially set to false, that will hold a Boolean indicating whether this tile has already been successfully matched.
  4. This is UIImageView‘s required initializer, which must be overridden even though you’ll never use it.
  5. init(letter:sideLength:): a custom initializer to set up an instance of the class with a given letter and tile size. It saves the letter to the tile’s variable and loads the tile.png image.
  6. You then calculate by how much you need to scale the default tile so that you get a size that will fit your board for the given word or phrase. To do that, you just adjust the frame of the TileView. UIImageView resizes its image automatically to match its frame size.

Why do you need to set the size of the tile, you might ask?

Look at the these two setups:

The first example shows a short word that requires large tiles to fill the screen. The latter example shows a phrase that requires smaller tiles because it has almost double the tile count. You can see why the tile view needs to be resize-able so that you can show different size tile depending on how many tiles you need on the screen at a time.

Your controller will calculate the phrase length, divide the screen width by the number of characters and decide on a tile size. You’ll implement that soon, but this code is already enough to show tiles containing just the default empty tile.png image.

Now is a good time to implement more functionality of the game controller, so you can at least see some empty tiles lining up on the screen.

5) Dealing the Tiles on the Screen

Switch back to GameController.swift – your dealRandomAnagram() method already loads the data you need, but it still does not do much. Time to fix that!

Add the following property to the GameController class:

private var tiles: [TileView] = []

This is an array to hold the TileView objects that will display the tiles at the bottom of the screen. These tiles contain the initial phrase of the anagram.

Later you will also create an array to hold the target views that will display the spaces at the top of the screen where the player has to drag the tiles to form the second phrase of the anagram.

Before you continue, you also need a constant for the space between the tiles. Jump over to Config.swift and add the following:

let TileMargin: CGFloat = 20.0

Some of you might already be protesting, “Can’t I just use 20 where I need it and be done?” It’s a good point, but there is a reason for predefining in the config file.

My experience shows that you will have to tweak any numbers you have in your code when it comes time to fine-tune the gameplay. So the best practice is to externalize all numbers to a config file and give those variables meaningful names. This will pay off especially well if you are working in a team and you need to hand the game to a game designer for fine-tuning. :]

OK, back in GameController.swift, get ready to add some code to the end of dealRandomAnagram(). You have the number of characters in both phrases, so it’s easy to calculate what size tiles you need. Add this code at the end of the method:

//calculate the tile size
let tileSide = ceil(ScreenWidth * 0.9 / CGFloat(max(anagram1length, anagram2length))) - TileMargin

You take 90% of the width of the screen and divide it by the number of characters. You use the length of the longer phrase – remember, the number of characters can vary! You decrease the result by TileMargin to account for spacing between tiles.

Next find the initial x position of the first tile. It will depend on the length of the word and the tile size you just calculated. Once again, add the following at the end of dealRandomAnagram():

//get the left margin for first tile
var xOffset = (ScreenWidth - CGFloat(max(anagram1length, anagram2length)) * (tileSide + TileMargin)) / 2.0
 
//adjust for tile center (instead of the tile's origin)
xOffset += tileSide / 2.0

You take the screen width, subtract the calculated width of the word tiles and find where the first tile should be positioned on the screen. Wouldn’t it be nice if there were a simpler way to “center” the tiles!

LeSighHisLeg

Continuing in the same method, add the following code to display the tiles:

//1 initialize tile list
tiles = []
 
//2 create tiles
for (index, letter) in enumerate(anagram1) {
  //3
  if letter != " " {
    let tile = TileView(letter: letter, sideLength: tileSide)
    tile.center = CGPointMake(xOffset + CGFloat(index)*(tileSide + TileMargin), ScreenHeight/4*3)
 
    //4
    gameView.addSubview(tile)
    tiles.append(tile)
  }
}

Here’s what’s happening above:

  1. First you initialize a fresh copy of your tiles array. It’s important to start with an empty array here because this function will be called multiple times during a run of your app. Since spaces are skipped, if you didn’t clear out the array then there might be old tiles left over from a previous phrase where there should be spaces.
  2. You then loop through the phrase. You will need both the letter from the phrase and the position of the letter, so use enumerate which returns a tuple of the index + the value.
  3. You check each letter and if it is not a space, it’s a go! You create a new tile and position it using xOffset, tileSide and TileMargin. Here you are calculating the position based on that letter’s position in the phrase, which is represented by index. So if index is 5, this math will figure out how much space five tiles take up and add the new tile to the right of that space.
    You position the tiles vertically at 3/4ths of the screen height.
  4. Finally, you add the tile to the gameView and to the tiles array. The first actually shows the tile on the screen, while the latter helps you loop faster over the tiles later on.

Alrighty! Time for the final touch – you need to load the level data and call dealRandomAnagram(). Switch to ViewController.swift and add these two lines at the end of viewDidLoad():

controller.level = level1
controller.dealRandomAnagram()

Remember that you already have a Level object, so you just pass it on to your GameController and call dealRandomAnagram().

It’s been a long time coming, but build and run to check out the result! Your app should look something like this:

Empty Tiles

Awesome, it works! It’s alive!!!

Note: Your view probably won’t look exactly like this because the app is choosing a random anagram each time it runs. Run it a few times to see how the app sizes the tiles differently for different phrases. The console output will show you the phrases used.

You are closing in on the finish line for the first part of this tutorial series!

6) Add the Letters

Switch to TileView.swift. This is where you’re going to add letters to those tiles. Find init(letter:sideLength:) and add the following code to the end:

//add a letter on top
let letterLabel = UILabel(frame: self.bounds)
letterLabel.textAlignment = NSTextAlignment.Center
letterLabel.textColor = UIColor.whiteColor()
letterLabel.backgroundColor = UIColor.clearColor()
letterLabel.text = String(letter).uppercaseString
letterLabel.font = UIFont(name: "Verdana-Bold", size: 78.0*scale)
self.addSubview(letterLabel)

The above code creates a new UILabel and adds it to the tile view. Because you want the letter to be as easy to read as possible, you create the label to be as large as the tile itself. You then align the letter to show up in the center of the tile.

You ensure the letter is uppercase by setting the label text with String(letter).uppercaseString. Using capital letters will ease the game play, as they are easier to recognize, specifically by children. Always think about your game’s target audience!

Finally you reuse the scale factor you calculated earlier. For the full-size tile a Verdana font with a size of 78 pts fits well, but for other sizes you need to scale the font size accordingly.

Build and run the project. As I said, you’re now moving fast towards your goal. Good job! :]

Tiles with Letters

Once again, your screen probably won’t look just like this one. But that just means your game controller is doing what’s it’s supposed to do and dealing a random anagram. Nice!

Have another look at the image above. Right now the tiles look like they were put on the board by a pedantic robot: they are perfectly aligned. Now comes the time to add a pinch of randomization!

7) Slightly Rotate the Letters Randomly

Randomization is one of the keys to building a successful computer game. You want to randomize your game as much as possible. For example, no player enjoys enemies that all do the same thing every time the game runs.

In the case of the Anagrams game, you can randomize the placement of each tile so that they look more natural on the game board, as if a human put them down without trying too hard to align them properly:

In order to accomplish this randomization, add the following method to the TileView class in TileView.swift:

func randomize() {
  //1
  //set random rotation of the tile
  //anywhere between -0.2 and 0.3 radians
  let rotation = CGFloat(randomNumber(minX:0, maxX:50)) / 100.0 - 0.2
  self.transform = CGAffineTransformMakeRotation(rotation)
 
  //2
  //move randomly upwards
  let yOffset = CGFloat(randomNumber(minX: 0, maxX: 10) - 10)
  self.center = CGPointMake(self.center.x, self.center.y + yOffset)
}

This code does two things:

  1. It generates a random angle between -0.2 and 0.3 radians (using the helper function randomNumber defined in Config.swift). Then it calls CGAffineTransformMakeRotation() to create a new transform for the tile view that will rotate it around its center by that random angle.
  2. It generates a random value between -10 and 0 and moves the tile up by that offset.

Note: You might want to replace all of these numbers with constants you define in Config.swift so you can fine-tune the tile appearance more easily.

Now you just need to call this method. Inside GameController.swift, edit dealRandomAnagram() by adding the following line of code just after the line that begins with tile.center = ...:

tile.randomize()

And that’s all it takes! Hit run again to see the randomized tiles on the board:

Randomized Tiles

Using what you’ve already achieved, you can also quickly add the targets to the game board. Let’s do that before wrapping up this part of the tutorial.

8) Add the Targets

The target views are pretty similar to the tile views. They also subclass UIImageView and show a default image, and they also are assigned a letter. The difference is that they don’t show a label with that letter and can’t be dragged around. This means the code you need for the targets is similar to what you did before – but simpler!

Inside the file group Anagram/Classes/Views, create a new file called TargetView. Add the following to TargetView.swift:

import UIKit
 
class TargetView: UIImageView {
  var letter: Character
  var isMatched:Bool = false
 
  //this should never be called
  required init(coder aDecoder:NSCoder) {
    fatalError("use init(letter:, sideLength:")
  }
 
  init(letter:Character, sideLength:CGFloat) {
    self.letter = letter
 
    let image = UIImage(named: "slot")!
    super.init(image:image)
 
    let scale = sideLength / image.size.width
    self.frame = CGRectMake(0, 0, image.size.width * scale, image.size.height * scale)
  }
}

Yes, this uses exactly the same properties and function (aside from changing the image) as for the TileView! You resize the image according to the provided side length and assign the letter – that’s all.

Now to display the targets on the screen. Open up GameController.swift and add the following property to the class:

private var targets:[TargetView] = []

Then add the following code inside dealRandomAnagram(), just before the comment that reads “//1 initialize tile list”:

//initialize target list
targets = []
 
//create targets
for (index, letter) in enumerate(anagram2) {
  if letter != " " {
    let target = TargetView(letter: letter, sideLength: tileSide)
    target.center = CGPointMake(xOffset + CGFloat(index)*(tileSide + TileMargin), ScreenHeight/4)
 
    gameView.addSubview(target)
    targets.append(target)
  }
}

This is almost the same code you used to deal the tiles on the board, except this time you grab the letters from the phrase stored in anagram2 and you don’t randomize their position. You want the target views to look nice and neat, after all!

Why does the target initialization have to come before the tile initialization? Subviews are drawn in the order they are added to their parent view, so adding the target views first ensures that they will appear behind, or below, the tiles.

If you did want to add the target views after the tile views, there are other ways to get them behind the tiles, such as UIView‘s sendSubviewToBack(view:) method. But adding them first is the most efficient solution.

Build and run again to see that your board is already close to being finished!

Targets

Remember, the anagrams consist of two phrases which have the same letters but might have different spacing. So everything is working as expected if you see something like the screenshot above with three tiles followed by four tiles, while the targets at the top are four tiles followed by three tiles.

Where to Go from Here?

Click here to download the full source code for the project up to this point.

Congrats, you’ve achieved a lot today! Let’s see what you’ve done so far:

  • You’ve created a model to load the level configuration.
  • You’ve connected the game controller, game view and model.
  • You have two custom views, one for tiles and one for targets.
  • You’ve finished the initial board setup.

You now have a sound foundation on which to build. Stay tuned for Part 2 of the series, where you’ll begin interacting with the player and building up the gameplay.

In the meantime, if you have any questions or comments about what you’ve done so far, drop by the forums to contribute your two tiles’ worth. :]

How To Make a Letter / Word Game with UIKit and Swift: Part 1/3 is a post from: Ray Wenderlich

The post How To Make a Letter / Word Game with UIKit and Swift: Part 1/3 appeared first on Ray Wenderlich.

Video Tutorial: Introduction to CloudKit Part 4: Saving Data

iOS Games by Tutorials Updated for Xcode 6.1

$
0
0
iOS Games by Tutorials Updated for Xcode 6.1!

iOS Games by Tutorials Updated for Xcode 6.1!

Good news – the team and I have updated iOS Games by Tutorials for Xcode 6.1!

Xcode 6.1 has a few small changes to Swift – mostly minor syntax things – but we wanted to make sure that all the instructions work without any issues.

In addition to updating the book for Xcode 6.1, we have fixed some errata pointed out by readers, and added the missing chapters and challenges on porting the games to OS X.

Here’s how you can get the update:

  • If you’re an iOS Games by Tutorials PDF customer, you can download the update for free on your My Loot page (version 2.2).
  • If you haven’t picked up a copy of iOS Games Tutorials yet, grab your copy now.

At this point, all 5 of our new Swift books are fully updated for Xcode 6.1, w00t!

The team and I hope you enjoy this update!

iOS Games by Tutorials Updated for Xcode 6.1 is a post from: Ray Wenderlich

The post iOS Games by Tutorials Updated for Xcode 6.1 appeared first on Ray Wenderlich.

How To Make a Letter / Word Game with UIKit and Swift: Part 2/3

$
0
0
Learn how to create a fun anagrams game!

Learn how to create a fun anagrams game!

Update note: This tutorial was updated for Swift and iOS 8 by Caroline Begbie. Original series by Tutorial Team member Marin Todorov.

Welcome back to our 3-part tutorial series that shows you how to make a letter / word game with UIKit – in this case, a game of anagrams!

If you successfully followed through the first part of this series, you should now have your game board showing up onscreen. So far, you’ve learned how to kick-start your UIKit game, how to plan your controllers and how to connect your views, and have also started implementing the game elements.

Now you’ll take on the gameplay itself and grant the player some special powers, like dragging the tiles around and dropping them onto the targets at the top of the screen. A heads-up-display with a timer and score ticker will keep the player’s ego in check.

Time to grab your UIKit and get back to work!

Getting Started: Your Epic Goal

When you run the completed project from Part 1 of this tutorial, you should see something like this:

Part 2 Start

In this second part of the tutorial series, you’ll aim for developing a fully playable version of the game. When you’re finished, the player will be able to drag the tiles and drop them on the correct targets, where they will “stick” to the spot. When all tiles have been placed on the correct targets, the player will win that puzzle.

There will also be a timer – the player will have a limited amount of time to finish each puzzle – and a score display that will increase and decrease in real time, according to the player’s actions.

You’ll achieve these epic goals by taking on these smaller steps:

  • Make the tiles draggable.
  • Make the tiles notify the game controller when they are dropped somewhere.
  • Implement handling of tile drops in the game controller.
  • Check if the player has won after each successful tile placement.
  • Create a separate view layer to contain elements like score readouts and menus. It’s usually best to keep these arranged in their own view, rather than including them in the same view as the actual gameplay elements.
  • Add a level timer and a player score. This is a game, after all!

All right! You’ve been debriefed. Now back to the code!

Drag Those Tiles

You might already be familiar with how to handle touch events with UIKit. If you are, there’s nothing different about handling touches in a UIKit game. You just need to implement the touch delegate methods in TileView. Before your tiles can receive touch events, however, you need to enable them.

Inside TileView.swift, add the following line to the end of init(letter:sideLength:):

self.userInteractionEnabled = true

This instructs iOS to send touch events to this object. By default, this is set to false for a UIImageView (which this class derives from), so you have to set it to true manually.

Next, you need to add the dragging code. To accomplish this, you are going to take the following strategy:

  • When the player touches down on a tile, figure out the offset within the tile of where their finger lies.
  • When the player drags, you’ll set the center of the tile to the new position of their finger – except you’ll shift the tile by the offset you computed earlier to account for where the player’s finger is within the tile.

Let’s try this out. Still in TileView.swift, add new properties to the top of the class:

private var xOffset: CGFloat = 0.0
private var yOffset: CGFloat = 0.0

You’ll use xOffset and yOffset to keep track of the distance between the center of the tile and the initial placement of the player’s finger when the touch begins.

To handle dragging the tiles, add the following touch handling methods to the TileView class:

//1
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
  let point = touches.anyObject()!.locationInView(self.superview)
  xOffset = point.x - self.center.x
  yOffset = point.y - self.center.y
}
 
//2
override func touchesMoved(touches: NSSet, withEvent event: UIEvent)  {
  let point = touches.anyObject()!.locationInView(self.superview)
  self.center = CGPointMake(point.x - xOffset, point.y - yOffset)
}
 
//3
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
  self.touchesMoved(touches, withEvent: event)
}

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

  1. When a touch is detected, you fetch its location within the tile’s superview (that is, the view that contains the tile). You calculate and store the distance from the touch to the tile’s center.
  2. When the player moves their finger, you move the tile to that location, but you adjust the location by the offsets you stored in xOffset and yOffset. This keeps the tile from centering itself under the player’s finger as soon as they start moving it – you want it to feel like the player is dragging the tile by a particular point.
  3. When the player lifts their finger, you make one last call to touchesMoved(touches:withEvent:) to make sure the tile’s position is set to the touch’s final location. You could have just typed the same code here as in touchesMoved(touches:withEvent:), but it’s better to avoid repeating code where possible to make maintenance easier.

All right! Build and run the project and have fun dragging the game tiles around.

Moving the Tiles

Cool – you’re already one step closer to your goal.

Hey, Game Controller! A Tile Is Dropping!

In order to make the game controller accept notifications from tiles when they are dropped somewhere on the board, you’ll make the game controller a delegate to all tiles. The tiles will then invoke a method on their delegate when the player drops them. Therefore, get ready to get some experience with the delegation pattern!

At the top of the TileView.swift file (after the import lines), declare the protocol with a single method:

protocol TileDragDelegateProtocol {
  func tileView(tileView: TileView, didDragToPoint: CGPoint)
}

TileDragDelegateProtocol requires one method – the one that handles a finished drag and drop operation.

Now inside the class, add a property to store the delegate:

var dragDelegate: TileDragDelegateProtocol?

All right! That should be enough declarations – time to add the code. Still in TileView.swift and at the end of touchesEnded(touches:withEvent:) add:

dragDelegate?.tileView(self, didDragToPoint: self.center)

Totally easy, right? If the dragDelegate property is not nil, you just call the delegate’s tileView(_:didDragToPoint:) method, passing it a reference to the tile (self) and self.center.

Now you need to make GameController conform to your new protocol and actually do something with this information.

Handling Tile Drops

Open up GameController.swift and change the class declaration to conform to the TileDragDelegateProtocol protocol:

class GameController: TileDragDelegateProtocol {

Add the initial implementation of the delegate method at the bottom of the GameController class:

//a tile was dragged, check if matches a target
func tileView(tileView: TileView, didDragToPoint point: CGPoint) {
  var targetView: TargetView?
  for tv in targets {
    if CGRectContainsPoint(tv.frame, point) && !tv.isMatched {
      targetView = tv
      break
    }
  }
}

This code loops over all objects in the targets array and, for each of the target views, checks whether the given drag point is within the target’s frame.

Ha! The simple if statement effectively checks if the tile’s center point was dropped within the target – that is, whether the tile was dropped on a target. And because the point passed to this method is the tile’s center, the function will not succeed if only a small portion of the tile is within the target.

If a tile is found to be within a target, the matching target is saved to targetView.

Now go on and check whether the letter has been dragged to the correct target to make the anagram. Add the following code to the end of the same method:

//1 check if target was found
if let foundTargetView = targetView {
 
  //2 check if letter matches
  if foundTargetView.letter == tileView.letter {
 
    //3
      println("Success! You should place the tile here!")
 
      //more stuff to do on success here
 
      println("Check if the player has completed the phrase")
    } else {
 
    //4
    println("Failure. Let the player know this tile doesn't belong here")
 
    //more stuff to do on failure here
  }
}

Now to break this down step-by-step:

  1. If the tile was not dropped onto a target, then targetView will still be nil, and the rest of the code will not be performed
  2. Compare the tile’s letter with the target’s letter to see if they match.
  3. If the letters do match, you will do various bits of processing. For now, you just print some messages to the console.
  4. If the letters do not match, you want to indicate that to the player. Again, for now just use a log statement until you’ve verified that the logic is working correctly.

OK, build and run the project and try dragging some tiles onto targets.

If everything went well, there shouldn’t be any difference compared to what you saw last time you ran the project. But why no print statements? That’s a good question! Can you figure out why the tiles don’t react to being dropped on the targets?

Solution Inside: Answer SelectShow>

In GameController.swift, just after tile.randomize() in dealRandomAnagram(), add the following line:

tile.dragDelegate = self

Run the project again and you will see your success/failure statements printed to the console when you drag a tile onto a target. Now that you know the right things are happening at the right times, you can make it do something more fun than printing to the console!

Inside GameController.swift, add the following method:

func placeTile(tileView: TileView, targetView: TargetView) {
  //1
  targetView.isMatched = true
  tileView.isMatched = true
 
  //2
  tileView.userInteractionEnabled = false
 
  //3
  UIView.animateWithDuration(0.35,
                      delay:0.00,
                    options:UIViewAnimationOptions.CurveEaseOut,
                 //4
                 animations: {
                    tileView.center = targetView.center
                    tileView.transform = CGAffineTransformIdentity
                  },
                  //5
                  completion: {
                    (value:Bool) in
                    targetView.hidden = true
                  })
}

You’ll call this method when the player successfully places a tile. Here’s what’s happening above:

  1. You set the isMatched property on both the targetView and tileView. This will help you later when you check to see if the player has completed the phrase.
  2. Disable user interactions for this tile. The player will not be able to move a tile once it’s been successfully placed.
  3. Create an animation that will last for 35 hundredths of a second. By passing in .CurveEaseOut, UIAnimation will automatically calculate an ease-out animation. Rather than making changes in even increments across the given time, it will do larger changes in the beginning and smaller changes toward the end, slowing down the animation.
  4. This closure defines the changes that should occur during the animation. In this case, you move the tile so its center is on the target’s center, and you set the tile’s transform to CGAffineTransformIdentity. The identity transform is basically no transform. This effectively undoes any changes you’ve made to scale and rotation. In this case, it straightens out the tile.
  5. When the animation is complete, you hide targetView. This isn’t absolutely necessary, since targetView will be completely behind tileView. But in general, if you know you have a view object that will not be visible, it’s more efficient to hide it so that its parent view knows it’s safe to skip it for certain types of processing.

Inside tileView(_:didDragToPoint:) in GameController.swift, replace the println() statement that begins with “Success!” with the following:

self.placeTile(tileView, targetView: foundTargetView)

Now handle what happens when the player puts a tile on an incorrect target. Still inside tileView(_:didDragToPoint:) in GameController.swift, replace the println() statement that begins with “Failure” with the following code:

//1
tileView.randomize()
 
//2
UIView.animateWithDuration(0.35,
    delay:0.00,
    options:UIViewAnimationOptions.CurveEaseOut,
    animations: {
      tileView.center = CGPointMake(tileView.center.x + CGFloat(randomNumber(minX:0, maxX:40)-20),
                                    tileView.center.y + CGFloat(randomNumber(minX:20, maxX:30)))
    },
    completion: nil)

There are only two major things happening here:

  1. You randomize the tile’s rotation again.
  2. You create an animation that slightly offsets the tile’s position.

Taken together, these two effects demonstrate to the player that the tile does not “fit” into the dropped target.

Build and run the project. This time, instead of just statements printed to your console, you will see the tiles slide onto the target positions when dropped in the correct place, and sliding away when placed in the wrong place. Cool!

Tiles sticking

You’re ready to check if the player has finished the current game. Inside GameController.swift, add the following:

func checkForSuccess() {
  for targetView in targets {
    //no success, bail out
    if !targetView.isMatched {
      return
    }
  }
  println("Game Over!")
}

The above code loops through the targets array and checks to see if ANY TargetView is not yet matched. If it finds an unmatched target, then the game is still not over and it bails out of the method.

If all the TargetViews are matched, then your log statement “Game Over!” appears in the console. Later, you will do some more interesting things here.

Inside tileView(_:didDragToPoint:) in GameController.swift, replace the println() statement that begins with “Check if” with the following code:

//check for finished game
self.checkForSuccess()

Build and run the app and complete a puzzle. You should see your log statement printed to the console when you are finished. Great!

Creating a HUD

HUD’s up!

Your game could use some controls and readouts. You might ask, “Should I add these elements to the gameView?”

No. The gameView is for all gameplay elements. You generally want to put elements like the score, time readouts and player controls onto their own view layer. This allows you to do many types of things more easily, like hide them when the game is paused, or maintain fixed sizes and locations for these controls while simultaneously zooming in on some area of the game board.

This separate layer is often called a heads-up-display, or HUD. It will be easier to test your HUD layer if you have something to display in it, so first you will make a label to display the game timer.

Create a new Swift file in Anagrams/Classes/Views named StopwatchView. This will be a subclass of UILabel that displays the remaining time in the format “[minutes]:[seconds]“.

Open up StopwatchView.swift and replace its contents with the following:

import UIKit
 
class StopwatchView: UILabel {
 
  //this should never be called
  required init(coder aDecoder:NSCoder) {
    fatalError("use init(frame:")
  }
 
  override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.clearColor()
  }
 
  //helper method that implements time formatting
  //to an int parameter (eg the seconds left)
  func setSeconds(seconds:Int) {
    self.text = String(format: " %02i : %02i", seconds/60, seconds % 60)
  }
}

The above code isn’t fancy. It just sets the label’s background to be transparent (the “clear” color), and creates a method to set the label’s text property to the mm:ss format.

Now that you have a label to display, you need a HUD layer to hold it. Create a new Swift file in Anagrams/Classes/Views named HUDView and replace its contents with the following:

import UIKit
 
class HUDView: UIView {
 
  var stopwatch: StopwatchView
 
  //this should never be called
  required init(coder aDecoder:NSCoder) {
    fatalError("use init(frame:")
  }
 
  override init(frame:CGRect) {
    self.stopwatch = StopwatchView(frame:CGRectMake(ScreenWidth/2-150, 0, 300, 100))
    self.stopwatch.setSeconds(0)
 
    super.init(frame:frame)
    self.addSubview(self.stopwatch)
  }
}

For now, you’ll have a single stopwatch property that holds a timer initialized to 0 seconds remaining.

Now to get that timer on the screen! You haven’t checked your progress in a while.

First add a HUDView property to the game controller. Inside GameController.swift at the top of the class, add:

var hud: HUDView!

Next you’ll create the HUD view in your ViewController – the same spot where you create the game view. Switch to ViewController.swift and inside viewDidLoad(), find the line controller.gameView = gameView and just below it, add the HUD to the window’s view and the game controller:

//add one view for all hud and controls
let hudView = HUDView(frame: CGRectMake(0, 0, ScreenWidth, ScreenHeight))
self.view.addSubview(hudView)
controller.hud = hudView

You create a new HUD view as big as the screen and you add it to the view controller’s view. Then you also assign it to the game controller’s hud property.

OK, build and run again and have a look at your new HUD layer!

Ugly Label!

Well, that’s some progress. Before you move on with the functionality, now is probably a good time to talk about….

The Art of Gamification

The fact you are using UIKit to create a game does not mean that you also have to use vanilla UIKit components. To make a game more “game-like”, you will want to use fonts, buttons and other controls that look like they belong in a game and not in a spreadsheet program.

For example, compare the two fonts below:

Compare fonts

If you think the first font rendered above is more exciting, in a game context at least, perhaps you should hire a graphic designer. :] Long story short, choose an appropriate font for your game. You’re not likely to excite players with a game menu rendered in Arial or Verdana.

Note: Then why did you go for good old Verdana when you created the tile view? On tiles, it makes sense to have maximum readability. Players shouldn’t get confused about which letters they’re seeing.

I’ve included a fun font for you in the project. To use it, first open up Config.swift and add these font constants:

let FontHUD = UIFont(name:"comic andy", size: 62.0)!
let FontHUDBig = UIFont(name:"comic andy", size:120.0)!

Some of you probably will ask, “Isn’t it faster to put the font definition in the code? Why should it be in a separate file?”

The answer is convenience. Imagine your graphic designer finds a much cooler font for your game. If you already have font assignments sprinkled all over the game code, replacing them will be a pain.

What’s more, abstracting the font size is a very good idea. That’s why you have two definitions – one for a big font and one for normal-sized font. This makes it a lot easier to change the font size in all HUDs throughout your game with a single line change.

Open StopwatchView.swift and add the following line to the end of init(frame:):

self.font = FontHUDBig

This sets the label’s font to FontHUDBig, which you just defined in Config.swift.

Build and run again to behold your new, game-ready label!

Note: If you want to include your own font, as well as importing it into the project, you need to add the font to the project’s Info.plist using the key Fonts provided by application.

Beautiful timer!

Nice! However… if you try to drag the tiles around you will notice they don’t drag anymore…

Well… actually, that’s fine. It’s all because of how you normally have views ordered in a game setup.

As illustrated in the schema below, you will always have the game controls, score, time, etc. on top, so that they are always visible. Under the controls you will have all the objects that move – heroes, word tiles, and so on. And usually at the very back you will have the background – whether static or parallax, it does not matter.

You have exactly the same setup so far, but since the HUD view is on top of everything it swallows all touches. Fear not! You can easily turn off the user’s interaction with the HUD view, thus allowing the user to touch the tiles in the underlying game objects view.

Switch to HUDView.swift and at the end of the init(frame:), add the code to disable touches:

self.userInteractionEnabled = false

Now it’s fixed forever!

Build and run the game again, and you’ll see that you can have your timer and drag tiles, too! Sweet victory!

HUD works

Adding a Level Timer

Implementing the game timer is incredibly simple. Remember that each level already has a corresponding maximum time in seconds in the level config file. You haven’t used this data yet, but now you will.

Open to GameController.swift and add the following two properties to the class:

//stopwatch variables
private var secondsLeft: Int = 0
private var timer: NSTimer?

secondsLeft will store the number of seconds left to complete the level. It will be decreased every second by timer.

Now you need three new helper methods:

  1. One to start the timer when the tiles are displayed on the board.
  2. One to stop the timer in case the player solves the puzzle or the time is up.
  3. One to fire each second and update the HUD.

Add them one at a time to the game controller. First add the following method to initialize the new variables and start the timer:

func startStopwatch() {
  //initialize the timer HUD
  secondsLeft = level.timeToSolve
  hud.stopwatch.setSeconds(secondsLeft)
 
  //schedule a new timer
  timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector:"tick:", userInfo: nil, repeats: true)
}

You initialize secondsLeft with the initial remaining time stored in the level, and update the stopwatch label to display this time. You also schedule a new NSTimer that will invoke tick() each second (you haven’t added this function yet).

Next, add stopStopwatch to stop the timer:

func stopStopwatch() {
  timer?.invalidate()
  timer = nil
}

Calling invalidate on the timer stops it, and then you set it to nil because it is no longer needed.

Now define tick(), which will be called once a second while timer is running.

@objc func tick(timer: NSTimer) {  
  secondsLeft--
  hud.stopwatch.setSeconds(secondsLeft)
  if secondsLeft == 0 {
    self.stopStopwatch()
  }
}

Note the @objc attribute. The GameController class does not inherit from NSObject, so tick() would normally not be visible from Objective-C. Since NSTimer is an Objective-C class, you need to mark tick() with @objc to make it usable in Objective-C land.

This method does nothing more than decrease the amount of seconds left by one, then update the stopwatch label with the new value. If the number of seconds remaining hits 0, it calls stopStopwatch(). That’s all!

Now you need to actually start the timer when the game starts! At the end of dealRandomAnagram(), add:

//start the timer
self.startStopwatch()

And of course you need to stop the timer if the player completes the phrase. At the end of checkForSuccess(), add the following call:

//stop the stopwatch
self.stopStopwatch()

All right, another feature is in! Build and run again to see the timer ticking down when the game starts:

Clock is ticking

Hmm, what else can you add to your fancy new HUD?

Keeping Score, Fair and Square

When making a game you want to have a separate class just to keep the game data for the current player session. This class will store such things as the player’s current score, remaining number of lives and progress through the game. In a more complicated game, you could have this data also sorted per user, which might require a simple database of some sort.

For this tutorial, your game will have a simple class to keep the score between games, but not between app restarts.

Create a new file in Anagrams/Classes/Models named GameData.swift. Add the following code:

class GameData {
  //store the user's game achievement
  var points:Int = 0 {
		didSet {
			//custom setter - keep the score positive
			points = max(points, 0)
		}
  }
}

The points property will store the player’s current score.

The didSet property observer on the points variable ensures the value is never negative. You don’t want the player to have fewer than zero points, right? So you pass points and 0 to the max function, which returns the greater value of its two arguments. Thus, if you try to store a negative number into points, it will assign 0 to points.

That’s all you need for your simple GameData class. But if your game evolves, this class will also become more complicated.

OK, it’s time to decide where in the game the player will receive or lose points.

There are two point-events so far in the gameplay:

  • When a tile is dropped on a correct target, award the player with points.
  • When a tile is dropped on a wrong target, subtract some points from the current score.

This way, to get the most points possible out of the current anagram, the player will have to solve it without making any mistakes.

Challenge: You can also award points upon puzzle completion, and subtract points when the player fails to complete a puzzle in time. How would you implement that yourself?

Add the following property to the GameController class in GameController.swift:

private var data: GameData

Find init() and add the following line to it:

self.data = GameData()

This gives you access to a GameData object to store the score.

In the same file, add the following code inside tileView(_:didDragToPoint:), just below the comment that reads “//more stuff to do on success here”:

//give points
data.points += level.pointsPerTile

Luckily the level config file already includes the points per title for every level of difficulty, so all you do here is increment the current score by that number.

To handle errors, add the following code in the same method, just below the comment that reads “//more stuff to do on failure here”:

//take out points
data.points -= level.pointsPerTile/2

Here, you do the opposite and subtract points. But there’s no point (ha, ha) in being too tough on the player – if they drop the tile on the wrong target, only half of what they receive for a matching one is subtracted from the current score.

All right! Keeping score – check.

Note: The GameData class is quite naïve as it is. Your own UIKit game will likely have some other game data you need to track, requiring you to adjust the class as you wish. A few possible features deserve an honorable mention:

  • You might want to add Game Center integration to your game, which will forward the score from GameData to Apple’s Game Center. More on Game Center.
  • You might want to persist the score by saving it to the NSUserDefaults or a keychain. More on secure storage of data with a keychain.
  • If you would like to store the game data to a keychain or persist it to a file, you might find using the JSONModel library super useful. It allows you to convert your model data to a JSON string, which is easily storable in a keychain or a text file.

Adding the Score to the HUD

Games are all about achievements and score, so there’s no sense in keeping the player’s score behind the scenes. You need to put it upfront, right on the HUD layer.

In Anagrams/Classes/Views, create a new Swift file called CounterLabelView. This will be another subclass of UILabel.

Open CounterLabelView.swift and replace its contents with the following:

import UIKit
 
class CounterLabelView: UILabel {
  //1
  var value:Int = 0 {
    //2
    didSet {
      self.text = " \(value)"
    }
  }
 
  required init(coder aDecoder:NSCoder) {
    fatalError("use init(font:frame:")
  }
 
  //3
  init(font:UIFont, frame:CGRect) {
    super.init(frame:frame)
    self.font = font
    self.backgroundColor = UIColor.clearColor()
  }
}

Here’s what you need to know about the above:

  1. value is a property that will hold the score currently shown on the label.
  2. Whenever the value is changed, update the label
  3. Set the label’s font and set the background transparent

Inside HUDView.swift, add the following property to the HUDView class:

var gamePoints: CounterLabelView

In the HUDView‘s init(frame:) initializer, add the following before the super.init() call:

//the dynamic points label
self.gamePoints = CounterLabelView(font: FontHUD, frame: CGRectMake(ScreenWidth-200, 30, 200, 70))
gamePoints.textColor = UIColor(red: 0.38, green: 0.098, blue: 0.035, alpha: 1)
gamePoints.value = 0

Then add the following after the super.init()) call:

self.addSubview(gamePoints)
 
//"points" label
var pointsLabel = UILabel(frame: CGRectMake(ScreenWidth-340, 30, 140, 70))
pointsLabel.backgroundColor = UIColor.clearColor()
pointsLabel.font = FontHUD
pointsLabel.text = " Points:"
self.addSubview(pointsLabel)

When initializing the class, the class’s own properties must be initialized before calling the super class’s initialization. However, the super class’s properties can’t be referenced until after it has been initialized.

Now to update the score. Remember the two places where you change the score? In GameController.swift in the tileView(_:didDragToPoint:) method, find data.points += level.pointsPerTile and add the following just below it:

hud.gamePoints.value = data.points

Then look for the line data.points -= level.pointsPerTile/2 and add the following just below it:

hud.gamePoints.value = data.points

These lines updates the score label on the HUD to the same value as the game’s data points.

Build and run to see your score updating.

Points updating

It’s a bit boring though, that the score label instantly changes from, say 500 to 750, as it will on the harder levels. It’s a lot more fun to have the score label rapidly cycle through 500, 501, 502, etc. all the way up to 750 – it just adds a little polish to an awesome game experience.

Inside the CounterLabelView class in CounterLabelView.swift, add new private variables:

private var endValue: Int = 0
private var timer: NSTimer? = nil

Basically, you will set up a timer to repeatedly update the HUD, incrementing (or decrementing) the label one point, until you reach endValue.

Now add the following helper method:

func updateValue(timer:NSTimer) {
  //1 update the value
  if (endValue < value) {
    value -= 1
  } else {
    value += 1
  }
 
  //2 stop and clear the timer
  if (endValue == value) {
    timer.invalidate()
    self.timer = nil
  }
}

There are two things happening in this method:

  1. Depending on whether endValue is higher than the current value, you increment or decrement the value. The didSet observer on value will update the label’s text every time value is set.
  2. When endValue is equal to the current value, you have finished, so stop the timer, and clear it.

Now it’s time to implement setValue(_:duration:), which is the method that initially calls updateValue() to get the counter rolling. Add the following method:

//count to a given value
func setValue(newValue:Int, duration:Float) {
  //1 set the end value
  endValue = newValue
 
  //2 cancel previous timer
  if timer != nil {
    timer?.invalidate()
    timer = nil
  }
 
  //3 calculate the interval to fire each timer
  let deltaValue = abs(endValue - value)
  if (deltaValue != 0) {
    var interval = Double(duration / Float(deltaValue))
    if interval < 0.01 {
      interval = 0.01
    }
 
    //4 set the timer to update the value
    timer = NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector:"updateValue:", userInfo: nil, repeats: true)
  }
}

This function is the most complicated one you’ve added thus far, so let’s go over it carefully.

  1. Set endValue to the value that you are counting to.
  2. In the event that the player is really fast at adding letters, cancel any existing timers, because you don’t want them overlapping.
  3. Here you calculate the interval between calls to updateValue(timer:). To do so, you do the following:
    • You find how many values the label needs to count through. For example, if the current score is 50 and you want it to go to 65, you’ll get the delta value 15. If the current value is 65 and you want to go to 50, you’ll get the same delta value of 15.
    • Only do the update if the value needs to be changed.
    • You divide the total duration for the animation, duration, by the number of values you need to count through. This gives you the time interval for firing of the timer.
    • If interval is less than 0.01 seconds, you increase it to 0.01. This just keeps the animation from moving too quickly, which wouldn’t look as nice.
  4. Finally, you schedule a NSTimer to call the update.

Nice – and you’re just about done!

Now you need to call the new update functions from the game controller to see the animation. Switch to GameController.swift and replace the success line hud.gamePoints.value = data.points with:

hud.gamePoints.setValue(data.points, duration: 0.5)

This will make the score label count to the just-updated score value, and it’ll do that in half a second.

Change the failure line hud.gamePoints.value = data.points to:

hud.gamePoints.setValue(data.points, duration: 0.25)

This updates the label, but does it in 0.25 seconds. Since the penalty values are half the success values, making the duration half as long will make the counter appear to change values at the same pace, whether it’s going up or down. Feel free to tweak these values to your liking.

Build and run the project to enjoy your new and shiny HUD:

Counting Points

Oh, sweet joy! The score label counts up and down as you drop tiles on the targets. Your game is really coming together!

Where to Go from Here?

You can download all of the source code up to this point by clicking this link

Woot, your game is starting to take its final shape and is almost fully-playable. You’ve done well to make it this far.

If you think you’ve progressed a lot in this part of the tutorial, just wait for Part 3, where you’ll add even more cool effects and interactivity, including those promised explosions!

While you’re waiting, let us know how it’s going for you so far in the forums.

How To Make a Letter / Word Game with UIKit and Swift: Part 2/3 is a post from: Ray Wenderlich

The post How To Make a Letter / Word Game with UIKit and Swift: Part 2/3 appeared first on Ray Wenderlich.

How To Make a Letter / Word Game with UIKit and Swift: Part 3/3

$
0
0
Learn how to create a fun anagrams game!

Learn how to create a fun anagrams game!

Update note: This tutorial was updated for Swift and iOS 8 by Caroline Begbie. Original series by Tutorial Team member Marin Todorov.

Welcome to the our tutorial series about creating a letter / word game with UIKit for the iPad.

If you successfully followed through the first and second parts of this tutorial, your game should be pretty functional. But it still lacks some key game elements and could use a bit more eye candy.

This third and final part of the series will be the most fun of them all! In this part, you’re going to be adding a lot of cool and fun features:

  • Visual effects to make tile dragging more satisfying
  • Gratuitous sound effects
  • In-game help for players
  • A game menu for choosing the difficulty level
  • And yes… explosions! :]

That’s quite a lot, so let’s once again get cracking!

Enhanced Tile Dragging: Not a Drag

When you run the completed project from Part 2 of this tutorial, you have this:

Counting Points

Your players can drag tiles around on the screen just fine, but the effect is very two-dimensional. In this section you’ll see how some simple visual effects can make the dragging experience much more satisfying.

When the player begins dragging a tile, it would be nice if the tile got a little bigger and showed a drop shadow below itself. These effects will make it look like the player is actually lifting the tile from the board while moving it.

To accomplish this effect, you’ll be using some features of the 2D graphics Quartz framework. To access this, all you have to do is add the proper import statement.

Open TileView.swift and add the following import after the other imports at the top of the file:

import QuartzCore

Now add the following code at the end of init(letter:sideLength:), just after the line where you enabled user interactions:

//create the tile shadow
self.layer.shadowColor = UIColor.blackColor().CGColor
self.layer.shadowOpacity = 0
self.layer.shadowOffset = CGSizeMake(10.0, 10.0)
self.layer.shadowRadius = 15.0
self.layer.masksToBounds = false
 
let path = UIBezierPath(rect: self.bounds)
self.layer.shadowPath = path.CGPath

Every UIView has a property called layer – this is the CALayer instance for the lower-level drawing layer used to draw the view. Luckily CALayer has a set of properties that you can use to create a drop shadow. The property names mostly speak for themselves, but a few probably need some extra explanation.

  • masksToBounds is set to true by default, which means the layer will never render anything outside its bounds. Because a drop shadow is rendered outside of the view’s bounds, you have to set this property to false to see the shadow.
  • shadowPath is a UIBezierPath that describes the shadow shape. Use this whenever possible to speed up the shadow rendering. In the code above, you use a rectangle path (same as the tile’s bounds), but you also apply rounding to the rectangle’s corners via shadowRadius, and you effectively have a shadow with the form of the tile itself. Nice!
  • Note that you’re setting the shadowOpacity to 0, which makes the shadow invisible. So you create the shadow when the tile is initialized, but you’ll later show and hide it when the player drags the tile.

Add the following code at the end of touchesBegan(_:event:):

//show the drop shadow
self.layer.shadowOpacity = 0.8

This turns on the shadow when the player starts dragging. Setting the opacity to 0.8 gives it a bit of transparency, which looks nice.

Add the following code at the end of touchesEnded(_:event:):

self.layer.shadowOpacity = 0.0

This turns off the shadow. The effect will look even better when you change the tile size, but build and run the app now and drag some tiles around to see it working:

Tile with shadows

It’s a nice subtle touch that the user will appreciate – even if subconsciously.

Now to handle resizing the tile so that it looks like it’s being lifted off the board. First add the following property to the class:

private var tempTransform: CGAffineTransform = CGAffineTransformIdentity

This will store the original transform for when the player stops dragging the tile. Remember, each tile has a small random rotation to begin with, so that’s the state you’ll be storing here.

Next, add this code to the end of touchesBegan(_:event:):

//save the current transform
tempTransform = self.transform
//enlarge the tile
self.transform = CGAffineTransformScale(self.transform, 1.2, 1.2)

This saves the current transform and then sets the size of the tile to be 120% of the current tile size.

Now find touchesEnded(_:event:) and add the following line just before the call to dragDelegate:

//restore the original transform
self.transform = tempTransform

This restores the tile’s size to its pre-drag state. While you’re at it, add the following method right after touchesEnded:

//reset the view transform in case drag is cancelled
override func touchesCancelled(touches: NSSet, withEvent event: UIEvent) {
  self.transform = tempTransform
  self.layer.shadowOpacity = 0.0
}

iOS calls touchesCancelled in certain special situations, like when the app receives a low memory warning or if a notification brings up a modal alert. Your method will ensure that the tile’s display is properly restored.

Build and run and move some tiles around!

You may have already noticed this issue while developing the app, but what’s wrong with the following screenshot?

Bad Layering

As you can see, the tile the player is dragging is displayed below another tile! That really destroys the illusion of lifting the tile.

This occurs because a parent view always displays its subviews in the order that they are added to it. That means any given tile may be displayed above some tiles and below others. Not good.

To fix this, add the following code to the end of touchesBegan:

self.superview?.bringSubviewToFront(self)

This tells the view that contains the tile (self.superview) to display the tile’s view above all other views. Dragging should feel a lot better now.

Good layering

Challenge: If you want to make tile dragging even cooler, how about if touching a tile that’s underneath other tiles animated those tiles out of the way, so it looks like the pile of tiles is disturbed by lifting the bottom tile? How would you implement that?

Adding Audio: From Mute to Cute

Tile dragging is now more realistic, but there’s only so far realism can go without audio. Sound is omnipresent and interactive in our daily lives, and your game can’t go without it.

The Xcode starter project includes some Creative Commons-licensed sound effects for your game. There are three sound files, which will correspond with the following game actions:

  • ding.mp3: Played when a tile matches a target.
  • wrong.m4a: Played when a tile is dropped on a wrong target.
  • win.mp3: Played when an anagram is solved.

For convenience, you will pre-define these file names in Config.swift. Add them after the constants you added there earlier:

// Sound effects
let SoundDing = "ding.mp3"
let SoundWrong = "wrong.m4a"
let SoundWin = "win.mp3"
let AudioEffectFiles = [SoundDing, SoundWrong, SoundWin]

You have each file name separately, to use when you want to play a single file. The array of all the sound effect file names is to use when preloading the sounds.

Now create a new Swift file in Anagrams/Classes/Controllers and call it AudioController.

Then inside AudioController.swift, add the following code:

import AVFoundation
 
class AudioController {
  private var audio = [String:AVAudioPlayer]()
 
}

Here you import the framework that you need to play audio or video, and set up a private dictionary audio to hold all preloaded sound effects. The dictionary will map String keys (the name of the sound effect) to AVAudioPlayer instances.

Next add the following method to preload all sound files:

func preloadAudioEffects(effectFileNames:[String]) {
  for effect in AudioEffectFiles {
    //1 get the file path URL
    let soundPath = NSBundle.mainBundle().resourcePath!.stringByAppendingPathComponent(effect)
    let soundURL = NSURL.fileURLWithPath(soundPath)
 
    //2 load the file contents
    var loadError:NSError?
    let player = AVAudioPlayer(contentsOfURL: soundURL, error: &loadError)
    assert(loadError == nil, "Load sound failed")
 
    //3 prepare the play
    player.numberOfLoops = 0
    player.prepareToPlay()
 
    //4 add to the audio dictionary
    audio[effect] = player
  }
}

Here you loop over the provided list of names from Config.swift and load the sounds. This process consist of a few steps:

  1. Get the full path to the sound file and convert it to a URL by using NSURL.fileURLWithPath().
  2. Call AVAudioPlayer(contentsOfURL:error:) to load a sound file in an audio player.
  3. Set the numberOfLoops to zero so that the sound won’t loop at all. Call prepareToPlay() to preload the audio buffer for that sound.
  4. Finally, save the player object in the audio dictionary, using the name of the file as the dictionary key.

That effectively loads all sounds, prepares them for a fast audio start and makes them accessible by their file name. Now you just need to add one method, which plays a given sound:

func playEffect(name:String) {
  if let player = audio[name] {
    if player.playing {
      player.currentTime = 0
    } else {
      player.play()
    }
  }
}

And voila! You have it!

This method takes in a file name, then looks it up in audio. If the sound exists, you first check if the sound is currently playing. If so, you just need to “rewind” the sound by setting its currentTime to 0; otherwise, you simply call play().

Hooray! You now have a simple audio controller for your game. Using it is extremely simple, too. First you need to preload all audio files when the game starts.

Switch to GameController.swift and add this property to the class:

private var audioController: AudioController

The audioController property stores the audio controller the GameController will use to play sounds.

Add the following lines to the end of init():

self.audioController = AudioController()
self.audioController.preloadAudioEffects(AudioEffectFiles)

This makes a new instance of the audio controller and uses the method you just wrote to preload the sounds listed in the config file. Nice! You can now go straight to playing some awesome sound effects!

Inside tileView(_:didDragToPoint:), add the following line after the comment that reads “//more stuff to do on success here”:

audioController.playEffect(SoundDing)

Now the player will see and hear when they’ve made a valid move!

Inside the same method, add the following line after the comment that reads “//more stuff to do on failure here”:

audioController.playEffect(SoundWrong)

Now the player will hear when they’ve made a mistake, too.

Build and run, and check out whether you can hear the sounds being played at the right moment by dragging tiles to the empty spaces.

As long as you’re taking care of the sound effects, you can also add the “winning” sound to the game. Just play the win.mp3 file at the end of checkForSuccess():

//the anagram is completed!
audioController.playEffect(SoundWin)

Sweet!

Ladies & Gentlemen – Explosions!

Gamers love explosions. Making them at least – cool gamers don’t look at explosions and just keep on playing :]

Tough luck, though, as UIKit does not have explosions – right? Guess again. If you think that, then you probably haven’t read iOS 5 by Tutorials, which includes a little chapter on particle effects with UIKit.

An abbreviated version of that chapter is also available online. Check that out for more details on particle effects since there isn’t enough room here to go into it.

Your Xcode starter project already includes a particle image file. Drill down in the file explorer to Anagrams/Assets/Particles, find particle.png and open it.

As you can see, there’s nothing fancy about the image – it’s just a white blur in fact, but that’s all it takes to create an explosion.

A particle image

You will now create two particle systems to use in the game.

Add a new Swift file in Anagrams/Classes/Views called ExplodeView.swift.

As the name hints, this system will emulate an explosion. From a given point in space, many particles will accelerate in all directions, until they disappear quite fast. Like so:



Believe it or not, this will be quite easy. To begin, inside ExplodeView.swift, add the following:

import UIKit
 
//1
import QuartzCore
 
class ExplodeView: UIView {
  //2
  private var emitter:CAEmitterLayer!
 
  //3 configure the UIView to have an emitter layer
  override class func layerClass() -> AnyClass {
    return CAEmitterLayer.self
  }
}
  1. Import QuartzCore to access the particle system classes.
  2. emitter is a convenience property used to give you access to the UIView‘s layer property, cast as a CAEmitterLayer.
  3. layerClass() is a class method of UIView. You override this method when you want to change the underlying layer of your view class. Here you return the CAEmitterLayer class and UIKit ensures that self.layer returns an instance of CAEmitterLayer rather than the default CALayer.

All right, you’re ready to start configuring the particle system. Create the initializers for the class:

required init(coder aDecoder:NSCoder) {
  fatalError("use init(frame:")
}
 
override init(frame:CGRect) {
  super.init(frame:frame)
 
  //initialize the emitter
  emitter = self.layer as CAEmitterLayer
  emitter.emitterPosition = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2)
  emitter.emitterSize = self.bounds.size
  emitter.emitterMode = kCAEmitterLayerAdditive
  emitter.emitterShape = kCAEmitterLayerRectangle
}

The above code stores a reference to self.layer in emitter, cast to type CAEmitterLayer because you know that’s what it is. (Remember, you overrode layerClass() to make it so.) Having the correct type makes it easier to manipulate your layer later on.

Then the code sets various properties on the emitter layer. Read through the code and if in doubt about a certain CAEmitterLayer property, consult the Apple docs or our particle systems tutorial.

The settings in init(frame:) only adjust the particle emitter layer. To actually start emitting particles, you need an emitter cell. You will create and configure your object’s emitter cell at the point when the view is added into the view controller’s hierarchy – that is, as soon as you add the view to a parent view.

Add the following implementation of didMoveToSuperview(), which is the method that gets called on a UIView object when it’s added to its parent:

override func didMoveToSuperview() {
  //1
  super.didMoveToSuperview()
  if self.superview == nil {
    return
  }
 
  //2
  let texture:UIImage? = UIImage(named:"particle")
  assert(texture != nil, "particle image not found")
 
  //3
  let emitterCell = CAEmitterCell()
 
  //4
  emitterCell.contents = texture!.CGImage
 
  //5
  emitterCell.name = "cell"
 
  //6
  emitterCell.birthRate = 1000
  emitterCell.lifetime = 0.75
 
  //7
  emitterCell.blueRange = 0.33
  emitterCell.blueSpeed = -0.33
 
  //8
  emitterCell.velocity = 160
  emitterCell.velocityRange = 40
 
  //9
  emitterCell.scaleRange = 0.5
  emitterCell.scaleSpeed = -0.2
 
  //10
  emitterCell.emissionRange = CGFloat(M_PI*2)
 
  //11
  emitter.emitterCells = [emitterCell]
}

That’s quite a bit of code. Let’s go through it one step at a time:

  1. Call the parent class’s implementation of didMoveToSuperview() and then exit the method if there is no superview set on this object. This might happen if the object was removed from its parent.
  2. Load the particle.png image into a UIImage instance. There’s another one of those assert statements that crashes the app if it can’t find the file it’s looking for.
  3. Create a new emitter cell. Most of the rest of the function is spent configuring this object.
  4. Set the cell’s contents property to the texture you loaded. This is the image that will be used to create each of the particles that this cell will emit. The final shape and color of the particle will be determined by the other settings you make in this method.
  5. Name the cell “cell”. The name will be used later to modify the emitter layer’s properties via key-value coding. You can check out Apple’s docs if you want to learn more about key-value coding.
  6. Set the cell’s birthRate property to 1000, which tells it to create 1000 particles per second. You also set the cell’s lifetime property to 0.75, which makes each particle exist for 0.75 seconds.
  7. Here you set the cell’s color to randomly vary its blue component. Setting blueRange to 0.33 will get you particles with random colors between [1,1,1] (rgb) and [1,1,0.67] (rgb) – basically anywhere between white and orange. You also set a negative blueSpeed – this will decrease the blue component of the blending over time, decreasing the intensity of the particle’s color.
  8. The birth velocity of the particles has a base value of 160 and a range of 40, so the actual velocity will be anywhere between 120 and 200.
  9. The particles are emitted by default with a scale of 1.0. Therefore, setting a range of 0.5 will get you random particles from 0.5 to 1.5 times their original size. Finally you set a negative speed for the scale, thus continuing to shrink the particles over time. Not much shrinking will happen over a 0.75-second lifetime, but it for sure adds to the effect.
  10. Here you set a range (an angle) for the direction the emitter will emit the cells. You set it to a range of 360 degrees – that is, to randomly emit particles in all directions. Remember, this function takes its value in radians, not degrees, so 2*pi radians.
  11. Finally, you add the cell you created to the emitter layer. emitterCells is an array of CAEmitterCells for this emitter. (You can have more than one.)

Aaaaand you’re done. :]

You have now an awesome explosion view. Now add it behind a tile that has been dropped onto a proper target. Open up GameController.swift and add this code to the end of placeTile(_:targetView:):

let explode = ExplodeView(frame:CGRectMake(tileView.center.x, tileView.center.y, 10,10))
tileView.superview?.addSubview(explode)
tileView.superview?.sendSubviewToBack(explode)

You make a new instance of ExplodeView, positioned at the center of the dropped tile view, and add it to the gameView. To make sure it does not cover the tile, you also call sendSubviewToBack() to make the explosion happens behind the tile.

Go! Go! Go! Build and run the project! Wowza!

Particle effect

That wasn’t that difficult, right? However, the effect looks much more like a gas leak than a single explosion. And also – it never stops!

What you would like to do now is kill the emitter after a second to make it look more like an explosion.

Go back to ExplodeView.swift and add a method to stop the emitter cell.

func disableEmitterCell() {
  emitter.setValue(0, forKeyPath: "emitterCells.cell.birthRate")
}

This is that key-value coding I mentioned earlier. The above string accesses the birthRate property of the object named cell that is contained in the array returned from the emitterCells property. By instructing the cell to emit 0 particles per second, you effectively turn it off. Nice.

Now add the following to the end of didMoveToSuperview():

//disable the emitter
var delay = Int64(0.1 * Double(NSEC_PER_SEC))
var delayTime = dispatch_time(DISPATCH_TIME_NOW, delay)
dispatch_after(delayTime, dispatch_get_main_queue()) {
  self.disableEmitterCell()
}
 
//remove explosion view
delay = Int64(2 * Double(NSEC_PER_SEC))
delayTime = dispatch_time(DISPATCH_TIME_NOW, delay)
dispatch_after(delayTime, dispatch_get_main_queue()) {
  self.removeFromSuperview()
}

Here you are using Grand Central Dispatch to dispatch blocks to disable the emitter and remove it from its superview. First you schedule a delay of 1/10th of a second to disable the emitter, and after a delay of 2 seconds, you make another call to remove the explosion view from its parent. Why not just remove the view? You want to let the exploded particles fly away and dissolve before killing the effect.

Build and run the game again and enjoy some nice explosions!


Note: If you want to create your own particle systems, check out original author Marin’s UIEffectDesigner app, which allows you to visually design your particle system effects and then show them onscreen with just a couple of lines of code. It’s still an early beta, but if you are interested in creating particle systems for UIKit or AppKit, give it a try.

Now you’re going to add one more effect. It’s quite similar to ExplodeView, but involves a bit of gravity, since this effect will be a long lasting emitter rather than a simple explosion.

Create a new Swift file called StardustView in Anagrams/Classes/Views.

Add to the end of StardustView.swift:

import UIKit
import QuartzCore
 
class StardustView:UIView {
  private var emitter:CAEmitterLayer!
 
  required init(coder aDecoder:NSCoder) {
    fatalError("use init(frame:")
  }
 
  override init(frame:CGRect) {
    super.init(frame:frame)
    //initialize the emitter
    emitter = self.layer as CAEmitterLayer
    emitter.emitterPosition = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2)
    emitter.emitterSize = self.bounds.size
    emitter.emitterMode = kCAEmitterLayerAdditive
    emitter.emitterShape = kCAEmitterLayerRectangle
  }
 
  override class func layerClass() -> AnyClass {
    //configure the UIView to have emitter layer
    return CAEmitterLayer.self
  }
 
  override func didMoveToSuperview() {
    super.didMoveToSuperview()
    if self.superview == nil {
      return
    }
 
    //load the texture image
    let texture:UIImage? = UIImage(named:"particle")
    assert(texture != nil, "particle image not found")
 
    //create new emitter cell
    let emitterCell = CAEmitterCell()
    emitterCell.contents = texture!.CGImage
    emitterCell.name = "cell"
    emitterCell.birthRate = 200
    emitterCell.lifetime = 1.5
    emitterCell.blueRange = 0.33
    emitterCell.blueSpeed = -0.33
    emitterCell.yAcceleration = 100
    emitterCell.xAcceleration = -200
    emitterCell.velocity = 100
    emitterCell.velocityRange = 40
    emitterCell.scaleRange = 0.5
    emitterCell.scaleSpeed = -0.2
    emitterCell.emissionRange = CGFloat(M_PI*2)
 
    let emitter = self.layer as CAEmitterLayer
    emitter.emitterCells = [emitterCell]
  }
 
  func disableEmitterCell() {
    emitter.setValue(0, forKeyPath: "emitterCells.cell.birthRate")
  }
}

As you can see, the code is almost identical to ExplodeView. The only differences are a longer lifetime for the particles, and values set to xAcceleration and yAcceleration to give acceleration to the particles. This is the way to simulate gravity in your particle systems.

This new particle will emit sparkles for as long as it exists, like a lit fuse on a stick of dynamite.

You’re going to animate this effect to go through the screen behind the solved puzzle!

Switch to GameController.swift and create the animation at the end of checkForSuccess():

// win animation
let firstTarget = targets[0]
let startX:CGFloat = 0
let endX:CGFloat = ScreenWidth + 300
let startY = firstTarget.center.y

This piece of code grabs the very first target on the screen and captures its y-coordinate. You also prepare two constants with the start and end x-coordinates.

Add the next bit of code right after what you just added:

let stars = StardustView(frame: CGRectMake(startX, startY, 10, 10))
gameView.addSubview(stars)
gameView.sendSubviewToBack(stars)

This actually creates the effect and adds it to the view, behind everything else.

Add the following after that:

UIView.animateWithDuration(3.0,
      delay:0.0,
      options:UIViewAnimationOptions.CurveEaseOut,
      animations:{
        stars.center = CGPointMake(endX, startY)
      }, completion: {(value:Bool) in
        //game finished
        stars.removeFromSuperview()
      })

Here you fire off a UIKit animation that moves the effect position through the screen and removes the particle effect from its parent when it’s complete. The following image shows the path it will take:

Animation Path

Build and run the project, and try solving a puzzle. When you do, you’ll see the emitter going through the screen spreading sparkles all over the place. :]

The following screenshot shows it in action, but you really need to see it moving to get the full effect:

Sparkles

That’s some Sparkle Motion! You can refine the effect further by making it follow different paths, zooming in and out, and so on, as you wish.

Adding a Hint Feature

By now you’ve probably already noticed that if you aren’t trained in anagrams, the game can be quite challenging. Unless, of course, you’ve been cheating and looking up the answers in the Plist! :]

It would be a good idea to implement in-game help for your player so they don’t get stuck and lose interest. What you are going to develop next is a Hint button, which will move a tile onto a correct target, thus helping the player solve the puzzle.

Begin by adjusting the HUD. In HUDView.swift, add one more property to the class:

var hintButton: UIButton!

Then add the code to create the button on the HUD. At the end of init(frame:) add:

//load the button image
let hintButtonImage = UIImage(named: "btn")!
 
//the help button
self.hintButton = UIButton.buttonWithType(.Custom) as UIButton
hintButton.setTitle("Hint!", forState:.Normal)
hintButton.titleLabel?.font = FontHUD
hintButton.setBackgroundImage(hintButtonImage, forState: .Normal)
hintButton.frame = CGRectMake(50, 30, hintButtonImage.size.width, hintButtonImage.size.height)
hintButton.alpha = 0.8
self.addSubview(hintButton)

This should configure the button nicely! You set the title to “Hint!”, set the custom game font you use for the HUD and also position the button on the left side of the screen. In the end, you add it to the hud view.

Build and run the project, and you should see the button appear onscreen:

That was quick! Now you need to connect the button to a method so that it will do something when player needs a hint.

Inside GameController.swift, update the hud property to add a didSet property observer. Replace var hud:HUDView! with:

var hud:HUDView! {
  didSet {
    //connect the Hint button
    hud.hintButton.addTarget(self, action: Selector("actionHint"), forControlEvents:.TouchUpInside)
    hud.hintButton.enabled = false
  }
}

Have a look at this observer. When a HUD instance is set to the property, the game controller can also hook up the HUD’s button to one of its own methods. It’s not the HUD’s job to give hints since it doesn’t know about the words and current state of the puzzle, so you want to do this from the game controller instead. The game controller just sets the target/selector pair of the hud.hintButton button to its own method, actionHint. Sleek! :]

Also, the Hint button starts off as disabled. You’ll turn this on and off at the right times as the game progresses.

You’ll also need to add actionHint() to the GameController class:

//the user pressed the hint button
@objc func actionHint() {
  println("Help!")
}

The @objc attribute is needed to make the function available to the Objective-C UIButton class. You’ll replace this code with more than just a log statement later.

Add the following inside checkForSuccess(), just before the line that reads self.stopStopwatch():

hud.hintButton.enabled = false

This disables the hint button at the end of the game, but before any effects begin to play.

Add the following at the end of dealRandomAnagram():

hud.hintButton.enabled = true

This enables the hint button when a new anagram is displayed.

And that should do it! Now when you tap the hint button, you should theoretically see “Help!” appear in the Xcode console. Build and run the project and give the button a try.

Button_why_no_click

Your Hint button does not work for a reason. Remember when you added this line earlier in HUDView’s init(frame:)?

self.userInteractionEnabled = false;

Because HUDView does not handle touches, it also does not forward them to its subviews! Now you have a problem:

  • If you disable touches on the HUD, you can’t connect HUD buttons to methods.
  • If you enable touches on the HUD, the player cannot interact with game elements that are under the HUD layer.

What can you do? Remember the layer hierarchy?

You are now going to use a special technique that comes in handy on rare occasions, but it’s the way to go in this case – and its the most elegant solution as well.

UIKit lets you dynamically decide for each view whether you want to handle a touch yourself, or pass it on to the view underneath. Since HUDView is at the top of the view hierarchy, you’ll add a method there that will handle all touches and then decide what to do with it.

In HUDView.swift, find the line in init(frame:) where you disable user interaction. Change that line to:

self.userInteractionEnabled = true

Now that you will be handling touches in HUDView, you need to decide which ones you want to handle. You’ll implement a custom override of hitTest(_:event:) for the HUDView class.

hitTest(_:event:) gets called automatically from UIKit whenever a touch falls on the view, and UIKit expects as a result from this method the view that will handle the touch. If the method returns nil, then the touch is forwarded to a view under the current view, just as if userInteraction is disabled.

Add the following to HUDView.swift:

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
  //1 let touches through and only catch the ones on buttons
  let hitView = super.hitTest(point, withEvent: event)
 
  //2
  if hitView is UIButton {
    return hitView
  }
 
  //3
  return nil
}

The logic behind this method is quite simple:

  1. First you call the super’s implementation to get which view would normally handle the touch.
  2. Then you check whether this view is a button (i.e. the Hint button!), and if it is, then you forward the touch to that button.
  3. If it’s not a button, you return nil, effectively forwarding the touch to the underlaying game elements layer.

With this method in place, you have a working HUD layer. Build and run the project, and you will see that the Hint button reacts to touches AND you can drag the tiles around:

Hint button

Challenge: For puzzles with small tiles, it’s actually possible to drop a tile under the button, where it will be stuck forever. How would you solve this problem?

OK, going back to GameController.swift, you can also quickly implement the hinting function. Here’s the plan: you’ll take away some of the player’s score for using the Hint feature, then you’ll find the first non-matched tile and its matching target, and then you’ll just animate the tile to the target’s position.

Replace the println() statement in actionHint() with the following:

//1
hud.hintButton.enabled = false
 
//2
data.points -= level.pointsPerTile / 2
hud.gamePoints.setValue(data.points, duration: 1.5)

This is pretty simple:

  1. You temporarily disable the button so that no hint animations overlap.
  2. Then you subtract the penalty for using a hint from the current score and tell the score label to update its display.

Now add the following to the end of the same method:

//3 find the first unmatched target and matching tile
var foundTarget:TargetView? = nil
for target in targets {
  if !target.isMatched {
    foundTarget = target
    break
  }
}
 
//4 find the first tile matching the target
var foundTile:TileView? = nil
for tile in tiles {
  if !tile.isMatched && tile.letter == foundTarget?.letter {
    foundTile = tile
    break
  }
}

To continue:

  1. You loop through the targets and find the first non-matched one and store it in foundTarget.
  2. You do the same looping over the tiles, and get the first tile matching the letter on the target.

To wrap up, add this code to the end of the method:

//ensure there is a matching tile and target
if let target = foundTarget {
  if let tile = foundTile {
 
    //5 don't want the tile sliding under other tiles
    gameView.bringSubviewToFront(tile)
 
    //6 show the animation to the user
    UIView.animateWithDuration(1.5,
              delay:0.0,
            options:UIViewAnimationOptions.CurveEaseOut,
         animations:{
              tile.center = target.center
         }, completion: {
            (value:Bool) in
 
                //7 adjust view on spot
                self.placeTile(tile, targetView: target)
 
                //8 re-enable the button
                self.hud.hintButton.enabled = true
 
                //9 check for finished game
                self.checkForSuccess()
 
        })
  }
}

The above code animates the tile to the empty target:

  1. First bring the tile to the front of its parent’s view hierarchy. This ensures that it doesn’t move under any other tiles, which would look weird.
  2. Set the tile’s center to the target’s center, and do so over 1.5 seconds.
  3. Call placeTile(tileView:, targetView:) to straighten the tile and hide the target.
  4. Enable the Hint button again so the player can use more hints.
  5. Finally, call checkForSuccess() in case that was the last tile. Players will probably not use a hint for the last tile, but you still have to check.

And that’s all! You had already implemented most of the functionality, like placing tiles on a target, checking for the end of the game, etc. So you just had to add a few lines and it all came together. :]

Build and run the project and give the Hint button a try!

Finished game play

What’s On the Menu

The gameplay is complete, but the player can only play Level 1, and can’t choose to solve more difficult anagrams. So your final task for this tutorial is to add a game menu.

Add the following methods to the ViewController class in ViewController.swift:

func showLevelMenu() {
  //1 show the level selector menu
  let alertController = UIAlertController(title: "Choose Difficulty Level",
                                          message: nil,
                                    preferredStyle:UIAlertControllerStyle.Alert)
 
  //2 set up the menu actions
  let easy = UIAlertAction(title: "Easy-peasy", style:.Default,
                    handler: {(alert:UIAlertAction!) in
                            self.showLevel(1)
                    })
  let hard = UIAlertAction(title: "Challenge accepted", style:.Default,
                    handler: {(alert:UIAlertAction!) in
                            self.showLevel(2)
                    })
  let hardest = UIAlertAction(title: "I'm totally hard-core", style: .Default,
                    handler: {(alert:UIAlertAction!) in
                            self.showLevel(3)
                    })
 
  //3 add the menu actions to the menu
  alertController.addAction(easy)
  alertController.addAction(hard)
  alertController.addAction(hardest)
 
  //4 show the UIAlertController
  self.presentViewController(alertController, animated: true, completion: nil)
}
 
//5 show the appropriate level selected by the player
func showLevel(levelNumber:Int) {
  controller.level = Level(levelNumber: levelNumber)
  controller.dealRandomAnagram()
}

Here’s what’s going on:

  1. You create a UIAlertController with a title.
  2. Set up a UIAlertAction for each difficulty level with a title, and also define what happens when the player taps the option.
  3. Add the actions to the UIAlertController.
  4. Show the UIAlertController.
  5. When the player selects a level, the action handler calls showLevel. In this method, you create a new Level instance for the selected level, assign it to the game controller and call dealRandomAnagram() on the game controller.

You would like to show the game menu as soon as the game appears on the screen, so add the following implementation of viewDidAppear to ViewController.swift:

//show the game menu on app start
override func viewDidAppear(animated: Bool) {
  super.viewDidAppear(animated)
  self.showLevelMenu()
}

This calls showLevelMenu() to display the menu to the player.

Woop, woop!

Build and run the project. You’ll see that you have things a bit mixed up – the game appears with an anagram already loaded, while the player still sees the menu:

Mixed menu

To make matters worse, if you choose an item from the menu, it displays it on top of the existing anagram!

Tiles need clearing

To fix the first problem, scroll inside ViewController.swift, find these two lines inside viewDidLoad() and delete them:

controller.level = level1
controller.dealRandomAnagram()

In the same method, but a bit above, also delete this line:

let level1 = Level(levelNumber: 1)

These were all test code chunks that you no longer need.

Build and run again. Now the player sees the menu first, and when they choose the difficulty level the game starts. Nice!

Menu

But now, when the game is over the player cannot go back to the menu screen!

You could make the ViewController be a delegate of GameController, so that when the game is over GameController could send a message straight to ViewController. That would be overkill for this situation, however. And since you want to know tricks for flexible game design with UIKit, why don’t you add a closure to show the game menu that gets executed upon game completion.

Open up GameController.swift and add the following to the list of properties:

var onAnagramSolved:( () -> ())!

This is how you declare a closure that does not take arguments or return a result. The idea here is that GameController will call this closure when the player solves an anagram. It’ll be up to ViewController to fill in this property with some code to show the game menu.

Add the following helper method to the GameController class that you’ll call between levels:

//clear the tiles and targets 
func clearBoard() {
  tiles.removeAll(keepCapacity: false)
  targets.removeAll(keepCapacity: false)
 
  for view in gameView.subviews  {
    view.removeFromSuperview()
  }
}

The method removes all tiles and targets from the controller and the view. You’ll use this to fix the problem you saw earlier, where new anagrams are displayed on top of old ones.

Inside checkForSuccess(), find the line stars.removeFromSuperview(). This is when the final win animation ends. Just below that line, but still inside the block where it is located, add:

//when animation is finished, show menu
self.clearBoard()
self.onAnagramSolved()

Here you call clearBoard() to clean up between levels, and then you call the closure stored in onAnagramSolved.

And finally, add the end-game code closure! Switch for the last time to ViewController.swift and at the end of viewDidLoad(), add:

controller.onAnagramSolved = self.showLevelMenu

Very simple and elegant! You just set the game controller onAnagramSolved closure to call showLevelMenu().

Build and run one last time:

Your finished letter / word game with UIKit!

Congratulations, you have made a complete and polished letter / word game with UIKit!

Where to Go from Here?

Here is a link to the final source code for the tutorial.

You made it! It was a long tutorial, but you learned a ton of cool stuff, from particle effects to game logic to timers. And maybe even improved your vocabulary and anagram skill? ;]

The game is complete, but there are all sorts of ways you could expand it. Here are some ideas off the top of my head:

  • Think about how to make this game (or your own) multi-player via Game Center.
  • You could also simply implement leaderboards via Game Center.
  • Add more explosions, more levels and more anagrams.
  • Implement local high score tracking for different players. You could load and save scores from a plist or JSON file.

That’s all for today. Thanks for sticking with this tutorial, and do leave a comment in the forums below!

How To Make a Letter / Word Game with UIKit and Swift: Part 3/3 is a post from: Ray Wenderlich

The post How To Make a Letter / Word Game with UIKit and Swift: Part 3/3 appeared first on Ray Wenderlich.

Video Tutorial: Introduction to CloudKit Part 5: Fetching Data


Working with JSON in Swift Tutorial

$
0
0

Learn how to parse JSON using Swift!

JavaScript Object Notation, or JSON for short, is a common way to transmit data to and from web services.

JSON is simple to use and it’s human-readable, which is why it’s so incredibly popular.

Consider the following JSON snippet:

[
  "person": {"name":"Dani","age":"24"},
  "person": {"name":"ray","age":"70"}
]

In Objective-C, parsing and deserializing JSON is fairly straightforward:

NSString *age = json[0][@"person"][@"age"];
NSLog(@"Dani's age is %@", age);

In Swift, parsing and deserializing JSON is a little more tedious due to Swift optionals:

if let item = json[0] {
  if let person = item["person"] {
    if let age = person["age"] {
      println(age)
    }
  }
}

In the code above, each object from the JSON must be checked before you use it via optional binding. This makes your code safe, but the more complicated your JSON gets, the more ugly your code gets.

In this tutorial, you’re going to learn an easier way to parse JSON in Swift – using a popular open source library called SwiftyJSON.

In particular, you’ll use SwiftyJSON to parse a JSON document containing the top 25 apps in the US App Store. You’ll see that parsing JSON in Swift can be just as easy as it is in Objective-C! :]

Note: This tutorial assumes that you have some basic knowledge of Swift. If you are new to Swift, check out our Swift Quick Start tutorial series.

Getting Started

Download the starter project for this tutorial, and build and run. You’ll see a blank view controller.

BlankViewControllerA user interface isn’t important for this tutorial, so you’ll be working with the console only. Get used to this blank white screen! :]

The starter project has a few files in it already, to keep the focus purely on parsing JSON in Swift. Take a look at the following files to get an overview of what’s included:

  • TopApps.json: Contains the JSON string to be parsed.
  • AppModel: A plain old Swift object representing an app. Your goal is to parse the JSON into a collection of these objects.
  • DataManager: Manages the data retrieval whether local or from the network. You’ll use the methods in this file to load some JSON later in this tutorial.
  • ViewController: An empty view controller. You’ll add code here to request data from DataManager.swift and parse it in several different ways.

Once you feel like you have a good understanding of what’s currently in the starter project, read on!

Parsing JSON the Native Swift Way

Note: If you already know about the pain of parsing JSON the native way and want to jump straight to SwiftyJSON, skip to the next section.

First, you’ll start by parsing JSON the native Swift way – i.e. without using any external libraries. This will help you understand the benefit of using a library like SwiftyJSON.

Let’s parse the provided JSON file to get the name of the #1 app on the App Store.

Open ViewController.swift and add the following code to the end of viewDidLoad():

DataManager.getTopAppsDataFromFileWithSuccess { (data) -> Void in
  // Get the number 1 app using optional binding and NSJSONSerialization
  //1
  var parseError: NSError?
  let parsedObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(data,
    options: NSJSONReadingOptions.AllowFragments,
    error:&parseError)
 
  //2
  if let topApps = parsedObject as? NSDictionary {
    if let feed = topApps["feed"] as? NSDictionary {
      if let apps = feed["entry"] as? NSArray {
        if let firstApp = apps[0] as? NSDictionary {
          if let imname = firstApp["im:name"] as? NSDictionary {
            if let appName = imname["label"] as? NSString {
              //3
              println("Optional Binding: \(appName)")
            }
          }
        }
      }
    }
  }
}

Are you rolling your eyes already at that list of cascading closing braces? :] Here’s what’s going on above:

  1. First you deserialize the data using NSJSONSerialization.
  2. You need to check each and every subscript value in the JSON object to make sure that it is not nil. Once you’re sure it has a valid value, search for the next object. Once you’ve made your way through all of the subscripts, you’ll get the appName value to display.


    Note that if any element in the JSON is unexpected, you bail on the whole mess and the app name never gets printed. This is desirable in this case.

  3. The last step simply prints the value of appName to the debugger.

Build and run your project; you should see the following result in your debugger console:

Optional Binding: Clash of Clans

Yes — “Clash of Clans” is the #1 app in the JSON file.

It took a lot of code just to retrieve the name of the first app — it’s time to see how SwiftyJSON stacks up.

Integrating SwiftyJSON in Your Project

It’s fairly straightforward to integrate SwiftyJSON into your project.

Simply go to the SwiftyJSON Github page and download the library to a convenient location.

Then drag SwiftyJSON\SwiftyJSON.swift into your project navigator in Xcode. Make sure to select Copy items if needed, make sure that your TopApps target is selected, and click Finish.

That’s it! Now that you have SwiftyJSON integrated into your project, you can start parsing JSON without the optional binding headache!

Parsing JSON the SwiftyJSON Way

SwiftyJSON lets you eliminate all of those nil checks so you can get the name of the #1 app in a single if statement.

Replace viewDidLoad() with the following:

override func viewDidLoad() {
  super.viewDidLoad()
 
  DataManager.getTopAppsDataFromFileWithSuccess { (data) -> Void in
    // Get #1 app name using SwiftyJSON
    let json = JSON(data: data)
    if let appName = json["feed"]["entry"][0]["im:name"]["label"].stringValue {
      println("SwiftyJSON: \(appName)")
    }
  }
}

Seriously — that’s all the code you need.

First you create a JSON constant via the JSON() init method and your data object. SwiftyJSON then converts this data into a JSON object using NSJSONSerialization.

The bonus here is that SwiftyJSON takes care of all the optional validation that you previously had to code by hand. You only need to know which keys and indices you want to access and you can leave the rest to SwiftyJSON.

In the above case, you want to retrieve a string value so you pass .stringValue at the end of the parsing process. If you wanted an array, you would pass .arrayValue. Other return types use a similar construct.

Build and run your app; you’ll see that you successfully get the app name again, but this time with a lot less code:

SwiftyJSON: Clash of Clans

That takes care of parsing local data — but how would you take care of parsing data from a remote source?

Retrieving Remote JSON

It’s time to make this project a bit more realistic. Normally, you’d be retrieving data remotely, not from a local file. You can easily grab the App Store ratings using an online request.

Go to DataManager.swift and add the following method:

class func getTopAppsDataFromItunesWithSuccess(success: ((iTunesData: NSData!) -> Void)) {
  //1
  loadDataFromURL(NSURL(string: TopAppURL)!, completion:{(data, error) -> Void in
      //2
      if let urlData = data {
        //3
        success(iTunesData: urlData)
      }
  })
}

The above code looks pretty familiar; but instead of retrieving a local file you’re using NSURLSession to pull the data from iTunes. Here’s what’s happening in detail:

  1. First you call loadDataFromURL; this takes the URL and a completion closure that passes in an NSData object.
  2. Next you make sure the data exists using optional binding.
  3. Finally, you pass the data to the success closure as you did before.

Open ViewController.swift and add the following line to the end of viewDidLoad():

// Get the #1 app name from iTunes and SwiftyJSON
DataManager.getTopAppsDataFromItunesWithSuccess { (iTunesData) -> Void in
  let json = JSON(data: iTunesData)
  if let appName = json["feed"]["entry"][0]["im:name"]["label"].stringValue {
    println("NSURLSession: \(appName)")
  }
  // More soon...
}

The above code is almost identical to what you did in the first section — only now you’re retrieving real data from iTunes.

Build and run your project; you’ll see that the data parsing still arrives at the same conclusion of the #1 app:

SwiftyJSON: Clash of Clans
NSURLSession: Clash of Clans

The above value may be different for you, as the top apps in the App Store change constantly.

Usually people aren’t just interested in the top app in the App Store — they want to see a list of all top apps. That means you’ll need to retrieve an array of app store ratings instead.

Parsing JSON for Arrays

Add the following code to ViewController.swift just after the “More soon” comment:

//1
if let appArray = json["feed"]["entry"].arrayValue {
  //2
  var apps = [AppModel]()
 
  //3
  for appDict in appArray {
    var appName: String? = appDict["im:name"]["label"].stringValue
    var appURL: String? = appDict["im:image"][0]["label"].stringValue
 
    var app = AppModel(name: appName, appStoreURL: appURL)
    apps.append(app)
  }
 
  //4
  println(apps)
}

The code above iterates over all apps in the JSON response and creates a model object of AppModel as follows:

  1. First you retrieve the list of apps with SwiftyJSON.
  2. Next you create a mutable array to hold the objects to be created.
  3. You then loop through all the items and create a new instance of AppModel from the JSON data.
  4. Finally, you print the new objects out to the debugger.

Build and run your app; you’ll see the previous three results from your JSON parsing attempts as well as a list of the top 25 apps in the iTunes store as shown below:

TopApps4

In real-life applications, you could use all the code you wrote above and implement a UICollectionView or a UITableView to display the results instead.

And that’s it! That’s all there is to using JSON in Swift. The rest of this tutorial is optional, if you want to learn more about how SwiftyJSON works under the hood.

Peeking Under the Hood at SwiftyJSON

You can definitely see that SwiftyJSON works really well to collapse your code into one or two lines — but how does it work under the hood?

When you call JSON() you pass an instance of an optional NSData or even AnyObject. JSONValue() is the initializer for an enumeration in SwiftyJSON:

public enum JSON {
    case ScalarNumber(NSNumber)
    case ScalarString(String)
    case Sequence(Array<JSON>)
    case Mapping(Dictionary<String, JSON>)
    case Null(NSError?)
    // ...
}

Remember that to retrieve different different values from the returned JSON object you simply access different keys and indices. Here’s the code you used to get the name of the #1 app on the App Store:

 json["feed"]["entry"][0]["im:name"]["label"]

This works under the hood through Swift subscripting:

extension JSON {    
    // ...    
    subscript(key: String) -> JSON {
        get {
            switch self {
            case .Mapping(let dictionary) where dictionary[key] != nil:
                return dictionary[key]!
            default:
                return .Null(NSError(domain: SwiftyJSONErrorDomain, code: 0, userInfo: nil))
            }
        }
    }
}

Note the result of the subscript operator is another JSON object. It’s up to you to decide what the expected type is that you wish to retrieve. In this case, you expect this to return the app’s name as a String, so you add a .stringValue to the end of the JSON object.

extension JSON {
 
    var stringValue: String? {
        get {
            switch self {
            case .ScalarString(let string):
                return string
            case .ScalarNumber(let number):
                return number.stringValue
            default:
                return nil
            }
        }
    }
 
    // ...
}

The string() method is one of a set of methods named after the various types you can retrieve from a JSON object; each function returns an optional of its namesake type.

var stringValue: String?
var numberValue: NSNumber?
var URLValue: NSURL?
var charValue: Int8?
var unsignedCharValue: UInt8?
var shortValue: Int16?
var unsignedShortValue: UInt16?
var longValue: Int?
var unsignedLongValue: UInt?
var longLongValue: Int64?
var unsignedLongLongValue: UInt64?
var floatValue: Float?
var doubleValue: Double?
var integerValue: Int?
var unsignedIntegerValue: Int?

Notice that all of these values are optionals which avoids crashes if the value is nil. This is how SwiftyJSON handles optional binding.

You haven’t touched on error handling in SwiftyJSON yet, but it’s equally simple.Here’s how to handle an error condition in SwiftyJSON:

let json = JSON(dataFromNetworking)["some_key"]["some_wrong_key"]["wrong_name"]
if json{
  // Handle success
} else {
  println(json)
  //> JSON Keypath Error: Incorrect Keypath "some_wrong_key/wrong_name"
  //It always tells you where your key went wrong
  switch json{
  case .JInvalid(let error):
    //An NSError containing detailed error information 
  }
}

I highly recommend looking through SwiftyJSON.swift to see how it works. It’s a great example of how to combine a number of useful Swift techniques for a handy result!

Where to Go From Here?

Here is the final example project from the above tutorial.

You can definitely use the above project as the starter code for your next app; simply replace the URL for retrieving remote data with your own URL, handle the individual keys and indices of your new JSON response, and you’ll have a new project that parses something else like the results of football matches or any other piece of data that can be downloaded over the network as JSON.

Development on SwiftyJSON will continue here on Github, so keep an eye out for the latest updates.

Swift is still evolving as well, so you’ll want to keep up to date on Apple’s documentation for any future updates for the language.

I hope you enjoyed this tutorial; don’t forget to check out all the other Swift tutorials on the website. If you have any questions or comments, feel free to join the discussion below!

Working with JSON in Swift Tutorial is a post from: Ray Wenderlich

The post Working with JSON in Swift Tutorial appeared first on Ray Wenderlich.

Video Tutorial: Introduction to CloudKit Part 6: Working with References

Android Tutorial for Beginners: Part 1

$
0
0

android_tutorial_title_image

Update note: This tutorial was updated for the latest version of Android Studio by Darryl Bayliss. Original tutorial by Matt Luedke.

“But when does the Android version come out?”
–The first blog comment after any iOS app gets announced.

Clearly there’s a demand for Android app development, and it’s turning the platform with the lovable green mascot into more and more of a strong first choice rather than just a secondary option to iOS.

With over one billion devices activated, Android is an exciting space to make apps to help you communicate, organize, educate, entertain or anything else you’re passionate about.

If that’s not enough, here are a few more reasons to learn Android:

  • You’ll be plugged into the open source platform with (at the time of press) the largest market share of smart devices worldwide.
  • Android’s policies on device provisioning and app submission are more open than Apple’s, meaning that once you complete your first app—as you’ll do in this tutorial—you and your friends can enjoy it on your devices right away!
  • If you have experience developing for iOS, you can become well-versed in the ways that the two platforms coincide and differ (we’ll discuss a few in this tutorial) and what you like about each. Then you’ll have more tools at your disposal for your next mobile project.
  • It’s not just the iPhone anymore. There are so many smartphones, tablets, glasses, and watches out there, coming from so many manufacturers, and they’re all trying to jump into the game. You don’t have to be any sort of market analyst to know that there are a few important platforms and Android is one of them.

So if you’ve been intent on, thinking about, or simply playing with the idea of learning Android… Make Your First Android App is the tutorial series for you!

nows_your_chance

There aren’t any prerequisites to start. You’ll learn how to set up all the tools you need to become an Android developer-in-training. Then you’ll put together your own full-fledged Android app from scratch! This app will, when completed, help you get details about a book you’re interested in using online search sources.

By the end of Part Three of this series, your app will include useful features like:

  • Saving app data locally on the phone.
  • Loading and interacting with a dynamic list of data.
  • Accessing an online data source.
  • Sharing links through social networks.

Android, and several popular frameworks for it, make all of these features really simple to implement. Why not start learning this easy and powerful platform for yourself, today?

Getting Started

How does Android development go down? First, the zoomed-out basics:

  • You’ll write your programming—what you want your app to do—in Java files and design your layouts—how you want your app to look—in XML files.
  • Once your app is ready, you’ll use a build tool to compile all the project files and package them together into a .apk file that you can run on Android devices and/or submit to Google Play.
  • All of the files you used to put your app together are managed by an Integrated Development Environment (IDE). The IDE is the program you will open to edit your code files and to manage your projects.
  • The standard IDE for Android used to be Eclipse, but this is now being replaced by Google’s own Android Studio.

If you zoom in (metaphorically), you’ll find more in-depth processes going on behind the scenes during all of the above steps. For example, advanced users will want to investigate the role of the Dalvik Virtual Machine and it’s new replacement, ART.

But for now, let’s move on. Here’s what you’re going to accomplish in this part of the tutorial:

  1. Download and install Android Studio.
  2. Set up testing on devices and emulators.
  3. Create a simple “Hello World!” Android app that prints to your device’s screen.
  4. Make small edits to the app so it can congratulate you by name.

In the second part of this tutorial, you’ll make an app that records a message you type, adds it to a list, saves it in memory and shares it with friends. Along the way, you’ll learn how to add and configure various UI elements such as ImageViews, Buttons, ListViews, and EditText controls.

Finally, the third part will cover how to make an app to search an online database of books, display and share the cover images of the search results, and navigate between the different screens of your new app!

Installing Android Studio

It’s really tempting to jump in, start writing code right away and figure out the various Android features as quickly as possible. And you will get there soon! But one of the most important parts of getting started with a new platform is setting up your environment.

Especially for beginners, it’s important to take your time here and follow each step methodically. Even if you follow the steps perfectly, you may have to troubleshoot some small issue, depending on your system configuration or product versions.

It’s important to not let any roadblocks prevent you from your ultimate goal of learning Android. Even seasoned professionals have been known to have some trouble with the new Android Studio.

Note: Just as much as you’re training in programming syntax and frameworks, it’s important to train yourself to have a successful programming mindset — one that won’t accept file X not found as a final answer. 90% of this mindset is simply training yourself to keep trying till you find a solution.

With all of this in mind, let’s quickly check that you have the Java Development Kit (JDK) installed. You might already, even if you don’t know for sure.

To check, you’ll use the Terminal. If you’re unfamiliar with the Terminal, you may want to read a good introductory tutorial about working with the Terminal.

In a nutshell, your Terminal is like looking under your car’s hood. It’s how you really get to know the machine face-to-face, without any complex graphical interface in the middle. You can find the Terminal app quite easily on a Mac using Spotlight. Search for terminal and click the top hit to run Terminal.

screenshot_terminal

Once you have the Terminal open, type in java -version. You should see some output that mentions a version number, like below.

screenshot_terminal2

If you don’t have the JDK installed, your Terminal will tell you command not found. If that’s the case, you should download the JDK from Oracle.

When ready, head over to the Android Studio page and click the big blue button to download the correct version for your Operating System.

screenshot_android_studio_download

Google is constantly updating this page, so the version you see may be newer than the screenshot above. Once you have clicked the button you’ll be asked to agree to the Terms and Conditions:

terms_conditions

After reading these carefully (as you always do) accept the Terms and Conditions and click the blue button underneath titled Download Android Studio. Your download will finally begin. It may take a few minutes but once finished you can install Android Studio similar to any other program.

The download page will helpfully redirect to a webpage that contains installation instructions for OSX, Windows and Linux Operating Systems. If for some reason the instructions don’t appear then you can also view them here.

Now that you’ve installed Studio, let’s fire it up! Launch Android Studio. It may ask you if you want to import any settings:

opening_studio_2

Since you’re starting from scratch, if given the choice just select I do not have a previous version… and move on. You’re presented with the loading screen, complete with all the various phone and tablet screen sizes in the background. More on screen size diversity later. ;]

opening_studio_3

Once Android Studio has finished loading, you’ll be greeted with the Welcome screen.

android_studio_welcome_screen

Even though you just downloaded Android Studio, you might not actually have the latest version. Right away, you need to check to see if any updates are available and if necessary, follow any instructions to get the latest version. You can check whether any updates are available by clicking the check for updates at the bottom of the welcome screen.

If any update is available you will have a window like this appear:

update_now

When you see this screen. Always choose Update and Restart. In some cases, you may need to download the full installer – in that case you will see a Download button that will take you to instructions for installing.

Great! As all programmers in the movies say when they are successfully greeted with a new interface: We’re in!

Optional/Advanced: Moving from Eclipse

You can skip to the next section if you are new to Android development.

Android Studio is a new IDE that Google is constantly updating. If you are already involved in Android development, you are probably using Eclipse. For the transition, the Android team has put together a helpful guide on how to move from Eclipse to Studio.

The process can still be a little bumpy, even for advanced users, so the best advice I can offer on that front is to make sure that your version of Gradle is up-to-date, as well as your versions of the Android Platform Tools and Studio itself.

It’s also important to check the PATH of your Android software development kit (SDK) when switching to Studio. Otherwise, Studio may not be able to find the right Android SDK or Build Tools!

The Android SDK Manager

The next thing you need to do is download a version of the Android SDK. With the huge amount of devices that use the Android Operating System, you need to have access to every SDK that has been released and is in use all over the world.

Once you have an SDK you can begin to create AVD’s (Android Virtual Devices) to test your Apps on, customized to your personal configuration. Want to see how your Android App looks on a TV sized screen? If you have a screen big enough you can find out. More on AVD’s later.

Lets get to it. From the Android Studio welcome screen, click Configure.

studio_configure_click

The menu will slide across and present a new menu with various options. The option you want is the SDK Manager. This is the go to place if you need to download a specific version of Android to develop or test your app on. It also contains other useful things such as API documentation, version specific code samples and even previews of software kits that interact with Android such as Android Wear and Google Glass.

For now lets focus on downloading a version of Android to develop with. Click the SDK Manager option, a new window will present itself to you with checkboxes, folders and statuses across the page.

studio_configure_click

Lets make some sense of this. Each folder is a directory of tools, software and documentation. The majority of directories are specific to an SDK version of Android but there are some that cater to multiple versions. The first folder for example, entitled Tools, is a folder that contains components that are designed to assist in the development of Android and work across multiple SDK’s.

The Android 5.0 (API 21) directory on the other hand holds everything specific to that version of the Android SDK. Including sample code for new features within the SDK, API documentation and system images you can use to simulate a certain mobile architecture using an AVD.

If you don’t understand what all this means then don’t worry, just think of each folder as a place where each version of Android and their tools live happily. From the latest preview version right down to the original Android Beta (API 2).

You should already have a version of the Android SDK Tools, Android SDK Platform-tools and Android SDK Build-tools downloaded from the tools directory. If an update for any of these tools is available then the checkbox next to the tool will automatically be ticked, alongside a polite message in the Status column of the window telling you what the latest version is.

Next you need to grab a version of the SDK. Lets dive into the latest version, that being Android 5.0 (API 21). Lucky for you Android Studio comes bundled with the Android 5.0 SDK when you install Android Studio, although its most likely the SDK Manager will have marked this for an update if one is available.

To get an idea of how the SDK Manager works, you’ll download everything the Android 5.0 Directory offers. Click the tick box next to the folder icon for Android 5.0, this will select everything within that directory for download. You can always come back to the SDK Manager to delete anything you don’t use.

Important: It’s alway worth opening the SDK Manager every time you start Android Studio to see if there is any updates to tools or SDK’s you have installed. This ensures you get access to the latest features in your SDK’s alongside any fixes for nasty bugs.

Your SDK Manager window should look something like this:

opening_studio_16_arrow

Click Install x packages (x being the amount of packages checked for download) on the bottom right of the SDK Manager. A new window will appear with a drop down list of the packages you wish to install, simply click the root of the drop down list and then click the Accept License radio button in the bottom right.

You may need to do this for multiple licenses depending on what packages you download.

studio_sdk_accept_terms_and_conditions

Finally, click the install button at the very bottom right of the window to begin your download.

studio_sdk_install_packages

The window will disappear and the SDK Manager will begin to download and install your selected items. Go grab a drink and take in what you’ve just done whilst the SDK Manager is ticking away. This will become a regular task that you need to get accustomed to so you can quickly acquire and update the various SDK’s you want to work with.

Once the SDK Manager has finished downloading and installing your items you can move onto creating your first Android App!

Creating OMG Android

It’s time. Let’s make your first project.

You’ll start simple. Many first programs are called “Hello World.” Let’s follow that tradition and then make a few small edits so that the app uses your name to greet you. By the end, you’ll be able to load your new app onto a device and show it to your friends!

Android Studio has a nice little step-by-step tool to help you make your project. Click New Project from the Welcome to Android Studio screen:

android_studio_new_project

Note: If you currently have an Android Studio project open and the Welcome screen isn’t showing, select File\New Project from the menu to create a new project.

Studio will present you with your first project creation screen:

android_studio_configure_new_project

Enter OMG Android in Application name as shown above. Feel free to put your own name in the Company Domain textfield. As you type, you’ll notice the Package Name will automatically change to create a reverse domain style name based on your Application name and Company Domain.

The Package Name is used to uniquely identify your app amongst other apps, that way any work an Android device has to be perform on behalf of the app always knows its source and can’t get confused between two apps. iOS developers will recognize this concept as being similar to the Bundle Identifier.

You can set the Project location to any location on your hard drive – you do not need to follow the screenshot for that one :]

Click Next at the bottom of the window to progress to the next part of the project setup.

android_studio_set_form_factors

The next screen is where you select device types and operating systems to target. Want an App to focus on just Phone and Tablet? Not a problem! How about an App for TV and Google Glass? Thats great too. For now though you just want an App that works on an Android Phone. This option is selected as the default, alongside the default Minimum SDK.

The Minimum SDK drop down menu sets the minimum version of Android needed to run your app. Selecting this value for your own projects is a matter of balancing the SDK capabilities you want and the devices you want to support.

For your first app, you’ll use the default – API 15, which is Android 4.0.3 (Ice Cream Sandwich). Every app will have different requirements and you may want to choose something else, depending on the situation.

If you really want to get into the details of what Minimum SDK version is best for your App then Android Studio can help you out. As you change the Minimum SDK in the drop down menu, the percentage in the text underneath reflects what percentage of devices currently run that version of Android.

If you are more about features than numbers, Android Studio has got your back too. Click the highlighted Help me choose underneath the drop down list to display a useful new window.

android_studio_help_me_choose

What you are looking at is a bar chart, split by the amounts of devices running a specific version of Android. Click on any part of the bar and the text to the right will change, telling you the most significant features of the Android Version that part of the bar represents. Useful if you need a quick overview of what each version of Android provides for your App.

android_studio_sdk_features_shown

Take note of the Cumulative Distribution values on the right of the bar. This represents the percentage of devices supporting that particular version of Android – which includes backwards compatibility. As you descend down the bar, the version of Android increases and you gain more features that your App can make use of. The downside to this is the amount of devices that can actually run your App is reduced.

Picking what Minimum SDK your App will require is a crucial choice. It will influence what features you have available to you in your project while also influencing how many Android users can run your App. Choose wisely!

For more information on API versions and their use, check out the Android Dashboards, which are updated every few days.

android_dashboard_1

Getting back to the new project window, click Next in the bottom right to pick more options for your project.

android_studio_create_activity

This screen lets you choose a default Activity for your app. Think of an Activity as a window within your App that displays content the user can interact with – not unlike a View Controller in iOS. An activity can take up the entire screen or it could be a simple pop-up.

Available activities on this template range from a blank activity with an Action Bar right up to an Activity with a MapView embedded. You will be making a lot of activities, so it’s good to get accustomed with them.

Select the Blank Activity option and click Next.

android_studio_name_activity

If you have made it this far then well done, you are at the final screen before you dig into some actual coding. To speed this part up a little bit you will use the pre-populated default values, but what is actually done with these values?

  • Activity Name. This will give your Activity a name to refer to in code. Once the project setup is complete Android Studio will create a .java class and use the contents of this textfield to give the class a name. This is the name you will use to refer to your Activity inside your code.
    Note: What it’s actually doing is making a subclass of Activity. Those familiar with object-oriented programming will know what this is, but for newcomers, this basically means that your MainActivity is going to be a customized version of Activity that acts just like the default one, handling things like its lifecycle and the user interface display.
  • Layout Name. You’re going to define your Activity in Java, but the layout of everything it will show to the user is defined in a special sort of Android XML. You will learn how to read and edit those files shortly.

Click Finish. Android Studio takes this as its cue to go do a bunch of behind-the-scenes operations and create your project. As it shoots out some descriptions of what it’s doing from time to time, you may notice it say something like the following:

opening_studio_22

You see your project name, which is familiar. But then there is this Gradle word, and then a mention of Maven in the URL. The benefit of having a modern IDE like Android Studio is that it handles a lot for you. But as you’re just beginning to learn how to use the software, it’s good to know, in general, what it’s doing for you.

  • Gradle is a new build tool that is easy to use, but it also contains a lot of advanced options if you investigate it further. It takes your Java code and XML layouts, and then uses the latest Android build tools to create the app package file, known as an APK file. You can customize your configurations to have development or production versions of the app that behave differently, or add dependencies for third-party libraries.
  • Maven is another project build tool, and it can also refer to the Maven Central repository of java libraries. It is absurdly easy to use Gradle and Maven Central in concert with Android Studio to incorporate all sorts of functionality from the Android development community. Those with an iOS background will know how cool this sort of thing can be from using the CocoaPods tool. You’ll learn more about Maven in Part Three of the tutorial.

After a brief moment, Android Studio will finish building your project. The project is pretty empty, of course, but it still has everything it needs already set up so that it can be launched on an Android device or emulator. You will be dropped off in this spot:

android_studio_inital_project_screen

Android Studio will contain three windows. To the left you have your project folder structure, the middle shows a layout file in XML and the right contains a preview of your layout on a Nexus 4 device. Before you get into any programming, let’s talk about how you’re going to get this app running. It’s time to say “Hello world!”

Running on an Emulator or Device

All right: You’ve got Android Studio and you’ve created an app. So how do you run it?

If you have a physical Android device available, you’ll learn how to use that soon. But for those without one, you also have the choice to run your App on an emulator.

Android Studio comes free with the ability to set up a software-based Android device on your computer and run apps on it, browse websites, debug and everything you would expect. This capability is known as the Android Emulator.

You can set up multiple emulators and set the screen size and platform version for each one to whatever you like. This is great, as with the diversity of the Android platform, you’d otherwise need a large amount of devices for testing.

The downside to the emulator is a big one. Unfortunately, the emulator is painfully slow. For those coming from iOS development, you will really start to appreciate the iOS Simulator after using the Android Emulator.

Note: The reasons why the emulator is frustratingly slow boil down to one thing. Instruction sets. The majority of Android devices run on ARM based processors whilst the majority of computers use x86 based processors.

What the Android Emulator does is completely emulate an Android device running on an ARM based processor, forcing your computer to translate from x86 to ARM based instructions. This is computationally taxing on your computer, hence why the initial loading of the emulator takes so long.

The lightning quick Genymotion Emulator is a fantastic alternative to the stock emulator, although setting it up has a quite a few steps. Intel has also made impressive efforts to offer x86 compatible System Images via the SDK Manager that can be Hardware Accelerated. Feel free to use ether of these alternatives if you just can’t wait for the stock emulator to load.

emulator_ragecomic

All of that being said…let’s set up an emulator anyway, because you’re going to need it!

Click AVD Manager. It’s the button in the toolbar that has an Android popping its head up next to a device with a purple display.

screenshot_android_studio_select_avd_manager

Since your list is probably empty (if you are just starting Android development), you will need to create one. Click the Create button.

create_new_device

Now you see a bunch of options to create your emulator:

android_studio_create_avd_setup

Configure your settings as follows:

  1. Enter EmulateMasterGeneral for the AVD Name.
  2. The Device dropdown contains a number of useful presets to help you base your virtual device off a real one. Choose the Nexus 4 option.
  3. For the Target dropdown, choose the Android 5.0 option. Remember the SDK Manager? Well as you use it to download more SDK’s to develop and test for, they will appear here for you to use on your AVD’s, allowing you to test your App across multiple versions of Android.
  4. For CPU/API, choose ARM.
  5. For Skin, choose Skin with dynamic hardware controls.

You can leave the rest as default. Once you’re ready, click OK.

Note: If your Device selection doesn’t automatically pick a CPU, make sure to select an ARM processor for your emulator. You can use the CPU options such as the Intel Atom (x86) but these can take some additional effort to setup and use effectively.

If you downloaded any of the alternative emulators mentioned earlier in this tutorial then follow the instructions provided on each website.

You’ll see a brief summary pop-up of the options you just chose. Click Ok, your newly-created emulator will now be on the list and waiting to be brought to life!

opening_studio_30

Now, close the AVD Manager to go back to Android Studio’s main view. Now that you’ve configured everything, there’s but one step left…

Click the Run button. It looks like a “play” icon.

run_button

A new window will appear, asking you to choose the device you wish to test your App on. You currently have no devices running, so lets start the AVD you just created. Ensure the Launch Emulator radio button is checked and your AVD is selected in the drop down menu, then click OK.

run_button

Note: If you get an error that says “This AVD’s configuration is missing a kernel file!!”, check to make sure that you don’t have the ANDROID_SDK_ROOT environment variable set from a previous installation of the Android SDK. See this thread for more troubleshooting tips.

You may have to wait a while as the emulator loads, and you may even need to try it more than once for the emulator to get it right, but once it’s ready, you should see something like this:

hello_world

Congratulations! You made your first Android app!

Android Apps used to be something you only interacted with on the consumer side, but now… you’re a creator. There’s power and possibility in that. It’s worth taking a moment to think about where you might want to go with this newfound ability.

When you’re ready, you need to revisit something I quickly glossed over earlier — testing on devices.

Navigating the Android Candy Store

One of Android’s advantages, the diversity of devices that can run the platform, is also a major complication for developers. You have to consider just about everything, such as the items on the following non-exhaustive list, to be variable:

  • Screen sizes, both physically and in terms of pixels
  • Processor speed
  • Screen density, or the number of pixels per mm
  • The ratio of the screen width to the screen height
  • The number of simultaneous touches the touchscreen can register
  • The quantity and positioning (front vs. back) of cameras
  • Bluetooth capabilities
  • Platform and software versions

If you want to make an App that will run on a hundred different devices, how can you tell if it’s going to work? Well, there are six main strategies I can recommend:

  1. Nail down your target
  2. Filter your manifest
  3. Check Android’s best practices
  4. Emulate
  5. Pick at least one representative device
  6. Fake other screens on your device

Let’s go through them one by one.

1. Nail down your target

Does your App have some specific, indispensable hardware or software requirement? What about nice-to-haves? Take stock of device needs early, so that if your App is camera-based, or communicates with a specific product through Bluetooth, you’re ready to target your App to devices with those capabilities.

Check the often-updated Android Dashboards to see the prevalence of platform versions as well as screen sizes and densities. You can see, for example, that your choice in this tutorial to only support Ice Cream Sandwich and higher will lose you just over a quarter of Android users. It’s a reasonable sacrifice in your case.

2. Filter your manifest

Once you’ve determined your App’s requirements, you need to let Android know about them. That way, the Google Play Store can keep non-compatible devices from purchasing your App.

This will save you a lot of frustration and poor reviews from users who might have downloaded your app, only to find a strange error awaiting them. It won’t, however, absolve you from communicating in any marketing materials the list of devices your users should expect to be able to run your App on.

The device features you need should be listed in a file. This file, available in every project, is called the Android Manifest. This is an XML file that contains all the high-level info about your App. Remember when you chose API 15: Ice Cream Sandwich as the minimum SDK when you created the OMG Android project? That choice needs to be reflected in your Android Manifest.

Find your AndroidManifest.xml file on the left side of the Android Studio window, likely under app/src/res, and double-click it to open it up. You will see a few elements contain values, but nothing that looks like it determines what SDK is used in your App. Thats fine, lets just add it in. Add the following to your Android Manifest above the application XML tag.

        <uses-sdk
        android:targetSdkVersion="21"
        android:minSdkVersion="15" />

Looking good. You’ve just told your Android App what version of Android it is targeting and what the minimum version a device needs to run it. Or have you? Mouse your cursor over your newly added XML and you should receive the following message.

android_manifest

As the message politely tells you, your newly input values are being overridden by a Gradle Build Script. Lets go see where this happens, double-click on the build.gradle file in the app folder and you will be presented with something like this.

apply plugin: 'com.android.application'
 
android {
    compileSdkVersion 21
    buildToolsVersion "20.0.0"
 
    defaultConfig {
        applicationId "com.darrylbayliss.omgandroid"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
 
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

There are quite a few things going on here, but for now you will focus on just one part – the defaultConfig element. Inside its curly brackets you will see some familiar looking values that are affecting your App when it is being compiled. This was what the message in your Manifest was warning you about. Fortunately, it isn’t a concern, but it is something worth understanding.

Whenever you click Run in your main project window, any values within the defaultConfig element of build.gradle are used to populate some additional information into your AndroidManifest.xml file. The reason for this is to make use of the flexibility of the Gradle Build Toolkit.

Before Android Studio, things such as trying to build multiple versions of an App from the same project was something of a pipe dream. An App project only has one manifest file to declare it’s features and rules so if you wanted to test different configurations of your App, it would be a long and labored process because you would have to make your changes, compile the App and then repeat this process until you were happy with the results.

The arrival of Gradle changes all that, allowing for multiple bespoke versions of your App to be created using specific rules you can set yourself. Project dependencies can be linked to from remote code repositories, ensuring every time you build your App you are using the latest version of 3rd party libraries. You can even set rules up to test your APK using a variety of source files during the build process.

Gradle makes use of Groovy syntax, a Java like language, so if you are intent on learning Java then you will easily pick Groovy up as well.

You can learn more about Gradle and its treasure chest of features right here on the Android Developers website.

3. Check Android’s best practices

There’s a great list of best practices to address compatibility issues that’s available on the Android Developer site. Some of the most useful tips include:

The tutorial will discuss these in more detail in Part Two, when you lay out views in XML.

4. Emulate

When you set up your Emulator earlier, you saw how many options you have to work with different screen sizes. If you used the stock emulator then you also saw how slow it can be. As mentioned earlier, there are ways to improve it and alternative emulators all together you can make use of to try your App on a huge variety of configurations.

If the stock emulator isn’t for you, try them out and see what works best.

5. Pick at least one representative device

The most expensive option, unless you already own an Android device, is to go out and buy one. I recommend trying to find a used, unlocked device from the Google Nexus series. If your budget is tight, go two generations back, which at the moment would mean a Galaxy Nexus. Of course, if you’ve got the money, you can go for the new snazzy Nexus 5!

With all the time you will save avoiding the emulator, if you continue on with Android (which I hope you will!), it will definitely be a worthwhile investment.

If you have a device, you don’t need any silly Provisioning Profiles. You just need to turn on USB debugging for your device. Sometimes the checkbox option is available just by going to Settings > Developer Options on your device. Check these instructions for more details.

Other times, you have to do some weird shenanigans. I can’t make this up! A direct quote from Android: “On Android 4.2 and newer, Developer options is hidden by default. To make it available, go to Settings > About phone and tap Build number seven times. Return to the previous screen to find Developer options.”

No matter if you had to do a little dance or whistle a perfect C to reveal the option, once USB debugging is on, you can go back to the Run/Debug Configurations screen and set your Target Device to USB Device. This will serve you well for the rest of the tutorial.

6. Fake other screens on your device

If you are lucky enough to have a device and have enabled USB Debugging on it, then you have another testing advantage: you can use it to “fake” other screen sizes. Here’s how.

Open your Terminal as you did earlier, when you checked for the JDK. Then locate a tool called the Android Debug Bridge (adb). With early versions of Android Studio, it will be in the /Applications/Android\ Studio.app/sdk/platform-tools directory, or wherever you installed your copy of Android Studio, if elsewhere. Later versions of Android Studio do not come with the Android SDK bundled in and so you might have your Android SDK installed in a totally different location.

You can use the following command at the Terminal prompt to see if adb is available in your system PATH:

adb version

The result should be something like this:

check_for_adb

Note: If the adb version command results in an error message, your Android SDK folder is probably not in your PATH. Then you’d need to find the exact location of the Android SDK and change to the correct folder (as in the first steps in the screenshot above) and prefix any adb commands with ./. Alternatively, you can add the adb path to your PATH.

The adb version command is just an example to show you how to call adb from the command line. It can run all sorts of commands and you can get a list of available commands by typing adb help.

If not already set up, you can optionally add the Android SDK platform tools folder to your $PATH so that you can run adb from anywhere on your system. You should only do this if you are familiar with UNIX and feel comfortable doing so.

With your device plugged in and with its screen turned off, type the following:

adb shell wm size 640x480

And then type:

adb shell wm density 160

This represents a screen size of 640×480 pixels with 160 pixels per inch pixel density.

Note: In Android versions earlier than 4.3 Jelly Bean, these commands are slightly different, as documented here.

When you turn the device screen back on, you should see that the resolution has changed to match the new values you entered!

Feel free to turn the screen off, try another set of dimensions and turn it back on again.

To return your device to its normal settings, type:

adb shell wm size reset

And then type:

adb shell wm density reset

So you could get a full-size tablet (like a Nexus 10, perhaps) and then easily simulate all sorts of smaller devices, without having to use the emulator! If you are trying this with a device that has a relatively small screen then it’s not really worth going beyond the dimensions of your screen as it will begin to display elements offscreen.

I hope that information helps you navigate the Gingerbreads, KitKats, Jelly Beans, and all the other varieties of Android candy. Now, back to the app at hand…

So… WHY did that work?

You’ve got your first app behind you. To start making changes and adding cool features, it’s necessary to get a working knowledge of what’s going on behind the scenes.

Take a look at the Project section of Android Studio, with the files and folders on the left side of the screen. You may need to press the little tab on the edge (see below) if the project explorer isn’t visible at the moment.

find_project_files

Browse around for a few minutes without any explicit instructions, expanding and collapsing folders and double-clicking on files to see their contents in the main window. If you notice any trends, great. If it all still looks cryptic, not to worry!

Android Project Structure: The Team

Every great team is composed of people who play different roles. Do you want to do the job right? You need the right team. Android Projects have a few key elements and each has a role to play:

  1. Java: The Professional
  2. Resources: The Artist
  3. AndroidManifest.xml: The Boss
  4. Intent: The Job itself

Java: The Professional

It’s the job of your Java code to get things done. Your code is all going to be in the src/main/java directory under your main project folder. You will be given all the code you need to complete this tutorial, but if you want to learn or refresh your Java knowledge, here is a nice online interactive tutorial.

It will be worth your time to learn more and more Java as you explore Android development. Your team is relying on the professional.

Resources: The Artist

It’s not enough to just get the job done. It needs to be done in style. Your App is never going to stand out unless it has great icons and images, well-designed layouts, engaging copy text, and maybe even some smooth animations.

Initially, the src/main/res (Resources) folder contains:

  • Drawable folders that hold images — just the default launch icon for now.
  • The layout folder with XML that represents the screen designs.
  • The menu folder with XML of the items that will appear on the Action Bar. More on that later.
  • The values folder with XML containing dimensions, strings, and styles.

AndroidManifest.xml: The Boss

Someone’s got to call the shots. That “someone” would be the Android Manifest. This XML file informs your system of the app’s hardware and software requirements and contains your app’s name, icon, and version.

The manifest also filters the Intents coming in. You need a job done by your app? Talk to the boss first. Now, more about the jobs themselves…

Intent: The Job itself

Want to show the user a screen? Want to navigate to a website? Whatever the job is, in Android it is going to take the form of an Intent. If you come from an iOS background, pay close attention because this is a very “Android” concept.

The Android system knows that you will potentially have a lot of Apps on your device, and wants to make it easy for them to talk to each other. So, it allows you to send and receive what are essentially requests for jobs to be done.

A job could get picked up by your App’s own boss (the manifest) or another App. When creating an Intent, it’s up to you to either write it very generally to have the option of picking from several Apps to perform the job (implicit), or very specifically to follow a certain path (explicit). You’ll see an example of each type if Intent later in this tutorial.

For an immediate example, your App already has an Activity called MyActivity. Your manifest has it labeled with an intent filter that causes the MyActivity to launch when the user selects the App icon from their home screen. You could potentially move that filter to another Activity and then that activity would launch instead of MyActivity. Basically, the App does whatever the boss says.

If you don’t fully grasp everything about Intents right away, don’t worry. Just keep the concept in mind as you see Intents throughout the code, and eventually you will start to get an idea of their potential.

Putting a Personal Stamp on Your App

You’ve made your first App, but what’s the first thing you always want to put on any of your work? Thats right, your name!

Navigate to res/values/strings.xml and double-click the file. When you open the file, you’ll see three string resources in XML.

These resources are accessed in different places, but it is very convenient to have all of the text used in your App in one file. If you need to translate it, or if your marketing coworker tells you to remove all the nerdy references from your App, it will be easy to make all the changes here.

Change the hello_world string. That string is the one that the app displays on the screen. So, change it to something more personal that incorporates your own name – something like:

<string name="hello_world">Darryl is learning Android!</string>

opening_android_46

So remember: When you launch the App, you’re essentially doing the same thing as sending a launch Intent to the manifest. As the boss, the manifest takes a look at the Intent and decides it has the perfect fit for the job: MyActivity. The Java does the heavy lifting of opening the screen, but for what to display it goes and asks the artist, eventually leading to strings.xml.

Click Run. When the App launches again, you’ll see your personalized message!

personalized_hello_world

Congratulations! If you have a device, you can go around showing off your new app to your friends or take a screenshot from the emulator and send it to them.

You’ve entered the world of Android. You’ve set up your development environment (no easy task!), created your first app, run it on an Emulator or device, and changed the App so that it specifically addresses you. Great job!

Updating With the SDK Manager

This tutorial will work with whatever SDK version you downloaded with Android Studio, but as mentioned earlier it’s a good idea to always keep your SDK versions and Android Platform Tools up-to-date.

To access the SDK Manager quickly from your project, click the sdk_manager_button button, which allows you to easily download or update your Android SDK components.

sdk_manager

Where to Go From Here?

There’s a lot still to come, but here are some extra tips to think about before jumping into the next part of the tutorial:

  • Follow Android. The development community around any language or framework can be its strongest asset. It’s never too soon or too late to start checking out Google I/O videos, following the Android Developers blog or watching DevBytes videos.
  • Get the full source for this section of the tutorial on GitHub or as a .zip.
  • Post any comments/suggestions/questions below.
  • Stick around for the second and third sections of the tutorial! Thank you!

The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.

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

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

FMDB with Gus Mueller – Podcast S02 E05

$
0
0
Learn about FMDB with Gus Mueller!

Learn about FMDB with Gus Mueller!

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

Remember that among the many changes in this season, we are now moving to a weekly (and shorter) format – so we’re cracking along with episodes (5 already)!

In this episode, we talk with Gus Mueller, founder of Flying Meat (developer of Acorn) and author of FMDB, an Objective-C wrapper around SQLite and an alternative to Core Data.

In this episode, we take a deep dive into FMDB and also discuss Gus’s experience running his own indie software company.

[Subscribe in iTunes] [RSS Feed]

Links and References

Contact Us

Where To Go From Here?

We hope you enjoyed this podcast, and the changes we made for season 2.

Remember – we’re now on a weekly format, so stay tuned for a new episode next week! :]

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

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

FMDB with Gus Mueller – Podcast S02 E05 is a post from: Ray Wenderlich

The post FMDB with Gus Mueller – Podcast S02 E05 appeared first on Ray Wenderlich.

Video Tutorial: Introduction to CloudKit Part 7: Subscriptions

Viewing all 4373 articles
Browse latest View live


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