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

Video Tutorial: How to Make a Game Like Flappy Bird in Swift Part 8: Main Menu & Tutorial Screen


Continuous Integration, and Live Rendering in Interface Builder – Podcast S05 E06

$
0
0
continuous integration

Continuous Integration is important in any development environment. Find out why in this episode.

Join Mic, Jake, and Andy as they discuss the value of continuous integration, before moving onto live rendering of custom controls in Interface Builder.

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

This episode was brought to you by the incredibly kind folks over at Hired.

Hired is the platform for the best iOS developer jobs.

Candidates registered with Hired receive an average of 5 offers on the platform, all from a single application. Companies looking to hire include Facebook, Uber and Stripe.

With Hired, you get job offers and salary and/or equity before you interview, so you don’t have to waste your time interviewing for jobs you might not end up wanting, and it’s totally free to use!

Plus you, our loyal audience, will receive a $2000 bonus from Hired if you find a job through the platform, just for signing up using the show’s exclusive link: hired.com/ray

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

Show Notes

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. Be sure to subscribe in iTunes to get notified when the next episode comes out.

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

The post Continuous Integration, and Live Rendering in Interface Builder – Podcast S05 E06 appeared first on Ray Wenderlich.

Build for Yourself: A Top App Dev Interview with Drew Wilson

$
0
0

Drew Wilson

Welcome to another article of the Top App Dev Interview series, where we interview developers and designers who are running successful software businesses.

Building a successful business isn’t easy, and it doesn’t happen overnight–it takes passion, hard work and a few million cups of coffee :]

For this interview, we have none other than Drew Wilson, the impressively prolific author of many web, iOS and Mac apps. He started building software almost twenty years ago, and apparently nobody can stop him (not that we’d want to).

Read on to discover how Drew works, how he got started, and his best piece of advice.

Meet Drew

Hi Drew, and welcome! For our readers who don’t know you yet, can you give us an overview of who you are and what you do?

The Plasso Market

For sure. I’m Drew Wilson and I make software.

I got started early on, and made my first website in 1996. These days I focus on designing and developing my own software. Mostly web software, but I also have built a number of iOS apps and a couple Mac apps.

Currently I’m working on my payments platform Plasso and I am about to launch a new photo editing platform for Mac and iOS called Filtron.

Awesome, it sounds like you have a lot going on. How did you get started as an indie software developer?

I started doing traditional art as a kid. I was lucky enough to have access to Photoshop when it was at version 2!

A few years later, I started experimenting with designing websites. I had seen microsoft.com way back in ’95 or ’96 and was blown away at how they had a sidebar and header that came together with a curved line. I was so curious as to how they made a curved line and a website that felt cohesive, rather than just a bunch of text/images on a page.

That curiosity led me to learn HTML/CSS. But I never wanted to code, which seemed so boring to me at the time. It wasn’t until 2002 that I finally decided to learn a server side language (PHP).

Learning to code totally changed my life; being able to fully realize my designs all by myself was amazing. I immediately started building my own ideas. It wasn’t until 2008 that I released my first piece of paid software.

Build And Build And Build

What’s your process for building a product? Do you start by scratching an itch, or do you conduct market research?

I build what I want. So if I wish there was a tool to do X or to do X better, I’ll build it.

It’s great because even if the tool doesn’t do well commercially, I still benefit because now I have a tool that works the way I want it to. I never need to do market research because I like to build things where I am the target market.

You work mostly solo, but when you team up with other developers or designers, where do you find people to work with, and how do you handle payments or royalties?

I reach out to people I like and know are smart. I like to build for fun, so I mostly partner up with people I can have fun building with. Typically these are people I’ve met before through some event or just from twitter convos.

Long ago I built a website to connect designers and developers called builditwith.me (which is about to re-launch with new owners). I once used that to find a developer and he ended up being a good friend–we still make stuff together all these years later!

When it comes to split, it’s always even. If there are two of us, then it’s 50/50. The only time that has changed is if I already have an existing product with traction and/or revenue. If that’s the case then the split is not 50/50, but something fair for sure.

Dev puppies

Good dev puppies split profits equitably!

You develop Mac apps, iOS apps and web products. Which of these have you found to be the most lucrative?

Web. The most profitable thing I’ve built to date is my payments platform Plasso.

Second most profitable would be my icons, Pictos.

I also built and launched a screen-capturing app for Mac years ago called Screeny and it did really well; it was the tenth top paid app in the Mac App Store. At its best, it made around $3-4k one month. But significant sales didn’t last more than a few months.

My most downloaded and used iOS app is one I built in 24 hours – LOL! It’s a free app called OffOf and it has a 5 star rating!

A screenshot of OffOf

A screenshot of OffOf

I’m hoping to change all that and finally be featured by Apple (hopefully) with Filtron. I’m releasing a Mac and iOS app at the same time, as well as a web component. Hoping people love it as much as I do. I’ve been working on it for two years. Yes, two years.

Mac development is hard (especially since this is really my first Mac app where I’m doing more than just UI development). It’s been a very painful road and I’m super excited to get it out.

Blood, Sweat and Tears

What’s the product that required the biggest effort? How long did it take to build?

Up until Filtron, it was my first piece of software, Firelift, which took two years to make and involved multiple all-nighters per week.

I’m not doing all-nighters with Filtron, but it’s the largest task I’ve undertaken to date. It started out as a different app altogether, and evolved into what I’m building now. Counting the time I spent building what Filtron used to be, I’ve been working on it since 2012. Insane, I know.

ragecomic1

What challenges did you stumble upon during its development?

The biggest challenge was finding people to work on Filtron. UI development is one thing, but Filtron has its own filtering engine based on GPUImage. Not many people know how or want to work on something that complex. Finding people to work on Filtron with me has literally been the single hardest thing I have ever done. Literally.

I eventually realized I needed to get good at Mac and iOS development very quickly. In that regard, it has been great. I’m super confident these days in my ability to make Mac and iOS apps. Literally one year ago I hardly knew anything about Mac and iOS beyond UI development.

Let’s talk about Swift. Have you used it? What was your experience?

I use Swift in the Filtron Mac app. The iOS app was built before Swift came out, so rather than spend any time converting it, I’m finishing the Mac app.

Swift is great, but the bummer with someone learning it this early, for a pretty complex app, is lack of documentation. I always tell my wife, “If Filtron were a web app, I literally would have built it in a month”. It’s very true. Many web developers don’t have a clue how good they have it!

UIKit and iOS is pretty close to the web, with tons of resources, documentation, OSS, etc. But it’s a completely different universe when you go to the Mac.

I often feel like I’m the only human building Mac apps. Most articles written about Mac dev or code samples on the web are years old. It’s terrible. Unless you are building a super simple app, you have to figure most everything out yourself. Which is great, but ultra time consuming.

To Infinity and Beyond

Can you give us a glimpse of your next product?

Filtron! The tag line is: “Create and share your own photo filters.” The idea is to make Filtron THE platform for photo effects.

A screenshot of Filtron

Filtron

For now, this means creating them and sharing them with others for free. Later, it will mean that anyone can integrate with Filtron to have access to tens of thousands of filters for their apps. That might seem like too many filters, but we already have discovery and search stuff built in. So you can easily surface the best filters or newest, etc.

There is a lot planned, and this really is just the beginning. I stripped out a number of features just so I could get this thing out. So there will be more added to it once it is out.

What advice would you give to a teenager who wants to build software products for a living?

Start now. Spend time learning and practicing. The best way to do that is build things for yourself.

Also, build small so you can finish things. Eventually you will be able to build bigger things. Just start building!

Where To Go From Here?

And that’s a wrap for the interview! Many thanks to Drew Wilson for letting us peek into his work. It’s always interesting to see where devs got their start, how they work now, and what’s in their future. Good luck with all your projects, Drew!

We hope you all enjoyed the interview, and … why are you still reading? Didn’t you read Drew’s advice? Start building!

And if you need help with Swift or even OS X tutorials, we’re here :]

Note from Ray: Did you like this top app dev interview and would you like to see more in the future? Is there anyone in particular you’d like to see? Let us know!

The post Build for Yourself: A Top App Dev Interview with Drew Wilson appeared first on Ray Wenderlich.

Video Tutorial: How to Make a Game Like Flappy Bird in Swift Part 9: Game Over Screen

Video Tutorial: How to Make a Game Like Flappy Bird in Swift Part 10: Animation & Rotation

Video Tutorial: How to Make a Game Like Flappy Bird in Swift Part 11: Finishing Touches

Video Tutorial: How to Make a Game Like Flappy Bird in Swift Part 12: Making It Work on Apple TV (tvOS)

Video Tutorial: Beginning iOS Animation: Series Introduction


Video Tutorial: Beginning iOS Animation Part 1: Beginning Constraint Animations

Best Markdown Editors for OS X

$
0
0

Best Markdown Editors for OS X!

Markdown is an easy-to-use markup language in a plain text format. For example, you can write some markup like this:

# This is a header

This is a main paragraph with some *emphasized* text.

Markdown feels very natural to write, and the best part is once you’re done you can use various tools to rendered your Markdown into richly formatted text files, such as HTML, Word, or PDF. But to do this, you need a editor – and that’s what this article is all about!

For this article, I surveyed the raywenderlich.com team to see what editors we use, what we like about those editors, and what these editors lack. From a initial list of more than twenty editors, I’ve assembled a list of the five top best Markdown editors for OS X.

Here are the top 5 best Markdown editors for OS X as chosen by the raywenderlich.com team!

Note: For the sake of this article, we are calling an “editor” any tool that allows you to edit or render Markdown (not necessarily both).

Getting Started

Before we dive into the top 5 Markdown editors, let’s talk about why you should use Markdown in the first place, and why you need a Markdown editor at all.

Why Markdown?

Github logo

I discovered Markdown the same way I suspect many developers did — through its use on GitHub, which uses Markdown to format issues, comments, and pull request descriptions.

Markdown quickly became my preferred writing format because it helps me stay focused on recording my thoughts and ideas quickly and efficiently.

Since a Markdown document is just a text document, any text editor can create and edit Markdown documents. I can create a document on my MacBook and edit on my Windows machine or iPad without worrying about cross-platform issues.

You’ll find support for Markdown in many tools, workflows, and web sites. For example, we use it here at raywenderlich.com to create our books, using a custom tool we wrote that converts Markdown into book PDFs.

Once you start using Markdown, you’ll get addicted. The team and I are now officially Markdown junkies! :]

Why a Markdown Editor?

TextEdit Like a Boss

You might be asking, “Do I really need a Markdown editor? Can’t I just use any old plain-text editor?”

Generally, Markdown won’t be the final destination format of your piece of work, so you’ll need a tool that can convert Markdown to a richly formatted document such as HTML, Word, or PDF, which can be customized along the way via CSS or other display formatters.

Some Markdown editors provide a preview of the rendered document in real time when writing or editing, which reduces the number of times you need to render your work externally to proof for markup mistakes. In my initial drafts, I prefer tools that let me hide this preview so I can work in distraction-free text mode.

As well, many Markdown editors offer formatting assistance, such as syntax highlighting and coloration, to point out markup errors or missing markup elements. Some tools provide templates for more complex or rarely-used markup items such as table markup in MultiMarkdown.

Some groups have extended the original Markdown specification to include new formatting options. MultiMarkdown and GitHub Flavored Markdown are two of the most common Markdown flavors; support for these two ubiquitous and highly useful formats in a Markdown tool is pretty much a must-have.

Without further ado, let’s get into the top 5 Markdown editors on OS X!

Note: Looking for an OS X Markdown editor? There are two ways to find one based on this article.
  • You can read through our descriptions and pick the one that seems the best match for you.
  • Alternatively, you can follow the instructions to download and install each editor and choose your favorite based on your own experience.

5) Visual Studio Code

Price: Free and open source
Pros: Good for ASP.NET and Node.js developers; allows user defined snippets.
Cons: A bigger and heavier tool than others, and not as flexible as Atom.

Getting Started with Visual Studio Code

You won’t find Visual Studio Code on the Mac App Store; it’s still in pre-release and its installation process reflects that. You can download the app from the Visual Studio home page. The site will auto-detect your OS and provide an appropriate download link:

Visual Studio Code Download Page

Once you’ve downloaded the install package, double-click the file to unzip it in Finder, and drag Visual Studio Code.app into your Applications folder.

Run Visual Studio Code and close the welcome pane. Then start writing some Markdown (you can use the snippet from earlier in the article if you’d like), and save the file with a .markdown extension to get Markdown syntax highlighting to appear:

TestMarkdown

Click the Split Editor button in the upper right to open up another pane:

TestMarkdown2

Finally click the Open Preview button in the upper right to display a rendered version of the Markdown:

TestMarkdown3

You can now edit on the left hand side and see a live preview on the right!

Why Visual Studio Code?

Sample Markdown Document in Visual Studio Code

Sample Markdown Document in Visual Studio Code

I bet you didn’t expect something from Microsoft on this list! :]

Microsoft isn’t the same company it used to be, and neither are their tools. Despite being under the Visual Studio banner, Visual Studio Code is nothing like the bulky IDE you might have seen before. Visual Studio Code delivers a well-thought out, lightweight code editor that’s my personal favorite.

Visual Studio Code targets web developers; it’s not a dedicated Markdown tool. Instead, it focuses on the languages and frameworks used by web developers, especially ASP.NET and Node.js. It still provides solid Markdown support with syntax highlighting and a great HTML preview side-by-side with your Markdown code.

One drawback is there isn’t any way to render Markdown to HTML or PDF directly from Visual Studio Code; you have to create these files as part of a project build.

Overall, Visual Studio Code is a useful Markdown editor, but it’s really designed as tool for web developers working with ASP.NET or Node.js who have a side requirement for Markdown. Once Visual Studio Code is officially released and developers take advantage of the recently added extension support, I think this will become an even better Markdown editor for developers.

4) Sublime Text with MarkdownEditing

Price: $70 per user on any number of computers.
Pros: The Markdown plugin adds syntax highlighting and editing features to already great features.
Cons: Expensive at $70 per user and more complex to configure than similar tools. Installing the Markdown Editing package is not a straightforward process. Preview is only possible with another tool.

Getting Started with Sublime Text

While Sublime Text license costs $70 per user, there’s a free, unlimited evaluation you can try.

Again, you won’t find Sublime Text in the App Store and must download it directly from the the Sublime Text site. You can either choose the stable 2.0 version, or try the beta 3.0 version. The installation instructions below will work for both versions; only the filenames will be different.

Once you’ve downloaded the DMG, double-click the file to open it, and drag the Sublime Text 2.app icon to the Applications folder.

Your next step is to install the MarkdownEditing package into Sublime Text. Start Sublime Text and press Ctrl+` to open the Sublime Text console:

The Sublime Text console

Next, you’ll need to enter a Python command here to install Sublime Package Control; head to https://packagecontrol.io/installation#st2 to get the exact command, since it changes with each release. Once you have it, paste the command into the Sublime Text Console like so:

Python to install Sublime Text Package Control

You’ll be prompted to restart Sublime Text once the package has installed.

Now that Sublime Package Control is installed, you can install the MarkdownEditing package. Press Cmd+Shift+P to bring up the Command Palette. At the prompt, type install package and press Return:

Enter Install Package into Command Pallet

You’ll see the list of packages once it’s been retrieved from the server. Type MarkdownEditing to select the package and press Return to install it. Once the package is installed, Sublime will display a Markdown document with more information about the package:

Install MarkdownEditing package

The Markdown Editing plugin adds better syntax highlighting for Markdown along with additional editing features such as automatic pairing, support for GitHub-flavored Markdown and a host of keystrokes to insert Markdown formatting for links, images, headers and footnotes.

To see this, try opening a file with a .md or .markdown extension:

Sublime1

To see a rendered preview of the Markdown, you’ll need the Markdown Preview extension. To install this, press Cmd+Shift+P to bring up the Command Palette. At the prompt, type install package and press Return:

Sublime2

Then start typing Markdown Preview and hit enter once you find it:

Sublime3

To run the plugin, press Cmd+Shift+P and look for Markdown Preview: Preview in Browser:

Sublime4

Select Github, and then a browser will appear with your Markdown rendered as HTML:

SublimeText5

Note: Optionally, you might want to enable the LiveReload plugin in Sublime Text and your web browser so that as you change your text, your web browser updates automatically. To learn how to do this, check out this handy StackOverflow post that helped me do this.

Why Sublime Text?

Sample Markdown Document in Sublime Text

Sample Markdown Document in Sublime Text

If you’re looking for a simple Markdown tool, but rarely work with plain text in any other capacity, this probably isn’t the tool for you. Sublime Text is a powerful text editor for advanced users — with a complexity and price tag to match. To change editor settings, you’ll need to directly edit the settings files. There’s a rich set of add-ins and plugins, but you’ve seen that the installation process is not exactly straightforward.

So why is Sublime Text on this list, then? If you take the time to learn Sublime Text, you can probably do anything in it faster than any other tool on this list. You can customize the editor to exactly suit the task at hand, and in a few keystrokes you can accomplish what would otherwise take a lot of menu hunting and clicking.

However, the learning curve is steep and not everyone needs the complexity and the full feature set of Sublime Text.

3) Marked 2

Price: $13.99.
Pros: Works in combination with any Markdown editor or other text editor; can compile multiple files for a full preview of your work; previews update in real time as source files change.
Cons: Marked is only a preview tool, so you will need another tool for editing.

Getting Started with Marked

You can either find Marked on the Mac App Store, or purchase the app directly from the author. Want to try before you buy? You can download a trial from the author’s site.

The trial version comes as a zip file; extract Marked 2.app from the zip and drag it to your Applications folder to install. You can convert the trial into a full version at any time.

Once you have it installed, open Marked and open a Markdown file:

Marked

This gives you a preview of the markdown, and you can use the main menu (or one of the buttons in the bottom right) to render the Markdown to different format such as PDF or HTML.

Why Marked?

Viewing Sample Markdown Document in Marked

Viewing Sample Markdown Document in Marked

Marked is different than the other tools on this list as it’s only a preview tool. Nevertheless, I still find it’s one of the most useful Markdown tools in my arsenal, and it was the most popular add-on tool mentioned in our survey. Whenever I’m writing in Markdown, I have this tool open as well.

Marked works with any editor; it detects changes to any file it has open and reflects those changes automatically in its preview. As you work in your Markdown editor, you’ll see Marked update its preview of your work each time you save your changes. Marked can use various stylesheets, including custom CSS, to reflect different rendering requirements.

Changing the CSS style can drastically change the way Markdown converts to rich text.

Changing the CSS style can drastically change the way Markdown converts to rich text.

Marked also provides unique and useful writing tools. Along with the standard statistics of word and sentence counts, it also provides advanced readability statistics and estimates of reading time. It can also highlight a customizable list of overused phrases, show passive voice, and mark duplicated words.

Marked Advanced Statistics

When it’s time to convert your Markdown documents, Marked handles this task perfectly. It can export any Markdown file to PDF, Microsoft Word, or as a complete collection of HTML documents including styles and images. It can also copy HTML source or RTF data from the Markdown to your clipboard for use in other apps.

I’d like to see more options to customize the Word export options, but Marked is still my first choice to convert Markdown documents into formats that I can share with others.

2) Atom

Price: Free and open source.
Pros: Cross-platform with a rich plugin infrastructure; customizable and hackable without the complexity of Sublime Text.
Cons: Can be a memory hog and feels slower than other tools.

Getting Started with Atom

Download the zipped distribution from the main Atom site and extract its contents. Drag the extracted Atom.app file to your Applications folder to complete the install.

Open Atom and open a Markdown file:

Atom1

Then go to Packages\Markdown Preview\Toggle Markdown Preview (or Control-Shift-M) to toggle a Markdown preview:

Atom2

Why Atom?

Editing Sample Markdown in Atom.

Editing Sample Markdown in Atom.

GitHub built Atom with the goal of combining the convenience of modern text editors with the deep configurability of classic, though complex, text editors like Emacs and Vim.

Atom comes with full Markdown support including a robust previewer. It supports GitHub flavored Markdown and includes spell check along with predefined Markdown snippets; all you have to do is type img or table and press Tab to have the template appear in your document.

Using snippets in Atom

You can easily extend Atom using the built-in package manager. The popularity of Markdown means you’ll find several useful packages for it that extend Markdown support, add more export formats and support more specific Markdown uses such as static blogging tools.

Installing Packages in Atom

1) MacDown

Price: Free and open source.
Pros: Comes with great preview abilities; a stable and flexible tool.
Cons: Not signed with a developer certificate; a less fully-featured text editor that’s not built for coding.

Getting Started with MacDown

Download the zip file using the Download MacDown link on the author’s site. Extract the MacDown.app and drag the file to your Applicatons folder to install. If you use Homebrew Cask, you can install it from Terminal with brew cask install macdown.

MacDown has one complication the other tools don’t: it’s not signed with a developer certificate, which means if you’re running OS X Lion or later and have Gatekeeper running, you’ll see an error noting you can’t run the app:

MacDown Gatekeeper Error

To use MacDown in this scenario, you must set your Gatekeeper settings under System Preferences\Security & Privacy to either Mac App Store and identified developers or Anywhere:

System Preferences Gatekeeper

If you choose “Mac App Store and identified developers”, you’ll have to authorize the app to run it. Right-click on the app, hold down Shift then click Open. You’ll be warned this app is from an unidentified developer:

MacDown Unidentified Warning

Simply click Open to override this and you won’t be asked again.

Then you can open a Markdown file as usual:

MacDown

You can also use File\Export to export your document to HTML or PDF.

Why MacDown?

Editing Sample Markdown in MacDown.

Editing Sample Markdown in MacDown.

I use MacDown more than any other Markdown tool, and the number of times it was mentioned in my survey results confirms its spot as the number one Markdown tool. If you want a simple, clean editor just for Markdown editing, it’s hard to find a better tool than this one.

MacDown author Tzu-Ping Chun began work on the tool after the announcement that one of his favorite tools, Mou, was ending active development. MacDown provides a popular and well-thought out editor that’s focused on composing Markdown. It’s not a code editor, and it’s not a full featured text editor such as Sublime Text. This is intentional; MacDown is a minimalistic tool that gets out of your way and treats your interaction with your document as a priority.

When I write, I usually choose a tool that will stay out of my way but provide assistance when I need it. MacDown fits that role really well. You can apply formatting through the menu or via keyboard shortcuts. It’s easy to use and looks great.

Despite it’s minimalist design, MacDown is full-featured, supports a lot of Markdown syntax, provides autocompletion, and lets you customize the rendering of previews. Exporting to PDF or HTML produces consistently good results.

Where to Go From Here?

You might be thinking “which of these Markdown editors is best for me?”

Unfortunately, there really isn’t one tool to rule them all; I personally use all of these tools (with the exception of Sublime Text) at different times. Each tool has its strengths and provides a good solution for the specific task at hand:

  • If you’re looking for a pure Markdown writing and prose writing experience, MacDown provides a solid Markdown editor without a lot of extra features you’ll probably never use. It’s especially good for new Markdown users.
  • If you’re a developer and looking to work with Markdown in development projects, you’ll probably find the best results with Atom — unless you’re working with ASP.NET or Node.js, where Visual Studio Code is the clear winner. Atom is likely the best choice if you really want to customize your editor by adding (or writing!) plugins to match your needs exactly.
  • If you’re a power user, for a powerful text editor that also supports Markdown, Sublime Text with the MarkdownEditing plugin provides the most powerful setup.
  • If you want the most export options or writing statistics, Marked isn’t an editor, but it’s the best export and preview tool available for Markdown. For prose writers, the advanced statistics and insight into your writing are valuable. It also pairs nicely with Sublime Text or other tools that have poor or no live Markdown preview.

And that’s it – happy Markdown editing! Don’t forget to chime in with what you think is the best Markdown editor for OS X – by joining the forum discussion below.

The post Best Markdown Editors for OS X appeared first on Ray Wenderlich.

Video Tutorial: Beginning iOS Animation Part 2: Intermediate Constraint Animations

Video Tutorial: Beginning iOS Animation Part 3: Spring Animations

Android SDK Versions Tutorial

$
0
0

Android-sdk-versions-feature

Ever since the first release of Android, the range of supported devices has grown to represent a wide array of phones, smart watches and more. Everything necessary to start developing Android applications for those devices falls under one specification called the Android SDK (software development kit).

New versions of the SDK, which are released with each new version of Android, take advantage of the increased processing power available on the latest devices to provide great new features. Awesome, right? The flip side, of course, is that Android developers are faced with the challenge of making sure an application will work on a range of devices running different versions of the Android SDK.

Luckily, there are some best practice guidelines and tools to help get the work done without compromising on UX or deadlines.

In this Android SDK Versions tutorial you’ll learn about:

  • Android SDK versions and API Levels
  • Android Support Libraries and their importance
  • How to use the Android Support Library to make an app backward-compatible
  • How to use the CardView Support Library

To put theory into practice, you’ll play with a simple application called Continents that gives short descriptions of the continents in the world.

Note: This Android SDK Versions tutorial assumes you are already familiar with the basics of Android development. If you are completely new to Android development, read the Android Tutorial for Beginners to familiarize yourself with the basics.

Getting Started

Download the starter project for this tutorial and extract the downloaded zip file to get the project.

Open the starter project in Android Studio by selecting Open an existing Android Studio project from the Quick Start menu:

android_sdk_versions_1

You can also select File \ Open. Navigate to and select the starter project folder.

Build and run the project on the emulator or device to make sure it compiles and runs correctly.

Emulating Different SDK Versions

We want to try running the sample app on different Android versions, but since it’s unlikely anyone has an Android device for every single API Level of the SDK, first let’s learn how to set up emulators with different SDK versions.

To set up an emulator, locate the AVD (Android Virtual Device) Manager on the Android Studio Toolbar.

Pasted_Image_20_01_2016__14_37

If the Toolbar is not showing, select View \ Toolbar to show it. You can also open the AVD Manager by selecting Tools \ Android \ AVD Manager.

android_sdk_versions_4

Click the Create a virtual device button. That will open the Select Hardware section of the Virtual Device Configuration window.

android_sdk_versions_5

Select a device of your choice and click Next. That opens the System Image section, which currently shows all installed system images.

android_sdk_versions_6

Checking the Show downloadable system images checkbox will show all system images including the ones not installed yet.

To download a system image, click the Download link by the release name.

android_sdk_versions_7

Notice that the Android platform currently has thirteen major versions of the SDK. Starting with Android 1.5, major versions of the SDK have been developed under a confectionery-themed code name. Google has managed to choose these code names in an alphabetical order. They haven’t run out of names of sweets yet :]

Each version (minor or major) of the Android SDK has an integer value that uniquely identifies it. This unique identifier is referred to as the API Level. The higher the API Level, the later the version. For developers, API Level is important because it is what determines the range of devices an app can run on.

Let’s look at an example, the Android 6.0 release. We can see that:

  • It is the most recent version of the Android SDK
  • Its version number is 6.0
  • Its code name is Marshmallow
  • It has an API Level of 23

For this tutorial, we will need at least two emulators, one with API Level 7 and another one with API Level 22.

Going back to the System Image screen in Android Studio, click the Download button for each of the SDK versions you will need for this tutorial (Level 7 and Level 22). Then select the system image for Level 21 and click Next.

android_sdk_versions_8

On the next screen, click Finish.

android_sdk_versions_9

Try running the sample app on the emulator running API Level 22:

android_sdk_versions_2

It all looks great, right? But if you were to try and run the app on a device with API Level lower than 21 it wouldn’t run. This is because the app only runs on devices that run Android API Level 21 and upwards, which isn’t great for older devices. Later on, you’ll learn how to extend the app’s support from Android API Level 21 to as low as Android API Level 7.

SDK Versions and API Levels

As mentioned earlier, the API Level is a unique integer that identifies a specific version of the Android SDK. Let’s take a look at how API Levels can be specified in Android Studio to compile and release an application.

Open build.gradle for the app module:

build_gradle_21

Here we can see three important attributes:

  • minSdkVersion is the minimum API Level with which the app is compatible. The Android system will prevent a user from installing the application if the system’s API Level is lower than the value specified in this attribute. Android requires the minSdkVersion attribute to always be set.
  • targetSdkVersion is the API Level that the application targets. This attribute informs the system that you have tested against the target version. The targetSdkVersion defaults to the minSdkVersion if not specified.
  • compileSdkVersion specifies the API Level that the application should be compiled against.

Notice here that the compileSdkVersion is set to 22, but at the time of this writing the latest version of Android SDK is 23 (Marshmallow). To upgrade the application to the latest version, change the compileSdkVersion and targetSdkVersion attributes to 23.

Your build.gradle file should now look like this:

build_gradle_23

Build and run the app again. It still looks the same.

android_sdk_versions_12

Note on SDK previews: It’s important to know that when you set the compileSdkVersion to a preview release of the Android framework, Android Studio will force the minSdkVersion and targetSdkVersion to equal the exact same string as compileSdkVersion. This policy is necessary to prevent situations where you might upload your app to the Google Play Store. As a result, you can only run applications where compileSdkVersion is set to a preview release on emulators with that exact same preview and you won’t be able to run it on older devices.

The Android SDK is by default forward compatible but not backward compatible — this means that an application that is built with and supports a minimum SDK version of 3.0 can be installed on any device running Android versions 3.0 and upwards, but cannot be installed on devices running Android versions below 3.0.

Since the Android SDK is not backward compatible, you have to choose the minimum SDK carefully. This means striking a balance between supporting a wide range of devices and designing an app that implements useful features in later SDK versions.

For example, when Android 3.0 was released in 2011, the Action Bar was unleashed on the Android Community. Since the Action Bar was only supported in Android 3.0 and later, using it in an app meant choosing either a cool user interface or supporting devices that ran older versions of the SDK. Sometimes you can’t have your honeycomb and eat it too :[

Or can you? To help with the Action Bar issue, the Android Support Library introduced a backward-compatible version in the v7-appcompat support library to let developers support older versions of the SDK and still use the latest Action Bar APIs in their apps. Sweet! Honeycomb for everyone!

Let’s take a deeper look at what the Support Library does and how it works.

Android Support Libraries

A wide range of components make up what is referred to as the “Support Library” or “Support Libraries,” and they can be categorized in two groups:

  • The AppCompat library: The intention here is to make sure all (or most) of the framework APIs for the latest API Level have been backported to earlier versions and can be found in this single library. The first version of AppCompat was released at Google IO 2013. The goal of this first release was to allow developers to backport the ActionBar to devices running IceScreamSandwich level, giving API parity to the framework across as many API Levels as possible. Since then, the AppCompat library has continued to evolve, and with Android L the support library is now at the point where the API is equivalent to the framework itself — the first time that has ever happened :]
  • Others: The rest of the libraries that make up the Support Library essentially provide new functionality with the same consideration for backward compatibility (palette, gridview, gridlayout, recycler view, material design widgets).

By breaking these up into independent libraries, you can pick and choose the ones you need in your project. It’s important to note that each support library is backward-compatible to a specific API Level and they are usually named based on which API Level they are backward-compatible to. For example, v7-appcompat provides backward compatibility to API Level 7.

You can find the full list of components that fall under the Support Library in the Android documentation.

How to Use an Android Support Library

Time to see an Android support library in action! Open MainActivity.java. As you may have noticed in the onCreate() method, the app uses a Toolbar (which is part of the material design patterns) instead of an Action Bar.

The Toolbar was added in API 21 (Android Lollipop) as a flexible widget that can be used anywhere in layouts, be animated and change in size, unlike the Action Bar.

Thanks to AppCompat, that feature has been back-ported all the way to API 7, which is code-named Eclair (are you hungry yet?). You’re going to use the v7-appcompat support library to extend your app’s compatibility to a minSdkVersion of 7.

Open build.gradle for the app module and add the following to the dependencies section:

compile 'com.android.support:appcompat-v7:23.0.1'

By adding this, you’re declaring the appcompat-v7 support library as a dependency for your application.

Next, change the minSdkVersion attribute to 7.

minSdkVersion 7

Here you’re declaring that the app should be able to run on devices with Android SDK version 2.1. Now try running your application on an emulator running API Level 7 — you should see the following exceptions in the logcat:

logcat

The important line to look for is:

Caused by: java.lang.ClassNotFoundException: android.widget.Toolbar in loader dalvik.system.PathClassLoader[/data/app/com.raywenderlich.continents.apk]

The ClassNotFoundException error indicates that there is no such class in the SDK version you’re running the app against. Indeed, it’s only available in API Level 21, while you’re currently running API Level 7.

You’re going to update the code to use the backward-compatible version of Toolbar. In MainActivity.java, replace android.widget.Toolbar with android.support.v7.widget.Toolbar.

Next do the same for the Fragment class. Open DescriptionFragment.java and find the following line:

import android.app.Fragment;

Update this line to match the following:

import android.support.v4.app.Fragment;

Here you’re using the support version of the Fragment class instead of the one in the main SDK, which can only be used in apps with a minSdkVersion of 11.

Note: AppCompat v7 depends on the v4 Support Library. That’s why you can also use all the APIs in the android.support.v4.app package.

Open the MainFragment.java class, and update the import android.app.Fragment; line to match the following:

import android.support.v4.app.Fragment;

Open the MainActivity.java class, and update the android.widget.Toolbar import statement to match the following:

import android.support.v7.widget.Toolbar;

This replaces the SDK import with one from the AppCompat library.

Now update the MainActivity class definition line so that it inherits from android.support.v7.app.AppCompatActivity:

public class MainActivity extends android.support.v7.app.AppCompatActivity

Once again, you’re replacing a class from the latest SDKs with one that exists in the support library.

You now need to work through the class and replace some method calls with their support library equivalents:

  • Find the call to setActionBar(toolbar) at the end of the onCreate() method body and update it to setSupportActionBar(toolbar).
  • Find the calls to getActionBar() in onContinentSelected() and goToContinentList() and replace both of them with getSupportActionBar().
  • Replace the calls to getFragmentManager() in onContinentSelected() and goToContinentList() with getSupportFragmentManager().

Here, you’ve replaced all the main API calls with corresponding methods from the support library.

In the res / layout folder, open toolbar_custom.xml and do the following:

  • Change android.widget.Toolbar to android.support.v7.widget.Toolbar
  • Change ?android:attr/actionBarSize to ?attr/actionBarSize

Again, all this does is change the package name from android to v7-appcompat.

Now that all of the compile-time errors have been checked and fixed, try to run the app again. You will now get the following run-time error:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.raywenderlich.continents/com.raywenderlich.continents.MainActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

The error message is pretty self-explanatory, but why do you need to use the AppCompat theme? A feature from the Lollipop release of AppCompat is the different approach to theming. One of the interesting things about this is the capability to get an L-friendly version of your app on prior versions. If an app uses the framework version of everything (Activity instead of AppCompatActivity for example), it would only get the material theme on phones with the L release. Devices with prior releases would get the default theme for those releases. The goal of the AppCompat theming feature is to have a consistent experience across all devices.

In the res\values folder, open styles.xml, and change android:Theme.Black.NoTitleBar to Theme.AppCompat.NoActionBar.

Open styles.xml (v21) and repeat exactly the same change: android:Theme.Black.NoTitleBar to Theme.AppCompat.NoActionBar.

styles_xml_files

Now build and run. You can test the app on an API 7 device or emulator as well.

android_sdk_versions_13

android_sdk_versions_14

Well done! The sample app is now backward compatible. Gingerbread and lollipops and jelly beans for everyone!

Let’s throw in some cards to make the detail screen look nicer.

How to Use the Card View Support Library

Open build.gradle for the app module and add the following to the dependencies section:

compile 'com.android.support:cardview-v7:23.1.1'

Adding this declares the v7-cardview support library as a dependency for the application.

Open the fragment_description.xml file and place the ImageView in a CardView:

 <android.support.v7.widget.CardView
         xmlns:card_view="http://schemas.android.com/apk/res-auto"
         android:id="@+id/card_view"
         android:layout_gravity="center"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         card_view:cardBackgroundColor="#316130"
         card_view:cardElevation="20dp">
   <ImageView
           android:id="@+id/continentImage"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:src="@drawable/africa"
           android:paddingBottom="@dimen/activity_vertical_margin"
           android:contentDescription="@string/continent_image_description"/>
 </android.support.v7.widget.CardView>

Notice that when using widgets from the Support Library, some XML attributes (cardBackgroundColor and cardElevation for the CardView) are not prefixed with “android.” That’s because they come from the Support Library API as opposed to the Android framework.

Now, build and run the project:

final_build

Cool, you’ve added this new-style cardview to your app and using the compatibility library it works from modern versions of Android, right back to ancient API-level 7.

Did You Say Material Design?

You’ve successfully used the AppCompat theming to give the app the Android Lollipop look and feel across a wide range of SDK versions. In addition to these elements, the Material Design specification includes many more patterns and widgets not contained by AppCompat. This is where the Design Library comes into play. It provides widgets such as navigation drawers, floating action buttons, snackbars and tabs. Let’s include it in the project and add a floating action button.

In build.gradle add the following in the dependencies section:

compile 'com.android.support:design:23.1.1'

Next add the following XML element below the ListView in fragment_main.xml:

<android.support.design.widget.FloatingActionButton
    android:id="@+id/search_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="16dp"
    android:src="@drawable/ic_search_white_18dp" />

Build and run — you will see the floating button as expected.

fab-button

Backport All the Things?

Some features in the latest releases of the SDK are just too complex to backport. Ultimately, it’s your call to strike the right balance between performance and usability. If you find yourself in a situation where you want to use a framework API that isn’t available in the Support Libraries, you can check for the API Level at run-time. In the onContinentSelected method of MainActivity.java, add the following after the description fragment is instantiated but before the fragment transaction:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  descriptionFragment.setEnterTransition(new Fade());
  mMainFragment.setExitTransition(new Fade());
  descriptionFragment.setExitTransition(new Slide(Gravity.BOTTOM));
  mMainFragment.setReenterTransition(new Fade());
  descriptionFragment.setAllowReturnTransitionOverlap(true);
}

Build and run on both emulators. You should see no animations on the emulator running API Level 7, but notice the fade in and slide out on the emulators running API Level 21 and above:

side-by-side

Where To Go From Here?

Congratulations! You’ve learned about Android SDK versions and their sweet code names, made an API Level 21 application backward-compatible to API Level 7, and used the cardview and design library to add additional components. You might also have a sugar craving :]

Blame Android.

Blame Android.

The final project for this Android SDK Versions tutorial can be downloaded here.

If you are interested in Android SDK version history, check out this wikipedia page or the versions page on the Android developer site. You can also read further about the minSdkVersion and targetSdkVersion attributes from the manifest page on the developer site. Finally, check out the developer pages on Support libraries and its feature list.

We hope you enjoyed this Android SDK Versions tutorial, and if you have any questions or comments, please join the forum discussion below!

The post Android SDK Versions Tutorial appeared first on Ray Wenderlich.

Video Tutorial: Beginning iOS Animation Part 4: View Transitions

Video Tutorial: Beginning iOS Animation Part 5: Beginning Non Auto Layout Animations


Video Tutorial: Beginning iOS Animation Part 6: Intermediate Non Auto Layout Animations

Video Tutorial: Beginning iOS Animation Part 7: Keyframe Animations

Bond Tutorial: Bindings in Swift

$
0
0
Bond tutorial

The name’s Bond, Swift Bond

Are you tired of manually wiring up your UI code? Yeah, I thought so. It’s such a mundane task, but we all have to do it. Or do we?

Swift Bond is a binding framework that removes the mundane task of wiring up your UI, giving you more time to think about the real problems you are trying to solve with your application.

In this Bond tutorial, you’ll learn how you can save time and write more maintainable code in this Bond.

Bond has a lot in common with ReactiveCocoa, something I’ll touch on towards the end of this article. For now, let’s get binding with Bond … Swift Bond.


Note: For those readers who don’t know the reference, the name of this framework, Swift Bond, is a pun based on the fictional spy James Bond, who famously introduces himself as “Bond … James Bond.” He also loved dry martinis, ordered “Shaken, not stirred,” so feel free to make yourself one to get in the Swift Bond mood!

A Quick Binding

Let’s fire up Xcode and start writing some code – martinis optional :]

First, download the starter project, which contains a ‘skeleton’ application. This will allow you to concentrate on Bond instead of fiddling with Interface Builder.

Once downloaded, ensure you have CocoaPods installed (if not, I’d suggest reading this tutorial to help you get started). Open the terminal and run pod install, which will result in an output similar to below:

$ pod install
Updating local specs repositories
Analyzing dependencies
Downloading dependencies
Installing Bond (4.3.0)
Installing DatePickerCell (1.0.4)
Generating Pods project
Integrating client project
[!] Please close any current Xcode sessions and use `BindingWithBond.xcworkspace` for this project from now on.
Sending stats
Pod installation complete! There is 1 dependency from the Podfile and 1 total
pod installed.

Open the newly generated workspace with Xcode, then build and run. You will be greeted with the following:

Bond tutorial

All good? Then it’s time to create your first binding!

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

searchTextField.bnd_text.observe {
  text in
  print(text)
}

The Bond framework adds various properties to UIKit controls. In this case, bnd_text is an ‘observable’ based on the text property of UITextField. Observables represent streams of events. Don’t worry, you’ll learn more about this shortly. For now, build and run, and then type “hello” to see what happens.

You will observe the following in the Xcode console:

Optional("")
Optional("h")
Optional("he")
Optional("hel")
Optional("hell")
Optional("hello")

Each time you press a key, the closure expression in the code you just added is being executed, which results in the application logging the current state of the text field.

This illustrates how events such as a property changing can be observed. Now you’re going to see what power that can bring.

Manipulating Data

Returning to ViewController.swift, update your code as follows:

let uppercase = searchTextField.bnd_text
  .map { $0?.uppercaseString }
 
uppercase.observe {
    text in
    print(text)
  }

Those of you who have used map to transform Swift arrays can probably guess what the code above does.

Note: If you’re not familiar with map, check out my tutorial on Functional Swift.

Build and run, then type in some more text: hello

Optional("")
Optional("H")
Optional("HE")
Optional("HEL")
Optional("HELL")
Optional("HELLO")

The map operation returns an observable by transforming the output of bnd_text into an uppercase string. Once again, the closure expression is being executed as events arise.

The result of applying the map operation is also an observable, therefore you don’t need the intermediate assignment. Update your code as follows:

searchTextField.bnd_text
  .map { $0?.uppercaseString }
  .observe {
    text in
    print(text)
  }

This gives rise to an elegant ‘fluent’ syntax. Build and run your application to see the same behavior.

You’re probably only mildly impressed at the moment, so how about I show you something absolutely awesome?

Replace your current code with the following:

searchTextField.bnd_text
  .map { $0!.characters.count > 0 }
  .bindTo(activityIndicator.bnd_animating)

Build and run your application. You will notice that the activity indicator animates only when the text field has text within it! That’s a pretty impressive feat with just three lines of code — perhaps even more impressive than a classic James Bond car chase :]

As you can see, Swift Bond provides a fluent and expressive way to describe how data flows between your application and your UI. This makes your applications simpler, easier to understand, and ultimately gets the job done more quickly.

In the next section you’ll learn more about how the above actually works. But for now, it’s worth taking a moment to see the power of Bond … Swift Bond.

Bond tutorial

I’ll drink to that!

A Peek Under the Hood

Before building a more meaningful app, let’s take a quick look at how Bond functions. I’d recommend navigating around the Bond types (via cmd+click) as you read the explanation below.

Starting with your current code, the bnd_text property is a Bond Observable with a generic type of String?. Observable is a very simple subclass of EventProducer, where most of the interesting stuff happens.

Event producers emit events where the type of the emitted data is defined by a generic parameter. When you call the observe method, you are registering the given closure expression as an observer. Each time an event is emitted, your closure expression is invoked with the event data (as defined by the generic type).

For example, consider the code you first added:

searchTextField.bnd_text.observe {
    text in
    print(text)
  }

The call to observe sets up the given closure to be executed every time the text property of searchTextField changes.

Note: This is based on a ‘classic’ design pattern known as the Observer Pattern.

EventProducer conforms to the EventProducerType protocol, which is where the map operation is defined via a protocol extension. You might have heard of “protocol oriented programming,” and this is a great example.

An Observable simply adds a value property to the EventProducer interface, allowing it to model a property or variable. You can ‘get’ or ‘set’ its value via the value property and observe changes thanks to the EventProducer functionality.

Bond extends UIKit, adding corresponding Observable properties. For example, UITextField has a text property and the observable equivalent bnd_text. So getting and setting ‘bnd_text.value’ is equivalent to getting and setting text, but with the added bonus that this change can now be observed.

The final piece of the puzzle is binding. The bindTo method can be used to connect a couple of Observable properties in order to synchronize changes. You saw this when you bound the animating property of the activity indicator to the length of text in the field, like so:

searchTextField.bnd_text
  .map { $0!.characters.count > 0 }
  .bindTo(activityIndicator.bnd_animating)

MVVM

While Bond makes it easy to bind UI properties directly to each other, this isn’t how you’ll likely want to use it in practice. Bond is a framework that supports the Model-View-ViewModel (MVVM) pattern. If you haven’t come across this pattern before, I’d recommend reading the first few sections of my previous tutorial on that topic.

That’s enough theory for now — you’re probably itching to write some more code. :]

Adding a View Model

First, remove those few lines of prototype code from ViewController.swift. You’re now ready to get started with a more realistic application structure. You should now have a viewDidLoad which looks like this:

override func viewDidLoad() {
  super.viewDidLoad()
}

Create a new file named PhotoSearchViewModel.swift within the ViewModel category, adding the following:

import Foundation
import Bond
 
class PhotoSearchViewModel {
  let searchString = Observable<String?>("")
 
  init() {
    searchString.value = "Bond"
 
    searchString.observeNew {
      text in
      print(text)
    }
  }
}

This creates a simple view model with a single property, initializing it with the value Bond.

Open ViewController.swift and add the following property near the top of the class:

private let viewModel = PhotoSearchViewModel()

Within the same file, update viewDidLoad() as follows:

override func viewDidLoad() {
  super.viewDidLoad()
  bindViewModel()
}

And then add this method to the class:

func bindViewModel() {
  viewModel.searchString.bindTo(searchTextField.bnd_text)
}

The bindViewModel() method is where you’ll be adding further bindings, but for now you’re just connecting the text field to the underlying view model.

Build and run your application. You’ll see the text ‘Bond’ display:

bond tutorial

Your view model currently observes changes to the searchString, but you’ll find that as you type text into the text field, the view model is not being updated. What gives?

Your current binding is one-way, which means it only propagates changes from the source (your viewModel property) to the destination (the text field bnd_text property).

How do we make changes propagate the other way? Simple — just update the binding as follows:

viewModel.searchString.bidirectionalBindTo(searchTextField.bnd_text)

That was easy!

Build and run, then type “Bond Love”:

Optional("Bond ")
Optional("Bond L")
Optional("Bond Lo")
Optional("Bond Lov")
Optional("Bond Love")

Great — we’ve confirmed that the text field updates are being propagated back to the view model.

Creating Observable from Observables

It’s time to do something a bit more useful with an obervable mapping. Returning to PhotoSearchViewModel.swift, add the following property to the view model:

let validSearchText = Observable<Bool>(false)

This boolean property indicates whether the current searchString value is valid or not.

Still within your view model, add the following within the initializer, init:

searchString
  .map { $0!.characters.count > 3 }
  .bindTo(validSearchText)

This maps the searchString observable to a boolean which is true when the string length is greater than four characters, then binds it to the validSearchText property.

Within ViewController.swift, locate your bindViewModel method and add the following:

viewModel.validSearchText
  .map { $0 ? UIColor.blackColor() : UIColor.redColor() }
  .bindTo(searchTextField.bnd_textColor)

This maps the validSearchText property to a color, then binds it to the text field’s textColor property.

Now build and run:

bond tutorial

As a result, when the text is too short to constitute a valid search, it is now highlighted in red.

Bond makes it very easy for you to connect and transform properties. As easy as…

bond tutorial

Pie! Yep, it really is this easy.

Preparing To Search

The app you’re building will query 500px to retrieve photos as the user types, giving the same kind of immediate feedback users are used to from Google.

You could trigger a search each time the searchString view model property changes, however this could result in TONS of requests. It’s much better to ‘throttle’ the queries so that at most only one or two are sent per second.

With Bond, this is really easy to do!

Within PhotoSearchViewModel.swift add the following to the init method:

searchString
  .filter { $0!.characters.count > 3 }
  .throttle(0.5, queue: Queue.Main)
  .observe {
    [unowned self] text in
    self.executeSearch(text!)
  }

This filters the searchString to exclude invalid (i.e. length <= 4) values, then applies the Bond throttle operation, which does exactly what we require, throttling changes so that at most we receive one notification each 0.5 seconds.

The closure expression supplied to observe invoked the executeSearch method, so add that one next:

func executeSearch(text: String) {
  print(text)
}

For now this just logs the result so that you can see the throttle in action.

Build and run, then try typing some text.

You will see something similar to the following, where the throttle disposes of events so that at most the text is logged once per 0.5 seconds:

Bond
Bond Th
Bond Throttles
Bond Throttles Good!

It would take forever to add this sort of functionality without Bond. Impressive stuff!

Using the 500px API

The app you are building uses the 500px API. This was selected because it has a relatively simple interface and authentication mechanism.

To use the interface, you’ll have to register as a developer. Fortunately this is free, quick and easy!

Sign up via the following URL: https://500px.com/signup

Once you have signed up, navigate to your applications: https://500px.com/settings/applications. Here you will see an interface that allows you to register an application.

bond tutorial

Fill in the registration form (only a few fields are mandatory) and your application will be created immediately.

bond tutorial

Click on your app and grab a copy of your consumer key. This is passed to 500px along with every request.

The starter application already has all the code you need in order to query 500px; you’ll find the code within the Model group. It’s all commented, so it should be easy to follow.

Returning to PhotoSearchViewModel.swift, add the following lazy property:

private let searchService: PhotoSearch = {
  let apiKey = NSBundle.mainBundle().objectForInfoDictionaryKey("apiKey") as! String
  return PhotoSearch(key: apiKey)
}()

This initializes the PhotoSearch class, which provides a Swift API for querying 500px, passing your consumer key.

The consumer key is obtained from your plist. Open up Info.plist and edit the apiKey, adding the consumer key supplied by 500px:

bond tutorial

Within PhotoSearchViewModel.swift, update the executeSearch method as follows:

func executeSearch(text: String) {
  var query = PhotoQuery()
  query.text = searchString.value ?? ""
 
  searchService.findPhotos(query) {
    result in
    switch result {
    case .Success(let photos):
      print("500px API returned \(photos.count) photos")
    case .Error:
      print("Sad face :-(")
    }
  }
}

This constructs a PhotoQuery, which represents the query parameters, and then invokes findPhotos on the searchService to execute the search. The result is returned asynchronously by the callback, with the Result enumeration representing success or failure.

Build and run the application. The view model will initiate the query on construction and you’ll see the following logged:

500px API returned 20 photos

If something went wrong then you’ll see the following:

Sad face :-(

If this happens, double-check your API key, your internet connection, cross your fingers, and try again! If it still doesn’t work, then it’s likely the 500px API is down. But in 99% of cases, it’ll be that your API key is entered incorrectly. Double check that you’ve entered the consumer key from your application on 500px.

Rendering the Results

It would be much more interesting if you could actually see the photos that your query returns, wouldn’t it? Let’s work on how to do that.

Within PhotoSearchViewModel.swift, add the following property:

let searchResults = ObservableArray<Photo>()

As the name suggests, this is a special type of observable, one that supports arrays.

Before trying it out, I’d suggest looking into the ObservableArray in a bit more detail; again, use cmd+click to navigate around the various Bond APIs.

The ObservableArray is similar to Observable in that it is also an EventProducer, meaning you can subscribe to events that signal when the array changes. In this case, the event emits ObservableArrayEvent instances.

The ObservabelArrayEvent encodes the change that occurred to the array via the ObservableArrayOperation enumeration. I’ll reproduce it here for reference:

public indirect enum ObservableArrayOperation<ElementType> {
  case Insert(elements: [ElementType], fromIndex: Int)
  case Update(elements: [ElementType], fromIndex: Int)
  case Remove(range: Range<Int>)
  case Reset(array: [ElementType])
  case Batch([ObservableArrayOperation<ElementType>])
}

As you can see, the events emitted by the ObservableArray are quite detailed. Rather than informing observers of the new array value, they instead describe the changes that have occurred.

There is a very good reason for this level of detail. You could use a Bond Observable to bind an array to the UI, via a table view perhaps. However, if you add a single item to this array, the Observable can only indicate that *something* has changed, and as a result then entire UI would have to be re-built. The detail provided by ObservableArray allows for much more efficient UI updates.

Note: ReactiveCocoa doesn’t have an observable array concept, which is a problem I have stumbled upon before. You can see my own solution (quite similar to Bond) over on my blog.

Now that you know what an observable array is, it’s time to put it to use.

Within PhotoSearchViewModel.swift, locate the executeSearch method and update the Success case as follows:

  case .Success(let photos):
    self.searchResults.removeAll()
    self.searchResults.insertContentsOf(photos, atIndex: 0)

This clears the array, adding the new results.

Within ViewController.swift, add the following to bindViewModel:

viewModel.searchResults.lift().bindTo(resultsTable) { indexPath, dataSource, tableView in
  let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)
                                                                      as! PhotoTableViewCell
  let photo = dataSource[indexPath.section][indexPath.row]
  cell.title.text = photo.title
 
  let qualityOfServiceClass = QOS_CLASS_BACKGROUND
  let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
  cell.photo.image = nil
  dispatch_async(backgroundQueue) {
    if let imageData = NSData(contentsOfURL: photo.url) {
      dispatch_async(dispatch_get_main_queue()) {
        cell.photo.image = UIImage(data: imageData)
      }
    }
  }
  return cell
}

Bond has a protocol extension for EventProducerType that is specifically intended for binding observable arrays to table views. The binding takes a table view instance and a closure expression; as you can see from the above, this expression takes on a similar role to the standard table view datasource.

Looking in a bit more detail, first the lift method is invoked on the observable array. Bond supports table views with categories via a nested array structure. The lift operation converts the observable array into the required nested form for a non-categorized table.

The closure expression is your standard table view cell wire-up. A cell is dequeued and various properties set. Notice that the image is downloaded via a background queue in order to keep the UI responsive.

Build and run to see your application coming to life:

bond tutorial

Notice that as you type into the text field, it automagically updates. Very cool.

A Bit of UI Flair

Time to wire up a bit more of your UI!

Within PhotoSearchViewModel.swift, add the following property:

let searchInProgress = Observable<Bool>(false)

Now update the executeSearch method to make use of it:

func executeSearch(text: String) {
  var query = PhotoQuery()
  query.text = searchString.value ?? ""
 
  searchInProgress.value = true
 
  searchService.findPhotos(query) {
    [unowned self] result in
    self.searchInProgress.value = false
    switch result {
    case .Success(let photos):
      self.searchResults.removeAll()
      self.searchResults.insertContentsOf(photos, atIndex: 0)
    case .Error:
      print("Sad face :-(")
    }
  }
}

This simply sets the property to true before querying 500px, then returns it to false when the result is asynchronously returned.

Within ViewController.swift, add the following to bindViewModel:

viewModel.searchInProgress
  .map { !$0 }
  .bindTo(activityIndicator.bnd_hidden)
 
viewModel.searchInProgress
  .map { $0 ? CGFloat(0.5) : CGFloat(1.0) }
  .bindTo(resultsTable.bnd_alpha)

This shows the activity indicator when a query is in progress and also reduces the opacity of the table view.

Build and run to see this in action:

bond tutorial

By now you should really be starting to feel the benefits of Bond! And the effects of that martini :]

Handling Errors

Currently if the 500px query fails, your app just logs it to the console. It really should report any failure back to the user in a helpful and constructive fashion.

The problem is, how should this be modeled? An error doesn’t feel like it should be a view model property, since it is a transient occurrence rather than a change in state.

The answer is simple enough: rather than an Observable, all you need is an EventProducer. Within PhotoSearchViewModel.swift, add the following property:

let errorMessages = EventProducer<String>()

Next, update the Error case of executeSearch as follows:

  case .Error:
    self.errorMessages
      .next("There was an API request issue of some sort. Go ahead, hit me with that 1-star review!")

Within ViewController.swift, add the following to bindViewModel:

viewModel.errorMessages.observe {
  [unowned self] error in
 
  let alertController = UIAlertController(title: "Something went wrong :-(",
                                                        message: error, preferredStyle: .Alert)
  self.presentViewController(alertController, animated: true, completion: nil)
  let actionOk = UIAlertAction(title: "OK", style: .Default,
    handler: { action in alertController.dismissViewControllerAnimated(true, completion: nil) })
 
  alertController.addAction(actionOk)
}

This subscribes to the events emitted by the errorMessages property, displaying the supplied error message via a UIAlert.

Build and run your application, then disconnect from the internet or remove your consumer key to see the error message in action:

bond tutorial

Perfect. :]

Adding Search Settings

The current application queries the 500px API based on a simple search term. If you look at the documentation for the API endpoint, you’ll see that it supports a number of other parameters.

If you tap the Settings button on your app, you’ll see it already has a simple UI for refining the search. You’ll wire that up now.

Add a new file named PhotoSearchMetadataViewModel.swift to the ViewModel group, with the following contents:

import Foundation
import Bond
 
class PhotoSearchMetadataViewModel {
  let creativeCommons = Observable<Bool>(false)
  let dateFilter = Observable<Bool>(false)
  let minUploadDate = Observable<NSDate>(NSDate())
  let maxUploadDate = Observable<NSDate>(NSDate())
}

This class is going to ‘back’ the settings screen.

Within PhotoSearchViewModel.swift, add the following property:

let searchMetadataViewModel = PhotoSearchMetadataViewModel()

Update executeSearch, adding the following lines just after the current one that sets the query.text property:

query.creativeCommonsLicence = searchMetadataViewModel.creativeCommons.value
query.dateFilter = searchMetadataViewModel.dateFilter.value
query.minDate = searchMetadataViewModel.minUploadDate.value
query.maxDate = searchMetadataViewModel.maxUploadDate.value

The above simply copies the view model state to the PhotoQuery object.

This view model will be bound to the settings view controller. It’s time to perform that wire-up, so open SettingsViewController.swift and add the following property:

var viewModel: PhotoSearchMetadataViewModel?

So just how does this property get set? When the Settings button is tapped, the storyboard performs a segue. You can ‘intercept’ this process in order to pass data to the view controller.

Within ViewController.swift add the following method:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  if segue.identifier == "ShowSettings" {
    let navVC = segue.destinationViewController as! UINavigationController
    let settingsVC = navVC.topViewController as! SettingsViewController
    settingsVC.viewModel = viewModel.searchMetadataViewModel
  }
}

This ensures that when the ShowSettings segue is executed, the view model is correctly set on the destination view controller.

Note: Why didn’t I use a guard statement here when performing both casts? Because if they fail, I want to know about it right away! The only reason they can fail is if the code is wrong.

In SettingsViewController.swift, add the following to the end of viewDidLoad():

bindViewModel()

Then add the implementation:

func bindViewModel() {
  guard let viewModel = viewModel else {
    return
  }
  viewModel.creativeCommons.bidirectionalBindTo(creativeCommonsSwitch.bnd_on)
}

The code above binds the view model property to the corresponding switch.

Build and run the application, open up the settings and toggle that switch. You should notice that its state persists, i.e. if you turn it on, it stays on, and the photos that are returned are different.

bond tutorial

Binding the Dates

The settings view has a few other controls that need to be wired up, and that’s your next task.

Within SettingsViewController.swift, add the following to bindViewModel():

viewModel.dateFilter.bidirectionalBindTo(filterDatesSwitch.bnd_on)
 
let opacity = viewModel.dateFilter.map { $0 ? CGFloat(1.0) : CGFloat(0.5) }
opacity.bindTo(minPickerCell.leftLabel.bnd_alpha)
opacity.bindTo(maxPickerCell.leftLabel.bnd_alpha)
opacity.bindTo(minPickerCell.rightLabel.bnd_alpha)
opacity.bindTo(maxPickerCell.rightLabel.bnd_alpha)

This binds the date filter switch to the view model, and also reduces the opacity of the date picker cells when they are not in use.

The date picker cells contain a date picker and a few labels, with the implementation provided by the aptly-named DatePickerCell CocoaPod. However, this poses a little problem: Bond does not supply bindings for the properties exposed by this cell type!

If you take a peek at the API for DatePickerCell, you’ll see that it has a date property which sets both the label and the picker that it contains. You could bind bidirectionally to the picker, but this would mean the label ‘setter’ logic is bypassed.

Fortunately a ‘manual’ two-way binding, where you observe both the model and the date picker, is quite straightforward.

Add the following method to SettingsViewController.swift:

private func bind(modelDate: Observable<NSDate>, picker: DatePickerCell) {
  modelDate.observe {
    event in
    picker.date = event
  }
 
  picker.datePicker.bnd_date.observe {
    event in
    modelDate.value = event
  }
}

Then add these two lines to bindViewModel():

bind(viewModel.minUploadDate, picker: minPickerCell)
bind(viewModel.maxUploadDate, picker: maxPickerCell)

Build, run and rejoice! The dates are now correctly bound:

bond tutorial

Note: The 500px API does not support date filtering; this is being applied to the photos returned by the code within the Model group; as a result, you can easily filter out all of the photos returned by 500px. For a better result, try integrating with Flickr, which does support server-side date filtering.

Date Constraints

Currently, the user can create date filters that don’t make sense, i.e. where the minimum date is after the maximum.

Enforcing these constraints is really rather easy. Within PhotoSearchMetadataViewModel.swift, add the following initializer:

init() {
  maxUploadDate.observe {
    [unowned self]
    maxDate in
    if maxDate.timeIntervalSinceDate(self.minUploadDate.value) < 0 {
      self.minUploadDate.value = maxDate
    }
  }
  minUploadDate.observe {
    [unowned self]
    minDate in
    if minDate.timeIntervalSinceDate(self.maxUploadDate.value) > 0 {
      self.maxUploadDate.value = minDate
    }
  }
}

The above simply observes each date, and if the situation where min > max arises, the values are changed accordingly.

Build and run to see the code in action. You should try setting the max date to something less than the min date. It’ll change the min date accordingly.

You might have noticed a small inconsistency: when you change the search settings, the app doesn’t repeat the query. This could be a bit confusing for your user. Ideally the application should execute the search if any of the settings change.

Each setting is an observable property, so you could observe each of one of them; however, that would require a lot of repetitive code. Fortunately, there’s a better way!

Within PhotoSearchViewModel.swift, add the following to the end of init():

combineLatest(searchMetadataViewModel.dateFilter, searchMetadataViewModel.maxUploadDate,
  searchMetadataViewModel.minUploadDate, searchMetadataViewModel.creativeCommons)
  .throttle(0.5, queue: Queue.Main)
  .observe {
    [unowned self] _ in
    self.executeSearch(self.searchString.value!)
  }

The combineLatest function combines any number of observables, allowing you to treat them as one. The above code combines, throttles, then executes the query.

Build and run to see it in action. Try changing the dates, or either of the toggles. The search results will update after each time you change something!

How easy was that?! :]

bond tutorial

A piece of cake, right?

Where To Go From Here?

You can find the finished project here.

Hopefully you’ve enjoyed this Bond tutorial and seen how easily you can wire-up your UI with Bond. In the introduction I stated that Bond has some similarities with ReactiveCocoa (and RxSwift). You might be wondering: which one should I use and why?

Put simply, ReactiveCocoa is a more complex framework; its concept of streams (which are analogous to Bond event producers) can emit a range of event types, which allows it to model more complex data flows, such as network requests. ReactiveCocoa can be used for UI binding, but that is not its main focus. Also, ReactiveCocoa 4.0 doesn’t have any UIKit extensions to support binding.

Bond is simpler, with full UIKit support. If you’re just interested in using the MVVM, or in more easily wiring up your UI in general, it is a great choice.

Currently the author of Bond is looking to grow the framework under the new name of ReactiveKit. Hopefully it won’t become a fully featured functional reactive framework to compete directly with ReactiveCocoa, because its current simplicity and focus on binding is what I find most appealing.

You can find the full sourcecode for this project on GitHub, with a commit for each build-and-run step.

Go forth and Bond … Swift Bond.

I hope you enjoyed this Bond tutorial. If you have any questions or comments, feel free to join the discussion below!

The post Bond Tutorial: Bindings in Swift appeared first on Ray Wenderlich.

Video Tutorial: Beginning iOS Animation Part 8: Beginning View Controller Transitions

TVML, and Facebook Shutting Down Parse – Podcast S05 E07

$
0
0
parse

What impact does Parse shutting down have on the iOS developer community?

Join Mic, Jake, and Sam as they chat about developing tvOS apps using TVML, before moving on to discuss Facebook shutting down Parse, and what this means for iOS developers who depended on the platform.

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

This episode was brought to you by the kind folks over at buddybuild.

buddybuild is a platform used by thousands of iOS developers every day to build their apps – enabling them to move faster, and much with less friction.

Git commits are built in the cloud, Xcode tests are run, provisioning profiles are automatically managed, builds are automatically sent to testers & their feedback and crash reports are received. When the final builds are ready – they are uploaded directly to iTunes Connect.

Most apps take less than 5 minutes to get set up, and you can get the development workflow you’ve always wanted at www.buddybuild.com.

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

Show Notes

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. Be sure to subscribe in iTunes to get notified when the next episode comes out.

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

The post TVML, and Facebook Shutting Down Parse – Podcast S05 E07 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>