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

NSTask Tutorial for OS X

$
0
0
See a practical example of using NSTask!

See a practical example of using NSTask!

Update note: This NSTask Tutorial for OS X has been updated to Swift by Warren Burton. The original tutorial was written by Andy Pereira.

Your Mac has a fully-fledged version of UNIX as its operating system, which means it has a massive amount of pre-installed command line utilities and scripting languages. Swift, Perl, Python, Bash, Ruby, plus anything you can install. Wouldn’t it be nice to use to that power to create awesome apps?

NSTask allows you to execute another program on your machine as a subprocess and monitor its execution state while your main program continues to run. For example, you could run the ls command to display a directory listing — from right inside your app!

A good analogy for NSTask is a parent-child relationship. A parent can create a child and tell it to do certain things, and (theoretically) the child must obey. NSTask behaves in a similar fashion; you start a “child” program, give it instructions and tell it where to report any output or errors. Better yet — it’s way more obedient than your average toddler :]

A great use for NSTask is to provide a front-end GUI to command line programs. Command line programs are powerful, but they require you to remember exactly where they live on your machine, how to call them and what options or arguments you can provide to the program. Adding a GUI on the front end can provide the user with a great deal of control — without having to be a command line guru!

This tutorial includes an NSTask example that shows you how to execute a simple command program with arguments and display its standard output as it runs in a text field. By the end, you’ll be ready to use NSTasks in your own apps!

Note: This tutorial assumes you have some basic familiarity with Mac OS X development and the Terminal. If you are completely new to programming for the Mac, check out our beginning Mac OS X development tutorial series.

Getting Started

To keep the focus squarely on NSTask, I’ve created a starter project for you that contains a basic user interface. Download the project, open it in Xcode, and build and run.

The starter app has one window, as shown:

initial_view

This window has the title “TasksProject”. It has a simple GUI that will, by invoking a shell script, let you build an iOS project, create an ipa and observe what is happening.

Creating Your First NSTask

The NSTask example will be to build and package an iOS app into an ipa file by using NSTask to run some command line tools in the background. Most of the basic UI functionality is in place — your job is do the heavy lifting with NSTask.

Note: It’s recommended that you have an iOS Developer account with Apple, as you’ll need the proper certificates and provisioning profile to create an ipa file that can be installed on one of your devices. Don’t worry if you don’t, though, as you’ll be able to follow the entire tutorial even without an account.

You are now going to work on the embedded View Controller titled “Tasks View Controller”. The first section in the window asks the user to select an Xcode project directory. To save time, rather than having to select a directory manually every time you run this app while testing, you’ll hard-code it to one of your own Xcode project directories.

To do this, head back to XCode and open TasksViewController.swift. Take a look at the properties and methods under the comment “Window Outlets”:

//View Controller Outlets
@IBOutlet var outputText:NSTextView!
@IBOutlet var spinner:NSProgressIndicator!
@IBOutlet var projectPath:NSPathControl!
@IBOutlet var repoPath:NSPathControl!
@IBOutlet var buildButton:NSButton!
@IBOutlet var targetName:NSTextField!

All of these properties correspond to the Tasks View Controller Scene in Main.storyboard. Notice the projectPath property — this is the one you want to change.

Open Main.storyboard and click on the Project Location item. You’ll find it 4 levels deep in the object hierarchy; it’s a child of the Stack View. In the Attributes Inspector, under Path Control, find the Path element:

set_path_1b

Set Path to a directory on your machine that contains an iOS project. Make sure you use the parent directory of a project, not the .xcodeproj file itself.

Note: If you don’t have any iOS projects on your machine, download a simple project here and unzip it to a location on your machine. Then set the Path property in your application using the instructions above. For example, if you unzip the package on your desktop, you would set Path to
/Users/YOUR_USERNAME_HERE/Desktop/SuperDuperApp
.

Now that you have a default source project path in your app to facilitate testing, you will also need a default destination path. Open Main.storyboard and click on the Build Repository item.

In the Attributes Inspector, find Path item under Path Control:

set_path_2b

Set the Path entry to a directory on your machine that’s easy to find, like the Desktop. This is where the .ipa file created by this application will be placed.

There are two additional fields in the Tasks View Controller Scene you need to know about: the Target Name and an associated text field.

initial_view_2

  1. Target Name is designated for the name of the iOS Target you want to build.
  2. The text area below Target Name will display output from the NSTask object in your project as it runs.

Don’t know the target name of your iOS project? To find it, select your project in Xcode’s project navigator and look under TARGETS in the Info tab. The screenshot below shows where to find this for a sample project called “SuperDuperApp”:

target_name

Remember the target name — you’ll be entering it into the running app later on.

Let’s start fleshing out the bits of code that will run when the “Build” button is pressed.

Preparing the Spinner

Open TasksViewController.swift and add the following code to startTask:

//1.
outputText.string = ""
 
if let projectURL = projectPath.URL, let repositoryURL = repoPath.URL {
 
  //2. we can use ! safely here because we know the URL exists
  let projectLocation = projectURL.path!
  let finalLocation = repositoryURL.path!
 
  //3.
  let projectName = projectURL.lastPathComponent!
  let xcodeProjectFile = projectLocation + "/\(projectName).xcodeproj"
 
  //4.
  let buildLocation = projectLocation + "/build"
 
  //5.
  var arguments:[String] = []
  arguments.append(xcodeProjectFile)
  arguments.append(targetName.stringValue)
  arguments.append(buildLocation)
  arguments.append(projectName)
  arguments.append(finalLocation)
 
  //6. 
  buildButton.enabled = false
  spinner.startAnimation(self)
 
}

Here’s a step-by-step explanation of the code above:

  1. outputText is the large text box in the window; it will contain all the output from the script that you will be running. If you run the script multiple times, you’ll want to clear it out between each run, so this first line sets the string property (contents of the text box) to an empty string.
  2. The projectURL and repositoryURL objects are NSURL objects, and this gets the string representations of these objects in order to pass them as arguments to your NSTask.
  3. By convention, the name of the folder and the name of the project file are the same. Getting the lastPathComponent property of the project folder contained in projectURL and adding an “.xcodeproj” extension gets the path to the project file.
  4. Defines the subdirectory where your task will store intermediate build files while it’s creating the ipa file as build.
  5. Stores the arguments in an array. This array will be passed to NSTask to be used when launching the command line tools to build your .ipa file.
  6. Disables the “Build” button and starts a spinner animation.

Why disable the “Build” button? The NSTask will run each time the button is pressed, and as the app will be busy for an amount of time while the NSTask does its work, the user could impatiently press it many times — each time spawning a new build process. This action prevents the user from creating button click events while the app is busy.

Build and run your application, then hit the Build button. You should see the “Build” button disable and the spinner animation start:

busy1

Your app looks pretty busy, but you know right now it’s not really doing anything. Time to add some NSTask magic.

Adding an NSTask to TasksProject

Open TasksViewController.swift and add the following method:

func runScript(arguments:[String]) {
 
  //1.
  isRunning = true
 
  let taskQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
 
  //2.
  dispatch_async(taskQueue) {
 
    //TESTING CODE
 
    //3.
    NSThread.sleepForTimeInterval(2.0)
 
    //4.
    dispatch_async(dispatch_get_main_queue(), {
      self.buildButton.enabled = true
      self.spinner.stopAnimation(self)
      self.isRunning = false
 
    })
 
   //TESTING CODE
 
  }
 
}

If you look at the method step-by-step, you’ll see that the code does the following:

  1. Sets isRunning to true. This enables the Stop button, since it’s bound to the TasksViewController‘s isRunning property via Cocoa Bindings. You want this to happen on the main thread.
  2. Uses dispatch_async to run the heavy lifting on a background thread. The application will continue to process things like button clicks on the main thread, but the NSTask will run on the background thread until it is complete.
  3. This is a temporary line of code that causes the current thread to sleep for 2 seconds, simulating a long-running task.
  4. Once the job has finished, re-enables the Build button, stops the spinner animation, and sets isRunning to false which disables the “Stop” button. This needs to be done in the main thread, as you are manipulating UI elements.

Now that you have a method that will run your task in a separate thread, you need to call it from somewhere in your app.

Still in TasksViewController.swift, add the following code to the end of startTask just after spinner.startAnimation(self):

runScript(arguments)

This calls runScript with the array of arguments you built in startTask.

Build and run your application and hit the Build button. You’ll notice that the Build button will become disabled, the Stop button will become enabled and the spinner will start animating:

busy2

While the spinner is animating, you’ll still be able to interact with the application. Try it yourself — for example, you should be able to type in the Target Name field while the spinner is active.

After two seconds have elapsed, the spinner will disappear, Stop will become disabled and Build will become enabled.

Note: If you have trouble interacting with the application before it’s done sleeping, increase the number of seconds in your call to sleepForTimeInterval.

Now that you’ve solved the UI responsiveness issues, you can finally implement your call to NSTask.

In TasksViewController.swift, find the lines in runScript that are bracketed by the comment //TESTING CODE. Replace that entire section of code inside the dispatch_async(taskQueue) block with the following:

//1.
guard let path = NSBundle.mainBundle().pathForResource("BuildScript",ofType:"command") else {
  print("Unable to locate BuildScript.command")
  return
}
 
//2.
self.buildTask = NSTask()
self.buildTask.launchPath = path
self.buildTask.arguments = arguments
 
//3.
self.buildTask.terminationHandler = {
 
  task in
  dispatch_async(dispatch_get_main_queue(), {
    self.buildButton.enabled = true
    self.spinner.stopAnimation(self)
    self.isRunning = false
  })
 
}
 
//TODO Output Handling
 
//4.
self.buildTask.launch()
 
//5.
self.buildTask.waitUntilExit()

The above code:

  1. Gets the path to a script named BuildScript.command, included in your application’s bundle. That script doesn’t exist right now — you’ll be adding it shortly.
  2. Creates a new NSTask object and assigns it to the TasksViewController‘s buildTask property. The launchPath property is the path to the executable you want to run. Assigns the BuildScript.command‘s path to the NSTask‘s launchPath, then assigns the arguments that were passed to runScript:to NSTask‘s arguments property. NSTask will pass the arguments to the executable, as though you had typed them into terminal.
  3. NSTask has a terminationHandler property that contains a block which is executed when the task is finished. This updates the UI to reflect that finished status as you did before.
  4. In order to run the task and execute the script, calls launch on the NSTask object. There are also methods to terminate, interrupt, suspend or resume an NSTask.
  5. Calls waitUntilExit, which tells the NSTask object to block any further activity on the current thread until the task is complete. Remember, this code is running on a background thread. Your UI, which is running on the main thread, will still respond to user input.

Build and run your project; you won’t notice that anything looks different, but hit the Build button and check the output console. You should see an error like the following:

Unable to locate BuildScript.command

This is the log from the guard statement at the start of the code you just added. Since you haven’t added the script yet, the guard is triggered.

Looks like it’s time to write that script! :]

Writing a Build Shell Script

In Xcode, choose File\New\File… and select the Other category under OS X. Choose Shell Script and hit Next:

script1

Name the file BuildScript.command. Before you hit Create, be sure TasksProject is selected under Targets, as shown below:

target_choice

Open BuildScript.command and add the following commands at the end of the file:

echo "*********************************"
echo "Build Started"
echo "*********************************"
 
echo "*********************************"
echo "Beginning Build Process"
echo "*********************************"
 
xcodebuild -project "${1}" -target "${2}" -sdk iphoneos -verbose CONFIGURATION_BUILD_DIR="${3}"
 
echo "*********************************"
echo "Creating IPA"
echo "*********************************"
 
/usr/bin/xcrun -verbose -sdk iphoneos PackageApplication -v "${3}/${4}.app" -o "${5}/app.ipa"

This is the entire build script that your NSTask calls.

The echo commands that you see throughout your script will send whatever text is passed to them to standard output, which you capture as part of the return values from your NSTask object and display in your outputText field. echo statments are handy statements to let you know what your script is doing, since many commands don’t provide much, if any, output when run from the command line.

You’ll notice that besides all of the echo commands, there are two other commands: xcodebuild, and xcrun.

xcodebuild builds your application, creates an .app file, and places it in the subdirectory /build. Recall that you created an argument that references this directory way back in startTask, since you needed a place for the intermediate build files to live during the build and packaging process.

xcrun runs the developer tools from the command line. Here you use it to call PackageApplication, which packages the .app file into an .ipa file. By setting the verbose flag, you’ll get a lot of details in the standard output, which you’ll be able to view in your outputText field.

In both the xcodebuild and xcrun commands, you’ll notice that all of the arguments are written “${1}” instead of $1. This is because the paths to your projects may contain spaces. To handle that condition, you must wrap your file paths in quotes in order to get the right location. By putting the paths in quotes and curly braces, the script will properly parse the full path, spaces and all.

What about the other parts of the script, the parts that Xcode automatically added for you? What do they mean?

The first line of the script looks like this:

#!/bin/sh

Although it looks like a comment since it’s prefixed with #, this line tells the operating system to use a specific shell when executing the remainder of the script. It’s called a shebang. The shell is the interpreter that runs your commands, either in script files or from a command line interface.

There are many different shells available, but most of them adhere to some variation of either Bourne shell syntax or C shell syntax. Your script indicates that it should use sh, which is one of the shells included with OS X.

If you wanted to specify another shell to execute your script, like bash, you would change the first line to contain the full path to the appropriate shell executable, like so:

#!/bin/bash

In scripts, any argument you pass in is accessed by a $ and a number. $0 represents the name of the program you called, with all arguments after that referenced by $1, $2 and so forth.

Note: Shell scripts have been around for about as long as computers, so you’ll find more information than you’ll ever want to know about them on the Internet. For a simple (and relevant) place to start, check out Apple’s Shell Scripting Primer.

Now you’re ready to start calling your script from NSTask, right?

Not quite. At this point, your script file doesn’t have execute permissions. That is, you can read and write the file, but you can’t execute it.

This means if you build and run right now, your app will crash when you hit the Build button. Try it if you like. It’s not a big deal while developing, and you should see the exception “launch path not accessible” in your Xcode console.

To make it executable, navigate to your project directory in Terminal. Terminal defaults to your Home directory, so if your project is in your Documents directory, you would type the command:

cd Documents/TasksProject

If your project is in another directory besides “Documents/TasksProject”, you’ll need to enter the correct path to your project folder. To do this quickly, click and drag your project folder from the Finder into Terminal. The path to your project will magically appear in the Terminal window! Now simply move your cursor to the front of that path, type cd followed by a space, and hit enter.

To make sure you’re in the right place, type the following command into Terminal:

ls

Check that BuildScript.command in the file listing produced. If you’re not in the right place, check that you’ve correctly entered your project directory in Terminal.

Once you’re assured that you’re in the correct directory, type the following command into Terminal:

chmod +x BuildScript.command

The chmod command changes the permissions of the script to allow it to be executed by your NSTask object. If you try to run your application without these permissions in place, you’d see the same “Launch path not accessible” error as before. You only need to do this once for each new script that you add to your project.

Note: Using scripts like this is simple if you are developing for yourself or shipping your app outside the Mac App Store (MAS), however when developing for the MAS the sandbox rules that apply to your app are inherited by your scripts and you’ll need to use more complex techniques to use command line programs. These techniques are beyond the scope of this tutorial. See the links at the end for more details.

Clean and run your project; the “clean” is necessary as Xcode won’t pick up on the file’s permissions change, and therefore won’t copy it into the build repository. Once the application opens up, type in the target name of your test app, ensure the “Project Location” and “Build Repository” values are set correctly, and finally hit Build.

When the spinner disappears, you should have a new .ipa file in your desired location. Success!

Using Outputs

Okay, you’re pretty well versed in passing arguments to command line programs, but what about dealing with the output of these command line programs?

To see this in action, type the following command into Terminal and hit Enter:

date

You should see a message produced that looks something like this:

Fri 19 Feb 2016 17:48:15 GMT

date tells you the current date and time. Although it isn’t immediately obvious, the results were sent back to you on a channel called standard output.

Processes generally have three default channels for input and output:

  • standard input, which accepts input from the caller;
  • standard output, which sends output from the process back to the caller; and
  • standard error, which sends errors from the process back to the caller.

Pro tip: you’ll see these commonly abbreviated as stdin, stdout, and stderr.

There is also a pipe that allows you to redirect the output of one process into the input of another process. You’ll be creating a pipe to let your application see the standard output from the process that NSTask runs.

To see a pipe in action, ensure the volume is turned up on your computer, then type the following command in Terminal:

date | say

Hit enter and you should hear your computer telling you what time it is.

Note: The pipe character “|” on your keyboard is usually located on the forward slash \ key, just above the enter/return key.

Here’s what just happened: you created a pipe that takes the standard output of date and redirects it into the standard input of say. You can also provide options to the commands that communicate with pipes, so if you would like to hear the date with an Australian accent, type the following command instead:

date | say -v karen

Its the date, mate!

You can construct some rather long chains of commands using pipes, redirecting the stdout from one command into the stdin of another. Once you get comfortable using stdin, stdout, and pipe redirects, you can do some really complicated things from the command line using tools like pipes.

Now it’s time to implement a pipe in your app.

Open TasksViewController.swift and replace the comment that reads // TODO: Output Handling in runScript with the following code:

self.captureStandardOutputAndRouteToTextView(self.buildTask)

Next, add this function to TasksViewController.swift:

func captureStandardOutputAndRouteToTextView(task:NSTask) {
 
  //1.
  outputPipe = NSPipe()
  task.standardOutput = outputPipe
 
  //2.
  outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
 
  //3.
  NSNotificationCenter.defaultCenter().addObserverForName(NSFileHandleDataAvailableNotification, object: outputPipe.fileHandleForReading , queue: nil) {
 
    notification in
 
    //4.
    let output = self.outputPipe.fileHandleForReading.availableData
    let outputString = String(data: output, encoding: NSUTF8StringEncoding) ?? ""
 
    //5.
    dispatch_async(dispatch_get_main_queue(), {
      let previousOutput = self.outputText.string ?? ""
      let nextOutput = previousOutput + "\n" + outputString
      self.outputText.string = nextOutput
 
      let range = NSRange(location:nextOutput.characters.count,length:0)
      self.outputText.scrollRangeToVisible(range)
 
    })
 
    //6.
    self.outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
  }
}

This function collects the output from the external process and adds it to the GUI’s outputText field. It works as follows:

  1. Creates an NSPipe and attaches it to buildTask‘s standard output. NSPipe is a class representing the same kind of pipe that you created in Terminal. Anything that is written to buildTask‘s stdout will be provided to this NSPipe object.
  2. NSPipe has two properties: fileHandleForReading and fileHandleForWriting. These are NSFileHandle objects. Covering NSFileHandle is beyond the scope of this tutorial, but the fileHandleForReading is used to read the data in the pipe. You call waitForDataInBackgroundAndNotify on it to use a separate background thread to check for available data.
  3. Whenever data is available, waitForDataInBackgroundAndNotify notifies you by calling the block of code you register with NSNotificationCenter to handle NSFileHandleDataAvailableNotification.
  4. Inside your notification handler, gets the data as an NSData object and converts it to a string.
  5. On the main thread, appends the string from the previous step to the end of the text in outputText and scrolls the text area so that the user can see the latest output as it arrives. This must be on the main thread, like all UI and user interaction.
  6. Finally, repeats the call to wait for data in the background. This creates a loop that will continually wait for available data, process that data, wait for available data, and so on.

Build and run your application again; make sure the Project Location and Build Repository fields are set correctly, type in your target’s name and click Build.

You should see the output from the building process in your outputText field:

last_view

Stopping an NSTask

What happens if you start a build, then change your mind? What if it’s taking too long, or something else seems to have gone wrong and it’s just hanging there, making no progress? These are times when you’ll want to be able to stop your background task. Fortunately, this is pretty easy to do.

In TasksViewController.swift, add the following code to stopTask:

if isRunning {
  buildTask.terminate()
}

The code above simply checks if the NSTask is running, and if so, calls its terminate method. This will stop the NSTask in its tracks.

Build and run your app, ensure all fields are configured correctly and hit the Build button. Then hit the Stop button before the build is complete. You’ll see that everything stops and no new .ipa file is created in your output directory.

Where to Go From Here?

Here is the finished NSTask example project from the above tutorial.

Congratulations, you’ve begun the process of becoming an NSTask ninja!

In one short tutorial, you’ve learned:

  • How to create NSTasks with arguments and output pipes; and
  • How to create a shell script and call it from your app!

To learn more about NSTask, check out Apple’s official NSTask Class Reference.

To learn about using command line programs in a sandboxed app see Daemons and Services Programming Guide and XPC Services API Reference.

This tutorial only dealt with working with stdout with NSTask, but you can use stdin and stderr as well! To practice your new skills, try working with these.

I hope you enjoyed this NSTask tutorial and that you find it useful in your future Mac OS X apps. If you have any questions or comments, please join the forum discussion below!

The post NSTask Tutorial for OS X appeared first on Ray Wenderlich.


Video Tutorial: Intermediate iOS Animation Part 10: Stroke Animations

Video Tutorial: Intermediate iOS Animation Part 11: Conclusion

Announcing the RWDevCon 2016 Vault!

$
0
0

RWDevCon 2016 Vault

This year we had our second annual tutorial conference, RWDevCon 2016, and it was a huge hit.

Attendees called the conference “a great mix of conference and training”, “well organized and executed”, and my personal favorite – “better than WWDC.” :]

Our team of speakers put so much time, effort, and care into each of our tutorials, and it seemed a shame that they would never be seen again. Plus, we heard from so many attendees that they had trouble deciding which tutorial to attend, since they often wanted to attend two at once – or all three.

So this year, for the first time ever, we are providing a way for you to enjoy the RWDevCon experience virtually – through the RWDevCon 2016 Vault!

Keep reading to find out what the RWDevCon 2016 Vault is, how to get the launch discount, and how to enter for a chance to win a free copy!

What is the RWDevCon 2016 Vault?

The RWDevCon 2016 vault consists of three things.

1) Over 24 hours of hands-on video tutorials from beginning to advanced:

vault_01

2) Over 700 MB of sample projects – including iOS, tvOS, and watchOS projects, fully updated for Xcode 7.3:

vault_02

3) A 570 page conference book chock-full of demo and lab materials!

vault_03

The RWDevCon 2016 Vault includes tutorials on the following topics:

  • UIStackView
  • iOS Design Patterns in Swift
  • Programming in a Swift (rather than Objective-C) Style
  • Custom Controls
  • Advanced LLDB and Console Debugging
  • Introduction to Protocol-Oriented Programming
  • Swift and C Interoperability
  • App Architecture
  • MVVM in Practice
  • Architecting for Multiple Platforms
  • …and much more – 24 hands-on tutorials in total!

The RWDevCon Vault is a great way to level-up your iOS skills, and experience a taste of what RWDevCon is all about: hands-on experience, team coordination, inspiration, and friendship.

RWDevCon 2016 Vault Week and Giveaway

To celebrate the launch of the RWDevCon 2016 Vault, each day this week we’re going to do something special:

Vault-week-calendar2

  • Today we’ll release the conference’s keynote speech – an inspirational speech about motivation titled “Feed Your Fire”.
  • On Tuesday-Thursday we’ll release 3 tutorials from the conference for free. This will get give you a chance to check them out and see if you like them – we’re confident you will! :]
  • On Friday we’ll round out our week of celebration with a special giveaway. 3 lucky winners will win access to the RWDevCon 2016 Vault (or a book of your choice if you already attended RWDevCon 2016).

To enter into this giveaway, simply leave a comment on this post. We’ll choose winners randomly and announce the results on Friday.

Where To Go From Here?

As mentioned, the RWDevCon Vault is available today.

  • If you attended RWDevCon 2016, you get free access. Check your email for a code for a free copy, or if you didn’t get it, please contact us.
  • If you weren’t at RWDevCon 2016, there’s some good news! To celebrate the launch week, we are offering a massive 50% off discount until this Friday.

If you want the special discount, be sure to order now.

The RWDevCon team and I hope you enjoy the RWDevCon 2016 Vault, and hope that you enjoy the hands-on tutorials!

The post Announcing the RWDevCon 2016 Vault! appeared first on Ray Wenderlich.

RWDevCon 2016 Inspiration Talk – Feed Your Fire by Ray Wenderlich

$
0
0

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

We recorded these talks so that you can enjoy them, even if you didn’t get to attend the conference. Here’s our first talk – titled Feed Your Fire, by myself – I hope you enjoy!

Note from Ray: Did you enjoy this inspiration talk? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2017 tickets go on sale, or check out our vault of tutorial videos!

Transcript

As a computer geek, I spend most of my time indoors. On a typical day I’m only in one of three spots: sleeping in bed, in front of the computer, or stuffing my face in front of the fridge.

3Spots

I’m ashamed to admit it, but sometimes I’ve gone an entire week without leaving the house at all!

But last summer, I decided I’d had enough of the indoors – it was time to experience the great outdoors. So for the first time ever, I went on a camping trip. Just me, a tent, and the woods.

If you had seen it, you would have laughed at all struggles I had trying to get a basic campfire going:

  • How many pieces of wood do I need?
  • How do I lay out the logs?
  • Why won’t this darn thing light?
  • I know, I’ll just look up how to do this on the Internet… oh wait, no cell phone reception.

But I kept at it, and after 5-6 failed attempts, I was finally roasting hot dogs in front of a roaring campfire. This may not seem like a big achievement for those of you who are outdoor folks, but for my geeky indoor self it was a big deal – and let me tell you, those were the best hot dogs I’ve ever tasted.

A Fireside Reflection

As I was spending this time learning how to make a campfire, I had a lot of time afterwards to sit in front of the fire, watch the embers, and drink a beer.

As you do when you’re in front of a campfire, you start replaying the story of your life, and all of its highs and lows.

Campfire

And as I did this, I realized that all the highs in my life were when I was really motivated about what I was doing, and all the lows in my life were when I was unmotivated.

So today, I invite you to sit back and listen to the campfire story that consumed my thoughts that night as I roasted hot dogs and drank beer.

The Case of the Mysteriously Missing Motivation

CaseOfTheMysteriouslyMissingMotivation

The story begins about 6 years ago, when the iPhone SDK was first released, and there was this feeling of excitement in the air. Who here remembers that time?

Now I want you to think – how would people describe you back then, if they had just a single word? Maybe it would be optimistic. Maybe it would be obsessive. Maybe it would be passionate.

Well, the single word my family and friends would’ve used to describe me was: cheap.

Being Cheap

At this time, I had just quit my job to become an iOS developer, and my apps weren’t making any money yet, so I was trying to last as long as I could on my savings. I would do anything to save money.

Cheap

The Italian Sausage

One time, I was at a barbeque at my grandfather’s house, and he was making Italian Sausage, but unfortunately he lost track of time and ended up burning the entire batch to a crisp. I’m talking caked in soot, black all the way around, you could smell the smoke – you could’ve called it Italian Charcoal.

He came to the family and said “I’m really sorry, but I burnt all the sausages, and I’m going to have to throw them all out.” But I said “Wait! Don’t throw them out – I’ll take them!”

My grandfather said, “What are you talking about, you can’t eat these – they’re ruined! Watch this!” he said, and he took a piece and gave it to Peanut, his dog. Peanut was a poodle who was notorious for eating anything, but you know what Peanut did? Peanut took one look at that burned charcoal sausage, sniffed, and turned up his nose.

But despite my family’s horror, I insisted on taking those charred sausages home anyway, and for me it was an epic success – an entire month of cheap eats.

The Haircut Trim

I even gave my haircut budget a trim. “Why pay for a haircut when you can just shave it all off?”, I thought.

Now, some people look great without hair, like Bruce Willis, or Charlie Fulton.

However, I am not one of those people. Who here has seen Lord of the Rings?

I looked kinda like Gollum, hording the money I had saved and saying “my precious”.

You can say I had a lot of motivation for being cheap. But there was one big area I didn’t have a lot of motivation with – a project I was working on that I call the Neverending App.

The Neverending App

Have any of you ever had a project at work that felt like it was neverending? One where every time you take a step forward, the finish line is so far away that it’s like you haven’t moved at all?

Well, there was this app I was working on that felt just like this – it was called Battle Map 2, a map making tool for geeky people like me who like to play Dungeons & Dragons. The project started out great – I was working with a nice clean slate and implementing some cool technical challenges like networking and custom OpenGL code – but 6 months later, I’m still working on the app, and I have a long laundry list of easy but boring features left to do.

Every day, it seemed like I barely made a dent in what needed this list, and every day I’d complain to Vicki and say “Aargh, I feel like this app is never going to get done!”

TheNeverendingApp

Since this app was neverending, I started to lose my motivation and soon I didn’t feel like working on the project at all. Instead, I would let myself get distracted by side projects that seemed smaller and easier, and I would work on them instead. I would also do stupid things like stay up too late playing video games, and then I would sleep in too much the next day, as a subconscious way of avoiding working on the app.

Even worse, this compounded upon itself because the longer I’d go without making progress, the more depressed I’d get, and the less I’d feel like working. I started having this pit of sadness in my stomach and I started thinking I was a huge slacker, that I was worthless, and that I’d never be able to make it as an indie iOS developer. It was a really low period in my life, and I felt like I had hit rock bottom.

The Case of the Mysteriously Missing Motivation

CaseOfTheMysteriouslyMissingMotivation

The weird thing was, I knew that when I started as an indie iOS developer, I was so excited and so motivated. I knew this is what I wanted to do, and this is where I was meant to be. But now, I felt like that initial spark of motivation had disappeared, and was nowhere to be found. I kept hoping I’d wake up one day and that my motivation would magically pop up again, but it never did. It was the case of the mysteriously missing motivation.

This was a pretty low period of my life – unmotivated, unproductive, and don’t forget – cheap.

However this experience of hitting rock bottom taught me something important. I couldn’t just sit around and wait for my mysteriously missing motivation to show up knocking on my door – because it never would. Unfortunately, your motivational fire isn’t something that just spontaneously combusts all by itself – you have to take control, and build it and nurture it, just like you feed a fire.

Feed Your Fire

Over the years, I’ve tried many different ways of feeding my motivational fire, and I’ve found 3 techniques that have always worked for me that I’d like to share with you today. Without these, I never would have accomplished any of my goals, and would probably still be waiting around for my motivation to come knocking.

Start Small

StartSmall

The first thing technique that helped me was to Start Small.

Sometimes, the reason why we avoid working on a project is that it seems too huge or overwhelming. The trick is, rather than thinking about how big the project is, instead think about the smallest possible next step to get started.

This technique of starting small is like giving your motivational fire some kindling – a nice small task is easy to burn, and gets the rest of the fire going.

Here’s how it looks in practice: when I didn’t feel like working, I would say, “OK – all you have to do is just work on this for one hour”, or “just fix this one bug.” Or on days that were really bad, I’d say, “All you have to do is open Xcode.”

The cool thing is most of the time when I did this, I ended up working far more than the initial small task I promised myself, because I got “in the zone”. It turns out the hardest part of working on something is overcoming your initial resistance, so by making the initial step small, it makes that resistance easier to overcome.

Get External Motivation

ExternalMotivation

The second thing technique that helped me was to get External Motivation.

When I was working on this app, I was an indie iOS developer, working all by myself, literally living in my mother-in-law’s basement. I had no co-workers, I had no deadlines, and I had no boss saying “Yeah if you could finish the app, that’d be great”.

At first I thought this was pretty awesome. However, in practice this caused major issues with my motivation. For example, I found that since no-one was counting on me to deliver features at any particular time, it made it easier to avoid working on the app entirely, or to work at a slow pace.

When you know that somebody is counting on you to get a project done, and you don’t want to let them down, that’s what I call external motivation. I’ve found that often it’s a lot harder to let somebody else down than it is to let your own self down.

That’s kinda terrible if you think about it, but it’s often true – and that’s why external motivation is so powerful. In fact, I believe external motivation is so strong that it’s like firewood – it’s the core fuel that you need to going through the duration of a long project. You can’t really have a fire without firewood.

Luckily, this is one of the easiest parts of motivation to control. To build in some external motivation for your project, you just need to find someone who will hold you accountable. Ask a friend or relative to watch over you, or publicly declare what you are doing and share progress so you know the world is watching.

Stickk

In my case, I found this website called stickk.com (with two K’s) where you can set up a goal – say working on Battle Map 2 each day, and set up a stake – say $20 – and finally you set up an impartial referee who will check whether you’ve accomplished your goal or not. I picked Vicki’s twin sister, Andrea, to be my referree. If I accomplished my goal, I got my $20 back, otherwise Andrea got it.

Every day Andrea would check in with me, just hoping to hear that she’d be getting $20.

Gloat

And then, she’d use the money she won to buy movie tickets, glasses of wine, dinners out at restaurants, and send me gloating pictures!

Well, you guys already know how cheap I am, so this worked great with me :] But all jokes aside it wasn’t really the money that helped me here – it was knowing that somebody was checking up on me, and I’d have to explain to them if I ended up slacking off. Having some external motivation was some much-needed firewood to keep the fire burning.

Do Your Most Important Task First

MostImportantTask

The third technique that helped me was to do your Most Important Task first. This is one of the most useful tricks I’ve learned over the years – so powerful that I think of it like throwing gasoline on a fire. It guarantees dramatic results that are extremely satisfying and will jump-start your motivational fire every time you do it.

Every day, figure out what your most important task is for that day – say working on Battle Map 2 for 4 hours – and then do that first thing. And I mean first thing – especially before email or checking Twitter, which can be horrible time sinks.

That way, after you finish your most important task for that day, you can rest assured that you’ve made progress toward your #1 goal. If you make progress on something every day, it will eventually get done. It’s a mathematical certainty.

Out of the three tricks we’ve covered so far, this is the one that really pushed me over the edge and got me going. By working on the app for a few hours a day before anything else, I started seeing some noticeable progreess, I started to gain some momentum, I started feeling good again, soon I started feeling excited, and before I had completed the project and launched the app.

An Expert at Being Demotivated

These is just one of the many times in life that I’ve struggled with motivation – perhaps you can say I’m an expert at being demotivated.

But the side benefit is, I’ve learned three ways to feed your fire so it keeps burning strong:

  1. Start Small, which is like using kindling to start a fire.
  2. Get External Motivation, which is like the core component of a fire – firewood.
  3. Do your Most Important Task first, which is like throwing gasoline while laughing like a maniac.

RWDevCon and You

RWDevCon

My hope is that this weekend at RWDevCon, some our team’s passion for iOS, tvOS, and watchOS development spreads to you, and that we help you gain motivation to take what you learn here and create something incredible with it.

But how is that gonna work? I’ve been at too many conferences where all I did was fill up a document in Evernote and never look at it again. While I’m at a conference, my motivational fire is going strong – but when I go home, it often fizzles out.

The key here is to step up and take control your motivation. For example:

  • Start with something small when you get home – like take one thing you learn here and integrate it into one of your apps.
  • Find a friend to make sure do this – like a co-worker, a supervisor, or even someone you meet here at RWDevCon.
  • Consider making this your Most Important Task for a certain day, that you do before anything else.

At the end of this conference, you’ll have a blazing spark of motivation – and if you feed your fire with these techniques, it’ll keep burning brighter and brighter even after you return home.

Where To Go From Here?

Remember, that everybody has struggles with motivation. But don’t fall into the trap I did, of thinking of motivation as this mysterious force that comes and goes on its own, and that you have to sit around and wait to come knocking. Because that knock may never come.

Instead, remember that just like building a fire, you have control, and you need to feed and nurture your motivation.

Campfire

If you do this, one day you’ll be able to sit back in front of a roaring campfire, replay the story of your life, and think of all the highs that you’ve accomplished – with a big smile, and a cold beer. Thank you.

Note from Ray: Did you enjoy this inspiration talk? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2017 tickets go on sale, or check out our vault of tutorial videos!

The post RWDevCon 2016 Inspiration Talk – Feed Your Fire by Ray Wenderlich appeared first on Ray Wenderlich.

ReactiveCocoa vs RxSwift

$
0
0

Reactive Cocoa vs. RxSwift

Functional Reactive Programming is an increasingly popular programming methodology for Swift developers. It can make complex asynchronous code easier to write and understand.

In this article, you’ll compare the two most popular libraries for Functional Reactive Programming: RxSwift vs. ReactiveCocoa.

You’ll start with a brief review of what Functional Reactive Programming is, and then you’ll see a detailed comparison of the two frameworks. By the end, you’ll be able to decide which framework is right for you!

Let’s get reactive!

What Is Functional Reactive Programming?

Note: If you’re already familiar with the concept of Functional Reactive Programming, skip ahead to the next section, titled “ReactiveCocoa vs RxSwift”.

Even before Swift was announced, Functional Reactive Programming (FRP) has seen
a tremendous rise in popularity in recent years versus Objected Oriented Programming. From Haskell to Go to Javascript, you will find FRP-inspired implementation. Why is this? What’s so special about FRP? Perhaps most importantly, how can you make use of this paradigm in Swift?

Functional Reactive Programming is a programming paradigm that was created by Conal Elliott. His definition has very specific semantics and you are welcome to explore them here. For a more loose/simple definition, Functional Reactive Programming is a combination of two other concepts:

  1. Reactive Programming, which focuses on asynchronous data streams, which you can listen to and react accordingly. To learn more, check out this great introduction.
  2. Functional Programming, which emphasizes calculations via mathematical-style functions, immutability and expressiveness, and minimizes the use of variables and state. To learn more, check out our Swift functional programming tutorial.

Note: André Staltz explores the difference between the original FRP formulation and the practical approach in his article “Why I cannot say FRP but I just did”.

A Simple Example

The easiest way to understand this is through an example. Consider an app that wants to track the user’s location and alert her when she is near a coffee shop.

If you were to program this in an FRP way:

  1. You would construct an object that emits a stream of location events that you can react to.
  2. You would then filter the emitted location events to see which ones are near a coffee shop, and send alerts for those that match.

Here’s what this code might look like in ReactiveCocoa:

locationProducer // 1
  .filter(ifLocationNearCoffeeShops) // 2
  .startWithNext {[weak self] location in // 3
    self?.alertUser(location)
}

Let’s review this section by section:

  1. locationProducer emits an event each time the location changes. Note that in ReactiveCocoa this is called a “signal”, and in RxSwift it’s called a “sequence”.
  2. You then use functional programming techniques to respond to the location updates. The filter method performs exactly the same function as it would on an array, passing each value to the function ifLocationNearCoffeeShops. If the function returns true, the event is allowed to proceed to the next step.
  3. Finally, startWithNext forms a subscription to this (filtered) signal, with the code in the closure expression executed each time an event arrives.

The code above looks very similar to the code you might use for transforming an array of values. But here’s the clever bit … this code is executed asynchronously; the filter function and the closure expression are invoked ‘on demand’ as location events occur.

The syntax might feel a bit strange, but hopefully the underlying intent of this code should be clear. That’s the beauty of functional programming, and why it’s such a natural fit with the whole concept of values over time: it’s declarative. It’s shows you what’s happening, instead of the detail of how it’s being done.

Note: If you want to learn more about the ReactiveCocoa syntax, have a look at a couple of examples I created on GitHub.

Transforming Events

In the location example, you only started to observe the stream, without really doing much with the events aside from filtering the locations for those near coffee shops.

Another fundamental piece in the FRP paradigm is the ability to combine and transform these events into something meaningful. For that, you make use of (but are not limited to) higher order functions.

As expected, you will find the usual suspects you learned about in our Swift functional programming tutorial: map, filter, reduce, combine, and zip.

Let’s modify the location example to skip repeated locations and transform the incoming location (which is a CLLocation) into a user-friendly message.

locationProducer
  .skipRepeats() // 1
  .filter(ifLocationNearCoffeeShops)
  .map(toHumanReadableLocation) // 2
  .startWithNext {[weak self] readableLocation in
    self?.alertUser(readableLocation)
}

Let’s look at the two new lines added here:

  1. The first step applies the skipRepeats operations to the events emitted by the locationProducer signal. This is an operation that doesn’t have an array analogue; it is ReactiveCocoa specific. The function it performs is pretty obvious: repeated events (based on equality) are filtered out.
  2. After the filter function is performed, map is used to transform the event data from one type to another, perhaps from a CLLocation to a String.

By now, you should be starting to see some of the FRP’s benefits:

  • It’s simple, yet powerful.
  • Its declarative approach makes code more understandable.
  • Complex flows become easier to manage and represent.

please tell me more

ReactiveCocoa vs RxSwift

Now that you have a better understanding of what FRP is and how it can help make your complex asynchronous flows easier to manage, let’s look at the two most popular FRP frameworks – ReactiveCocoa and RxSwift – and why you might choose one over the other.

Before diving into the details, let’s take a brief look at the history of each framework.

ReactiveCocoa

The ReactiveCocoa framework started life at GitHub. While working on the GitHub Mac client, the developers found themselves struggling with managing their application data-flows. They found inspiration in Microsoft’s ReactiveExtensions, an FRP framework for C#, and created their own Objective-C implementation.

Swift was announced while the team was working on their v2.0 release. They realised that Swift’s functional nature was highly complementary to ReactiveCocoa, so they started work immediately on a Swift implementation, which became v3.0. The version 3.0 syntax is deeply functional, making use of currying and pipe-forward.

Swift 2.0 introduced protocol-oriented programming, which resulted in another significant ReactiveCocoa API change, with the version 4.0 release dropping the pipe-forward operator in favour of protocol extensions.

ReactiveCocoa is a tremendously popular library with more than 13,000 stars on GitHub at the time of writing.

RxSwift

Microsoft’s ReactiveExtensions inspired many other frameworks that brought FRP concepts to JavaScript, Java, Scala and many other languages. This eventually lead to the formation of ReactiveX, a group which created a common API for FRP implementations; this allowed the various framework authors to work together. As a result, a developer familiar with Scala’s RxScala should find it relatively easy to transition to the Java equivalent, RxJava.

RxSwift is a relatively recent addition to ReactiveX, and thus currently lacks the popularity of ReactiveCocoa (about 4,000 stars on GitHub at the time of writing). However, the fact that RxSwift is part of ReactiveX will no doubt contribute to its popularity and longevity.

It’s interesting to note that both RxSwift and ReactiveCocoa share a common ancestor in ReactiveExtensions!

RxSwift vs. ReactiveCocoa

It’s time to dig into the details. RxSwift and ReactiveCocoa handle several aspects of FRP differently, so let’s take a look at a few of them.

Hot vs. Cold Signals

Imagine that you need to make a network request, parse the response and show it to the user:

let requestFlow = networkRequest.flatMap(parseResponse)
 
requestFlow.startWithNext {[weak self] result in
  self?.showResult(result)
}

The network request will be initiated when you subscribe to the signal (when you use startWithNext). These signals are called cold, because, as you might have guessed, they are in a “frozen” state until you actually subscribe to them.

On the other hand are hot signals. When you subscribe to one, it might already have started, so you might be observing the third or fourth event. The canonical example would be tapping on a keyboard. It doesn’t really make sense to “start” the tapping, like it makes for a server request.

Let’s recap:

  • A cold signal is a piece of work you start when you subscribe to it. Each new subscriber starts that work. Subscribing to the requestFlow three times means making three network requests.
  • A hot signal can already be sending events. New subscribers don’t start it. Normally UI interactions are hot signals.

ReactiveCocoa provides types for both hot and cold signals: Signal<T, E> and SignalProducer<T, E>, respectively. RxSwift, however, has a single type called Observable<T> which caters to both.

Does having different types to represent hot and cold signals matter?

Personally, I find that knowing the signal’s semantics is important, because it better describes how it is used in a specific context. When dealing with complex systems, that can make a big difference.

Independently of having different types or not, knowing about hot and cold signals is extremely important. As André Staltz puts it:

“If you ignore this, it will come back and bite you brutally. You have been warned.”

If you assume you are dealing with a hot signal and it turns out to be a cold one, you will be starting side effects for each new subscriber. This can have tremendous effects in your application. A common example, would be three or four entities in your app wanting to observe a network request and for each new subscription a different request would be started.

+1 point for ReactiveCocoa!

Evil toddler

Error Handling

Before talking about error handling, let’s briefly recap the nature of the events that are dispatched in RxSwift and ReactiveCocoa. In both frameworks, there are three main events:

  1. Next<T>: This event is sent every time a new value (of type T) is pushed into the stream of events. In the locator example, the T would be a CLLocation.
  2. Completed: Indicates that the stream of events has ended. After this event, no Next<T> or Error<E> is sent.
  3. Error: Indicates an error. In the server request example, this event would be sent if you had a server error. The E represents a type that conforms with the ErrorType protocol. After this event, no Next or Completed is sent.

You might have noticed in the section about hot and cold signals that ReactiveCocoa’s Signal<T, E> and SignalProducer<T, E> have two parameterized types, while RxSwift’s Observable<T> has one. The second type (E) refers to a type that complies with the ErrorType protocol. In RxSwift the type is omitted and instead treated internally as a type that complies with ErrorType protocol.

So what does this all mean?

In practical terms, it means that errors can be emitted in number of different ways with RxSwift:

create { observer in
  observer.onError(NSError.init(domain: "NetworkServer", code: 1, userInfo: nil))
}

The above creates a signal (or, in RxSwift terminology, an observable sequence) and immediately emits an error.

Here’s an alternative:

create { observer in
  observer.onError(MyDomainSpecificError.NetworkServer)
}

Since an Observable only enforces that the error must be a type that complies with ErrorType protocol, you can pretty much send anything you want. But it can get a bit awkward, as in the following case:

enum MyDomanSpecificError: ErrorType {
  case NetworkServer
  case Parser
  case Persistence
}
 
func handleError(error: MyDomanSpecificError) {
  // Show alert with the error
}
 
observable.subscribeError {[weak self] error in
  self?.handleError(error)
 }

This won’t work, because the function handleError is expecting a MyDomainSpecificError instead of an ErrorType. You are forced to do two things:

  1. Try to cast the error into a MyDomanSpecificError.
  2. Handle the case where the error is not cast-able to a MyDomanSpecificError.

The first point is easily fixed with an as?, but the second is harder to address. A potential solution is to introduce an Unknown case:

enum MyDomanSpecificError: ErrorType {
  case NetworkServer
  case Parser
  case Persistence
  case Unknown
}
 
observable.subscribeError {[weak self] error in
  self?.handleError(error as? MyDomanSpecificError ?? .Unknown)
}

In ReactiveCocoa, since you “fix” the type when you create a Signal<T, E> or a SignalProducer<T, E>, the compiler will complain if you try to send something else. Bottom line: in ReactiveCocoa, the compiler won’t allow you to send a different error than the one you are expecting.

Another point for ReactiveCocoa!

UI Bindings

The standard iOS APIs, such as UIKit, do not speak in an FRP language. In order to use either RxSwift or ReactiveCocoa you have to bridge these APIs, for example converting taps (which are encoded using target-action) into signals or observables.

As you can imagine, this is a lot of effort, so both ReactiveCocoa and RxSwift provide a number of bridges and bindings out of the box.

ReactiveCocoa brings a lot of baggage from its Objective-C days. You can find a a lot of work already done, which has been bridged to work with Swift. These include UI Binds, and other operators that have not been translated to Swift. This is, of course, slightly weird; you are dealing with types that are not part of the Swift API (like RACSignal), which forces the user to convert Objective-C types to Swift ones (e.g. with the use of toSignalProducer() method).

Not only that, but I feel I’ve spent more time looking at the source code than the docs, which have been slowly falling behind the times. It’s important to notice, though, that the documentation from a theoretical/mindset point of view is outstanding, but not so much from a usage point of view.

To compensate for this, you can find dozens of ReactiveCocoa tutorials.

On the other hand, RxSwift bindings are a joy to use! Not only do you have a vast catalogue, but there are also a ton of examples, along with more complete documentation. For some people, this is enough reason to pick RxSwift over ReactiveCocoa.

+1 point for RxSwift!

Happy-Crying-Face-Meme-11

Community

ReactiveCocoa has been around far longer than RxSwift. There are numerous people who could carry on with the work, a fair amount of tutorials about it online, and the Reactive Cocoa tag at StackOverflow is a good source for help.

ReactiveCocoa has a Slack group, but it’s small at only 209 people, so a lot of questions (by myself and others) go unanswered. In times of urgency, I am forced to PM ReactiveCocoa’s core members, and I assume others are doing the same. Still, you can most probably find a tutorial online to explain your particular problem.

RxSwift is newer, and at this time is is pretty much a one man show. It also has a Slack group, and it’s much larger at 961 members, and has more discussion volume. You can also always find someone to help you out with questions there.

Overall, right now both communities are great in different ways so in this category they are about even.

What Should You Pick?

As Ash Furrow said in “ReactiveCocoa vs RxSwift”:

“Listen, if you’re a beginner, it really doesn’t matter. Yes, of course there are technical differences, but they aren’t meaningful to newcomers. Try one framework, then try the other. See for yourself which one you prefer! Then you can figure out why you prefer it.”

I would advise doing the same. Only when you have enough experience will you appreciate the subtleties between them.

However, if you are in a position where you need to pick one and don’t have time to play with both, here’s my suggestion:

Pick ReactiveCocoa if:

  • You want to be able to better describe your system. Having different types to differentiate between hot and cold signals, along with a parameterized type for the error case, will do wonders for your system.
  • Want a battle tested framework, used by many people, in many projects.

Pick RxSwift if:

  • UI Binds are important for your project.
  • You are new to FRP and might need some hand-holding.
  • You already know RxJS or RxJava. Since they and RxSwift are all under the ReactiveX organization, once you know one, the others are just a matter of syntax.

Where to Go From Here?

Whether you choose RxSwift or ReactiveCocoa, you won’t regret it. Both are very capable frameworks that will help you to better describe your system.

It’s also important to mention that once you know RxSwift or ReactiveCocoa, jumping between one and the other will be a matter of hours. From my experience going ReactiveCocoa to RxSwift, as an exercise, the most troubling part was the error handling. Above all, the biggest mind shift is getting into FRP and not a particular implementation.

The following links should help you in your journey into Functional Reactive Programming, RxSwift and ReactiveCocoa:

I hope to see you use one of these great libraries in your future projects. If you have any comments or questions, please join the forum discussion below!

The post ReactiveCocoa vs RxSwift appeared first on Ray Wenderlich.

RWDevCon 2016 Session 103: Beginning UIStackView

$
0
0

We recently released the RWDevCon 2016 Vault, a collection of over 24+ hours of hands-on video tutorials, 700+ MB of sample projects, and a 570 page conference book.

To celebrate its launch, we’re releasing 3 videos from the vault for free so you can check them out and see if you like them.

Today’s video is an example from the beginning track – Beginning UIStackView. Enjoy!

 

Download demo resources

Note from Ray: Did you enjoy this tutorial? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2017 tickets go on sale, or check out our massive vault of tutorial videos!

The post RWDevCon 2016 Session 103: Beginning UIStackView appeared first on Ray Wenderlich.

RWDevCon 2016 Session 202: Programming in a Swift Style

$
0
0

We recently released the RWDevCon 2016 Vault, a collection of over 24+ hours of hands-on video tutorials, 700+ MB of sample projects, and a 570 page conference book.

To celebrate its launch, we’re releasing 3 videos from the vault for free so you can check them out and see if you like them.

Today’s video is an example from the intermediate track – Programming in a Swift Style. Enjoy!

 

Download demo resources

Note from Ray: Did you enjoy this tutorial? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2017 tickets go on sale, or check out our massive vault of tutorial videos!

The post RWDevCon 2016 Session 202: Programming in a Swift Style appeared first on Ray Wenderlich.


How to Make App Mockups With AppCooker

$
0
0

AppCooker feature image

Let’s face it – these days, clients expect mockups for their apps. Before you begin coding, they want to see onboarding and login flows, activity feeds, perhaps even a settings page – and visualize the flow between all these pages.

To do your job right, it really helps to have a good interactive mockup tool. In this tutorial, you’ll learn how to use one of these tools – AppCooker – to create beautiful interactive mockups right on your iPad.

AppCooker’s distinguishing feature is the use of widgets that mimic native UIKit objects. These widgets support commonly configured properties found in Xcode—for example, whether a table view is grouped. If you’re an iOS developer, you’ll feel right at home.

AppCooker feels like a simplified version of Interface Builder. So if you’re a designer who’s tried prototyping in Xcode’s storyboard but got tangled up with Auto Layout, give AppCooker a try. It might feel limited compared to other design tools, but these limitations help ensure your designs translate smoothly to the development phase. If it’s easy in AppCooker, it’s probably easy in Xcode.

Animated GIF demonstrating how complicated red arrows get with multiple screens.

Note: AppCooker is just one of many great interactive mockup tools, like Flinto, Principle and InVision, to name a few. For more ideas, check out our reviews of app mockup tools here and here.

Getting Started

To follow along with this tutorial, you’ll need to purchase AppCooker for the iPad, available for $29.99 as of this writing. Also download the Resources folder, which contains the images and icons you’ll need to complete the tutorial.

If you’ve bought the app, skip ahead to the “Sample Project Overview” section. But if for some reason you can’t – read the section below!

Can’t Buy the App?

If you don’t own an iPad, or you’re not quite sold on AppCooker, you can still download the free AppTaster companion app, which works on both iPad and iPhone.

With AppTaster, you can view these demo files to get a taste of what you can do with AppCooker.

After installing AppTaster, just email the .appTaster files to yourself. When you open the attachments, choose the Copy to AppTaster action extension.

Animated GIF, clicking through an AppCooker demo of RWDevCon.

You can play around with the mockup in AppTaster, as shown above. This should give you an idea of what AppCooker is capable of making, and you can simply read through the rest of the tutorial if you’d like.

Sample Project Overview

In this tutorial, you’re going to create an interactive high-fidelity mockup for a client. As your example, you’ll use RWDevCon, our conference companion app with an event lineup, a personal schedule and a list of videos from prior conferences.

Don’t worry, you’re not going to mock-up the whole app. You’ll just make the first tab and link it to some placeholder screens. By the end, you should feel pretty comfortable using AppCooker.

finalProjectAppCooker

A Quick Tour

AppCooker has quite a lot of functionality. To keep these features organized, AppCooker has different modes, or workspaces.

  • App Board: A springboard from which you can plan all facets of your prototype, including App Store metadata, pricing, and refinement of your app idea.
  • Screen View: An infinitely scrolling canvas that contains all the screens in your app, including their link relationships.
  • Editor: Where you edit an individual screen. You can drag and drop native widgets, images, shapes and more.
  • Preview: This is an interactive demo of your mockup, where you can tap links and transition between screens.

appCookerWorkspaces

Creating a New Project

Let’s dive in and create a new project. Open AppCooker, close the tutorial if it appears, and follow these steps:

  1. In the AppCooker project screen, tap Create Project, which is the first cell with a big plus sign.
  2. In the New Project modal, change the Project Name to RWDevCon.
  3. Under the Targeted Device list, select iPhone 6, iPhone 5.
  4. Tap Create on the top-right of the modal.
  5. Select your new RWDevCon project.
  6. In the App Board of RWDevCon, select the blue pane that says iPhone 5 & 6 Mockup.
  7. If all goes well, you’ll see a Home screen in the Screen View.

Animated GIF of creating a new project in App Cooker.

When you create a new project, you can choose between device classes such as iPhone, iPad or Apple Watch. Some UI elements are only available on certain devices; for example, popovers are available on iPad but not on iPhone.

Note you can only choose one targeted device per project; so if you’re targeting multiple devices, you will need to create multiple projects for the same app.

Adding Native Widgets

Your app’s design uses a tab bar for navigation, and each tab contains a table view. You’ll begin by adding a few of these UI elements to the screen.

  1. Single-tap on the Home screen, and a small popover menu will appear.
  2. Tap the Edit button next to the pencil icon. This will take you into the Editor.
  3. In the navigation bar, tap the Widgets button widgetsButtonAppCooker, which reveals a collection of widgets.
  4. Tap the Status Bar item, and it will automatically appear at the top of your screen.
  5. Tap the tab bar item (the one with a star), and it will appear at the bottom of your screen.
  6. Tap the table view item. Drag and resize it so that the bottom is flush with the tab bar and the height takes up roughly two-thirds of the screen.

Animated GIF of adding a few native widgets like the Status Bar, Tab Bar, and Table View.

With just a few taps, your first screen is taking shape.

The widgets menu has many UIKit elements, like navigation bars, sliders and date pickers. There are also black-and-white versions of these widgets on the Wireframe tab. These are useful for iterating quickly without being bogged down by details like color.

Saving Colors to the Palette

Since you’re making a high-fidelity mockup, you want to use branded colors. The color picker supports different modes, including RGB, HSB and grayscale. In this section, you’ll save a few colors to the palette for future use, as well as set the background color.

Follow these steps:

  1. Tap the canvas background to make sure no UI elements are selected.
  2. Tap the Bkg. button in the bottom property bar. This opens up a color palette popover.
  3. Select the third circle to enter RGB Mode.
  4. Slide the values for (Red, Green, and Blue) to (0, 110, and 55), respectively. We’ll refer to this color as RWGreen.
  5. Tap the first available plus icon to save this color to your palette.
  6. Select the last circle to enter Gray Scale Mode.
  7. Tap the square that says 50 and save it to your palette using the plus button.
  8. Also tap the 80 square and save it to your palette.
  9. Make sure the Bkg. square is dark gray when you’re done. The screen’s background should be dark gray, as well.

Adding colors to the color palette.

You just set the background color to a dark gray. Along the way, you saved some colors to a color palette. You’ll use the green for cell titles, and the lighter gray for subtitles.

Changing the Status Bar Color

Now that the background color is dark gray, it’s hard to see the status bar. You’re going to fix this.

  1. Tap the status bar.
  2. In the property bar, tap the Style button.
  3. Select Light Content from the popover menu. The status bar will now be white.

Changing the Status Bar style to Light Content.

You may have noticed that AppCooker gives you options for dark content and light content rather than “black” and “white”. This is because the native widget properties tend to map directly to an API in iOS. In this case, the two UIStatusBarStyle options are .Default (dark content) and .LightContent.

Configuring the Table

Table views are an essential part of mobile development. Naturally, there are a lot of configuration options for cell styles, cell accessories, sections and headers. AppCooker makes many of these properties available in the table view widget.

Delete Unused Sections and Rows

By default, the table view widget is populated with pre-configured cells to give you a sense of what’s possible. Your first order of business: delete some of this boilerplate.

  1. Select the table view on your screen.
  2. Tap the Sections button in the property bar. This opens the Sections modal.
  3. Swipe the row named Section 1 to the left and tap Delete.
  4. Select Section 0, which takes you to the Section Details page.
  5. Swipe to delete the second cell, named Title.

Deleting some boilerplate table cells.

You’ll end up with one section containing a single cell.

Configure the Cell

Each cell needs to fit quite a bit of information, including the title of the talk, course number, difficulty level and room number. The Subtitle cell style is a good choice, since you can squeeze in two lines of information, one on top of the other.

  1. On the Section Details page, tap the first cell named Title. This takes you to the Cell Details page.
  2. Under the Style section, tap the example cell, which currently has a Basic style.
  3. On the Cell Style page, select the second cell, the one where the title is on top of the subtitle. This will take you back to the previous page.
  4. Under the Accessory section, tap the example cell, which is currently set to Detail Button.
  5. On the Cell Accessory page, select the first item, None. Again, this will take you back to the previous page.

Configuring various properties on a Table View cell.

You’ve changed the cell style from Basic to Subtitle, as well as gotten rid of a cell accessory button. Onward!

Change the Cell Text Color

The built-in subtitle cell is functional, but it doesn’t look exciting. Why don’t you change the title color to that dashing RWGreen you saved earlier?

  1. On the Cell Details page, find the Title row and tap the Info button. This will take you to the Title Attributes page.
  2. Tap the black row at the bottom to go to the Title Color page.
  3. Select the green square from the color palette you saved earlier.
  4. Tap the Back button twice until you return to the Cell Details page.
  5. Repeat the same steps to change the Subtitle Color to the light gray color from the palette.

cellTextColorAppCooker

The cell title will now be green, and the subtitle a light gray.

Add Body Copy to the Cell

You’re going to enter some mock information to help you visualize the end product.

  1. On the Cell Details page, find the Title and Subtitle cells in the Content section.
  2. Change the Title to Beginning Swift.
  3. Change the Subtitle to 101 • Beginner • Edison A/B/C. On an iOS keyboard, hold down the hyphen key and the bullet character will appear in a popover.
  4. Tap the Back button to return to the Section Details page.
  5. Replace the Header text with FRIDAY 9:00 AM.

bodyCopyCellAppCooker

Data entry can be tedious. Fortunately, AppCooker makes it easy to duplicate cells.

Fill Up the Table With Duplicate Cells

Right now your table view has just a single cell. The mockup might look better with a fully populated table.

This is only a mockup, so why not copy and paste?

  1. On the Section Details page, tap Duplicate Last Cell.
  2. Keep duplicating the last cell until the table is fully populated.

Duplicating Table View cells.

Hey, maybe it’s a popular workshop!

Importing Images

AppCooker integrates with iCloud Drive, so it’s easy to import images. If you haven’t done so already, download this zip file containing images and icons. If you want, you can generate the icons yourself in this Sketch tutorial.

Transfer Images to iCloud Drive

  1. From a desktop web browser, log into www.icloud.com/#iclouddrive with your Apple ID.
  2. Within iCloud Drive, create a new folder called AppCookerImages.
  3. Unzip the AppCookerResourceFolder.zip file.
  4. Drag all the image files from Finder to the iCloud Drive folder.

AppCooker’s integration with iCloud makes it a cinch to transfer images and backup files.

Set the Tab Bar Icons

Currently, two tab bar icons are set to default star and ellipsis images. For this mockup, you’re going to use a calendar image with an “11” to represent Friday, March 11th. Likewise, you’ll use a “12” icon for Saturday.

  1. Back in the AppCooker Editor, select the tab bar at the bottom of the screen.
  2. Tap the Tabs button in the property bar. This will reveal a Tabs modal.
  3. Select the first cell, which is named Favorites.
  4. Rename the Title to Friday.
  5. Select the Icon cell. This will reveal an action sheet.
  6. Select iCloud Drive from the bottom of the list. This will open an iCloud Drive modal.
  7. Select the AppCookerImages folder you created earlier.
  8. Select march11fill.png. This sets the icon and dismisses the modal.

setTabIconAppCooker

Even though the image is green, you’ll notice the tab bar icon is blue. Certain icons in iOS are rendered as template or stencil images. In a later step, you’ll set a tint color to fix this.

For the icon on the second tab, repeat the same steps as before. Except this time:

  1. Change the Title from “More” to Saturday.
  2. Use the file march12outline.png.

otherTabIconAppCooker

As a final touch, set the tab bar’s tint color to RWGreen:

  1. Make sure the tab bar is still selected.
  2. In the property bar, tap the Tint button.
  3. Select RWGreen from the color palette.

Setting the tint color on the Tab Bar.

The Friday icon will now be green with a filled calendar icon, and the Saturday icon will be the gray outline version.

The calendar outline icon has a lot of empty space, so when you select it, the color change isn’t obvious. This is why you’re using a separate fill version for the selected state.

Add the RWDevCon Logo to the Table View Header

The last piece of UI on this screen is the RWDevCon branding logo in the table view header. It’s time to grab another icon from iCloud Drive.

  1. Tap the image icon imageIconAppCooker in the navigation bar.
  2. Select iCloud Drive from the drop-down list.
  3. Within the AppCookerImages folder, select rwdevconlogo.png. This adds an image to your screen.
  4. Drag and resize the image to center it inside the table view header.

addImageAppCooker

You can use the orange guides to help you maintain aspect ratio and snap to element boundaries.

Note: AppCooker also has useful image editing features in the property bar. For example, you can crop/mask, adjust the alpha and add a corner radius or shadow.

imagePropertyBarAppCooker

Tab Bar Transitions

One compelling use case for AppCooker is its ability to create interactive transitions between screens. You can customize these transitions with animations to mimic push, pop and tab bar transitions.

Duplicate the First Screen

Before you can create a transition, you need a second screen. Since the Friday and Saturday tabs are so similar, you’re just going to duplicate the first screen.

  1. If you’re on the Editor workspace, tap Done in the top-left corner to return to the Screen View workspace.
  2. Tap the Home screen. This will reveal a popover menu.
  3. Tap Duplicate to create an identical screen named Home 2.
  4. Tap the word Home and rename it Friday.
  5. Rename Home 2 to Saturday.

duplicateScreenAppCooker

Update the Tab Bar Icon Images

Right now, both tabs look identical. You’re going to update the Saturday tab so you can tell it apart from Friday.

  1. Double-tap the Saturday screen to return to the Editor.
  2. Using the steps outlined earlier, change the Friday tab icon to march11outline.png.
  3. Also change the Saturday tab icon to march12fill.png.
  4. While editing the Saturday tab icon, check off the Selected cell.
  5. Change the table view section header text to Saturday 9:00 AM instead of “Friday”.

updateTabIconsAppCooker

When you mark the Saturday tab bar icon as Selected, it automatically de-selects Friday.

Create the Tab Bar Transition

The tab bar widget has some built-in linking capabilities. You can leverage this to link the new Saturday tab to the Friday tab.

  1. Within the Saturday Editor, select the tab bar element.
  2. Select the Tabs button from the property bar. This opens up a Tabs modal.
  3. Select the Friday cell.
  4. In the Link options section, toggle the Link switch.
  5. Tap the Select a Target screen cell. This takes you to the Item Link page.
  6. Under the Screen targeted section, tap Select a Target.
  7. On the Screen Targeted page, select the Friday cell. This returns you to the previous page.
  8. Under the Type of transition section, select the Fade +0.3 sec cell. This takes you to the Type of Transition page.
  9. Change the transition type to None.

createTabLinkAppCooker

You just created a tab transition that goes from the second tab to the first, with no animation. You’ll see a blue square over the Friday icon, which indicates it’s tappable.

Now you can circle back and create a transition from the Friday screen to the Saturday screen.

  1. Tap Done in the top-left corner to return to the Screen View.
  2. Double-tap the Friday screen.
  3. Repeat the steps above for creating a tab bar link. But this time, link the Saturday tab bar icon to the Saturday screen.

Test the Transition in Preview Mode

You need to test the tab bar transitions to make sure they work. To do so, you have to use AppCooker’s Preview mode.

  1. In the Screen View workspace, tap the Play button, which is a triangle icon in the navigation bar. This takes you into Preview.
  2. Optionally, tap the Link icon to toggle off the blue tappable area.
  3. Tap the Play triangle to start the preview.
  4. Verify that the selected tab changes as you tap the Friday and Saturday icons.
  5. Double-tap with two fingers to exit the preview.

previewTabsAppCooker

When using Preview, you won’t be able to interact with the mockup until you tap the Play button. And once you’re in Play mode, remember to double-tab with two fingers to exit.

One benefit of AppCooker is that you can design and test on the same device. Since you’re using an iPad, you have access to gestures like tap, swipe, multi-touch and device rotation.

Smart Back Transitions

Screen transition animations usually come in pairs. When you push a detail page, you pop to go back. Likewise, when you present a modal, you dismiss to go back. AppCooker has a convenient feature called Smart Back that uses the reverse animation to return to the previous screen.

Create a Detail Page

Before you can play with this feature, you first need to create a detail page.

  1. Navigate back to the Screen View workspace.
  2. Double-tap on an empty area of the workspace to create a new screen.
  3. Rename the new screen Detail Page.
  4. Double-tap on the screen to enter Editor mode.
  5. From the Widgets menu, add a status bar, a navigation bar and a table view.
  6. Tap Done to return to the Screen View.

detailPageAppCooker

You just created a detail page with a few UI elements. But look closely at the navigation bar widget and you’ll notice a blue tappable area over the Back button. It turns out this button is pre-configured with a Smart Back link. Just by adding a navigation bar, you’re halfway to finishing your Smart Back transition.

Create a Simple Link

The next step is to create a link from the Friday screen to the Detail Page.

  1. Open the Editor for the Friday screen.
  2. Tap the Link button linkIconAppCooker in the navigation bar.
  3. Select Add a Simple Link area.
  4. A red box will appear onscreen. Drag and resize it so it covers up the first Beginning Swift cell.
  5. In the property bar, tap Choose a target screen. This will open a popover.
  6. Tap the Select a Target cell.
  7. Select the Detail Page cell.
  8. Change the Type of transition to Cover R.

createSimpleLinkAppCooker

The Simple Link creates a transition from the Friday tab to the Detail Page, using the Cover Right animation. The Smart Back button is already in place on the Detail Page, and it will play the animation in reverse on the return trip.

Test the Smart Back Link with Preview Mode

Use Preview to check out your new Smart Back link. Refer to the prior instructions for entering Preview mode, but this time, make sure the Link button is on so it’s easier to tell which areas are tappable.

smartBackAppCooker

Adding an App Icon

Before you show the client your progress, it’s a good idea to include an app icon.

  1. Navigate back to your project’s App Board.
  2. Select the App Icon editor.
  3. Tap the large blank icon. This takes you into Editor mode.
  4. In the navigation bar, select the image icon imageIconAppCooker, and select iCloud Drive from the list of options.
  5. Within the AppCookerImages folder, select rwdevconIcon.png.
  6. Pan and resize the image until it fills the entire icon area.
  7. Tap Done when you’re finished.

appIconAppCooker

The process of importing an app icon is similar to importing a regular image. The main difference is that you’re using the icon editor instead of the screen editor.

Note: You can use the App Icon editor to rapidly iterate over icon ideas. Use the shapes icon shapesIconAppCooker to draw freehand or add geometric shapes.

iconIterationAppCooker

Importing and Exporting Files

When exporting your project, you have three file formats to choose from:

  1. .appCooker is a full backup of your project. Anyone with this file can continue editing where you left off.
  2. .appTaster is a playable mockup that clients and coworkers can view using the free companion AppTaster app.
  3. .PDF lets you export screens and other project information for viewing on a computer.

Export your project in the AppTaster format so you can show off your progress to the client.

  1. Navigate to the App Board of your project.
  2. Tap the Action icon in the navigation bar. This brings up a modal where you can Choose a format.
  3. Select the AppTaster icon.
  4. (Optional) Enter your email address in the Send comments to field.
  5. Tap Continue.
  6. On the Send a Copy page, select the Email option. This opens an email composer which is pre-populated with instructions.
  7. Instruct your client to download the AppTaster app before opening the email attachment.

exportingAppCooker

When the client opens the .appTaster email attachment, she will have the option to Copy to AppTaster. Within AppTaster, the client can comment on individual screens, and these comments are sent to the email address you provided.

Challenge

You’ve started on the Detail Page, and your challenge is to build out the rest of the screen. This is what it looks like before and after:

appCookerChallenge2

You can continue with your existing project or download the challenge starter project below.

Your goal in this challenge is to not only apply what you’ve learned, but also to explore other properties available on native widgets. AppCooker doesn’t do everything Xcode does, so you’ll have to work around AppCooker’s limitations. Here are a few tips:

  • You can expand the height of the screen using the Screen Size button in the property bar.
  • You can customize the navigation bar’s Style and Tint colors.
  • The table view has a Grouped style and a Row Height property.
  • There are cell styles other than Subtitle, such as Left Detail.
  • For custom cells, you’ll need to drag and drop multi-line text and images.
  • Each table view only supports a single Row Height. To create cells of varying heights, one workaround in AppCooker is to use multiple table widgets.
  • The Resources folder has a few conference speaker avatars you can use as placeholder images.

Ready? Download the challenge starter project if you need it.

To import an .appCooker file, first transfer it to iCloud Drive. Then within AppCooker, tap the plus button in the navigation bar on the project screen to access iCloud Drive.

importAppCooker

If you want to check your work, you can download the finished challenge.

Where to Go From Here?

AppCooker is an easy-to-use prototyping tool for creating interactive mockups. There’s a lot more you can do with AppCooker beyond what you’ve seen here. To learn more, check out these video tutorials from the official website.

I hope you enjoyed this tutorial, and if you have any questions or comments, please join the discussion below!

The post How to Make App Mockups With AppCooker appeared first on Ray Wenderlich.

2D iOS & tvOS Games by Tutorials Updated for Xcode 7.3

$
0
0

2D iOS and tvOS Games by Tutorials

Today, we’re happy to announce that 2D iOS & tvOS by Tutorials is now fully up-to-date for Xcode 7.3.

Xcode 7.3 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 7.3, we’ve fixed some errata pointed out by readers – thanks all!

This is a free update for existing PDF customers. Here’s how you can get your copy:

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

At this point we’ve updated all of our books to Xcode 7.3 except for one (watchOS 2 by Tutorials), which is coming soon – stay tuned.

The 2D iOS & tvOS Games by Tutorials team and I hope you enjoy this update!

The post 2D iOS & tvOS Games by Tutorials Updated for Xcode 7.3 appeared first on Ray Wenderlich.

RWDevCon 2016 Session 303: Introduction to Protocol-Oriented Programming

$
0
0

We recently released the RWDevCon 2016 Vault, a collection of over 24+ hours of hands-on video tutorials, 700+ MB of sample projects, and a 570 page conference book.

To celebrate its launch, we’re releasing 3 videos from the vault for free so you can check them out and see if you like them.

Today’s video is an example from the advanced track – Introduction to Protocol-Oriented Programming. Enjoy!

 

Download demo resources

Note from Ray: Did you enjoy this tutorial? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2017 tickets go on sale, or check out our massive vault of tutorial videos!

The post RWDevCon 2016 Session 303: Introduction to Protocol-Oriented Programming appeared first on Ray Wenderlich.

RWDevCon 2016 Vault Giveaway Winners – And Last Day for Discount!

$
0
0

RWDevCon 2016 Vault Giveaway

Thank you for being a part of the RWDevCon 2016 Vault Week!

During the RWDevCon 2016 Vault week, we released three free video tutorials from RWDevCon 2016 (one beginner, one intermediate, and one advanced). We also released the conference keynote: an inspirational speech about some of my struggles with motivation.

Finally, we released the RWDevCon 2016 Vault itself: a collection of 24+ hours of video tutorials, 700+ MB of sample projects, and a 570 page conference book. But now, it’s time to say goodbye.

But first, there’s two important pieces of news!

RWDevCon 2016 Vault Giveaway Winners

To celebrate the RWDevCon 2016 Vault Week, we had a giveaway for three free copies of the RWDevCon 2016 Vault. All you had to do to enter was comment on the announcement post.

We had over 130 applicants, and we’ve selected some random winners from among them.

And now it’s time to announce the 3 lucky winners… drum roll please!

The 3 lucky RWDevCon 2016 Vault winners are: cherry, x0000ff, and simonqq. Congratulations! :]

Each winner will receive a free copy of the RWDevCon 2016 Vault (or a PDF of their choice if they already have a copy). We will be in touch with the winners directly via email.

Last Day for Discount!

Finally I’d like to remind everyone that today is the last day for the current discounted price of the RWDevCon Vault.

Starting tomorrow, the book will be raised to its normal price ($100 more). So be sure to grab the 50% off discount while you still can!

Thanks to everyone who entered the RWDevCon 2016 Vault giveaway, bought the vault, or simply read these posts. We really appreciate each and every one of you, and thank you for your support and encouragement – it is so amazing being a part of this community.

We hope you enjoy your virtual trip to RWDevCon 2016, and we hope to see you at the actual conference next year! :]

The post RWDevCon 2016 Vault Giveaway Winners – And Last Day for Discount! appeared first on Ray Wenderlich.

Readers’ App Reviews – April 2016

$
0
0

ArmadilloSmashThumb

April is here, and that means WWDC has finally been announced! I can’t wait to see the new APIs available and what the fantastic raywenderlich.com community will build with them.

Luckily for us, we don’t need to wait to see great apps from our community. My inbox is packed with great apps just released by readers like you.

I receive more than an app a day from fellow readers, and although I don’t have time to write about every app that hits my inbox, hopefully the few I show inspires you to finish your app.

This month we have:

  • A game where only one armadillo was harmed in the making
  • A photo filter app that gives you more control than ever
  • A guide for beer lovers in or visiting New York City
  • And of course, much more!

Keep reading to see the the latest apps released by raywenderlich.com readers like you!

Armadillo Smash

ArmadilloSmash
Armadillo Smash is an addicting retro themed arcade style game, ready to be your new favorite.

Armadillo Smash kicks off with you launching the Armadillo star of the show into the air.

Keeping your Armadillo in the air is all about timing. Each bounce requires a carefully timed tap to make sure he rolls and performs a perfect bounce.

Armadillo Smash is fully universal offering iPhone, iPad, and Apple TV. You can even play on your Apple Watch to influence the game for a second player on the iPhone, making it harder or easier for them to crack the high score.

Filteract

Filteract
Filteract is a must have for those of your looking to make professional looking photos easy right on your iPhone.

Filteract allows you to carefully paint individual filters on your photos wherever your want. Want a black and white with a colorful element still popping? Or maybe you want to make the background tinted. Filteract can help with all of it.

All you have to do is select a filter, then you can paint it onto your photo in one of three ways:

  1. You can paint freeform if you have a steady finger.
  2. Or you can use a special paint-roller tool to fill shapes as you paint. The paint-roller will automatically detect shape edges as you paint and expand the paint for you.
  3. Finally you can also use a magic-paint tool to select objects or fill shapes with a single touch. It works great on main subjects or brightly colored objects for quick flairs of color in a black and white photo.

K’s Challenge

KChallenge
We’ve all been addicted to the physics based puzzle games that exploded on the iPhone. But now you may never put your phone down again.

K’s Challenge is a simple game at the core. There is a yellow ball you need to connect to a yellow square. But how you get it there is by drawing your own objects that interact with the natural gravity of the space.

K’s Challenge is extremely addicting. Its tons of fun to interact with the game on such a fundamental level. Levels aren’t over after just one victory. Because the game offers unlimited creativity its fun to replay levels and try to solve them with different drawings.

Abel – A ride you want to share

Abel
Abel is a ride sharing app ready to take on the likes of Uber and Lyft in their hometown Amsterdam and some surrounding areas.

Ride sharing is something Uber and Lyft are starting to dabble in. Rather than pay for a private car. You can pay less to share a car with fellow travelers on a similar route. It allows Abel to be up to 50% cheaper per ride than Uber X.

For you, Abel still works the same. There is a slick app to set your pickup location and pay the driver automatically. But behind the scenes Abel will group travelers heading to the same or nearby locations and help the driver pick passengers up in the right order at the right places.

Its great to see an indie app from the Ray Wenderlich community taking on the big dogs. If you live in Amsterdam or visit, download Abel and give it a try, it will save you a few bucks and give you a chance to meet some fellow travelers.

Zero G

Zero
Match 3 games are a dime a dozen. But Zero G is a unique take on them that increases the skill level and addictiveness equally.

Zero G rather than moving individual gems, operates like a sliding puzzle. You swipe to slide the entire board. Each gem pops in one at a time between each board swipe. You can see the next gem like a Tetris game so you can try to prepare for it.

It takes some skill and luck to align sets of 3 gems with precision and planning. And it is very rewarding to get a few sets at a time with this more challenging game play.

Of course, being a well made iOS game, Zero G has Game Center leaderboards and achievements as well as Facebook and Twitter sharing.

Muzzle Flash FX

MuzzleFlash
Have you ever taken a video that needed a little more BANG!? You’re in luck!

Muzzle Flash FX is a special effects app that helps you add muzzle flashes, sparks, and bullet hits to your videos right on your iPhone. They have a library of effects covering handguns, sniper rifles, machine guns, and more.

All effects have full visual and audio and offer several angles to make sure its just right for your video. Muzzle Flash also lets you customize your sparks or hits with a full featured particle engine so you can get the sparks just right.

Muzzle Flash FX will definitely add some flair to your next home movie!

Scratchpad

Scratchpad
We’ve all done it. In the digital world TextEdit has become our scratch paper. The problem is, once we close it, we often have lost our notes if you didn’t remember to save it. Or worse we have hundreds of Untitled.txt saved to our desktop. But Scratchpad is here to help!

When you open Scratchpad you get a familiar interface similar to TextEdit. But it’s ready to go. No need to create a new document or find an old on – Scratchpad is ready for your ideas right away.

No need to worry about saving, Scratchpad is always saving. And with a simple scroll you can see your old notes. Scratchpad remembers all your notes, you can scroll back through all the versions along the way.

Call of the Universe

CallOfTheUniverse
NASA takes some amazing pictures of our universe and shares them regularly. Now with Call of the Universe you can get them right on your iPhone.

Call of the Universe has access to over 7,000 NASA images with new ones released everyday. Call of the Universe grabs the latest pictures and their NASA descriptions. You can mark your favorites to find them easily later, and get notified when new pictures drop each day.

Finally, you can easily search for specific dates. I love the photos from my past birthdays! :]

If you’re a space nerd, then this app is a must have for you.

Beer Guide NYC

BeersNYC
Beer Guide NYC is a must have app for any beer lovers in or visiting NYC.

Beer Guide has over 250 curated pubs around the city with reviews, photographs, websites, twitter handles, phone numbers, and more.

You can easily search for the pub nearest to you like you’d expect. But you can also lookup pubs by areas, landmarks, bus lines, or subway stations. Great for planning your night before you even leave.

The database of pubs is stored on your device, so even if you’re offline or limited on data, you’ll have no problem finding a great New York pub to visit.

Honorable Mentions

Every month I get way more submissions than I have time to write about. I download every app to try them out, but only have time to review a select few. I love seeing our readers through the apps submitted to me every month.

It’s not a popularity contest or even a favorite picking contest — I just try to share a snapshot of the community through your submissions. Please take a moment and try these other fantastic apps from readers like you.

Noble Ninja
Pomodo
SDA Hymnal – Free
Retro Formula 3D
Rainbow Burst
Gobi – Send snaps in groups!
Boost My Fund
in lumine
tpg offline
babla
Dot Dodging
Killer interview
Fly Froggy

Where To Go From Here?

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

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

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

The post Readers’ App Reviews – April 2016 appeared first on Ray Wenderlich.

Video Tutorial: Beginning Core Graphics: Series Introduction

Video Tutorial: Beginning Core Graphics Part 1: Getting Started


Alt-U iOS Apprentice Class Post-Mortem

$
0
0

Alt-U-Thumb

As you may know, we recently partnered up with the folks at Five Pack Creative to create a new series of classes based on the materials you know and love at raywenderlich.com: Alt-U.

Alt-U stands for “Alternative University”. The idea is simple – why pay for an expensive degree at a traditional 4-year university, when you can learn how to be an expert iOS developer in a fraction of the time and money?

Alt-U has three types of classes, for beginners to experts. This past week, I attended their first ever class – one for beginners called the iOS Apprentice – and wanted to report back on how it went.

Keep reading to find out what the class was like, my favorite thing about the class, and how to get a massive 25% off discount for the next beginner, intermediate, and advanced classes!

Alt-U iOS Apprentice Highlights

The class started off with a bang. Attendees dove straight into Xcode, and by the end of the first day had written their first app!

Bullseye

In the second day, the class took a step back and learned more about Swift, making heavy use of Playgrounds:

Arrays

From there, the class continued to make more apps, learning about topics like table views, Auto Layout, data persistence, networking, publishing to the App Store, and much more. It was a lot to cover in just 5 days!

My Favorite Things

I had a great time meeting the students and hanging out with Five Pack Creative and the team. It looks like the students learned a lot and had fun too – here are a few comments from the evaluations:

“Alt-U breaks concepts down into easy to understand chunks.”

“I love your staff’s eagerness to share their industry experience & best practices, along with not only how they implement, but why.”

“Five Pack Creative team has been phenomenal. Great teachers!”

Here are my three favorite things about the class:

1) Hands-On Focus

Rather than just listening to someone talk, you got to actually follow-along with the instructor as he coded up apps, or taught you Swift in playgrounds. This fits in great with our hands-on focus here at raywenderlich.com.

Labs

After the demos, there would be hands-on labs where you could try things out on your own. I think the mix was effective and really helped make the class interesting and fun.

2) Five Pack Creative Expertise

One thing that makes this class particularly strong is the expertise of the instructors from Five Pack Creative.

These guys make apps for clients like match.com, American Airlines, and Tapity every day. As such, not only do they teach you how to code for iOS in Swift, but they also teach you things you need to succeed in a real-world environment, like working in a team, using git, using JIRA, agile development, and more.

Jerry

This also allowed them to do cool things like show off real-world code they’ve written for clients, tell war stories, and even share content from video tutorials and books they’ve made at raywenderlich.com. It was truly being taught by battle-worn experts!

3) Excellent Food

I know this is a silly thing to mention, but hey I thought it was awesome so needed to say something :]

The food at the class was incredible! Breakfast, lunch, and dinner was included and boy was it good.

Lunch

There was a huge variety of food, including salad bars, pasta stations, carving stations, multiple buffets, and delicious dessert. It also helped that the venue was nice and close to the airport!

Where To Go From Here?

All-in-all I was very pleased with how it turned out. And it has me super-excited for the Journeyman & Master classes coming up! :]

Speaking of which, here’s the next three classes coming up at Alt-U:

  • iOS Apprentice (Aug 1-5): For beginners – the class I wrote about here. If you missed it, another offering is coming up soon!
  • iOS Journeyman (Aug 22-26): For intermediate developers. Covers asynchronous development, networking, Core Data, and more.
  • iOS Master (Oct 3-7): For advanced developers. Covers functional programming, app architecture, custom Collection View layouts, and more.

I spoke to the guys at Five Pack Creative, and they were nice enough to offer raywenderlich.com a 25% off discount for these next 3 classes! Just add it to your cart and enter this coupon code: RAYWENDERLICH.

Note the discount expires on June 24, so be sure to snag it as soon as you can.

I hope to see some of you at an upcoming Alt-U class – and if you have any questions or comments about any of the Alt-U classes, please join the forum discussion below!

The post Alt-U iOS Apprentice Class Post-Mortem appeared first on Ray Wenderlich.

Swift Style Guide: April 2016 Update

$
0
0
Swift Style Guide--it is fun to talk about!

Style–it’s fun to talk about!

Good news – we have updated our popular Swift Style Guide for Swift 2.2!

Here at raywenderlich.com, we want to have a consistent style for you in our tutorials, books, videos, and conference materials. We believe it improves readability, and makes our content easier and quicker to understand.

At the same time, we want to avoid making a style guide so strict that an author feels like they are wearing a straight-jacket!

We’ve tried our best to walk this line carefully, and you may even wish to adopt some of these standards in your own projects. That said, our style guide is different than other style guides; we’re a tutorial site, which means our priorities are making our code easily readable in printed books and on the web. Many of the decisions are made with an eye toward conserving space for print, legibility, and tutorial writing.

Since our last major style update in April 2015, readers and team members opened dozens of issues against the guide and generated long threads of discussion suggesting how things could be made better. While we could not adopt all of the suggestions, we are truly grateful for feedback and the thoughts it generated. We hope you find this to be a compelling update.

Let’s look at some of the highlights.

Crush the Warnings

In a way, the Swift evolution community sets its own minimal style guidelines by causing the compiler to emit warnings on deprecated language features. You should consider warnings to be errors and fix them.

I am always surprised when I jump on a new project and find that the previous developer didn’t take the time to fix the warnings. We all have deadlines, but don’t let this be you. :]

Swift 2.2 brought several deprecations. For example, the ++ and -- operators along with along with the C-style for-loop are slated for removal in Swift 3. Rather than falling back to using a while-loop, go ahead and use enumerate() or the full power of ranges. It’s easy and fun. For example:

// list the index and item
for (index, item) in items.enumerate() {
  print("\(index): \(item)")
}
 
// count up from zero up to items.count by twos
for index in 0.stride(to: items.count, by: 2) {
  print(index)
}
 
// count down from three to zero
for index in (0...3).reverse() {
  print(index)
}

Another deprecation includes using strings instead of the new #selector expression. Xcode’s “fix it” button helps you out here, but it always uses the fully qualified names. Usually you can take advantage of context to make it shorter and more readable. Make the extra effort.

Less is more: The Swift evolution community is doing great work not only expanding features of Swift but also removing the less useful ones and simplifying the language as well. 🎉

Mind the Golden Path

The Golden Path (or sometimes Happy Path) rule dates back to our Obj-C style guide. It refers to the notion that you don’t want to nest conditional statements too deeply. That quickly gets hard to read.

// Not preferred
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
 
  if let context = context {
    if let inputData = inputData {
      // use context and input to compute the frequencies
 
      return frequencies
    }
    else {
      throw FFTError.NoInputData
    }
  }
  else {
    throw FFTError.NoContext
  }
}

If you can help it, don’t nest at all. Embrace the concept of the early exit.

Every major release of Swift: 1.0 with optional chaining, 1.2 with multiple let optional binding and 2.0 with the guard, throws and defer statements have given you increasingly better tools to build a clean, readable golden paths through your methods. Use them!

// Preferred
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
 
  guard let context = context else { throw FFTError.NoContext }
  guard let inputData = inputData else { throw FFTError.NoInputData }
 
  // use context and input to compute the frequencies
 
  return frequencies
}

Advantages of Being Lazy

Swift is a “safe” language. This means, among other things, that your objects are always guaranteed to be fully initialized before you use them. The rules can sometimes get a bit tricky. In fact, you might want to consult out our Swift Initialization in Depth tutorial if you want to understand the finer points of the process.

With UIViewControllers, full initialization is often delayed until the views load. Lazy initialization is a handy (and often safer) approach to use.

Consider the following stored property in your view controller:

lazy var locationManager: CLLocationManager = {
    let manager = CLLocationManager()
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.delegate = self
    manager.requestAlwaysAuthorization()
    return manager
}()

This allows you to defer initialization until you actually refer to the stored property which might have side-effects such as a permissions popup to appear.

Lifetime Extension

caretodance

When you are dealing with asynchronous requests such as a network call and then use that data to update your UI it is easy to inadvertently create a retain cycle. (Heap leak!)

Swift cleverly makes you explicitly type out self to clue you in that you might be doing this. Swift also lets you supply a capture list to break the retain cycle.

Be very careful using [unowned self] in your capture list. If your UI doesn’t outlive your network request, you just created an asynchronous crasher. Instead, prefer the more bulletproof [weak self].

In your closure, rather than optionally unwrap self each time, extend lifetime by performing the so-called strong-weak dance. This results in fewer possible code paths so is more obviously correct. An example of the canonical strong-weak dance is:

resource.request().onComplete { [weak self] response in
  guard let strongSelf = self else { return }
  let model = strongSelf.updateModel(response)
  strongSelf.updateUI(model)
}

We converged on the constant name strongSelf by looking at what a few successful open source projects (such as Alamofire) were doing. Perhaps in the future there will be a language feature to help minimize this boilerplate. For now, extending lifetime using the strong-weak dance ensures that you don’t create a retain cycle and that you don’t crash.

Flip Flops

Part of being a good style guide is to keep up with the changes in Swift as they come. In this update of the style guide we tell you to do a couple of things exactly opposite of what we said in the past. Sorry. :]

For example, although the style guide still recommends using type inference rather than an explicit type annotation in most cases, initializing arrays an dictionaries is now different. The new preferred form is:

var names: [String] = []
var lookup: [String: Int] = [:]

Many publications, including Apple, now use this form. Even Swift engineer extraordinaire, Joe Groff was kind enough to chime in on this issue.

Another flip-flop is in the capitalization of enumerations. Following Apple’s lead, before we said to use UpperCamelCase. Now, in anticipation of the Swift 3 API Design Guidelines, lowerCamelCase is preferred. The rationale is that cases are values and should follow the same convention as other values. Since Xcode won’t fight you on the matter, we might as well adopting now. We welcome our new Optional .some and .none overlords when Swift 3 appears this Fall.

Where to Go From Here?

This style guide update contains a lot of smaller but important details not covered here: names of generic types, chaining closures, defining constants and more. Over time, you will see our tutorials and books adopt this style.

We encourage you to read through the entire guide as it is not that long. If there is something you like (or don’t), let us know in the comments below.

If you want to get even more involved, open a Github issue and start a community discussion on a specific issue. You can even create a pull request. Typos and errors that need to be immediately fixed will go directly into the master branch after a brief review period. A swift3 branch will handle changes for a future update this Fall.

Herb Sutter and Andrei Alexandrescu famously admonish:

"Think. Do follow good guidelines conscientiously; but don’t follow them blindly."

This is great advice; no set of programming guidelines can cover every use case. Exceptions will always exist. In addition to helping you read our code, we hope that this style guide helps authors worry less about the mundane and focus on more interesting things. Enjoy!

The post Swift Style Guide: April 2016 Update appeared first on Ray Wenderlich.

Migrating to Parse Server

$
0
0

parse server tutorial

Parse, one of the most popular backend solutions for mobile apps, recently announced it’s shutting down its service. Naturally, this caused confusion amongst developers because it was surprising and disruptive — in a bad way. As a result, anything built on the platform will need a new backend, or it’ll cease to function.

The good news is there are options, and the team here has analyzed and compared several viable alternatives to Parse.

The end of Parse begs the question: Should developers take the same risk and depend on third-party backend providers?

Any option outside of building and hosting your own backend service carries some risk, and when you think about it, DIY carries risks too. You might find it’s not worth your time or later decide it’s too much of a hassle to keep up.

If you’ve got Parse on any of your apps, then it’s up to you to analyze the options and decide how to move forward in a Parse-less world.

This Parse server tutorial will explore one specific option: setting up and hosting your very own Parse Server, and migrating your data.

Note: This Parse server tutorial assumes you know the basics of developing iOS apps using Parse, have an existing Parse account, and have worked through the Parse Tutorial: Getting Started with Web Backends.

If you haven’t gone through it, that’s fine, you can still read and make quite a bit of progress. You just won’t have a certificate and some other minutiae that would allow you to follow step by step.

Getting Started

First, you need an existing iOS app that uses Parse so you can follow the steps in this Parse server tutorial. Feel free to use your own demo app, or download this Parse Starter project. It’s set up to work with Swift 2.2, iOS 9 and includes the latest Parse SDK (at the time of writing v1.12.0).

Build and run the project in Xcode to see the following:

parse server tutorial

Migrating to Parse Server

In this Parse server tutorial, you’ll install your own Parse Server that can be maintained through the Parse SDK. It’s open source, thus (almost) guaranteeing it’ll never cease to exist. It can be hosted on all major web service providers, such as Heroku, Amazon AWS or Azure.

There are, however, a few features from Parse.com that have not been implemented on Parse Server, such as jobs, analytics and config. Moreover, with Parse Server, you do all of the work of installing and hosting the service either locally or in the cloud.

Parse made all the necessary tools available to help developers transition away from its service by January 28, 2017: an open source Parse Server, Migration guide, Push Notification guide and a Parse Dashboard for local development.

Parse further recommends that you use mLab (formerly known as MongoLab) and Heroku to host the database and server, respectively.

The minimum requirements to install Parse Server are:

  • Homebrew, latest version
  • Node 4.3
  • MongoDB version 2.6.X or newer
  • Python 2.x
  • For deployment, Heroku Toolbelt

The MongoDB requirements for Parse Server are:

  • About 10 times the space you’re currently using with Parse, because the current service heavily compresses your content.
  • The failIndexKeyTooLong parameter must be set to false to accommodate indexed fields larger than 1024 bytes and collections larger than 1 million documents.
  • An SSL connection — although it’s not required, it’s strongly recommended.
  • For minimal latency, host your MongoDB servers in the US-East region.

Migrating the Database and Installing Parse Server

Creating a New Database

Go to the mLab website and create an account if you don’t have one already, and then watch for the confirmation email that will let you activate your new account. Once activated, click the Create New button. Choose Amazon AWS, US East, Single-node and Sandbox — these are the recommended free options:

parse server tutorial

Your database name can be anything, but for now, just use tutorial-app. Click on Create new MongoDB deployment and wait for your new database to be created.

Next, select tutorial-app and go to Users / Add database user. Enter a username and password then click Create. Save your Database URI somewhere that’s easy to reference, because you’ll need it several times throughout this Parse server tutorial. It should look similar to the one below, but your database ID will be unique:

mongodb://<dbuser>:<dbpassword>@ds017678.mlab.com:17678/tutorial-app

Migrating the Parse Database to mLab

Go to the Parse dashboard and find your app. Click App Settings and then the red Migrate button under General. On the next screen, paste your Database URI, and then click Begin the Migration; ignore this warning for now:

We strongly suggest you enable SSL on your database and use the URL option 'ssl=true'.

Note: If you don’t see the red Migrate button, then check if you’re using the new Parse Dashboard. The old Parse Dashboard does not have the red Migrate button.

Once migration finishes, a warning will appear. Click Finalize after the warning: This action is irreversible!. Once the migration completes successfully, your general page should look like this:

parse server tutorial

Return to the mLab website to look for your migrated database. Under MongoDB Deployments, you should see the database you created: ds017678/tutorial-app.

Note: If you don’t see MongoDB Deployments, click the Home link in the top-left corner to make it show itself.

Click on the database to see all of its collections.

If you did the previous tutorial mentioned at the beginning, you’ll see the Player class, which is where you saved data when you built your app. Click on the Player class and notice that your old records are all there!

If you didn’t go through the previous Parse tutorial, then obviously you won’t see any data there.

You’ll write new records to this database soon, and they’ll appear as a new collection.

parse server tutorial

Install the Prerequisites

Open Terminal and run through the below steps to make sure the required support is in place.

Homebrew

If you don’t have Homebrew, enter this command:

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

If you already have Homebrew, make sure it’s up to date by entering this command:

$ brew update

MongoDM

Next, install MongoDB — this can take a few minutes:

$ brew install mongodb --with-openssl

Create a local MongoDB database by running the following:

$ mkdir -p /data/db

If you don’t have permission to write files at the root of your hard drive, then place sudo in front of mkdir and try again.

Now you just need to verify that you have the required MongoDB version: v2.6.X or newer:

$ mongo
MongoDB shell version: 3.2.3
connecting to: test
Welcome to the MongoDB shell.

Press Control + D to quit MongoDB.

Note: If your Mongod daemon isn’t already running, then use the following command after installing MongoDB to allow connections to your local MongoDB daemon.

$ mongod --config /usr/local/etc/mongod.conf

Python

It’s usually installed on all major OS versions, but check if you have it first:

$ python -V
Python 2.7.10

If you get a no, install Python by running this:

$ brew install python

Node

Install the latest version of Node:

$ brew install node

Confirm that you have the required version — v4.3 or newer:

$ node --version
V4.3.1

Installing the Parse Server

To make life a little easier for developers, Parse created a local version of its server and pushed it to GitHub. Make a clone of it on your system:

$ git clone https://github.com/ParsePlatform/parse-server-example.git Parse

Change the directory to the freshly cloned Parse directory:

$ cd Parse

Install Parse Server in this directory:

$ npm install

Start Parse Server:

$ npm run start

Check if it was successful by copying and pasting http://localhost:1337 into your browser:

parse server tutorial

Well, at least it dreams of being something. Rather progressive for a server, don’t you think? :]

Next, in the root folder of the ParsePlatform project, open index.js and replace the default database string with your MongoDB database URI:

// Replace this
var databaseUri = process.env.DATABASE_URI || process.env.MONGOLAB_URI;
 
// With this
var databaseUri = 'mongodb://<dbuser>:<dbpassword>@ds017678.mlab.com:17678/tutorial-app';

This configures Parse Server to talk to your mLab database.

You also need to specify your Application ID:

// Replace this
appId: process.env.APP_ID || 'myAppId',
 
// With this, the value that actually represents your Application ID
appId: process.env.APP_ID || '<myAppId>',

Now that you’ve wired it up, you need to test if the Parse Server is talking to the remote database. Remember to insert your Application ID from the Parse.com dashboard:

$ curl -X GET \
-H "X-Parse-Application-Id: <myAppId>" \
-H "Content-Type: application/json" \
-d '{}' \
http://localhost:1337/parse/classes/Player

The server should return any old records:

{
  "results": [
    {
      "objectId": "cZU7xfUNrX",
      "createdAt": "2016-02-25T22:54:02.679Z",
      "updatedAt": "2016-02-25T22:54:02.679Z",
      "Name": "John",
      "Score": 810
    },
    {
      "objectId": "sT4diOLqN3",
      "createdAt": "2016-02-25T22:52:01.139Z",
      "updatedAt": "2016-02-25T22:52:01.139Z",
      "Name": "John",
      "Score": 1230
    },
    {
      "objectId": "vRW6MAg3bX",
      "createdAt": "2016-02-25T22:54:35.189Z",
      "updatedAt": "2016-02-25T22:54:35.189Z",
      "Name": "Sally",
      "Score": 2400
    }
  ]
}

You now have a functioning Parse Server complete with real data.

parse server tutorial

Configure the iOS app

At last you get to dive back into the comfortable familiarity of Swift. The starter app doesn’t have the correct server URL to use Parse SDK with Parse Server.

Pull up the app in Xcode, open AppDelegate.swift and look for the line below in application(_:didFinishLaunchingWithOptions:):

Parse.setApplicationId("--AppID Goes Here--", clientKey: "--ClientKey Goes Here--")

Replace it with the block below, substituting your Application ID and Client Key from the Parse dashboard:

let configuration = ParseClientConfiguration {
  $0.applicationId = "YOUR_APP_ID"
  $0.clientKey = "YOUR_CLIENT_KEY"
  $0.server = "http://localhost:1337/parse"
}
Parse.initializeWithConfiguration(configuration)

The ParseClientConfiguration object represents the configuration the Parse SDK should use to connect with the server. It lets you create configuration variables for various connection parameters, including your Application ID, Client Key, Server URL and so on.

This configuration object is passed to initializeWithConfiguration(_:), which then sets up the Parse SDK before connecting to the server.

If you still have the username and password from the previous Parse tutorial, go ahead and enter them now. If not, simply make some new credentials on the User page inside the Parse Dashboard. Just click the + sign under the objectId column, then enter a new username and password:

parse server tutorial

Build, run and log in. Tap the Upload button and choose an image from your phone or Simulator’s stock images.

Write a short comment and tap Send. To double-check that you’re writing to the “online” database, try these two sanity checks:

  1. Go to the WallPost collection on the mLab website and look for the image you just sent.
  2. Delete the app from your phone or Simulator. Then build and run, log in and check if you can retrieve the image and comment from the Mongo database.

parse server tutorial

If it’s there, you’re ready to move the Parse Server to Heroku’s web hosting service.

Deploy the Parse Server to Heroku

In order to manage Heroku apps from Terminal, you’ll need to download and install the Heroku Toolbelt from the Heroku website. It’s a command line interface tool for creating and managing Heroku apps.

Note: You could have attempted the installation by using Homebrew, however, you’d have gotten a standalone version of the Heroku Toolbelt that doesn’t include all the required components.

If you don’t already have a Heroku account, please visit the Heroku sign up page and do the needful.

Next, authenticate against Heroku by running the following command inside the local Parse Server directory:

$ heroku login

The Heroku platform uses git for deploying applications. When you create an application on Heroku, it associates a new git remote, typically named heroku, with the local git repository for your application. Since the Parse project was cloned from GitHub, a local git repository exists. All you need to do is initialize Heroku, and push to its remote.

From the Parse project directory, create an application on Heroku and push your source code to the Heroku server:

$ heroku create
heroku-cli: Installing core plugins... done
Creating app... done, stack is cedar-14
https://intense-chamber-52549.herokuapp.com/ | https://git.heroku.com/intense-chamber-52549.git

Notice a Heroku service was created for you (in my case it was at: https://intense-chamber-52549.herokuapp.com).

Next, commit your changes, and push the local Parse Server to the newly created Heroku service with the following command:

$ git add .
$ git commit -m "Commit with my custom config"
$ git push heroku master

Paste the URL you made with the create command into a web browser and you should see the same message as before when you tested the server locally:

I dream of being a web site.

Now you need to test if that shiny new Heroku service still responds to GET requests. Remember to replace <myAppId> with your Application Id from the Parse dashboard, as well as your Heroku server URL:

$ curl -X GET \
-H "X-Parse-Application-Id: <myAppId>" \
-H "Content-Type: application/json" \
-d '{}' \
https://<your URL>.herokuapp.com/parse/classes/WallPost

This is a similar curl as before when you were executing against a local server. This command goes against the remote server.

You should see the JSON version of the wall post record you created inside the iOS app:

{
  "results": [
    {
      "objectId": "a8536MK9nC",
      "image": {
        "__type": "File",
        "name": "57eb6f36cd8bcce8141dc5ccca3072c0_image.bin",
        "url": "http:\/\/afternoon-harbor-27828.herokuapp.com\/parse\/files\/" \
          "jJ5Ds5h0eXWYhv7DGWYIrfLQTn2rjB0okakvo3LH\/57eb6f36cd8bcce8141dc5cc" \
          "ca3072c0_image.bin"
      },
      "user": {
        "__type": "Pointer",
        "className": "_User",
        "objectId": "SLPlVVfsvx"
      },
      "comment": "great pic!",
      "updatedAt": "2016-03-14T17:36:20.849Z",
      "createdAt": "2016-03-14T17:36:20.849Z"
    }
  ]
}

It works! You just migrated your Parse app and database to the cloud, and that’s an accomplishment!

Implement Basic Push Notifications

Note: If you’re setting up push notifications on iOS for the first time and want to go through all the steps outlined below, you’ll need to head to the Push Notifications Tutorial and work through it until you’ve generated and downloaded the certificate.

When initializing Parse Server, you need to set up an additional push configuration. Inside the Parse Server directory, open the index.js file and add the following code block after the serverURL line:

push: {
  ios: [
    {
      pfx: 'cert.p12',
      bundleId: 'com.example.ParseTutorial',
      production: false
    }
  ]
},

The certificate cert.p12 is the one you exported from the Push Notifications Tutorial (it may be named WenderCastPush.p12). The bundleId should be the one you previously created in the Push Notifications Tutorial. You also need to change the Bundle Identifier for the app as well to match in Xcode.

production should be false if you’re using a development certificate, and true if you’re using a production certificate.

Additionally, add the Master Key to index.js:

// Replace this
masterKey: process.env.MASTER_KEY || '',
 
// With the value of your app's Master Key completed:
masterKey: process.env.MASTER_KEY || '<your app's Master Key>',

Your next step is to put the certificate inside the local Parse Server directory, so it can be sent to the Heroku service, by running these commands in Terminal:

$ git add .
$ git commit -m "added certificate"
$ git push heroku master

Switch back to Xcode, open AppDelegate.swift and find the application(_:didFinishLaunchingWithOptions:) method. Replace this:

$0.server = "http://localhost:1337/parse"

With this (using your Heroku URL):

$0.server = "https://afternoon-harbor-27828.herokuapp.com/parse"

Add a private extension Selector, just below the class definition:

// 1
private extension Selector {
  // 2
  static let didReceiveRemoteNotification = #selector(
      UIApplicationDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:))
}

Here’s a step-by-step explanation of the above code:

  1. Set up a private extension on the Selector type so its code is only available inside the AppDelegate.swift file.
  2. Create a didReceiveRemoteNotification selector argument to use inside the Selector definition that you’ll implement next.

Now you’ll register your app for remote push notifications by adding the following lines in application(_: didFinishLaunchingWithOptions:):

// 1
if application.applicationState != .Background {
 
  // 2
  let preBackgroundPush = !application.respondsToSelector(Selector("backgroundRefreshStatus"))
  let oldPushHandlerOnly = !self.respondsToSelector(.didReceiveRemoteNotification)
  var pushPayload = false
  if let options = launchOptions {
    pushPayload = options[UIApplicationLaunchOptionsRemoteNotificationKey] != nil
  }
  if (preBackgroundPush || oldPushHandlerOnly || pushPayload) {
    PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
  }
}
 
// 3
let types: UIUserNotificationType = [.Alert, .Badge, .Sound]
let settings = UIUserNotificationSettings(forTypes: types, categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()

Here’s a step-by-step explanation of the above code:

  1. Verify the app isn’t opening in background mode
  2. Track the app open event here if you launch with a push, unless “content_available” triggered a background push. In that case, you skip tracking here to avoid double counting the app open.
  3. Set the type of notifications to register for your app, in this case it’s .Alert, .Badge and .Sound. Save these as default notification settings.

Next, you need to store the device token and handle the UI for notifications. Add the following below application(_:didFinishLaunchingWithOptions:):

// 1
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
    deviceToken: NSData) {
  let installation = PFInstallation.currentInstallation()
  installation.setDeviceTokenFromData(deviceToken)
  installation.saveInBackground()
}
// 2
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
    error: NSError) {
  if error.code == 3010 {
    print("Push notifications are not supported in the iOS Simulator.")
  } else {
    print("application:didFailToRegisterForRemoteNotificationsWithError: %@", error)
  }
}
// 3
func application(application: UIApplication, didReceiveRemoteNotification
    userInfo: [NSObject : AnyObject]) {
  PFPush.handlePush(userInfo)
  if case(.Inactive) = application.applicationState {
    PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
  }
}

Here’s a step-by-step explanation of what you just added:

  1. This method is called once the app successfully registers with the APNs (Apple Push Notification service). The device will only act on notifications that have the specified deviceToken.
  2. When the APNs can’t complete device registration due to an error, this method gets called with error information, so your app can determine why registration failed.
  3. When your app receives a remote notification from the APNs, this method is called. If the app is running, it calls this method to process incoming remote notifications.

Build and run the app on a device because push notifications aren’t supported in iOS Simulator. To test, run this command in Terminal — remember to replace the Application ID, Master Key and server URL:

curl -X POST \
-H "X-Parse-Application-Id: <YOUR_APP_ID>" \
-H "X-Parse-Master-Key: <YOUR_MASTER_KEY>" \
-H "Content-Type: application/json" \
-d '{
  "where": {
    "deviceType": "ios"
  },
  "data": {
    "alert": "Hello, Parse!"
  }
}' https://<YOUR_SERVER_URL>.herokuapp.com/parse/push

If all went well, you should get a notification on your screen as shown below:

parse server tutorial

Bonus: Parse Dashboard

Only a few days after releasing push notifications for the Parse Server, the team at Parse also opened up the very useful dashboard. It can be used locally or in the cloud.

To install it locally, you need to clone the GitHub repository on your machine. Enter this into Terminal:

$ git clone https://github.com/ParsePlatform/parse-dashboard.git
$ cd parse-dashboard
$ npm install

The dashboard isn’t fully compatible with the Parse Server instance you’ve set up. It’s only compatible with versions 2.1.4 or newer.

However, that’s no reason why you can’t take a peek at this powerful and useful tool which you can now use too, both in development and production.

Note: By the way, there’s no reason you can’t upgrade your instance later to experience the dashboard’s full-fledged capabilities.

In Terminal, in the Parse-Dashboard subfolder, edit parse-dashboard-config.json. Add your IDs, keys, URLs and names as shown below:

{
  "apps": [
    {
      "serverURL": "https://api.parse.com/1",
      "appId": "myAppId",
      "masterKey": "myMasterKey",
      "javascriptKey": "myJavascriptKey",
      "restKey": "myRestKey",
      "appName": "My Parse.Com App"
    },
    {
      "serverURL": "http://localhost:1337/parse",
      "appId": "myAppId",
      "masterKey": "myMasterKey",
      "appName": "My Parse Server App"
    }
  ]
}

Run this command in the Parse Dashboard directory from Terminal:

$ npm run dashboard

Next, copy and paste http://localhost:4040 into your browser, and you’ll see your app in the dashboard! For your apps on Parse.com, you currently have full run of the place, including the data browser, Parse config and API console. Your cloud code and logs as there too.

For apps on the Parse Server, only the data browser and API console are available.

parse server tutorial

Where to go From Here?

You can download the finished project here. As usual, you’ll need to replace the AppID and ClientKey with your own keys to make it all work right.

To expand on what you’ve done in this Parse server tutorial, you could:

  • Explore Parse dashboard’s full potential by setting up a full version of the Parse Server.
  • Explore the extended capabilities of using a push adapter for other push providers that use the default APN.
  • Look into and compare other Parse alternatives such as Firebase or CloudKit, but beware that these alternatives lack some features covered in this Parse server tutorial.

Now you know that the end of Parse as we know it is not the end of the world, nor will you have to reinvent the wheel to transition gracefully away from the status quo.

There’s certainly a lot to talk about though, so bring your thoughts, questions and findings to the forums and let’s make some magic happen. I look forward to connecting with you!

Parse.com is (soon) dead, long live the Parse Server!

The post Migrating to Parse Server appeared first on Ray Wenderlich.

Video Tutorial: Beginning Core Graphics Part 2: Paths

Android ListView Tutorial

$
0
0

How many times have you needed an app to display a group of related items in a list? How about all the time. :]

Displaying a specific list is essential to the function of almost any app that queries a set of data and returns a list of results, so many apps need to do this at one point or another. For instance, maybe you have a chat app that queries a certain social platform’s database to find your friends, and then want to display them in a list that lets you select which friends to connect with.

Any time you need to display a lot of data and make it easy to navigate, you’ve got a job for Android’s ListView, which handily creates scrollable lists.

By working through this tutorial, you’ll become familiar with a ListView, and you’ll do so by creating a recipe list app. Specifically, you’ll learn:

  • How to construct and populate a ListView
  • How to customize the layout
  • How to style and beautify a ListView
  • How to optimize a ListView’s performance

You’re welcome to up your game in the kitchen by learning the recipes too, but maybe wait until you’ve built the app, okay?

Note: If you’re new to Android Development, it’s highly recommended that you start with the Android Tutorial for Beginners to learn your way around the basic tools and concepts.

Getting Started

Download the starter project and open Android Studio.

In the Welcome to Android Studio dialog, select Import project (Eclipse ADT, Gradle, etc.).

In the following dialog, select the top-level directory of the starter project AllTheRecipes-Starter and click OK.

Inside the imported project, you’ll find some assets and resources that you’ll use to create your app, such as strings, colors, XML layout files, and fonts. Additionally, there’s some boilerplate code modeling a Recipe object and a bare bones MainActivity class.

Build and run. You should see something like this:

Are you ready to get cracking on this list thing? Awesome!

Add Your First ListView

The first order of business is to add a ListView to MainActivity.

Open res/layout/activity_main.xml. As you may know, this is the file that describes the layout of MainActivity. Add a ListView to MainActivity by inserting the following code snippet inside the RelativeLayout tag:

  <ListView
      android:id="@+id/recipe_list_view"
      android:layout_height="match_parent"
      android:layout_width="match_parent">
  </ListView>

Open MainActivity.java and add an instance variable for your ListView with the following line:

private ListView mListView;

Add the following snippet below the existing code inside the onCreate method:

mListView = (ListView) findViewById(R.id.recipe_list_view);
// 1
final ArrayList<Recipe> recipeList = Recipe.getRecipesFromFile("recipes.json", this);
// 2
String[] listItems = new String[recipeList.size()];
// 3
for(int i = 0; i < recipeList.size(); i++){
  Recipe recipe = recipeList.get(i);
  listItems[i] = recipe.title;
}
// 4
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, listItems);
mListView.setAdapter(adapter);

Here’s a breakdown of what’s happening in there:

  1. This loads a list of Recipe objects from a JSON asset in the app. Notice that the starter project contains a Recipe class that models and stores the information about the recipes that will be displayed.
  2. This creates an array of strings that’ll contain the text to be displayed in the List View.
  3. This populates the ListView’s data source with the titles of the recipes loaded in section one.
  4. This creates and sets a simple adapter for the ListView. The ArrayAdapter takes in the current context, a layout file specifying what each row in the list should look like, and the data that will populate the list as arguments.

Enough talk! Your ListView has all that it needs to function. Build and run the project. You should see something like this:

Adapters: Servants of the ListView

Your recipe app is starting to look functional, but not all that appetizing…yet.

In the previous section, you successfully built a list of recipe titles. It works, but it’s nothing to get excited about. What if you needed to show more than just the titles? More than just text? Maybe even add some screen-licking worthy thumbnails?

For these cases, the simple ArrayAdapter you just used won’t cut it. You’ll have to take matters into your own hands and write your own adapter. Well, you won’t actually write your own adapter, per se; you’ll simply extend a regular adapter and make some tweaks.

What Exactly is an Adapter?

An adapter loads the information to be displayed from a data source, such as an array or database query and creates a view for each item. Then it inserts the views into the ListView.

Adapters not only exist for ListViews, but for other kinds of views as well; ListView is a subclass of AdapterView, so you can populate it by binding it to an adapter.

The adapter acts as the middle man between the ListView and data source, or its provider. It works kind of like this:

The ListView asks the adapter what it should display, and the adapter jumps into action:

  • It fetches the items to be displayed from the data source
  • It decides how they should be displayed
  • It passes this information on to the ListView
  • In short, The ListView isn’t very smart, but when given the right inputs it does a fine job. It fully relies on the adapter to tell it what to display and how to display it.

    Building Adapters

    Okay, now that you’ve dabbled in theory, you can get on with building your very own adapter.

    Create a new class by Right-clicking on java/com.raywenderlich.alltherecipes and selecting New > Java Class. Name it RecipeAdapter and define it with the following:

    public class RecipeAdapter extends BaseAdapter {
    }

    You’ve made the skeleton of the adapter. It extends the BaseAdapter class, which requires several inherited methods you’ll implement after taking care of one more detail.

    Add the following snippet inside the RecipeAdapter class:

    private Context mContext;
    private LayoutInflater mInflater;
    private ArrayList<Recipe> mDataSource;
     
    public RecipeAdapter(Context context, ArrayList<Recipe> items) {
      mContext = context;
      mDataSource = items;
      mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    In here, you’ve added the instance variables that will be associated with the adapter and defined a constructor for RecipeAdapter.

    Your next step is to implement the adapter methods. Kick it off by placing the following code at the bottom of RecipeAdapter.

    //1
    @Override
    public int getCount() {
      return mDataSource.size();
    }
     
    //2
    @Override
    public Object getItem(int position) {
      return mDataSource.get(position);
    }
     
    //3
    @Override
    public long getItemId(int position) {
      return position;
    }
     
    //4
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      // Get view for row item
      View rowView = mInflater.inflate(R.layout.list_item_recipe, parent, false);
     
      return rowView;
    }

    Here’s a step-by-step breakdown:

    1. getCount() lets ListView know how many items to display, or in other words, it returns the size of your data source.
    2. getItem() returns an item to be placed in a given position from the data source, specifically, Recipe objects obtained from mDataSource.
    3. This implements the getItemId() method that defines a unique ID for each row in the list. For simplicity, you just use the position of the item as its ID.
    4. Finally, getView() creates a view to be used as a row in the list. Here you define what information shows and where it sits within the ListView. You also inflate a custom view from the XML layout defined in res/layout/list_item_recipe.xml — more on this in the next section.

    Defining the Layout of the ListView’s Rows

    You probably noticed that the starter project comes with the file res/layout/list_item_recipe.xml that describes how each row in the ListView should look and be laid out.

    Below is an image that shows the layout of the row view and its elements:

    Your task is to populate each element of the row view with the relevant recipe data, hence, you’ll define what text goes in the “title” element, the “subtitle” element and so on.

    In the getView() method, add the following code snippet just before the return statement:

    // Get title element
    TextView titleTextView =
      (TextView) rowView.findViewById(com.raywenderlich.alltherecipes.R.id.recipe_list_title);
     
    // Get subtitle element
    TextView subtitleTextView =
      (TextView) rowView.findViewById(com.raywenderlich.alltherecipes.R.id.recipe_list_subtitle);
     
    // Get detail element
    TextView detailTextView =
      (TextView) rowView.findViewById(com.raywenderlich.alltherecipes.R.id.recipe_list_detail);
     
    // Get thumbnail element
    ImageView thumbnailImageView =
      (ImageView) rowView.findViewById(com.raywenderlich.alltherecipes.R.id.recipe_list_thumbnail);

    This obtains references to each of the elements (or subviews) of the row view, specifically the title, subtitle, detail and thumbnail.

    Now that you’ve got the references sorted out, you need to populate each element with relevant data. To do this, add the following code snippet under the previous one but before the return statement:

    // 1
    Recipe recipe = (Recipe) getItem(position);
     
    // 2
    titleTextView.setText(recipe.title);
    subtitleTextView.setText(recipe.description);
    detailTextView.setText(recipe.label);
     
    // 3
    Picasso.with(mContext).load(recipe.imageUrl).placeholder(R.mipmap.ic_launcher).into(thumbnailImageView);

    Here’s what you’re doing in the above snippet:

    1. Getting the corresponding recipe for the current row.
    2. Updating the row view’s text views so they are displaying the recipe.
    3. Making use of the open-source Picasso library for asynchronous image loading — it helps you download the thumbnail images on a separate thread instead of the main thread. You’re also assigning a temporary placeholder for the ImageView to handle slow loading of images.
    Note: You should never perform long-running tasks on the main thread. When you do, you expose yourself to the risk of blocking the UI, and that would make scrolling your lists a nightmare!

    Now open up MainActivity.java so that you can get rid of the old adapter. In onCreate, replace everything below (but not including) this line:

    final ArrayList<Recipe> recipeList = Recipe.getRecipesFromFile("recipes.json", this);

    With:

    RecipeAdapter adapter = new RecipeAdapter(this, recipeList);
    mListView.setAdapter(adapter);

    You just replaced the rather simple ArrayAdapter with your own RecipeAdapter to make the list more informative.

    Build and run and you should see something like this:

    Now you’re cooking for real! Look at those recipes — thumbnails and descriptions sure make a big difference.

    Styling

    Now that you’ve got function under wraps, it’s time to turn your attention to the finer things in life. In this case, your finer things are elements that make your app more snazzy, such as compelling colors and fancy fonts.

    Start with the fonts. Look for some custom fonts under assets/fonts. You’ll find three font files: JosefinSans-Bold.ttf, JosefinSans-SemiBoldItalic.ttf and Quicksand-Bold.otf.

    Open RecipeAdapter.java and go to the getView() method. Just before the return statement, add the following:

    Typeface titleTypeFace = Typeface.createFromAsset(mContext.getAssets(), "fonts/JosefinSans-Bold.ttf");
    titleTextView.setTypeface(titleTypeFace);
     
    Typeface subtitleTypeFace =
      Typeface.createFromAsset(mContext.getAssets(), "fonts/JosefinSans-SemiBoldItalic.ttf");
    subtitleTextView.setTypeface(subtitleTypeFace);
     
    Typeface detailTypeFace = Typeface.createFromAsset(mContext.getAssets(), "fonts/Quicksand-Bold.otf");
    detailTextView.setTypeface(detailTypeFace);

    In here, you’re assigning a custom font to each of the text views in your rows’ layout. You access the font by creating a Typeface, which specifies the intrinsic style and typeface of the font, by using createFromAsset(). Next you call setTypeface() for the corresponding TextView to set the custom font.

    Now build and run. Your result should look like this:

    On to sprucing up the colors, which are defined in res/values/colors.xml. Open up RecipeAdapter.java and add the following below the instance variable declarations and above the constructor:

    private static final HashMap<String, Integer> LABEL_COLORS = new HashMap<String, Integer>() {{
      put("Low-Carb", R.color.colorLowCarb);
      put("Low-Fat", R.color.colorLowFat);
      put("Low-Sodium", R.color.colorLowSodium);
      put("Medium-Carb", R.color.colorMediumCarb);
      put("Vegetarian", R.color.colorVegetarian);
      put("Balanced", R.color.colorBalanced);
    }};

    You’ve created a hash map that pairs a recipe detail label with the resource id of a color defined in colors.xml.

    Now go to the getView() method, and add this line just above the return statement:

    detailTextView.setTextColor(ContextCompat.getColor(mContext, LABEL_COLORS.get(recipe.label)));

    Working from the inside out:

    • Here you get the resource id for the color that corresponds to the recipe.label from the LABEL_COLORS hash map.
    • getColor() is used inside of ContextCompat to retrieve the hex color associated with that resource id.
    • Then you set the color property of the detailTextView to the hex color.

    Build and run. Your app should look like this:

    User Interaction

    Now your list has function and style. What’s it missing now? Try tapping or long pressing it. There’s not much to thrill and delight the user.

    What could you add here to make the user experience that much more satisfying? Well, when a user taps on a row, don’t you think it’d be nice to show the full recipe, complete with instructions?

    You’ll make use of AdapterView.onItemClickListener and a brand spanking new activity to do this with elegance.

    Make a New Activity

    This activity will display when the user selects an item in the list.

    Right-click on java/com.raywenderlich.alltherecipes then select New > Activity > EmptyActivity to bring up a dialog. Fill in the Activity Name with RecipeDetailActivity. Leave the automatically populated fields as-is. Check that your settings match these:


    Click Finish.

    Open res/layout/activity_recipe_detail.xml and add a WebView by inserting the following snippet inside the RelativeLayout tag:

    <WebView
          android:id="@+id/detail_web_view"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />

    WebView will be used to load and display a webpage containing the selected recipe’s instructions.

    Open up RecipeDetailActivity.java, and add a WebView reference as an instance variable by adding the following line within the class definition:

    private WebView mWebView;

    Head back to MainActivity.java and add the following to the bottom of the onCreate method:

    final Context context = this;
    mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
     
      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // 1
        Recipe selectedRecipe = recipeList.get(position);
     
        // 2
        Intent detailIntent = new Intent(context, RecipeDetailActivity.class);
     
        // 3
        detailIntent.putExtra("title", selectedRecipe.title);
        detailIntent.putExtra("url", selectedRecipe.instructionUrl);
     
        // 4
        startActivity(detailIntent);
      }
     
    });

    Note: Before you dive into the explanation, make sure you understand the four arguments that are provided by onItemClick; they work as follows:

    • parent: The view where the selection happens — in your case, it’s the ListView
    • view: The selected view (row) within the ListView
    • position: The position of the row in the adapter
    • id: The row id of the selected item

    The first thing you do in the last snippet is set the OnItemClickListener object for the ListView. The OnItemClickListener class has a method named onItemClick that you override — more on that in a moment.

    At @Override, you override the existing onItemClick method and implement the following steps:

    1. Get the recipe object for the row that was clicked
    2. Create an intent to navigate to your RecipeDetailActivity to display more information
    3. Let the RecipeDetailActivity know the title and URL of the recipe to display by passing that data via the Intent.
    4. Launch the RecipeDetailActivity by passing the intent object you just created to the startActivity() method.
    Note: To learn more about intents, check out the awesome Android: Intents Tutorial.

    Once again, open RecipeDetailActivity.java and add the following snippet at the bottom of the onCreate method:

    // 1
    String title = this.getIntent().getExtras().getString("title");
    String url = this.getIntent().getExtras().getString("url");
     
    // 2
    setTitle(title);
     
    // 3
    mWebView = (WebView) findViewById(R.id.detail_web_view);
     
    // 4
    mWebView.loadUrl(url);

    You can see a few things happening here:

    1. You retrieve the recipe data from the Intent passed by MainActivity by using the getExtras() method.
    2. You set the title on the action bar of this activity to the recipe title.
    3. You initialize mWebView to the web view defined in the XML layout.
    4. You load the recipe web page by calling loadUrl() with the corresponding recipe’s URL on the web view object.

    Build and run. When you click on the first item in the list, you should see something like this:

    Optimizing Performance

    Whenever you scroll the ListView, its adapter’s getView() method is called in order to create a row and display it on screen.

    Now, if you look in your getView() method, you’ll notice that each time this method is called, it performs a lookup for each of the row view’s elements by using a call to the findViewById() method.

    These repeated calls can seriously harm the ListView’s performance, especially if your app is running on limited resources and/or you have a very large list. You can avoid this problem by using the View Holder Pattern.

    Implement a ViewHolder Pattern

    To implement the ViewHolder pattern, open RecipeAdapter.java and add the following after the getView() method definition:

    private static class ViewHolder {
      public TextView titleTextView;
      public TextView subtitleTextView;
      public TextView detailTextView;
      public ImageView thumbnailImageView;
    }

    As you can see, you create a class to hold your exact set of component views for each row view. The ViewHolder object stores each of the row’s subviews, and in turn is stored inside the tag field of the layout.

    This means you can immediately access the row’s subviews without the need to look them up repeatedly.

    Now, in getView(), replace everything above (but NOT including) this line:

    Recipe recipe = (Recipe) getItem(position);

    With:

    ViewHolder holder;
     
    // 1
    if(convertView == null) {
     
      // 2
      convertView = mInflater.inflate(R.layout.list_item_recipe, parent, false);
     
      // 3
      holder = new ViewHolder();
      holder.thumbnailImageView = (ImageView) convertView.findViewById(R.id.recipe_list_thumbnail);
      holder.titleTextView = (TextView) convertView.findViewById(R.id.recipe_list_title);
      holder.subtitleTextView = (TextView) convertView.findViewById(R.id.recipe_list_subtitle);
      holder.detailTextView = (TextView) convertView.findViewById(R.id.recipe_list_detail);
     
      // 4
      convertView.setTag(holder);
    }
    else{
      // 5
      holder = (ViewHolder) convertView.getTag();
    }
     
    // 6
    TextView titleTextView = holder.titleTextView;
    TextView subtitleTextView = holder.subtitleTextView;
    TextView detailTextView = holder.detailTextView;
    ImageView thumbnailImageView = holder.thumbnailImageView;

    Here’s the play-by-play of what’s happening above.

    1. Check if the view already exists. If it does, there’s no need to inflate from the layout and call findViewById() again.
    2. If the view doesn’t exist, you inflate the custom row layout from your XML.
    3. Create a new ViewHolder with subviews initialized by using findViewById().
    4. Hang onto this holder for future recycling by using setTag() to set the tag property of the view that the holder belongs to.
    5. Skip all the expensive inflation steps and just get the holder you already made.
    6. Get relevant subviews of the row view.

    Finally, update the return statement of getView() with the line below.

    return convertView;

    Build and run. If your app was running a bit slow on the last build, you should see it running smoother now. :]

    Where to Go From Here?

    You can download the completed project here.

    When you develop for Android, ListViews (as well as other AdapterViews) are a common concept that you’ll run into over and over again.

    If you want to know more about the inner workings of the ListView and performance details, check out this article on performance tips for Android ListViews.

    There are actually other ways to create lists, such as subclassing a ListActivity and ListFragment. Both of these links take you to the official Android developer site so that you can learn more about how they work.

    Both of these alternatives impose the restriction that the respective activity or fragment can only contain a ListView as its child view. Suppose you wanted an activity that had a ListView as well as some other views, it would be impossible with a ListActivity. The same goes for the ListFragment scenario.

    Look out for our upcoming tutorial on GridViews. In the meantime, feel free to share your feedback, findings or ask any questions in the comments below or in the forums. Talk to you soon!

    The post Android ListView Tutorial appeared first on Ray Wenderlich.

    Viewing all 4370 articles
    Browse latest View live


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