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

The real world doesn't have straight edges. Things are rounded. Our UIViews can be too! Most of us know about the cornerRadius property on CALayer. We can set a value, then see all the corners round themselves to that value:

contentView.layer.cornerRadius = 8

Nice, but what if we only want to round some of the corners though?

let cornerRadius: CGFloat = 8
let maskLayer = CAShapeLayer()

maskLayer.path = UIBezierPath(
  roundedRect: view.bounds,
  byRoundingCorners: [.BottomLeft, .BottomRight],
  cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)
).CGPath

view.layer.mask = maskLayer

For this, we'll need to get a bit more creative. We can use an often-overlooked type called UIRectCorner.

It lets us describe which corners we'd like to round. Then we'll use a UIBezierPath to create a "mask" layer that will only allow some of the content to "show through".

We pass in an option set for the byRoundingCorners parameter, listing out the corners we'd like rounded.

Success! Happy rounding!

Update: Shout-out to Reddit-reader /u/cuomo456 who reminds us to update/replace our layer masks anytime the view/layer we're masking's frame or bounds changes. If we don't, we could find ourselves scratching our heads why our rounded corners aren't working in a UITableViewCell, for example.

Weekly Sponsor: Hired 🏢

A continued huge thanks to the folks at Hired.com for sponsoring this week's bites. Finding a good job can be a daunting task. Today we'll take a look at how we can use Hired.com to save our sanity, and find a great job in the process. Let's dive in.

We'll start by entering our email and answering some basic questions:

That's it. Hired will then work with over 3,000 pre-screened companies (both big and small) in 13 major metro areas (North America & Europe) to try find us a great job. Software engineers and designers on Hired can get 5+ job offers in a single week. Each offer will include salary and equity details upfront.

We can view interview requests and accept or reject them before talking to any company. If we get a job through Hired, they'll give us a $1,000 "thank you" bonus!

Even better, if we sign up through this link: littlebitesofcocoa.com/hired, they'll double our bonus to $2,000!

More Reasons to Use Hired

  • Full time or contract opportunities are available
  • View offers and accept or reject them without talking to anyone.
  • Completely FREE + no obligations ever.

Hired is the real deal. They have solved some very real problems and fixed this historically messy process. Looking for a job? Don't waste time, sign up for Hired today so you can get back to work!

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

Topics

#209: Swift Enums Cookbook 🍳📖

Topics

Swift Enums are super handy. With associated values, they can be used in some quite interesting ways. Today we'll check out a couple. These aren't working examples, but might spark some ideas. Let's take a look.

Enums with Extensions

Keeping colors in one place is a great way to ensure consistency in a project.

public enum Color : String {
  case Green = "28A860"
  case Blue = "3B87D6"
}

extension Color : UIColorConvertible {
  public func asColor() -> UIColor {
    return UIColor(hexString: rawValue)
  }
}

This same technique is great for images too!

Enums with Closures

This one is a little crazy (but fun!). Imagine we had our own custom system for laying out views in our app. We could not only describe that system perfectly with enums, we could even add a little more dynamic spice to the mix by making one of the associated values of our enum a closure. Neat!

public enum LayoutStrategy {
  case SizeToFit
  case Fixed(width: CGFloat, height: CGFloat)
  case Relative(closure: ((parentSize: CGSize) -> CGSize))
}

Enums can describe so many types of state and data. Know of a cool use of them? Send it to hello@littlebitesofcocoa.com and it might be featured here!

Those who have been an iOS, OS X, tvOS, or watchOS developer for any significant amount of time know that Xcode is an incredible tool for creating awesome apps. Until it isn't. Sometimes Xcode gets confused and needs our help. Today we'll look at one way we can clean up our environment and possibly get back to work.

There's a myriad of reasons why the following technique resolves many common Xcode issues. The important part is that it works. Sometimes. Maybe.

Anyways, there's this folder full of "invariants" and temporary files that Xcode shuffles things around in as we use it to build our app. It's called DerivedData and contains caches, compiler waste, build products, etc.

If we ever find ourselves wondering if a certain compiler error or unexpected Xcode behavior really is our fault or a bug in Xcode, we can try clearing out this folder before jumping on the Google train.

The "manual" quick/dirty way is to quit Xcode then run:

rm -rf ~/Library/Developer/Xcode/DerivedData

Then re-launch Xcode. Also keep those fingers crossed.

Alternatively, we could use an app to do all this for us. Watchdog is an app that lives in our menu bar and cleans up stale cache files in Xcode. Very cool!

When Swift debuted, we said goodbye to using #pragma pre-processor definitions to organize our code. Don't worry, Xcode still has our backs. We can use a few different "special" comments in our code and Xcode will pick up on them and display them in its jump bar:

The extra dash character in the name of our MARK gets us those sweet separators in the source navigator dropdown.

Xcode also supports a similar bit of functionality for TODO and FIXME comments. They'll show up in bold in the same dropdown.

func launch() {
  // TODO: launch here
}

func land() {
  // FIXME: shouldn't crash
}

As a bonus, we can use a little regex magic to get Xcode to generate build warnings for TODO and FIXMEs. We'll just add a new Run Script build phase to our project that contains:

KEYWORDS="TODO|FIXME|\?\?\?:|\!\!\!:"
find "${SRCROOT}" \( -name "*.swift" \) -print0 | \
xargs -0 egrep --with-filename --line-number --only-matching "($KEYWORDS).*\$" | \
perl -p -e "s/($KEYWORDS)/ warning: \$1/"

Shout out to Jeffrey Sambells for originally sparking this idea!

Today we'll check out a few different tips and tricks for working with UITableView. Let's get started.

Adding a Refresh Control

We can add pull-to-refresh capabilities to any UITableView easily:

let refreshControl = UIRefreshControl()
refreshControl.addTarget(
  self, 
  action: Selector("refreshed:"), 
  forControlEvents: .ValueChanged
)

tableView.addSubview(refreshControl)

Then we just implement that refreshed: function like this:

func refreshed(sender: UIRefreshControl) {
  refreshTheThing {
    sender.endRefreshing()
  }
}

Reload Visible Cells

Here's a quick (almost) one-liner to reload only the visible cells in the table view:

tableView.reloadRowsAtIndexPaths(
  tableView.indexPathsForVisibleRows ?? [],
  withRowAnimation: .Automatic
)

Accessing Rects

It's often handy to grab a reference to the actual frame of a cell, section, header or footer. We can do this easily with:

tableView.rectForRowAtIndexPath(
  selectedIndexPath
)

Animate Height Changes

One easy trick to make our app look a little nicer is to animate changes to the heights of the UITableViewCells in our UITableView. All we need to do is make whatever changes to our models we want to cause our cells to be a different height. (For example we might let the user tap a button to "expand" all comments in an app). Then we just call:

tableView.beginUpdates()
tableView.endUpdates()

UIKit will interpolate & animate the changes, neat!

Weekly Sponsor: Hired 🏢

A continued huge thanks to the folks at Hired.com for sponsoring this week's bites. Finding a good job can be a daunting task. Today we'll take a look at how we can use Hired.com to save our sanity, and find a great job in the process. Let's dive in.

We'll start by entering our email and answering some basic questions:

That's it. Hired will then work with over 3,000 pre-screened companies (both big and small) in 13 major metro areas (North America & Europe) to try find us a great job. Software engineers and designers on Hired can get 5+ job offers in a single week. Each offer will include salary and equity details upfront.

We can view interview requests and accept or reject them before talking to any company. If we get a job through Hired, they'll give us a $1,000 "thank you" bonus!

Even better, if we sign up through this link: littlebitesofcocoa.com/hired, they'll double our bonus to $2,000!

More Reasons to Use Hired

  • Full time or contract opportunities are available
  • View offers and accept or reject them without talking to anyone.
  • Completely FREE + no obligations ever.

Hired is the real deal. They have solved some very real problems and fixed this historically messy process. Looking for a job? Don't waste time, sign up for Hired today so you can get back to work!

Page 15 of 38