- 
      
 - 
        
Save byJeevan/da1c69a143b68585ef1d0a2f610f2a01 to your computer and use it in GitHub Desktop.  
| /* | |
| * Author : Jeevan Rao | |
| * Date : 13/0/2017 | |
| * Swift : V3.1 | |
| */ | |
| /* UI + UX Tricks */ | |
| //Selection style of table view cell (other than Default grey / Blue/ none) | |
| let selectionColorView = UIView() | |
| selectionColorView.backgroundColor = UIColor.blue | |
| cell.selectedBackgroundView = selectionColorView | |
| //UISeachBar Cancel button color | |
| UIBarButtonItem.appearance(whenContainedInInstancesOf:[UISearchBar.self]).tintColor = UIColor.white | |
| //Slowdown UI Updates | |
| func delay(_ delay:Double, closure:@escaping ()->()) { | |
| let when = DispatchTime.now() + delay | |
| DispatchQueue.main.asyncAfter(deadline: when, execute: closure) | |
| } | |
| /* Extensions */ | |
| //Bottom border for text field | |
| extension UITextField | |
| { | |
| //Bottom line/border for UITextfield | |
| func setBottomBorderColor(_ color:UIColor) | |
| { | |
| self.borderStyle = .none; | |
| let border = CALayer() | |
| let width = CGFloat(1.0) | |
| border.borderColor = color.cgColor | |
| border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height) | |
| border.borderWidth = width | |
| self.layer.addSublayer(border) | |
| self.layer.masksToBounds = true | |
| } | |
| } | |
| //Shadow - card effect for UIView | |
| extension UIView { | |
| func addDropShadowToView(){ | |
| self.layer.masksToBounds = false | |
| self.layer.shadowColor = UIColor.gray.cgColor; | |
| self.layer.shadowOffset = CGSize(width:2.0, height:2.0) | |
| self.layer.shadowOpacity = 0.75 | |
| } | |
| } | |
| // Make ‘String’ to return its Length | |
| extension String { | |
| var length: Int { | |
| return (self as NSString).length | |
| } | |
| } | |
| //Will return NSAttributedString from HTML String | |
| extension String{ | |
| func convertHtml() -> NSAttributedString{ | |
| guard let data = data(using: .utf8) else { return NSAttributedString() } | |
| do{ | |
| return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue], documentAttributes: nil) | |
| }catch{ | |
| return NSAttributedString() | |
| } | |
| } | |
| } | |
| myLabel.attributedText = "<b>Bolded</b>".convertHtml() //Example | |
| //Gives array of unique elements from given array | |
| extension Sequence where Iterator.Element: Hashable { | |
| func unique() -> [Iterator.Element] { | |
| var seen: [Iterator.Element: Bool] = [:] | |
| return self.filter { seen.updateValue(true, forKey: $0) == nil } | |
| } | |
| } | |
| /* Misc */ | |
| //Calculates execution time of block of code. | |
| let info = ProcessInfo.processInfo | |
| let begin = info.systemUptime | |
| //Code Stuff | |
| let diff = (info.systemUptime - begin) | |
| //List all the installed Fonts | |
| for fontFamilyName in UIFont.familyNames{ | |
| for fontName in UIFont.fontNames(forFamilyName: fontFamilyName){ | |
| print("Family: \(fontFamilyName) Font: \(fontName)") | |
| } | |
| } | |
| //RESET User Defaults (all keys) | |
| let domain = Bundle.main.bundleIdentifier! | |
| UserDefaults.standard.removePersistentDomain(forName: domain) | |
| UserDefaults.standard.synchronize() | |
| //Generate UIImage object from UIView | |
| func generateImage(for view: UIView) -> UIImage? { | |
| defer { | |
| UIGraphicsEndImageContext() | |
| } | |
| UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale) | |
| if let context = UIGraphicsGetCurrentContext() { | |
| view.layer.render(in: context) | |
| return UIGraphicsGetImageFromCurrentImageContext() | |
| } | |
| return nil | |
| } | |
| //:usage | |
| var iconWithTextImage: UIImage { | |
| let containerView = UIView.init(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) | |
| let icon = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) | |
| icon.image = UIImage.init(named: "shirt.png") | |
| icon.contentMode = .scaleAspectFit | |
| containerView.addSubview(icon) | |
| return generateImage(for: containerView) ?? UIImage() | |
| } | |
| //CLOSURE Callback Example | |
| //Closure Callback : | |
| public typealias Closure = () -> Void | |
| //Definition | |
| public var exitFromTap = Closure?({}) | |
| //Declaration in somewhere needs a callback. | |
| exitFromTap?() | |
| //Usage | |
| yourClass.exitFromTap = { print(“Good Bye”) } | |
| /// Returns the element at the specified index iff it is within bounds, otherwise nil. | |
| extension Collection { | |
| subscript (safe index: Index) -> Element? { | |
| return indices.contains(index) ? self[index] : nil | |
| } | |
| } | |
| let sample = ["BMW", "Audi", "Tesla", "Fiat"] | |
| sample[safe : 0] //Prints "BMW" | |
| sample[safe : 4] //Prints 'nil' | |
| /// String extension : replacement for' subString:' | |
| extension String { | |
| func slice(from: String, to: String) -> String? { | |
| let fromIndex = self.index(self.index(of: from)!, offsetBy: 1) | |
| let toIndex = self.index(self.index(of: to)!, offsetBy: -1) | |
| return String(self[fromIndex...toIndex]) | |
| } | |
| } | |
| //Usage : "Date(1511508780012+0530)".slice(from: "(", to: "+") | |
| //Core Data - Easy & Clean way to get NSManagedContext | |
| public static func getContext() -> NSManagedObjectContext { | |
| let appDelegate = UIApplication.shared.delegate as! AppDelegate | |
| return appDelegate.persistentContainer.viewContext | |
| } | |
| //Limit characters in text filed | |
| func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { | |
| let currentCharacterCount = textField.text?.count ?? 0 | |
| if (range.length + range.location > currentCharacterCount){ | |
| return false | |
| } | |
| let newLength = currentCharacterCount + string.count - range.length | |
| return newLength <= Constants.nameCharLimit | |
| } | 
Core Data - Easy & Clean way to get NSManagedContext :::
   public static func getContext() -> NSManagedObjectContext {
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        return appDelegate.persistentContainer.viewContext
    }
//Limit characters in text filed
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let currentCharacterCount = textField.text?.count ?? 0
    if (range.length + range.location > currentCharacterCount){
        return false
    }
    let newLength = currentCharacterCount + string.count - range.length
    return newLength <= Constants.nameCharLimit
}
    UIWindow has three default levels: (windowLevel)
- .normal
 - .statusBar
 - .alert
 
With .alert > .statusBar > .normal. If a more fine-grain level of control is needed it's possible to use a custom level:
window.windowLevel = .normal + 25
As of iOS 13: .alert has a raw value of 2000, .statusBar has a raw value of 1000 and .normal has a raw value of 0.
link)
- 
Any UIViewController (including UINavigationControllers as UINavigationControllers are a type of UIViewControllers) presented modally must be dismissed.
 - 
Since UINavigationControllers hold UIViewControllers in their stack, they can present UIViewControllers both modally and via a push. When navigating away from any pushed UIViewControllers, UINavigationControllers must pop the UIViewController.
 - 
Though it is possible to present UIViewControllers both modally and via a push, UIViewControllers can only present other UIViewControllers. Therefore, UIViewControllers can only be dismissed (unless they are inside a UINavigationController stack and the UINavigationController is handling the pop — see lesson #2). This is why it is not possible to call popViewController on a UIViewController.
 - 
PresentingViewController is a property provided by Apple that is available on both UIViewControllers and UINavigationControllers. Calling presentingViewController.dismiss(animated:completion) will dismiss everything presented by the parentViewController. The parentViewController is the UIViewController that presented the current UIViewController. So, if you have a UINavigationController with 3 UIViewControllers within its stack, calling presentingViewController.dismiss(animated:completion) will dismiss both the UINavigationController and the 3 UIViewControllers held within its stack.
 
5.Similarly, Apple also provides another property on UIViewControllers and UINavigationControllers — presentedViewController. Calling presentedViewController.dismiss(animated:completion) will dismiss the childViewController. The childViewController is the current UIViewController that is being presented.
//Open URL
let fbAppStoreLink = URL.init(string: "https://itunes.apple.com/in/app/facebook/id284882215")!
let fbAppLinkURL = URL.init(string: "fb://page/?id=203525053017188")!