Active Filters: Libraries

In-App Purchases have become a very important part of our business. Adding them to an app can involve quite a bit of boilerplate code though. Today we'll look at SwiftyStoreKit, a framework from Andrea Bizzotto that can help.

SwiftyStoreKit provides a few static functions we can use to easily implement all the common In-App Purchase tasks like getting the info about our "products" from Apple, purchasing, restoring, and even receipt verification. Let's take a look:

SwiftyStoreKit.retrieveProductInfo("com.littlebitesofcocoa.products.volume1") { result in
  switch result {
    case .Success(let product):
      let priceString = NSNumberFormatter.localizedStringFromNumber(product.price, numberStyle: .CurrencyStyle)
      print("Product: \(product.localizedDescription), Price: \(priceString)")

    case .Error(let error): print("Error: \(error)")
  }
}

We pass in the product identifier, and supply a closure that can process the result. If successful, we use NSNumberFormatter (Bite #182) to print a nice looking summary of the product.

From here, we just need to wire up the other functions SwiftyStoreKit provides like purchaseProduct, restorePurchases, and verifyReceipt.

More info about SwiftyStoreKit can be found at git.io/swiftystorekit

GIFs are amazing. They make us laugh, cry, and are the medium of choice for cat owners worldwide. 🐱

Unfortunately, GIFs can also be a bit of a headache when it comes to performance. Imagine an iOS app that displays a vertically scrolling list of animated GIFs. Making sure each of those GIFs is properly scaled, animating smoothly and handling memory well can be trickier than you might think.

Today we'll check out a library from Reda Lemeden called Gifu that aims to provide a high performance solution for this.

let imageView = AnimatableImageView(frame: CGRect.zero)
imageView.animateWithImage(named: "cat.gif")

It's that simple! Under the hood, AnimatableImageView uses CADisplayLink. It will keep the current frame, as well as the next few frames in memory, ensuring we're good memory citizens. It ends up looking like this:

Gifu also provides a few functions (startAnimatingGIF, stopAnimatingGIF, and isAnimatingGIF) for controlling the actual animation. Nice.

More info about Gifu can be found at git.io/gifu

Some libraries and frameworks provide large, far-reaching sets of tools for us to build our apps. Sometimes though, we just need a single component. Today we'll look at one such component that does one thing and one thing well: text views that adjust their height as a user types into them.

It's called NextGrowingTextView and it's by Hiroshi Kimura.

let textView = NextGrowingTextView(frame: CGRect.zero)

Then, we can use it as the inputAccessoryView of our view controller. This will cause it to be displayed when it becomes first responder. (Be sure to also return true from canBecomeFirstResponder too!)

self.inputAccessoryView = textView

NextGrowingTextView has a couple of properties for min/max number of allowed lines, but the real star is its robust delegates property allowing us to set closures for all sorts of events:

textView.textViewDidChange = { textView in print(textView) }

More info about NextGrowingTextView can be found at git.io/growingtextview

We've looked at allowing users to capture or choose images for use in our apps a couple times here. We learned about UIImagePickerController in Bite #83 and then ImagePicker in Bite #157.

Today we've got a new contender in this space called Fusuma. It's by Yuta Akizuki and aims to provide a very full-featured drop-in solution for this task. Let's try it.

We'll start by presenting the main FusumaViewController:

let fusuma = FusumaViewController()
fusuma.delegate = self

self.presentViewController(fusuma, animated: true, completion: nil)

Then later we conform to the FusumaDelegate protocol:

func fusumaImageSelected(image: UIImage) {
    imageView.image = image
}

There's also fusumaDismissedWithImage and fusumaCameraRollUnauthorized functions for handling those cases.



More info about Fusuma can be found at git.io/fusuma

We've covered 3D Touch quite a bit here, we checked out View Controller Previews with Peek and Pop back in Bite #80.

Peek/Pop are great features, it's a shame only our users with the latest hardware can take advantage of them. Today, we'll check out a brand new library that aims to remedy this. It's from Roy Marmelstein and called PeekPop. Let's dive in.

The basic idea of PeekPop is to allow us to support 3D Touch style peeking and popping on devices that don't actually have 3D Touch hardware

The API is quite similar to UIKit's built-in one, let's try it out.

First, we'll register as a delegate, then conform to it:

peekPop = PeekPop(viewController: self)
peekPop?.registerForPreviewingWithDelegate(self, sourceView: collectionView!)

func previewingContext(previewingContext: PreviewingContext, viewControllerForLocation location: CGPoint) -> UIViewController? {
  return self.previewControllerForLocation(location)
}

func previewingContext(previewingContext: PreviewingContext, commitViewController viewControllerToCommit: UIViewController) {
  self.navigationController?.pushViewController(viewControllerToCommit, animated: false)
}

That's it! Neat.

PeekPop will use 3D Touch if available, then fall back on older devices to monitoring signficant changes in a UITouch's majorRadius property. (Pressing harder usually causes this to increase, even on older devices, since often more of the surface area of the finger is in contact with the screen).

More info about PeekPop can be found at git.io/peekpop

Setting our app apart can be tricky. We don't want to deviate too far from established conventions, but we don't want to blend in to the crowd either. Small amounts of "polish" to an app's UI can go a long way to making it feel special.

Today we'll check out one more tool in our arsenal for doing this. It's a library from Andrea Mazzini called SubtleVolume.

The idea here is to improve upon the default, screen-obscuring, built-in volume overlay. iOS's system interface is fine for most apps, but often it can get in the way of the content the underlying app is presenting.

SubtleVolume solves this by providing an elegant volume view that we can put anywhere on the screen. Let's try it out:

let volume = SubtleVolume(style: .Plain)

volume.frame = CGRect(x: 0, y: 20, width: w, height: 4)
volume.barTintColor = .whiteColor()
volume.barBackgroundColor = UIColor(white: 1.0, alpha: 0.3)
volume.animation = .FadeIn

view.addSubview(volume)

Now, the view will automatically hide/show when the user changes the volume, Neat!

More info about SubtleVolume can be found at git.io/subtlevolume

Today we'll look at an interesting library from Evan Dekhayser called KBKit. It extends UIKit to add support for navigating around using a physical keyboard. (Think either bluetooth or other keyboard connected to an iPad, but would also work on iPhone.) Let's take a look.

KBKit consists of a few subclasses of common UIKit classes. KBTableView adds Up Arrow, Down Arrow, and Return Key functionality to UITableView. Very cool.

let tableView = KBTableView(frame: CGRect.zero, style: .Plain)

tableView.onSelection = { (indexPath: NSIndexPath) in
  // called when user pressed 'Return' or 'Command + D'
}

tableView.onFocus = { (current: NSIndexPath?, previous: NSIndexPath?) in
  // called as user navigates with arrow keys
}

We can use KBNavigationController to gain a Command + Left Arrow shortcut for going "back" (i.e. popping to the previous view controller in the stack).

Last but not least, KBTabBarController adds support for pressing Command + 1, Command + 2, Command + 3, etc. to change the currently selected tab. It supports up to 5 tabs. Neat!

More info about KBKit can be found at git.io/kbkit

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:

"<rock>blah</hardplace>".between("<rock>", "</hardplace>") // "blah"
"hello".isNumeric() // false
"hello7".isNumeric() // false
"31.0".isNumeric() // true
"-31.0".isNumeric() // true
"star wars".split(" ")[0] // "star"
"star wars"[0...1] // "st"
"#203: Simplifying Common String Operations".slugify() // "203-simplifying-common-string-operations"
"Some [string], *with* %junk in it.)".stripPunctuation() // "Some string with junk in it"
"yay &quot;strings&quot;".decodeHTML() // "yay \"strings\""

We might only need one or two of these functions in a single app, but thanks to SwiftString, we'll never have to write them ourselves again.

More info about SwiftString can be found at git.io/swiftstring

iOS gives us a ton of great capabilities to build upon. Being able to use the user's current geographic location in our apps really has changed the world.

We always need to ask for the user's permission first though, so we might as well do it in style! Today we'll check out a simple yet beautiful library from Sven Tiigi called STLocationRequest that uses Flyover to provide a great looking "location access prompt" view controller.

We'll begin by importing STLocationRequest, and configuring and showing a location request controller.

self.showLocationRequestController(
  setTitle: "Allow location access?", 
  setAllowButtonTitle: "Sure", 
  setNotNowButtonTitle: "Nope", 
  setMapViewAlphaValue: 0.7, 
  setBackgroundViewColor: .orangeColor()
)

Then, we can subscribe to the NSNotifications the library posts to know how the user responds.

More info about STLocationRequest can be found at git.io/stlocationrequest

Vector graphics are fantastic. They give us small, compressible files, crispy rendered pixels at any scale, and they're supported by many different kinds of software and frameworks.

Except iOS 😭, which doesn't support them out of the box. Today we'll try a library from Michael Choe called SwiftSVG which provides great support for parsing and rendering SVG files. Let's take a look.

SwiftSVG supports a ton of different ways of getting SVGs into our app.

CAShapeLayer(SVGURL: SVGURL)
UIView(SVGURL: SVGURL)
UIView(pathString: deathStarBlueprints)
CAShapeLayer(pathString: superSecretNewLogoIdea)
UIBezierPath(pathString: "M150 0 L75 200 L225 200 Z")

SwiftSVG also provides a custom UIView subclass we can use in Interface Builder that supports IBInspectable/IBDesignable.

More broadly, it's important to think about the reasons why we might want to use SVGs in our app. SVGs are essentially XML files (Open one up in a text editor, you'll see.)

They are instructions on how to draw a set of paths. The files are incredibly small.

Getting a good workflow going for creating them at-will can be tricky, but Sketch (eventually) makes it mostly painless.

Once we have this, we can build some awesome abstractions. Imagine a Swift struct with SVGName, color, and size that can produces a UIImage.

struct SVGImage {
  let SVGName: String
  let size: CGSize
  let color: UIColor

  func asImage() -> UIImage {
    // Neato!
  }
}

More info about SwiftSVG can be found at git.io/swiftsvg

Page 4 of 10