Skip to content

Instantly share code, notes, and snippets.

@irace
Last active November 29, 2017 19:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save irace/8e640774596c0abc25fed6c025be4df9 to your computer and use it in GitHub Desktop.
Save irace/8e640774596c0abc25fed6c025be4df9 to your computer and use it in GitHub Desktop.
import UIKit
/**
A drop-in replacement for the `UITableView`’s default section footer title, adding support for inline links. This class
will call the same, single target/action pair for *all* inline links, regardless of what their `NSLinkAttributeName`
values are. If you need to support multiple different inline links, this class is not for you.
Instead of implementing `tableView(tableView:titleForFooterInSection:)` and returning a string, implement
`tableView(tableView:, viewForFooterInSection section: Int)` and return an instance of this class.
You’ll also want to implement `tableView(tableView: UITableView, heightForFooterInSection section: Int)` and return
something along the lines of `footerView.sizeThatFits(CGSize(width: tableView.bounds.width, height: .max)).height`.
*/
public final class TargetActionSectionFooterTitleView: UIView {
private enum Constants {
/*
Match the default used by `UITableView` when `tableView(tableView:titleForFooterInSection:)` is implemented
(determined via trial and error).
*/
static let fontSize: CGFloat = 13
static let lineSpacing: CGFloat = 2.2
static let textColor: UIColor = UIColor(colorLiteralRed: 109/255, green: 109/255, blue: 114/255, alpha: 1)
static let containerTopBottomMargin: CGFloat = 8.5
static let containerLeftRightMargin: CGFloat = 10
}
// MARK: - Subviews
private let textView = UITextView()
// MARK: - Inputs
private let targetAction: WeakTargetAction
// MARK: - Initialization
public init(attributedText: NSAttributedString, targetAction: WeakTargetAction) {
self.targetAction = targetAction
super.init(frame: .zero)
textView.textContainerInset = UIEdgeInsets(
top: Constants.containerTopBottomMargin,
left: Constants.containerLeftRightMargin,
bottom: Constants.containerTopBottomMargin,
right: Constants.containerLeftRightMargin
)
textView.translatesAutoresizingMaskIntoConstraints = false
textView.delegate = self
textView.editable = false
textView.scrollEnabled = false
textView.attributedText = {
// Match `UITableView`’s default footer title text style
let mutableCopy = attributedText.mutableCopy() as! NSMutableAttributedString
mutableCopy.addAttributes(
[
NSParagraphStyleAttributeName: {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = Constants.lineSpacing
return paragraphStyle
}(),
NSFontAttributeName: UIFont.systemFontOfSize(Constants.fontSize),
NSForegroundColorAttributeName: Constants.textColor,
],
range: NSRange(location: 0, length: attributedText.length)
)
return mutableCopy
}()
addSubview(textView)
NSLayoutConstraint.activateConstraints([
textView.topAnchor.constraintEqualToAnchor(topAnchor),
textView.leadingAnchor.constraintEqualToAnchor(leadingAnchor),
textView.trailingAnchor.constraintEqualToAnchor(trailingAnchor),
textView.bottomAnchor.constraintEqualToAnchor(bottomAnchor),
])
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - UIView
public override func sizeThatFits(size: CGSize) -> CGSize {
return textView.sizeThatFits(size)
}
}
import Foundation
/**
A wrapper around a target/action pair, holding the target weakly since the target (e.g. a view controller) often holds
a strong reference to the object that ends up owning the `WeakTargetAction` instance (e.g. a view).
*/
public final class WeakTargetAction {
weak var target: AnyObject?
let action: Selector
public init(target: AnyObject, action: Selector) {
self.target = target
self.action = action
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment