Skip to content

Instantly share code, notes, and snippets.

@Quaggie
Last active July 6, 2017 13:16
Show Gist options
  • Save Quaggie/0bd560f47491c0aa1c20b68d2c1f7ad9 to your computer and use it in GitHub Desktop.
Save Quaggie/0bd560f47491c0aa1c20b68d2c1f7ad9 to your computer and use it in GitHub Desktop.
//
// Extensions.swift
// Swift 3 compatible
//
// Created by Quaggie.
// Copyright © 2017 Quaggie. All rights reserved.
//
import UIKit
extension UIColor {
convenience init(hexString: String) {
var cString: String = hexString.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines).uppercased()
if (cString.hasPrefix("#")) {
cString = (cString as NSString).substring(from: 1)
}
if (cString.characters.count != 6) {
self.init(white: 0.5, alpha: 1.0)
} else {
let rString: String = (cString as NSString).substring(to: 2)
let gString = ((cString as NSString).substring(from: 2) as NSString).substring(to: 2)
let bString = ((cString as NSString).substring(from: 4) as NSString).substring(to: 2)
var r: CUnsignedInt = 0, g: CUnsignedInt = 0, b: CUnsignedInt = 0;
Scanner(string: rString).scanHexInt32(&r)
Scanner(string: gString).scanHexInt32(&g)
Scanner(string: bString).scanHexInt32(&b)
self.init(red: CGFloat(r) / CGFloat(255.0), green: CGFloat(g) / CGFloat(255.0), blue: CGFloat(b) / CGFloat(255.0), alpha: CGFloat(1))
}
}
}
protocol ReusableView: class { }
extension ReusableView where Self: UIView {
static var reuseIdentifier: String {
return String(describing: self)
}
}
extension UITableViewCell: ReusableView { }
protocol NibLoadableView: class { }
extension NibLoadableView where Self: UIView {
static var nibName: String {
return String(describing: self)
}
}
extension UITableView {
func register<T: UITableViewCell>(_: T.Type) where T: ReusableView, T: NibLoadableView {
let nib = UINib(nibName: T.nibName, bundle: nil)
register(nib, forCellReuseIdentifier: T.reuseIdentifier)
}
func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T where T: ReusableView {
guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
}
return cell
}
}
extension String: Error {
func floatingPoint () throws -> Double {
let value = try self.characters.map { char throws -> String in
if String(char).rangeOfCharacter(from: CharacterSet.letters) != nil {
throw "Letters not allowed!"
}
return char == "." ? "" : String(char)
}.joined()
return Double(value) ?? Double()
}
func limitDecimals (by num: Int) -> String {
return String(format: "%.\(num)f", Double(self) ?? 0)
}
func toArrayWith(separator: String) -> [String] {
return self.characters.split(separator: ",").map { String($0).trimmingCharacters(in: .whitespacesAndNewlines) }
}
var dateFromISO8601: Date? {
return Date.Formatter.iso8601.date(from: self)
}
func getDataFromUrl (completion: @escaping (_ data: Data?) -> Void) {
URLSession.shared.dataTask(with: NSURL(string: self)! as URL, completionHandler: { (data, response, error) -> Void in
if let error = error {
print(error)
return
}
completion(data)
}).resume()
}
var digits: String {
return components(separatedBy: CharacterSet.decimalDigits.inverted)
.joined(separator: "")
}
}
// Date ----------------------------------------------------------------------------------------------------------------
extension Date {
struct Formatter {
static let iso8601: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
return formatter
}()
}
var iso8601: String {
return Formatter.iso8601.string(from: self)
}
func string (format: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.string(from: self)
}
/// Returns the amount of years from another date
func years(from date: Date) -> Int {
return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
}
/// Returns the amount of months from another date
func months(from date: Date) -> Int {
return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
}
/// Returns the amount of weeks from another date
func weeks(from date: Date) -> Int {
return Calendar.current.dateComponents([.weekOfYear], from: date, to: self).weekOfYear ?? 0
}
/// Returns the amount of days from another date
func days(from date: Date) -> Int {
return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
}
/// Returns the amount of hours from another date
func hours(from date: Date) -> Int {
return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
}
/// Returns the amount of minutes from another date
func minutes(from date: Date) -> Int {
return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
}
/// Returns the amount of seconds from another date
func seconds(from date: Date) -> Int {
return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
}
/// Returns the a custom time interval description from another date
func offset(from date: Date) -> String {
if years(from: date) > 0 { return "\(years(from: date))y" }
if months(from: date) > 0 { return "\(months(from: date))M" }
if weeks(from: date) > 0 { return "\(weeks(from: date))w" }
if days(from: date) > 0 { return "\(days(from: date))d" }
if hours(from: date) > 0 { return "\(hours(from: date))h" }
if minutes(from: date) > 0 { return "\(minutes(from: date))m" }
if seconds(from: date) > 0 { return "\(seconds(from: date))s" }
return ""
}
var fromNow: String {
let now = Date()
let years = now.years(from: self)
let months = now.months(from: self)
let weeks = now.weeks(from: self)
let days = now.days(from: self)
let hours = now.hours(from: self)
let minutes = now.minutes(from: self)
let seconds = now.seconds(from: self)
if years > 0 {
if years > 1 {
return "\(years) anos atrás"
}
return "\(years) ano atrás"
}
if months > 0 {
if months > 1 {
return "\(months) meses atrás"
}
return "\(months) mês atrás"
}
if weeks > 0 {
if weeks > 1 {
return "\(weeks) semanas atrás"
}
return "\(weeks) semana atrás"
}
if days > 0 {
if days > 1 {
return "\(days) dias atrás"
}
return "\(days) dia atrás"
}
if hours > 0 {
if hours > 1 {
return "\(hours) horas atrás"
}
return "\(hours) hora atrás"
}
if minutes > 0 {
if minutes > 1 {
return "\(minutes) minutos atrás"
}
return "\(minutes) minuto atrás"
}
if seconds > 0 {
return "Ainda agora"
} else {
return "Agora"
}
}
}
// Timer ----------------------------------------------------------------------------------------------------------------
extension Timer {
// Adds a delay to the main Queue
static func delay (_ delay: Double, closure: @escaping ()->()) {
DispatchQueue.main.asyncAfter(
deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC),
execute: closure
)
}
}
// UIView ----------------------------------------------------------------------------------------------------------------
extension UIView {
func addContraintsWith (format: String, views: UIView...) {
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerated() {
let key = "v\(index)"
view.translatesAutoresizingMaskIntoConstraints = false
viewsDictionary[key] = view
}
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
}
func fillSuperview() {
translatesAutoresizingMaskIntoConstraints = false
if let superview = superview {
leftAnchor.constraint(equalTo: superview.leftAnchor).isActive = true
rightAnchor.constraint(equalTo: superview.rightAnchor).isActive = true
topAnchor.constraint(equalTo: superview.topAnchor).isActive = true
bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
}
}
@discardableResult
func anchor(top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil, topConstant: CGFloat = 0, leftConstant: CGFloat = 0, bottomConstant: CGFloat = 0, rightConstant: CGFloat = 0, widthConstant: CGFloat = 0, heightConstant: CGFloat = 0) -> [NSLayoutConstraint] {
translatesAutoresizingMaskIntoConstraints = false
var anchors = [NSLayoutConstraint]()
if let top = top {
anchors.append(topAnchor.constraint(equalTo: top, constant: topConstant))
}
if let left = left {
anchors.append(leftAnchor.constraint(equalTo: left, constant: leftConstant))
}
if let bottom = bottom {
anchors.append(bottomAnchor.constraint(equalTo: bottom, constant: -bottomConstant))
}
if let right = right {
anchors.append(rightAnchor.constraint(equalTo: right, constant: -rightConstant))
}
if widthConstant > 0 {
anchors.append(widthAnchor.constraint(equalToConstant: widthConstant))
}
if heightConstant > 0 {
anchors.append(heightAnchor.constraint(equalToConstant: heightConstant))
}
anchors.forEach({$0.isActive = true})
return anchors
}
func anchorCenterXToSuperview(constant: CGFloat = 0) {
translatesAutoresizingMaskIntoConstraints = false
if let anchor = superview?.centerXAnchor {
centerXAnchor.constraint(equalTo: anchor, constant: constant).isActive = true
}
}
func anchorCenterYToSuperview(constant: CGFloat = 0) {
translatesAutoresizingMaskIntoConstraints = false
if let anchor = superview?.centerYAnchor {
centerYAnchor.constraint(equalTo: anchor, constant: constant).isActive = true
}
}
func anchorCenterSuperview() {
anchorCenterXToSuperview()
anchorCenterYToSuperview()
}
var usesAutoLayout: Bool {
get { return !translatesAutoresizingMaskIntoConstraints }
set { translatesAutoresizingMaskIntoConstraints = !newValue }
}
}
// Array ----------------------------------------------------------------------------------------------------------------
extension Array where Element: Equatable {
var unique: [Element] {
var uniqueValues: [Element] = []
forEach { item in
if !uniqueValues.contains(item) {
uniqueValues += [item]
}
}
return uniqueValues
}
}
// Notification Center
extension Notification.Name {
static let onUserLogin = Notification.Name("onUserLogin")
static let onUserLogout = Notification.Name("onUserLogout")
}
// UITabBar
extension UITabBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
super.sizeThatFits(size)
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 38
return sizeThatFits
}
}
// NavigationBar
extension NavigationBar {
func configure () {
tintColor = Color.white
depthPreset = .depth4
dividerColor = Colors.red
backgroundColor = Colors.red
isOpaque = true
isTranslucent = false
}
func setTransparent () {
setBackgroundImage(UIImage(), for: .default)
shadowImage = UIImage()
isTranslucent = true
backgroundColor = UIColor.clear
}
}
// UIApplication
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
// UIImageView
extension UIImageView {
func roundImgWithBorder (width: CGFloat, color: UIColor) {
self.layer.cornerRadius = self.height / 2
self.borderWidth = width
self.borderColor = color
}
func roundImg () {
self.layer.cornerRadius = self.height / 2
}
func imageFromServerURL(urlString: String) {
URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in
if let error = error {
print(error)
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
})
}).resume()
}
func imageFromServerURL(urlString: String, completion: @escaping (_ img: UIImage?) -> Void) {
URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in
if let error = error {
print(error)
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
completion(image)
})
}).resume()
}
}
// Int
extension Int {
var kFormatted: String {
if self >= 1000 && self < 1000000 {
return String(format: "%iK", self / 1000)
} else if self >= 1000000 {
return String(format: "%iKK", self / 100000)
} else {
return String(describing: self)
}
}
}
// Double
extension Double {
var kFormatted: String {
if self >= 1000 && self < 1000000 {
return String(format: "%.2fK", self / 1000)
} else if self >= 1000000 {
return String(format: "%.2fKK", self / 1000000)
} else {
return String(format: "%.2f", self)
}
}
}
// UIViewController
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment