Last active
September 27, 2017 09:18
-
-
Save Erkened/2f1a62550988046479482c5e525c5899 to your computer and use it in GitHub Desktop.
Extensions I use often in my projects. Swift 4.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import UIKit | |
extension UIColor{ | |
class var random: UIColor { | |
let hue : CGFloat = CGFloat(arc4random() % 256) / 256 // use 256 to get full range from 0.0 to 1.0 | |
let saturation : CGFloat = CGFloat(arc4random() % 128) / 256 + 0.5 // from 0.5 to 1.0 to stay away from white | |
let brightness : CGFloat = CGFloat(arc4random() % 128) / 256 + 0.5 // from 0.5 to 1.0 to stay away from black | |
return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1) | |
} | |
class func hex(_ hex:String, alpha:CGFloat = 1.0) -> UIColor { | |
var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() | |
if (cString.hasPrefix("#")) { | |
let index = cString.index(cString.startIndex, offsetBy: 1) | |
cString = String(cString[index...]) | |
} | |
if (cString.characters.count != 6) { | |
return UIColor.gray | |
} | |
var rgbValue:UInt32 = 0 | |
Scanner(string: cString).scanHexInt32(&rgbValue) | |
return UIColor( | |
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, | |
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, | |
blue: CGFloat(rgbValue & 0x0000FF) / 255.0, | |
alpha: CGFloat(alpha) | |
) | |
} | |
var invert: UIColor { | |
var red : CGFloat = 255.0 | |
var green : CGFloat = 255.0 | |
var blue : CGFloat = 255.0 | |
var alpha : CGFloat = 1.0 | |
self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) | |
red = 255.0 - (red * 255.0) | |
green = 255.0 - (green * 255.0) | |
blue = 255.0 - (blue * 255.0) | |
return UIColor(red: red / 255.0, green: green / 255.0, blue: blue / 255.0, alpha: alpha) | |
} | |
} | |
extension UIFont{ | |
// FONTELLO | |
public class func fontello(withSize fontSize: CGFloat) -> UIFont{ return self.init(name: "fontello", size: fontSize)! } | |
} | |
extension UITextField{ | |
func addDoneButtonToKeyboard(withAction action: Selector?){ | |
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 300, height: 40)) | |
doneToolbar.barStyle = UIBarStyle.default | |
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil) | |
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: action) | |
var items = [UIBarButtonItem]() | |
items.append(flexSpace) | |
items.append(done) | |
doneToolbar.items = items | |
doneToolbar.sizeToFit() | |
self.inputAccessoryView = doneToolbar | |
} | |
} | |
extension String{ | |
var underlined: NSAttributedString { | |
get { | |
let textRange = NSMakeRange(0, self.characters.count) | |
let attributedText = NSMutableAttributedString(string: self) | |
attributedText.addAttribute(NSUnderlineStyleAttributeName , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange) | |
return attributedText | |
} | |
} | |
func underlined(withColour colour: UIColor) -> NSAttributedString{ | |
let textRange = NSMakeRange(0, self.characters.count) | |
let attributedText = NSMutableAttributedString(string: self) | |
attributedText.addAttribute(NSUnderlineStyleAttributeName , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange) | |
attributedText.addAttribute(NSForegroundColorAttributeName, value: colour, range: textRange) | |
return attributedText | |
} | |
var localised: String { return NSLocalizedString(self, comment: "") } | |
} | |
// Get the topmost view controller | |
extension UIApplication { | |
class func topViewController(_ base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? { | |
if let nav = base as? UINavigationController { | |
return topViewController(nav.visibleViewController) | |
} | |
if let tab = base as? UITabBarController, let selected = tab.selectedViewController { | |
return topViewController(selected) | |
} | |
if let presented = base?.presentedViewController { | |
return topViewController(presented) | |
} | |
return base | |
} | |
} | |
extension NSLayoutConstraint { | |
public class func useAndActivate(_ constraints: [NSLayoutConstraint]) { | |
for constraint in constraints { | |
if let view = constraint.firstItem as? UIView { | |
view.translatesAutoresizingMaskIntoConstraints = false | |
} | |
} | |
activate(constraints) | |
} | |
} | |
// Make cell identifiers reusable for collection views | |
// Source: https://medium.com/@gonzalezreal/ios-cell-registration-reusing-with-swift-protocol-extensions-and-generics-c5ac4fb5b75e#.3ey5f2nvs | |
protocol ReusableView: class {} | |
extension ReusableView where Self: UIView { | |
static var reuseIdentifier: String { | |
return String(describing: self) | |
} | |
} | |
//extension UICollectionViewCell: ReusableView {} | |
extension UICollectionReusableView: ReusableView {} | |
extension UICollectionView { | |
func register<T: UICollectionViewCell>(_: T.Type){ | |
register(T.self, forCellWithReuseIdentifier: T.reuseIdentifier) | |
} | |
func dequeueReusableCell<T: UICollectionViewCell>(forIndexPath indexPath: IndexPath) -> T{ | |
guard let cell = dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as? T else{ | |
fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)") | |
} | |
return cell | |
} | |
func registerHeader<T: UICollectionReusableView>(_: T.Type){ | |
register(T.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: T.reuseIdentifier) | |
} | |
func registerFooter<T: UICollectionReusableView>(_: T.Type){ | |
register(T.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: T.reuseIdentifier) | |
} | |
func dequeueReusableHeader<T: UICollectionReusableView>(forIndexPath indexPath: IndexPath) -> T{ | |
guard let reusableView = dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: T.reuseIdentifier, for: indexPath) as? T else { | |
fatalError("Could not dequeue header with identifier: \(T.reuseIdentifier)") | |
} | |
return reusableView | |
} | |
func dequeueReusableFooter<T: UICollectionReusableView>(forIndexPath indexPath: IndexPath) -> T{ | |
guard let reusableView = dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionFooter, withReuseIdentifier: T.reuseIdentifier, for: indexPath) as? T else { | |
fatalError("Could not dequeue footer with identifier: \(T.reuseIdentifier)") | |
} | |
return reusableView | |
} | |
} | |
// This function makes sure the index is in the array by using the "safe" keyword | |
// Example: if let item = array[safe: index] { .. } | |
// Source: http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings | |
extension Collection { | |
/// Returns the element at the specified index iff it is within bounds, otherwise nil. | |
subscript (safe index: Index) -> Iterator.Element? { | |
return index >= startIndex && index < endIndex ? self[index] : nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment