Text is a huge part of iOS apps. Today we'll look at one way we can polish up the text in our apps, by allowing it to naturally "flow" around objects. Let's begin.
We'll start with a "before" picture. Here we've got a basic setup with some text and an image in the top right corner. Nothing too fancy here, just a regular UITextView and UIImageView:
letimageView=UIImageView(image:UIImage(named:"steve"))lettextView=UITextView(frame:.zero)textView.text="Here's to the crazy ones..."
This looks fine. But our text is needlessly narrow. It'd be great if we could make the textexpand to the full width of the device. We'll change our Text View's layout so it does:
Well, we're getting closer. Now we just need a way to make the text"flow" or "wrap" around our image. We'll start by getting the frame of the image view, then we'll create a path from it:
letimagePath=UIBezierPath(rect:imageView.frame)
Finally, we'll set our new path as one of the exclusionPaths of our Text View'stextContainer:
textView.textContainer.exclusionPaths=[imagePath]
Success! Since exclusionPaths is an Array, we can flow text around as many shapes as we want!
Validating data is usually one of the "chores" we encounter while building apps. It can be annoying and boring code to write, and can be a huge source of bugs. Today we'll check out a great library called FormValidatorSwift that can help us avoid all these issues. Let's take a look.
The core of FormValidatorSwift is built around checking if a String passes some sort of test to be deemed 'valid'.
We'll use individual Conditions or combined sets of Conditions called Validators. We'll attach these to controls like Text Fields and Text Views to allow them to be validated.
Let's try out the included ValidatorTextField to validate an email address:
Then, we'll configure it to allow the user to begin entering an email address that's invalid like "hello@", and specify that it should only be validated when it loses focus.
First up, Equatables. We can use XcodeEquatableGenerator from Serg Dort to quickly generate the long list of property comparisons often required when adopting the Equatable protocol in our Swift Structs or Classes:
Next, Localization. We've all been on a project with no localization. Adding that first round of NSLocalizedString() calls can be a pain. No longer! Now we can use Localizer from Esteban Torres.
With it, we can select a line of code like this:
let_="Mission Control Panel"
Then, when we run Localizer's command, this line becomes:
let_=NSLocalizedString("Mission Control Panel",comment:"Mission Control Panel")
Last but definitely not least, is XcodeWay by Khoa Pham. This one is a bit different in that it doesn't modify or generate any code, but rather lets us quickly open a bunch of commonly used directories, by adding them to our Editor Menu:
Nice! No more hunting around in Finder or Terminal for these.
Know of another neat Source Editor Extension? Send it along!
We're welcoming back one of our favorite sponsors again this week, it's Zendesk!
None of us have ever built a flawless app.
Chances are, no matter how good we think our app's user experience is, there's probably something users will need help with while they're in our app.
Yet in many apps, getting help is reduced to a "contact us" button that launches an compose email screen, or a just drops the user on a web page.
By forcing folks out of the app to get help, small problems can turn into big annoyances, and those will almost certainly turn into negative App Store reviews and poor ratings.
With Zendesk's Mobile SDKs, we can bring native, in-app support functionality to our apps quickly and easily.
Our users can view help and support content, and even submit tickets to support without ever leaving our app. Neat!
Tickets go into Zendesk and can include technical details about the user and their device, history with our apps, and more.
Best of all, it's included with Zendesk at no extra charge.
We can use Zendesk's "out-of-the-box" iOS UI components to get up and running quickly, or we can build your own UI with SDK API Providers.
Today we're going to continue our look at the new Measurement functionality in Foundation. (Bite #276). MeasurementFormatter offers some great ways to format and print Strings of our Measurements. Let's take a look.
First we'll make define some units to work with. One of the most common ones we'll use in our apps is Length (for example when displaying how "far away" something is).
We'll leave the locale setting alone, which causes it to use the current locale of the device. In our case, en_US.
Finally, we'll print the formatted String.
print(formatter.string(from:distance))
Nice. Now we can start to try out some of the options. Let's start with the *style, we have three choices:
formatter.unitStyle=.short// "0.87mi"formatter.unitStyle=.medium// (the default) "0.87 mi"formatter.unitStyle=.long// "0.87 miles"
We'll use the .long style.
By default, our device locale being en_US is causing the distance to formatted with "miles" instead of "kilometers" (our input value). We can change this with unitOptions:
We can even drop down and configure the NumberFormatter (Bite #182) that the MeasurementFormatter uses when formatting the numerical part of our Measurements:
MeasurementFormatter is just another in a long list of wonderful little gems tucked away inside Foundation. Know of another that should be covered here? Send it along!.
Apple added something pretty neat to Foundation this year: Measurements. We can represent units, convert them to other units, compare them, and even convert them into formatted strings. Let's dive in.
Last but certainly not least, we can nicely format a measurement into a String. Apple provides a MeasurementFormatter type that is fully locale-aware. This allows us to easily display Measurements in our apps in whichever ways our users expect.
Foundation is such a powerhouse of functionality, it can be easy to miss great new additions like this. Next time, we'll learn more about formatting Measurements for display in our apps.
Xcode Source Editor Extensions are really starting to come into their own. Today we'll look at one that solves an age-old annoyance for Xcode users: Importing.
We've all been there. We're deep down in the depths of file, and we realize we need to import a module. We dutifully scroll all the way up, type the import, then scroll back down trying to find our place, and get back in "the zone". Yuck.
As the name suggests, it allows us to type an import Module statement anywhere, then press a keyboard shortcut and have the import fly to the top where it belongs.
That's it, Rollout is now integrated into our app. Neat!
Now let's fast-forward a bit, to a time after we've shipped our imaginary app to the App Store. We get approved, and we're celebrating the launch and then 😣 doh! Something is causing our app to crash on launch. Yikes.
First we'll take a look at our project, and find the culprit. In our case, it looks like part of our code is throwing a non-fatal exception when we didn't expect it to. Yuck.
Not to worry though, because our app has Rollout inside.
We'll head to the Rollout dashboard and add a hotfix.
We'll select the "Surround Invocation with Try Catch" type, and test it out.
That fixes it! Now that things are fixed up, we can switch our hot patch to "Production" mode. (We could even release it gradually to only a percentage of our user base).
This kind of flexibility and freedom really does feel like magic. It's sort of like "insurance" knowing we won't be stuck waiting on Apple to get critical changes out to users. Neat!
Rollout supports Objective-C apps, Swift is supported (in beta) and will be fully released in November.
Last but certainly not least, Rollout is offering a sweet discount for LBOC readers: Use the code cocoa20 to get 20% off any paid plan for 6 months!
A huge thanks to Rollout for sponsoring this week's Bites!
Attributed Strings are a fantastic way to work with rich, styled-text. (We've covered them in Bites #143 & #144 for the curious.) We've even looked at ways to improve upon how verbose the FoundationNSAttributedString API can be.
Today we'll check out another approach using a library from Eddie Kaiger called SwiftyAttributes. It dramatically improves how we work with Attributed Strings. Let's dive in.
Let's start by looking at how things work in vanilla Foundation:
Things get even nicer when we need to concatenate two NSAttributedStrings together. We've all had to do this before and it could have involved applying attributes to specific ranges, etc. Now, we can use a much more declarative and readable syntax:
letsomeString="We can easily ".withFont(.systemFont(ofSize:16))+"underline".withFont(.systemFont(ofSize:16)).withUnderlineStyle(.styleSingle)+" certain words.".withFont(.systemFont(ofSize:16))
Under the hood, SwiftyAttributes takes a pragmatic approach by extending both Swift's String type as well as NSAttributedString with a fairly comprehensive set of delicious, sugary functions: