When it comes to using Markdown on iOS and OS X, there's tons of options. Today we'll look at one popular solution from Simon Fairbairn called SwiftyMarkdown. It helps us translate Swift Strings containing Markdown into NSAttributedStrings. Let's take a look.
letmd=SwiftyMarkdown(string:"# SwiftyMarkdown\nConverts *Markdown* files and strings into NSAttributedString")md.attributedString()
It's that simple! SwiftyMarkdown will use some defaults for fonts, colors, etc. Customizing those is quite simple:
Often when working with data from an API or third-party we'll need to manipulate or analyze it in a very specific way. In these cases, many of us simply search Google for "how to do the thing to a String in Swift". This usually works out fine, but what a bummer.
Today we'll check out a library from Andrew Mayne called SwiftString, which can help us here.
SwiftString is essentially a collection of a ton of String manipulation and analysis utilities. It has functions like this:
Today we'll follow up with another Bite in our localization series (sort of). Units of measurement are important to get right when localizing our apps for different cultures.
Today we'll look at a library from Khoa Pham called Scale that can help us convert between different units of measurement (for either localization or just-for-fun purposes). Let's begin.
Scale makes it incredible simple to work with different units of measurement:
.stringsdict files were added in iOS 7 and OS X 10.9. They allow us to "pluralize" text in our app without a bunch of switch or ifstatements.
letspaceships=[Spaceship(selected:true)]letpluralized=String.localizedStringWithFormat(NSLocalizedString("%d ships selected",comment:"how many ships selected"),spaceships.filter{$0.selected}.count)
The localizedStringWithFormatfunction is terribly smart.
It will look for a Localizable.stringsdict file before returning and queryit for the correct format string to use before returning our final formatted string.
A Localizable.stringsdict is really just a .plist file with a few special strings in it.
We can create a Localizable.stringsdict file either completely by hand in a text editor, or by adding a new Property List to our project and naming it Localizable.stringsdict.
Now that we have a .stringsdict file, let's use it.
The root key is the same one we passed into NSLocalizedString.
Then, we define a sort of string-replacement-variable using some special characters: %#@VARIABLE_NAME_HERE@. The system will then find the sub-dictionary that shares a name with this variable, and use it to pluralize.
We can provide cases for zero, one, two, few, many, and other. Each potential plural case is optional for each language, except other.
Today we'll continue our series on localizing our apps by looking at NSNumberFormatter.
It can help us make sure we're displaying numbers using the format a user expects in their culture or language, as well as display numbers in some fun ways. Let's get started.
First, let's see how we can take advantage of NSNumberFormatter when localizing our app.
We'll create a new formatter, and tell it to use the user's current locale. (An NSLocale is a class that encapsulates information about linguistic, cultural, and technological conventions and standards).
Then, we ask the formatter for a string from a number.
Apple has done all the hard work of figuring out how numbers should change when displayed in different locales. The example before showed the output from a device in the US, what about one from Germany? Let's try it:
In addition to all of that, NSNumberFormatter also has an insanely long list of customizable properties allowing us to create completely custom formatters (best done via subclassing).
When browsing the App Store, users are likely to scroll right past apps that don't support the language they speak. Like any business, one way we can improve the sales of our apps is to make them useful to new, large groups of people.
Today we'll begin learning about localizing our apps. We'll start by setting up our Xcode project to be localized, then try a simple example using NSLocalizedString.
Let's dive in:
First, we'll head over to our Project's settings **and add a new **Localization language. We'll choose French, then Finish.
This will modify our project (and a few files) to make it localizable.
Next, we'll go to File > New > File⦠and add a new Strings file called Localizable to help us localize strings in our code.
Yep, it has to be named exactly like that. π
We'll select this new file and head over to the File Inspector panel. We'll click the Localize⦠button, then the Frenchcheckbox.
Now we can edit both versions of our .strings file, adding translate-able strings using a special key/value syntax:
Formatting strings is one of the most common tasks in building software. It's usually not that complex, but it can be tempting to cut corners.
When working with things like currency or street addresses, having a robust formatting system in place can be crucial in ensuring our app works well all over the world.
Today we'll look at Format, a library from Roy Marmelstein that can help us achieve all this with ease.
Format starts by extending Swift's number types to add a format function. We can call this on any number (even literals) and it will return a String with our desired format:
134.format(Decimals.Two)// => "134.00"
Format makes localizing a breeze. It uses the device's current locale by default, or we can render a specific one:
Ordinal numbers can really help class up the joint:
134.format(General.Ordinal)// => "134th"
Format can format in all sorts of interesting ways, for example:
10.11.format(General.SpellOut)// => "ten point one one"
Numbers are cool, but what about addresses? Almost every nation has a slightly different convention for how they format street addresses.
Format wraps CNPostalAddressFormatter from the Contactsframework (Bite #24) to make formatting addresses quite simple:
AddressFormatter().format("1 Infinite Loop",city:"Cupertino",state:"CA",postalCode:"95014",country:"USA",ISOCountryCode:"US")// => "1 Infinite Loop\nCupertino CA 95014\nUSA"
Format also extends CLPlacemark, adding a function to format that class's addressDictionary property. Users expect things to look familiar. Never underestimate the power of good localization.
More info about Format can be found at git.io/format
NSURLQueryItem is a great little class that joined Foundation in iOS 8. It can help us compose NSURLs in a safer and more predictable way.
iOS and OS X developers have long become familiar with composing URLs in Cocoa. It can be⦠"interesting" at times.
We've all written a line or two of NSString-concatenation or stringWithFormat code to quickly create a URL. This works in a pinch, but we could easily introduce a bug by putting an & character in the wrong spot, or some other silly typo.
NSURLQueryItem can help! Let's look at how to use it along with NSURLComponents to compose an NSURL:
This is great for a few reasons. For example, instead of doing something silly like string replacing shudder to change a query parameter, we can instead operate on the components' queryItemsarray, then export the URL again by calling .URL. Additionally, with this technique, we can now more easily validate query parameters in URLs in our tests! Double-win. Neat!
Regular Expressions are a fantastic way to search through text. Apple provides support for them via the NSRegularExpression class. It has great support for matching, extracting, etc. Its API can be a bit verbose for simple matches though. Today we'll look at Regex, a tiny little library from Adam Sharp that makes writing regular expressions in Swift much more friendly and expressive. Let's check it out:
Regex has a bunch of great features, but at its core it allows us to take regular expression code like this:
...and turn it into something just a tad more readable:
Regex("star (wars|trek)").matches(stringToMatch)
Regex is backed by NSRegularExpression under the hood, and it does a great job of "swift-ifying" its API. In addition to simple Boolean checks, we can also use Regex in a few other rather Swifty ways. For example, pattern matching:
switchstarThing{caseRegex("gate$"):print("dial the gate!")caseRegex("wars$"):print("the force is strong")caseRegex("trek$"):print("set phasers to stun")default:break}
Last but not least, we can easily grab any captured strings:
Grand Central Dispatch is the name of Apple's collection of task concurrencyfunctions in libdispatch. GCD (as it's often called) is packed full of interesting features involving concurrency, queuing, timers, and more. Let's dive in and take a look at some simple and common use cases:
Common Usage
One of the most common ways to use GCD is to hop to a background queue to do some work, then hop back to the main queue to update the UI:
If we wanted to run some code in viewDidAppear: but only wanted it to run the first time, we could store some flag in a Bool property. Or just use GCD:
We can also easily wait a specified amount of time, then run some code. Here we'll use this technique to pop back to the previous view controller a quick "beat" after the user selects an an option in a table view controller. (As seen in many apps, including Settings.app):