Last active
October 20, 2019 20:14
-
-
Save sharingisnice/b3ab71aadee691d1c04865f8bc8ea606 to your computer and use it in GitHub Desktop.
Stuff I used that is super handy
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
| // | |
| // UsefulExtensions.swift | |
| // | |
| // Created by Mert Ejder on 14.11.2018. | |
| // Copyright © 2018 mertejder. All rights reserved. | |
| // | |
| import Foundation | |
| extension UIViewController { | |
| func setMask(with hole: CGRect, in view: UIView){ | |
| // Create a mutable path and add a rectangle that will be h | |
| let mutablePath = CGMutablePath() | |
| mutablePath.addRect(view.bounds) | |
| mutablePath.addRect(hole) | |
| // Create a shape layer and cut out the intersection | |
| let mask = CAShapeLayer() | |
| mask.path = mutablePath | |
| mask.fillRule = CAShapeLayerFillRule.evenOdd | |
| // Add the mask to the view | |
| view.layer.mask = mask | |
| } | |
| func setMask(withCircle hole: CGRect, in view: UIView){ | |
| // Create a mutable path and add a rectangle that will be h | |
| let mutablePath = CGMutablePath() | |
| mutablePath.addRect(view.bounds) | |
| mutablePath.addEllipse(in: hole) | |
| // mutablePath.addRect(circleHole) | |
| // let circleHole = UIBezierPath(ovalIn: circleHole) | |
| // Create a shape layer and cut out the intersection | |
| let mask = CAShapeLayer() | |
| mask.path = mutablePath | |
| mask.fillRule = CAShapeLayerFillRule.evenOdd | |
| // Add the mask to the view | |
| view.layer.mask = mask | |
| } | |
| func alertWithTitle(title: String, message: String) -> UIAlertController { | |
| let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) | |
| alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) | |
| return alert | |
| } | |
| } | |
| public extension UIDevice { | |
| static let modelName: String = { | |
| var systemInfo = utsname() | |
| uname(&systemInfo) | |
| let machineMirror = Mirror(reflecting: systemInfo.machine) | |
| let identifier = machineMirror.children.reduce("") { identifier, element in | |
| guard let value = element.value as? Int8, value != 0 else { return identifier } | |
| return identifier + String(UnicodeScalar(UInt8(value))) | |
| } | |
| func mapToDevice(identifier: String) -> String { // swiftlint:disable:this cyclomatic_complexity | |
| #if os(iOS) | |
| switch identifier { | |
| case "iPod5,1": return "iPod Touch 5" | |
| case "iPod7,1": return "iPod Touch 6" | |
| case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4" | |
| case "iPhone4,1": return "iPhone 4s" | |
| case "iPhone5,1", "iPhone5,2": return "iPhone 5" | |
| case "iPhone5,3", "iPhone5,4": return "iPhone 5c" | |
| case "iPhone6,1", "iPhone6,2": return "iPhone 5s" | |
| case "iPhone7,2": return "iPhone 6" | |
| case "iPhone7,1": return "iPhone 6 Plus" | |
| case "iPhone8,1": return "iPhone 6s" | |
| case "iPhone8,2": return "iPhone 6s Plus" | |
| case "iPhone9,1", "iPhone9,3": return "iPhone 7" | |
| case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus" | |
| case "iPhone8,4": return "iPhone SE" | |
| case "iPhone10,1", "iPhone10,4": return "iPhone 8" | |
| case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus" | |
| case "iPhone10,3", "iPhone10,6": return "iPhone X" | |
| case "iPhone11,2": return "iPhone XS" | |
| case "iPhone11,4", "iPhone11,6": return "iPhone XS Max" | |
| case "iPhone11,8": return "iPhone XR" | |
| case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2" | |
| case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad 3" | |
| case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad 4" | |
| case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air" | |
| case "iPad5,3", "iPad5,4": return "iPad Air 2" | |
| case "iPad6,11", "iPad6,12": return "iPad 5" | |
| case "iPad7,5", "iPad7,6": return "iPad 6" | |
| case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad Mini" | |
| case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad Mini 2" | |
| case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad Mini 3" | |
| case "iPad5,1", "iPad5,2": return "iPad Mini 4" | |
| case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)" | |
| case "iPad6,7", "iPad6,8": return "iPad Pro (12.9-inch)" | |
| case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)" | |
| case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)" | |
| case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return "iPad Pro (11-inch)" | |
| case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return "iPad Pro (12.9-inch) (3rd generation)" | |
| case "AppleTV5,3": return "Apple TV" | |
| case "AppleTV6,2": return "Apple TV 4K" | |
| case "AudioAccessory1,1": return "HomePod" | |
| case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))" | |
| default: return identifier | |
| } | |
| #elseif os(tvOS) | |
| switch identifier { | |
| case "AppleTV5,3": return "Apple TV 4" | |
| case "AppleTV6,2": return "Apple TV 4K" | |
| case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))" | |
| default: return identifier | |
| } | |
| #endif | |
| } | |
| return mapToDevice(identifier: identifier) | |
| }() | |
| } | |
| extension Double { | |
| /// Rounds the double to decimal places value | |
| func rounded(toPlaces places:Int) -> Double { | |
| let divisor = pow(10.0, Double(places)) | |
| return (self * divisor).rounded(.down) / divisor | |
| } | |
| func rounded(toPlaces places:Int, roundingRule: FloatingPointRoundingRule) -> Double { | |
| let divisor = pow(10.0, Double(places)) | |
| return (self * divisor).rounded(roundingRule) / divisor | |
| } | |
| } | |
| extension Date { | |
| var ticks: UInt64 { | |
| return UInt64((self.timeIntervalSince1970 + 62_135_596_800) * 10_000_000) | |
| } | |
| } | |
| extension String { | |
| var length: Int { | |
| return count | |
| } | |
| subscript (i: Int) -> String { | |
| return self[i ..< i + 1] | |
| } | |
| func substring(fromIndex: Int) -> String { | |
| return self[min(fromIndex, length) ..< length] | |
| } | |
| func substring(toIndex: Int) -> String { | |
| return self[0 ..< max(0, toIndex)] | |
| } | |
| subscript (r: Range<Int>) -> String { | |
| let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)), | |
| upper: min(length, max(0, r.upperBound)))) | |
| let start = index(startIndex, offsetBy: range.lowerBound) | |
| let end = index(start, offsetBy: range.upperBound - range.lowerBound) | |
| return String(self[start ..< end]) | |
| } | |
| } | |
| extension UIImageView { | |
| func setImageRenderingMode(_ renderMode: UIImage.RenderingMode) { | |
| assert(image != nil, "Image must be set before setting rendering mode") | |
| // AlwaysOriginal as an example | |
| image = image?.withRenderingMode(.alwaysOriginal) | |
| } | |
| } | |
| extension UIView { | |
| // Using a function since `var image` might conflict with an existing variable | |
| // (like on `UIImageView`) | |
| func asImage() -> UIImage { | |
| if #available(iOS 10.0, *) { | |
| let renderer = UIGraphicsImageRenderer(bounds: bounds) | |
| return renderer.image { rendererContext in | |
| layer.render(in: rendererContext.cgContext) | |
| } | |
| } else { | |
| UIGraphicsBeginImageContext(self.frame.size) | |
| self.layer.render(in:UIGraphicsGetCurrentContext()!) | |
| let image = UIGraphicsGetImageFromCurrentImageContext() | |
| UIGraphicsEndImageContext() | |
| return UIImage(cgImage: image!.cgImage!) | |
| } | |
| } | |
| } | |
| extension UIView { | |
| func findViewController() -> UIViewController? { | |
| if let nextResponder = self.next as? UIViewController { | |
| return nextResponder | |
| } else if let nextResponder = self.next as? UIView { | |
| return nextResponder.findViewController() | |
| } else { | |
| return nil | |
| } | |
| } | |
| } | |
| extension Array where Element == Int { | |
| func median() -> Double { | |
| let sortedArray = sorted() | |
| if count % 2 != 0 { | |
| return Double(sortedArray[count / 2]) | |
| } else { | |
| return Double(sortedArray[count / 2] + sortedArray[count / 2 - 1]) / 2.0 | |
| } | |
| } | |
| } | |
| extension UIView { | |
| var parentViewController: UIViewController? { | |
| var parentResponder: UIResponder? = self | |
| while parentResponder != nil { | |
| parentResponder = parentResponder!.next | |
| if let viewController = parentResponder as? UIViewController { | |
| return viewController | |
| } | |
| } | |
| return nil | |
| } | |
| } | |
| extension UIViewController { | |
| class func displaySpinner(onView : UIView) -> UIView { | |
| let spinnerView = UIView.init(frame: onView.bounds) | |
| spinnerView.backgroundColor = UIColor.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.5) | |
| let ai = UIActivityIndicatorView.init(style: .whiteLarge) | |
| ai.startAnimating() | |
| ai.center = spinnerView.center | |
| DispatchQueue.main.async { | |
| spinnerView.addSubview(ai) | |
| onView.addSubview(spinnerView) | |
| } | |
| return spinnerView | |
| } | |
| class func removeSpinner(spinner :UIView) { | |
| DispatchQueue.main.async { | |
| spinner.removeFromSuperview() | |
| } | |
| } | |
| class func addDarkBackground(to onView: UIView) -> UIView { | |
| let spinnerView = UIView.init(frame: UIScreen.main.bounds) | |
| spinnerView.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.5) | |
| onView.addSubview(spinnerView) | |
| return spinnerView | |
| } | |
| class func removeDarkBackground(view :UIView) { | |
| DispatchQueue.main.async { | |
| view.removeFromSuperview() | |
| } | |
| } | |
| func showAlert(title: String , message: String , okButtonText : String) { | |
| let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert) | |
| alert.addAction(UIAlertAction(title: okButtonText, style: UIAlertAction.Style.default, handler: nil)) | |
| self.present(alert, animated: true, completion: nil) | |
| } | |
| } | |
| extension String { | |
| var isInt: Bool { | |
| return Int(self) != nil | |
| } | |
| } | |
| extension String { | |
| func hexStringToUIColor (hex:String) -> UIColor { | |
| var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() | |
| if (cString.hasPrefix("#")) { | |
| cString.remove(at: cString.startIndex) | |
| } | |
| if ((cString.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(1.0) | |
| ) | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment