Skip to content

Instantly share code, notes, and snippets.

@vahan3x
Last active March 24, 2018 14:03
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 vahan3x/7de13fadd2e03a254e87fa5055d3279c to your computer and use it in GitHub Desktop.
Save vahan3x/7de13fadd2e03a254e87fa5055d3279c to your computer and use it in GitHub Desktop.
Useful extensions for Cocoa Touch frameworks
// Swift version: 4.0
public extension Comparable {
/// Returns a copy of the value clamped to the given limiting range.
///
/// Example:
///
/// let a = 50
/// print(a.clamped(to: 0 ... 10)) // prints 10
///
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameter limits: The range to clamp the value.
/// - Returns: A new value clamped to the bounds of `limits`.
public func clamped(to limits: ClosedRange<Self>) -> Self {
return min(max(self, limits.lowerBound), limits.upperBound)
}
/// Clamps the value to the given limiting range.
///
/// Example:
///
/// var a = -50
/// a.clamp(to: 0 ... 10)
/// print(a) // prints 0
///
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameter limits: The range to clamp the value.
public mutating func clamp(to limits: ClosedRange<Self>) {
self = clamped(to: limits)
}
}
// Swift version: 4.0
public extension UIColor {
/// Tells if the color will appear light for the human eye.
/// - Attention: The alpha component of the color is being ignored.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
public var isLightColor: Bool {
var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0
getRed(&red, green: &green, blue: &blue, alpha: nil)
return (red * 299.0 + green * 587.0 + blue * 114.0) / 1000.0 >= 0.5;
}
/// Initializes and returns a color object from the specified hex code.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameter hexCode: Hex code of the color object.
public convenience init(hexCode: Int) {
self.init(red: CGFloat(0xFF & (hexCode >> 24)) / 255.0,
green: CGFloat(0xFF & (hexCode >> 16)) / 255.0,
blue: CGFloat(0xFF & (hexCode >> 8)) / 255.0,
alpha: CGFloat(0xFF & (hexCode >> 0)) / 255.0)
}
}
/// Multiplies every channel of the color with the multiplier.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameters:
/// - color: A color multiplier.
/// - multiplier: A number multiplier.
/// - Returns: A new color with multiplied channels.
public func *(color: UIColor, multiplier: Int) -> UIColor {
return color * CGFloat(multiplier)
}
/// Multiplies every channel of the color with the multiplier.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameters:
/// - color: A color multiplier.
/// - multiplier: A number multiplier.
/// - Returns: A new color with multiplied channels.
public func *(color: UIColor, multiplier: Double) -> UIColor {
return color * CGFloat(multiplier)
}
/// Multiplies every channel of the color with the multiplier.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameters:
/// - color: A color multiplier.
/// - multiplier: A number multiplier.
/// - Returns: A new color with multiplied channels.
public func *(color: UIColor, multiplier: CGFloat) -> UIColor {
var (r, g, b, a) = (CGFloat(0.0), CGFloat(0.0), CGFloat(0.0), CGFloat(0.0))
color.getRed(&r, green: &g, blue: &b, alpha: &a)
return UIColor(red: (r * multiplier).clamped(to: 0.0 ... 1.0),
green: (g * multiplier).clamped(to: 0.0 ... 1.0),
blue: (b * multiplier).clamped(to: 0.0 ... 1.0),
alpha: (a * multiplier).clamped(to: 0.0 ... 1.0))
}
/// Divides every channel of the color by the divisor.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameters:
/// - color: A color dividend.
/// - divisor: A number divisor.
/// - Returns: A new color with divided channels.
public func /(color: UIColor, divisor: Int) -> UIColor {
return color / CGFloat(divisor)
}
/// Divides every channel of the color by the divisor.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameters:
/// - color: A color dividend.
/// - divisor: A number divisor.
/// - Returns: A new color with divided channels.
public func /(color: UIColor, divisor: Double) -> UIColor {
return color / CGFloat(divisor)
}
/// Divides every channel of the color by the divisor.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameters:
/// - color: A color dividend.
/// - divisor: A number divisor.
/// - Returns: A new color with divided channels.
public func /(color: UIColor, divisor: CGFloat) -> UIColor {
var (r, g, b, a) = (CGFloat(0.0), CGFloat(0.0), CGFloat(0.0), CGFloat(0.0))
color.getRed(&r, green: &g, blue: &b, alpha: &a)
return UIColor(red: (r / divisor).clamped(to: 0.0 ... 1.0),
green: (g / divisor).clamped(to: 0.0 ... 1.0),
blue: (b / divisor).clamped(to: 0.0 ... 1.0),
alpha: (a / divisor).clamped(to: 0.0 ... 1.0))
}
/// Adds values of the two color channels.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Parameters:
/// - lhs: A color addend.
/// - rhs: A color addend.
/// - Returns: A new color with added channels.
public func +(lhs: UIColor, rhs: UIColor) -> UIColor {
var (r1, g1, b1, a1) = (CGFloat(0.0), CGFloat(0.0), CGFloat(0.0), CGFloat(0.0))
var (r2, g2, b2, a2) = (CGFloat(0.0), CGFloat(0.0), CGFloat(0.0), CGFloat(0.0))
lhs.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
rhs.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
return UIColor(red: min(r1 + r2, 1.0),
green: min(g1 + g2, 1.0),
blue: min(b1 + b2, 1.0),
alpha: min(a1 + a2, 1.0))
}
// Swift version: 4.0
public extension UIDevice {
/// Values identifying the model of a `UIDevice`.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - unknown: Unknown device
/// - simulator: A Simulator
/// - iPhone1G: iPhone 1st Generation
/// - iPhone3G: iPhone 3G
/// - iPhone3GS: iPhone 3GS
/// - iPhone4: iPhone 4
/// - iPhone4S: iPhone 4S
/// - iPhone5: iPhone 5
/// - iPhone5C: iPhone 5C
/// - iPhone5S: iPhone 5S
/// - iPhone6: iPhone 6
/// - iPhone6Plus: iPhone 6 Plus
/// - iPhoneSE: iPhone SE
/// - iPhone6S: iPhone 6S
/// - iPhone6SPlus: iPhone 6S Plus
/// - iPhone7: iPhone 7
/// - iPhone7Plus: iPhone 7 Plus
/// - iPhone8: iPhone 8
/// - iPhone8Plus: iPhone 8 Plus
/// - iPhoneX: iPhone X
public enum Model {
case unknown
case simulator
case iPhone1G
case iPhone3G
case iPhone3GS
case iPhone4
case iPhone4S
case iPhone5
case iPhone5C
case iPhone5S
case iPhone6
case iPhone6Plus
case iPhoneSE
case iPhone6S
case iPhone6SPlus
case iPhone7
case iPhone7Plus
case iPhone8
case iPhone8Plus
case iPhoneX
}
/// The model of the device.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
public var deviceModel: Model {
switch machineName() {
case "iPhone1,1": return .iPhone1G
case "iPhone1,2": return .iPhone3G
case "iPhone2,1": return .iPhone3GS
case "iPhone3,1", "iPhone3,3": return .iPhone4
case "iPhone4,1": return .iPhone4S
case "iPhone5,1", "iPhone5,2": return .iPhone5
case "iPhone5,3", "iPhone5,4": return .iPhone5C
case "iPhone6,1", "iPhone6,2": return .iPhone5S
case "iPhone7,2": return .iPhone6
case "iPhone7,1": return .iPhone6Plus
case "iPhone8,4": return .iPhoneSE
case "iPhone8,1": return .iPhone6S
case "iPhone8,2": return .iPhone6SPlus
case "iPhone9,1", "iPhone9,3": return .iPhone7
case "iPhone9,2", "iPhone9,4": return .iPhone7Plus
case "iPhone10,1", "iPhone10,4": return .iPhone8
case "iPhone10,2", "iPhone10,5": return .iPhone8Plus
case "iPhone10,3", "iPhone10,6": return .iPhoneX
case "x86_64", "i386": return .simulator
default: return .unknown
}
}
/// Gets the current machine's name.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
///
/// - Returns: Current machine's name.
private func machineName() -> String {
var systemInfo = utsname()
uname(&systemInfo)
return String(cString: &systemInfo.machine.0)
}
}
// Swift version: 4.0
public extension UIScreen {
/// A Boolean value indicating whether there is a notch on the screen.
/// - Author: [Vahan Babayan](https://github.com/vahan3x)
/// - ToDo: Behaviour on the multi-screen devices is undefined, need to figure out a way to detect the notch for the specified screen.
public var hasNotch: Bool {
if #available(iOS 11.0, *), let insets = UIApplication.shared.keyWindow?.safeAreaInsets {
switch UIDevice.current.orientation {
case .portrait: return insets.top > 0.0
case .portraitUpsideDown: return insets.bottom > 0.0
case .landscapeLeft: return insets.left > 0.0
case .landscapeRight: return insets.right > 0.0
default: return insets.top > 0.0 || insets.bottom > 0.0 || insets.left > 0.0 || insets.right > 0.0 // Best guess
}
}
return false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment