This article is the 19th entry of the CAMPHOR - Advent Calendar 2017.
I have extracted and published several libraries implemented for iOS development, whether for personal use or for work. I hope they can be helpful to someone.
BetterUserDefaults#
This allows you to use a UserDefaults.Key
type to define UserDefaults keys instead of using strings, similar to Notification.Name
.
import BetterUserDefaults
extension UserDefaults.Key {
static let sampleKeyA = UserDefaults.Key("sampleKeyA")
static let sampleKeyB = UserDefaults.Key("sampleKeyB")
}
UserDefaults.standard.set(true, for: .sampleKeyA)
UserDefaults.standard.set(123, for: .sampleKeyB)
UserDefaults.standard.bool(for: .sampleKeyA) // true
UserDefaults.standard.integer(for: .sampleKeyB) // 123
UIViewBorders#
An extension that allows you to add borders of arbitrary color and thickness to the four sides of a UIView. The border itself is also a UIView, so it supports dynamic resizing of the parent view through AutoLayout.
view.addBorderViews(positions: [.left, .bottom], color: .red, width: 3)

KeyboardFriendlyScrolling#
This sets the contentInset.bottom
of the scroll view to the height of the keyboard. It calculates the overlapping height by converting and comparing the frames of the scrollView
and the keyboard to the coordinates on the window
, so it should work properly even if the scrollView
does not fill the entire screen.
import UIKit
import KeyboardFriendlyScrolling
class ViewController: UIViewController {
private var keyboardFriendlyScrollController: KeyboardFriendlyScrollController?
@IBOutlet private weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
keyboardFriendlyScrollController = KeyboardFriendlyScrollController(viewController: self, scrollView: scrollView).start()
}
}

CopyLinkActivity#
A UIActivity to place a "Copy Link" button in the iOS share options.
import UIKit
import CopyLinkActivity
class ViewController: UIViewController {
@IBAction func didTapShareButton(_ sender: UIButton) {
let linkURL = URL(string: "https://www.apple.com/")!
let activityViewController = UIActivityViewController(activityItems: [linkURL], applicationActivities: [CopyLinkActivity()])
activityViewController.completionWithItemsHandler = { [weak self] (activityType, completed, _, _) -> Void in
if completed && activityType == CopyLinkActivity.defaultActivityType {
let alert = UIAlertController(title: "Copied", message: linkURL.absoluteString, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self?.present(alert, animated: true)
}
}
present(activityViewController, animated: true)
}
}

While the standard share options include "Copy," there was a bug in iOS 11.1 where passing both a string and a URL to activityItems
would cause the URL to be ignored, and only the string would be copied to the clipboard. Therefore, I created one that can properly copy only the URL.
Details of the bug
RFC3339DateFormatter#
Even though the server says, "I'll send it in RFC3339 format," the specification is quite flexible, so I created a DateFormatter that can parse it even with variations. The implementation follows the specifications of RFC 3339 - Date and Time on the Internet: Timestamps.
Date from String
import RFC3339DateFormatter
// with T, nanosecond
RFC3339DateFormatter.date(from: "2017-01-01T00:00:00.000Z")
RFC3339DateFormatter.date(from: "2017-01-01T09:00:00.000+09:00")
// with T
RFC3339DateFormatter.date(from: "2017-01-01T00:00:00Z")
RFC3339DateFormatter.date(from: "2017-01-01T09:00:00+09:00")
// with ` `, nanosecond
RFC3339DateFormatter.date(from: "2017-01-01 00:00:00.000Z")
RFC3339DateFormatter.date(from: "2017-01-01 09:00:00.000+09:00")
// with ` `
RFC3339DateFormatter.date(from: "2017-01-01 00:00:00Z")
RFC3339DateFormatter.date(from: "2017-01-01 09:00:00+09:00")
// different number of digits of nanosecond
RFC3339DateFormatter.date(from: "2017-01-01 00:00:00.0Z")
Date to String
import RFC3339DateFormatter
RFC3339DateFormatter.string(from: Date()) // "2017-12-01T06:25:11.029Z"
Feelings
EasyButton#
A simple way to create buttons easily. When you specify the main color, it automatically calculates and sets the highlighted color, which is a nice feature.
// Set a darker color than the background color to the highlighted background color automatically
let lightColorButton = UIButton.button(title: "Hello World", titleColor: .white, backgroundColor: .orange, cornerRadius: 6)
// Set a lighter color than the background color to the highlighted background color automatically
let darkColorButton = UIButton.button(title: "Hello World", titleColor: .white, backgroundColor: .darkGray, cornerRadius: 6)

In addition to the above, the following functions are also available, so it can be used independently.
extension UIButton {
public func setBackgroundColor(color: UIColor, for state: UIControlState)
public func setBackgroundColor(color: UIColor, highlightedColor: UIColor? = nil)
public func setCornerRadius(radius: CGFloat)
public func setup(title: String? = nil, titleColor: UIColor, backgroundColor: UIColor, highlightedColor: UIColor? = nil, cornerRadius: CGFloat = 0)
}
Reflection on the Advent Calendar#
Looking back, I have participated in this Advent Calendar every year since 2014, making it my fourth year.
2014#
2015#
2016#
2017#
→ This article
I look forward to next year as well.