Active Filters: Libraries

Topics

#59: BRYXBanner 🎏

Topics

BRYXBanner is a great new library by Harlan Haskins for displaying "dropdown" notifications banners. It has a very straightforward API, while remaining extremely flexible. Let's take a look at some different ways to use it.

Momentarily show a banner. By default banners are dismissed on tap, swipe, or after the duration has elapsed.

let banner = Banner(
  title: "New Mission Alert",
  subtitle: "New mission added to the schedule.",
  image: nil,
  backgroundColor: UIColor.lightGrayColor()
)

banner.show(duration: 3.0)

Without a duration, the show function caused the banner to be shown until the user taps it. Here we're passing in a closure that will be executed when the user taps the banner.

let banner = Banner(
  title: "Life Form Detected",
  subtitle: "An unknown lifeform has been found.",
  image: UIImage(named: "alien"),
  backgroundColor: UIColor.redColor()
) {
  print("banner tapped!")
}

banner.hasShadows = false
banner.show()

Disable image tinting to display all kinds of images.

banner.shouldTintImage = false

Use the provided .textColor property to change all the colors at once, or use the exposed title and detail labels to completely customize the look of each banner, including font face, size, color, etc.

More info about BRYXBanner can be found at git.io/banner

Topics

#56: ResponseDetective 🔍

Topics

ResponseDetective is a new debugging library from Adrian Kashivskyy and the team at Netguru for "intercepting" HTTP activity and logging it. You can configure different sets of Interceptor classes, depending on what kinds of data you'd like to see. Let's set it up:

The first thing we'll need to do is register some request and response Interceptors. ResponseDetective comes with quite a few Interceptors out of the box, and you can of course create your own. Here we'll log all the headers of all requests and responses, as well as the content of any JSON requests.

We start with the default session config, and insert the InterceptingProtocol at the front of it's protocol classes.

Finally, we create a session with our config and kick off a new task to an example API endpoint.

InterceptingProtocol.registerRequestInterceptor(HeadersInterceptor())
InterceptingProtocol.registerResponseInterceptor(HeadersInterceptor())
InterceptingProtocol.registerErrorInterceptor(HeadersInterceptor())

InterceptingProtocol.registerResponseInterceptor(JSONInterceptor())

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()

configuration.protocolClasses = map(configuration.protocolClasses, {
  (var protocolClasses) in
    protocolClasses.insert(InterceptingProtocol.self, atIndex: 0)
    return protocolClasses
}) ?? [InterceptingProtocol.self]

let session = NSURLSession(configuration: configuration)

session.dataTaskWithRequest(
    NSURLRequest(URL: NSURL(string: "http://httpbin.org/get")!)
).resume()

Now, if we look at our console, we can see that all the HTTP activity has been logged:

GET http://httpbin.org/get

200 no error
Content-Length: 304
Server: nginx
Content-Type: application/json
Access-Control-Allow-Origin: *
Date: Mon, 10 Aug 2015 04:11:45 GMT
Access-Control-Allow-Credentials: true
Connection: keep-alive
{
  "args" : {

  },
  "headers" : {
    "User-Agent" : "056-responsedetective\/1 CFNetwork\/711.4.6 Darwin\/14.4.0",
    "Accept-Encoding" : "gzip, deflate",
    "Host" : "httpbin.org",
    "Accept-Language" : "en-us",
    "Accept" : "*\/*"
  },
  "origin" : "76.102.27.127",
  "url" : "http:\/\/httpbin.org\/get"
}

More info about ResponseDetective can be found at git.io/responsedetective

Topics

#53: Signatures with Jot 🖋

Topics

Jot is an awesome library from Laura Skelton and the team at IFTTT.

It makes it easy to add drawing and text overlay capabilities to your app. Today we're going to use it to build a view controller that will allow our users to sign their name on the screen using their finger. Let's get started.

We start with the "Single View" template and import jot.

We instantiate a new JotViewController, and add it as a child view controller of our SignatureViewController. We'll do this inside viewDidLoad:

class SignatureViewController: UIViewController {
  var jotViewController: JotViewController?

  override func viewDidLoad() {
    super.viewDidLoad()

    jotViewController = JotViewController()
    addChildViewController(jotViewController!)

    view.addSubview(jotViewController!.view)
    jotViewController!.didMoveToParentViewController(self)
    jotViewController!.view.frame = view.frame
  }
}

Now comes the fun part. We set the JotViewController's state to be .Drawing and its drawing color to black:

jotViewController!.drawingColor = UIColor.blackColor()
jotViewController!.state = .Drawing

If you launch the app now, you'll see you can now sign your name on the screen!

We finish things off with a Done button and some instructions. Finally, we can grab the image of the signature like this:

jotViewController!.renderImageOnColor(UIColor.whiteColor())

Download the final project here: j.mp/bite053

More info about Jot can be found at git.io/jot

Topics

#52: R.swift 🎨

Topics

R.swift is a tool by Mathijs Kadijk that takes the resources in your app (images, segues, storyboards, nibs, etc.), examines them and generates a file in the root of your project called R.generated.swift containing a simple struct that maps your resources' actual names to Swift properties. R.swift updates the file each time you build, so you can focus on using your resources instead of managing them.

Why do this? For starters, it gives us Xcode native autocompleteion of resources names (finally). We're also saved from hardcoding strings throughout our app, or needing to go update a set of constants somewhere everytime we add a resource.

Let's look at some examples of where R.swift comes in handy. First up, images:

if spaceship.model == SpaceshipModel.Xwing {
  cell?.imageView!.image = R.image.shipXwing
} else {
  cell?.imageView!.image = R.image.shipGeneric
}

Nibs are also much easier to work with, here we instantiate the top view in a nib:

let view = R.nib.controlPanelView.instantiateWithOwner(nil, options: nil)

Instantiate view controllers from Storyboards with ease:

let spaceshipVC = R.storyboard.main.spaceshipViewController

R.swift also makes it easy to work with our cell reuse identifiers. It even includes extensions for UITableView and UICollectionView that save you from casting your cell's type:

tableView.dequeueReusableCellWithIdentifier(
  R.reuseIdentifier.shipTableViewCell, 
  forIndexPath: indexPath
)

More info about R.swift can be found at git.io/rswift

Topics

#51: PINRemoteImage 📌🎮🌄

Topics

PINRemoteImage is a new and promising solution for asynchronously downloading images. It was created by the team at Pinterest and has been battle tested in their extremely popular iOS app. Let's import PINRemoteImage, take a look at how to use it, and see what it can do:

let imageURL = NSURL(string: "http://apple.com/iCar.png")
imageView.setImageFromURL(imageURL)

Images are downloaded and decoded off the main thread. They're then cached using a fast, non-deadlocking parallel object cache. (Courtesy of another Pinterest library, PINCache). Upon subsequent requests the in-memory, then disk caches will be checked before re-downloading.

Processing

You can process the image before caching occurs. Here we'll use Toucan (covered in Bite #40) to convert the image into a circular avatar.

imageView.setImageFromURL(
  imageURL, 
  placeholderImage: placeholder, 
  processorKey: "circleAvatar"
) { (result, cost) -> UIImage! in
  return Toucan.Mask.maskImageWithEllipse(result.image)
}

Progressive JPEGs

Optionally, you can enable a mode supporting progressive JPEG images. They're treated with a nice blur effect, so they look great even at low resolutions.

imageView.updateWithProgress = true

Animated GIF Support

PINRemoteImage also comes with built-in support for Flipboard's blazing fast animated GIF library, FLAnimatedImage. All you have to do to use it is create an FLAnimatedImageView instead of a UIImageView:

let animatedImageView = FLAnimatedImageView(frame: GIFRect)

let GIFURL = NSURL(string: "http://apple.com/eddy-dance.gif")
animatedImageView.setImageFromURL(GIFURL)

// #GIFnotJIF

More info about PINRemoteImage can be found at git.io/pri

Topics

#49: Realm Basics 🔮

Topics

Realm is a database made specifically for running on mobile devices. It works on Mac and iOS devices. (It even supports Android!) It's a great alternative to Core Data or even raw SQLite.

There's plenty to love about Realm, but the best part is it's ultra-simple API:

Define an Object

import RealmSwift

class Spaceship: Object {
  dynamic var name = ""
  dynamic var topSpeed = 0 // in km
}

Define a Related Object

class Spaceship: Object {
  dynamic var name = ""
  dynamic var topSpeed = 0
  dynamic var owner: User?
}

class User: Object {
  dynamic var firstName = ""
  dynamic var lastName = ""
  let spaceships = List<Spaceship>()
}

Create an Instance of an Object

var ship = Spaceship()

ship.name = "Outrider"
ship.topSpeed = 1150

var dash = User()

dash.firstName = "Dash"
dash.lastName = "Rendar"

ship.owner = dash

// need one Realm per thread
let realm = Realm()

realm.write {
  realm.add(ship)
}

Find Objects

Queries in Realm couldn't be simpler. They are chainable. You can add as many calls to .filter as you'd like. You can sort results using the chainable sorted function.

realm
  .objects(Spaceship)
  .filter("topSpeed > 1000")
  .filter("name BEGINSWITH 'O'")
  .sorted("topSpeed", ascending: false)

Performance

Realm uses a "zero-copy" design that allows it process > 35 queries a second, as well as insert > 95,000 records a second in a single transaction.

More info about Realm can be found at realm.io.

Topics

#40: Toucan 🐧

Topics

Whether you're applying a circular crop to user avatars or just resizing a photo downloaded from a web service, processing images can be a bit of a chore. Toucan is a Swift image processing library from Gavin Bunney that makes working with images a breeze.

Let's import Toucan and take a look at what it can do:

Resize Images

// userAvatar is a UIImage downloaded from the network

let resizedAvatar = Toucan.Resize.resizeImage(
    myImage,
    size: CGSize(width: 100, height: 100)
)

Apply a Circular Mask

let circularAvatar = Toucan.maskWithEllipse(resizedAvatar)

Apply a Rounded Rectangle Mask

let roundedAvatar = Toucan.maskWithRoundedRect(height: 5)

Image Borders & Method Chaining

Toucan provides another syntax for chaining different processing steps together. Just call .image at the end to get a final processed UIImage. Here we can also see how to apply a 1 point wide border to the final image.

Toucan(image: userAvatar)
  .resize(CGSize(width: 100, height: 100))
  .maskWithEllipse(
    borderWidth: 1, 
    borderColor: UIColor.lightGrayColor()
  )
  .image

More info about Toucan can be found at git.io/toucan

Topics

#35: Async 🔀

Topics

Grand Central Dispatch is a wonderful way to write asynchronous code in your app. It's actual API however, can sometimes be a bit, well, let's call it "dry". Async is a Swift library by Tobias Due Munk that adds some much-welcomed syntactic sugar to Grand Central Dispatch. Async's core API is simple enough to be understood in a single line of code, so let's look at some other fun things it can do:

Chain Blocks

Async.background {
  // Runs on the background queue
}.main {
  // Runs on the main queue, but only after
  // the previous block returns
}

Delayed Execution

Async.main(after: 0.5) {
  // executed on the main queue after 500 ms
}.background(after: 0.4) {
  // executed on the background queue
  // 400 ms after the first block completes
}

Cancel Blocks

let computeThings = Async.background {
  computeSomethingBig()
}

let computerOtherThings = computeThings.background {
  // this sucker is about to get cancelled
}

Async.main {
  computeThings.cancel() // this won't do anything

  // you can only cancel blocks that haven't yet started executing!

  computerOtherThings.cancel()
  // this second block *would* in fact get cancelled,
  // since it hasn't started executing yet
}

More info about Async can be found at git.io/async

Topics

#15: FontBlaster 📄

Topics

FontBlaster is probably one of the simplest things we'll cover in these bites.

Don't be fooled though, it is one of the most useful little utilities and has quickly made its way into my "standard set" of third-party I use in all my new projects.

Adding a custom font to an iOS app is normally just a little cumbersome:

😁 First drag the font file(s) into Xcode

😐 Open up your Info.plist

😒 Add a new key for "Fonts provided by application"

😲 Find the exact names of each font that iOS’s font system wants to hear, adding items in the .plist for each

😭 Watch as loading them all slows down your app’s initial launch

With FontBlaster, all you have to do is make sure your custom font files are added to your app's main bundle then call this method anywhere in your app:

FontBlaster.blast()

More info about FontBlaster can be found at git.io/fontblaster

Authors Note

Hey everyone, first off the response to little bites has been absolutely incredible. I'd like to thank every single one of you for reading, responding, retweeting, requesting, etc. as I get things off the ground here.

Second, I'd like to let everyone know that there will be no bites published next week as I'll be busy attending Apple's Worldwide Developer Conference learning what is sure to be tons of exciting new things that I’ll get to cover here in the coming months.

If you're going to be at the conference as well, reach out on Twitter, I'd love to meet and talk to as many of you all as I can! 👍

Bites will resume their regular schedule starting Monday June, 15th.

Cheers! 🍫
- Jake

Topics

#14: DZNEmptyDataSet 🐚

Topics

DZNEmptyDataSet is a library that makes it extremely easy to add custom "empty" data sets, for when a screen in your app either currently has no data, or the user hasn’t created any data yet.

You can configure it by implementing a bunch of different optional methods in the DZNEmptyDataSet protocol. A pretty simple setup is shown here, but the there are lots of more advanced options including custom views and even easily adding a button below the text.

extension PhotosViewController : DZNEmptyDataSetSource {
  func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
    return NSAttributedString(string: "No Photos")
  }

  func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
    let text = "Photos you take will appear here"

    return NSAttributedString(string: text, attributes: [
      NSForegroundColorAttributeName: UIColor.grayColor()
    ])
  }

  func imageForEmptyDataSet(scrollView: UIScrollView!) -> UIImage! {
    return UIImage(named: "cracked-egg")
  }
}

Detect interaction by implementing one of the methods in the DZNEmptyDataSetDelegate protocol.

extension PhotosViewController : DZNEmptyDataSetDelegate {
  func emptyDataSetDidTapButton(scrollView: UIScrollView!) {
    println("tapped button on the empty view!")
  }
}

Here's some example empty screens DZNEmptyDataSet can help you create:

Example Project

You can download a complete working project here

More Info

More info about DZNEmptyDataSet can be found at git.io/empty

Page 9 of 10