Last active
September 28, 2017 13:48
-
-
Save Erkened/35ce3189552a67a0c94f to your computer and use it in GitHub Desktop.
Snippets of Swift code I reuse often
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
| /* | |
| // TO APPLY DIFFERENT STRINGS FROM VARIANTS.STRINGS RATHER THAN LOCALIZABLE.STRINGS | |
| var localised:String | |
| { | |
| return Bundle.main.localizedString(forKey:self, value:Bundle.main.localizedString(forKey:self, value:nil, table:nil), table:"variants") | |
| } | |
| // TO CONTROL THE LINE HEIGHT OF AN ATTRIBUTED STRING (LIKE TAB BAR BUTTONS) | |
| let paragraphStyle = NSMutableParagraphStyle() | |
| paragraphStyle.lineSpacing = 6 | |
| paragraphStyle.alignment = .center | |
| myMutableString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range: NSRange(location:0,length:myMutableString.length)) | |
| // TO CLONE A REPOSITORY FROM ONE REMOTE TO ANOTHER (source: https://stackoverflow.com/questions/7818927/git-push-branch-from-one-remote-to-another) | |
| git remote add origin2 ssh://[email protected]/blabla.git | |
| git push origin2 refs/remotes/origin/*:refs/heads/* // This pushes all the branches from origin to origin2 | |
| git push origin2 refs/tags/*:refs/tags/* // This pushes all the tags from origin to origin2 | |
| // TO ENABLE DRAG AND DROP BETWEEN TWO TABLES | |
| https://www.hackingwithswift.com/whats-new-in-ios-11?utm_campaign=This%2BWeek%2Bin%2BSwift&utm_medium=email&utm_source=This_Week_in_Swift_134 | |
| // TO SWITCH WHAT XCODEVERSION TO BUILD | |
| xcode-select --print-path | |
| /Applications/Xcode.app/Contents/Developer | |
| /Users/john/Desktop/XCode 7/Xcode.app/Contents/Developer | |
| Then to change it just run | |
| sudo xcode-select --switch <path-to-beta-xcode>/Contents/Developer | |
| // TO CHANGE WHAT SWIFT VERSION COMPILES CARTHAGE | |
| Source http://stackoverflow.com/questions/37867753/change-carthage-swift-version | |
| xcrun swift -version | |
| carthage update --platform iOS --no-use-binaries | |
| Source http://stackoverflow.com/questions/40250381/module-compiled-with-swift-3-0-cannot-be-imported-in-swift-3-0-1 | |
| // USE PRIVATE(SET) TO MAKE SETTING PRIVATE, BUT KEEPING GET PUBLIC | |
| "private" to keep it local to a source file, "internal" to keep it local to the module/project. | |
| private(set) only makes the set private. Private makes both set and get functions private | |
| // INSTEAD OF GUARD LET - ASSIGN VAR - GUARD LET STRUCTURE, USE 1 GUARD LET THROUGHOUT BY WRAPPING VAR INTO AN OPTIONAL | |
| // Source: https://appventure.me/2016/04/14/force-optionals-in-guard-or-let-optional-binding/ | |
| func example() { | |
| guard let array = someArray(), | |
| numberThree = Optional.Some(array[2]) | |
| where numberThree == 3 | |
| else { return } | |
| print(numberThree) | |
| } | |
| // FUNCTORS, MONADS AND APPLICATIVES EXPLAINED | |
| // Source: http://www.russbishop.net/monoids-monads-and-functors | |
| Functors are containers you can call map on. That's it. Seriously. | |
| Applicative lets you stuff the function itself inside a container, otherwise it's almost identical to Functors. | |
| Monads are containers you can call flatMap on. Again, that's it. | |
| // Keep an eye on https://thatthinginswift.com/ | |
| // Remember that Optional are an Enum type with .Some(T) and .None, which means we can do this to test if an optional | |
| // holds a value: | |
| // Source: https://thatthinginswift.com/switch-unwrap-shortcut/ | |
| switch (self.textValidation, self.passwordValidation) { | |
| case (.Some, .Some): | |
| print("both look good!") | |
| default: | |
| print("something was nil...") | |
| } | |
| // HOW-TO: PUSH NOTIFICATIONS | |
| https://thatthinginswift.com/remote-notifications/ | |
| http://www.fantageek.com/blog/2016/04/15/push-notification-in-practice/ | |
| // HOW TO PROPERLY UPDATE THE LAYOUT WHEN A CHANGE NEEDS TO HAPPEN | |
| // layoutIfNeeded is called immediately, setNeedsLayout changed the UI in the next update cycle | |
| // Source: http://www.iosinsight.com/setneedslayout-vs-layoutifneeded-explained/ | |
| // Update the frame in case anything needed to be redrawn | |
| view.layoutIfNeeded() | |
| // Change whatever constraints need updating | |
| someview.blueHeight.constant = 25.0 | |
| // Animate and capture the redrawing phase in the block | |
| UIView.animateWithDuration(2.0) { | |
| self.view.layoutIfNeeded() | |
| } | |
| // EXTENSION TO FIND KEYS BY VALUE | |
| // Source: https://ijoshsmith.com/2016/04/14/find-keys-by-value-in-swift-dictionary/ | |
| extension Dictionary where Value: Equatable { | |
| /// Returns all keys mapped to the specified value. | |
| /// ``` | |
| /// let dict = ["A": 1, "B": 2, "C": 3] | |
| /// let keys = dict.keysForValue(2) | |
| /// assert(keys == ["B"]) | |
| /// assert(dict["B"] == 2) | |
| /// ``` | |
| func keysForValue(value: Value) -> [Key] { | |
| return flatMap { (key: Key, val: Value) -> Key? in | |
| value == val ? key : nil | |
| } | |
| } | |
| } | |
| // EXTENSION TO INCREASE THE TAPPABLE AREA OF A BUTTON | |
| // Source: http://www.sthoughts.com/2015/04/25/swift-expand-uibuttons-clickable-area/ | |
| extension UIButton { | |
| override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { | |
| let relativeFrame = self.bounds | |
| let hitTestEdgeInsets = UIEdgeInsetsMake(-44, -44, -44, -44) | |
| let hitFrame = UIEdgeInsetsInsetRect(relativeFrame, hitTestEdgeInsets) | |
| return hitFrame.contains(point) | |
| } | |
| } | |
| // SORTING EXPLAINED | |
| // Source: https://thatthinginswift.com/sort-and-sorted/ | |
| // TO ROLL BACK TO A PREVIOUS COMMIT IN GIT | |
| git status // Checks the status of the current branch. Use git checkout branchname to change branch | |
| git reset --hard 582acd2 // Resets back to the commit number 582acd2 | |
| git push --force // Pushes this commit on top of everything | |
| git pull // Makes sure the branch is up to date | |
| // TO REMOVE THE STATUS BAR | |
| // Set ViewController-based status bar appearance to NO in info.plist | |
| // Set hide status bar in the project > general | |
| // EXECUTE CODE IN A BACKGROUND THREAD | |
| https://www.hackingwithswift.com/read/9/3/gcd-101-dispatch_async | |
| // CATCH A THROWN ERROR IN A CLOSURE (AND MORE COOL STUFF TO KNOW) | |
| http://appventure.me/2015/06/19/swift-try-catch-asynchronous-closures/ | |
| // NIL COALESCING OPERATOR | |
| a ?? b | |
| is the same as | |
| a != nil ? a! : b | |
| // TO CREATE AN ENUM THAT TRANSLATES TO STRING | |
| enum SentBy : String { | |
| case User = "MessageSentByUser" | |
| case Opponent = "MessageSentByOpponent" | |
| } | |
| // TO HIDE THE STATUS BAR IN ALL THE UIVIEWCONTROLLERS | |
| // In info.plist add 2 keys: | |
| // View controller-based status bar appearance : NO | |
| // Status bar is initially hidden : YES | |
| // TO RESET THE NAVIGATION STACK | |
| func resetNavigationStack(viewController:UIViewController){ | |
| if let navigationController = viewController.navigationController{ | |
| var navigationArray = navigationController.viewControllers | |
| navigationArray.removeAll() | |
| navigationArray.append(viewController) | |
| navigationController.viewControllers = navigationArray | |
| } | |
| else { | |
| print("No navigation controller") | |
| } | |
| } | |
| // TO ADD BANNERS INSTEAD OF INTERSTITIALS | |
| https://twittercommunity.com/t/swift-and-banners/27025/3 | |
| // TO REMOVE WHITE SPACE BEFORE AND AFTER A STRING | |
| testString = testString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) | |
| // TO MAKE A STRUCT EQUATABLE AND HASHABLE SO THAT IT CAN BE ADDED TO DICTIONARIES ETC. // Source: http://kelan.io/2015/swift-hashable-for-sets/ | |
| struct S { | |
| let i: Int | |
| let str: String | |
| } | |
| extension S: Hashable, Equatable { | |
| var hashValue: Int { return i.hashValue ^ str.hashValue } | |
| } | |
| func ==(lhs: S, rhs: S) -> Bool { | |
| return lhs.i == rhs.i && lhs.str == rhs.str | |
| } | |
| // TO MAKE A STRUCT EQUATABLE SO THAT IT CAN BE USED WITH FIND, COMPARISON ETC. // Source: http://kelan.io/2015/swift-equatable-structs/ | |
| struct ExampleStruct{ | |
| var ID = "" | |
| var title = "" | |
| } | |
| extension ExampleStruct: Equatable {} | |
| func ==(lhs: ExampleStruct, rhs: ExampleStruct) -> Bool { | |
| return lhs.ID == rhs.ID && lhs.title == rhs.title | |
| } | |
| // LOCAL NOTIFICATIONS | |
| // BROADCAST (No object) | |
| NSNotificationCenter.defaultCenter().postNotificationName("toggleMode", object: nil) | |
| // BOADCAST (With object) | |
| NSNotificationCenter.defaultCenter().postNotificationName("showProductDetails", object: nil, userInfo: ["productID":productID]) | |
| // LISTEN | |
| // In ViewDidLoad | |
| NSNotificationCenter.defaultCenter().addObserver(self, selector: "toggleMode", name: "toggleMode", object: nil) | |
| // If the notification comes with userInfo | |
| func showProductDetails(notification:NSNotification){ | |
| guard let userInfo:[String:AnyObject] = notification.userInfo as? [String:AnyObject] else{ | |
| print("user info received incorrect") | |
| return | |
| } | |
| // Do whatever | |
| } | |
| // In Deinit | |
| // Remove self from receiving any notification | |
| NSNotificationCenter.defaultCenter().removeObserver(self) | |
| // TO CREATE A FUNCTION WITH A BLOCK | |
| func fillDictionaries(completion: (result:Bool) -> Void){ | |
| // Do your thing | |
| completion(true) | |
| } | |
| // IF LOCALIZATION DOESN'T WORK | |
| Uninstall the app and reinstall it... | |
| // TO USE SPECIAL CHARACTERS, LIKE THE ONES IN FONTELLO | |
| var font = UIFont(name: "fontello", size: 22.0) | |
| queueButton.setTitle("\u{E801}", forState: .Normal) | |
| queueButton.titleLabel?.font = font! | |
| // TO DISABLE SCROLLING IN A UIPAGEVIEWCONTROLLER | |
| //pageViewController.dataSource = self // Scrolling disabled when no data source | |
| // TO DISMISS THE KEYBOARD IF TAPPED OUTSIDE THE UITEXTFIELDS | |
| override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) { | |
| yourTextField.resignFirstResponder() | |
| } | |
| // HOW TO USE THE DELEGATION PATTERN | |
| - In parentViewController: | |
| class ParentViewController: UIViewController, ChildViewControllerDelegate{ | |
| override func viewDidLoad(){ | |
| super.viewDidLoad() | |
| ChildViewControllerDelegate = self | |
| } | |
| func doSomething(){ | |
| println("I did something!") | |
| } | |
| } | |
| - In childViewController: | |
| protocol ChildViewControllerDelegate{ | |
| func doSomething() | |
| } | |
| class ChildViewController: UIViewController{ | |
| var tellDelegateTo:ChildViewControllerDelegate? | |
| func doSomethingElse(){ | |
| if let tellDelegateTo = tellDelegateTo { | |
| tellDelegateTo.doSomething() | |
| } | |
| } | |
| } | |
| // TO FIT A LABEL WITHIN A CERTAIN WIDTH | |
| font = UIFont(name: "OpenSans-SemiBold", size: 18.0) | |
| MainTopBarViewControllerVariables.titleLabel.textColor = ColourConstants.wildSand | |
| MainTopBarViewControllerVariables.titleLabel.textAlignment = .Center | |
| MainTopBarViewControllerVariables.titleLabel.font = font! | |
| MainTopBarViewControllerVariables.titleLabel.adjustsFontSizeToFitWidth = true // Needed to shrink down the text to the right size | |
| MainTopBarViewControllerVariables.titleLabel.baselineAdjustment = UIBaselineAdjustment.AlignCenters // Needed to vertically center the shrinked text into its bounding box | |
| MainTopBarViewControllerVariables.titleLabel.minimumScaleFactor = 0.1 // How small the text can get | |
| MainTopBarViewControllerVariables.titleLabel.text = "Test" | |
| // TO RETRIEVE THE LIST OF FONTS AND THEIR NAMES IN APP.DELEGATE | |
| for family in UIFont.familyNames(){ | |
| println(family) | |
| for name in UIFont.fontNamesForFamilyName(family as! String){ | |
| println(" \(name)") | |
| } | |
| } | |
| // TO MODIFY THE TARGET OF A BUTTON IN ANOTHER CLASS | |
| TopViewVariables.peersButton.removeTarget(TopViewVariables.peersButton.superview, action: "showPeers", forControlEvents: .TouchUpInside) | |
| // SINGLETON >= IOS 8.3 / SWIFT 1.2 | |
| //static let sharedInstance = P2PBrain() // Makes it a Singleton | |
| // TO GET THE ROOT VIEW CONTROLLER (not safe) | |
| let rootViewController: UIViewController = UIApplication.sharedApplication().windows[0].rootViewController!! | |
| // TO EXECUTE AN ACTION AFTER A CERTAIN AMOUNT OF TIME | |
| let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))) | |
| dispatch_after(dispatchTime, dispatch_get_main_queue(), { | |
| // your function here | |
| }) | |
| // TO CENTER THE TEXT IN A UITEXTVIEW (RE-INIT IF SEGUED AWAY!) | |
| func centreTextInTextView(textViewToCenter:UITextView){ | |
| // Change the offset based on the content | |
| var topCorrect:CGFloat = (textViewToCenter.bounds.size.height - textViewToCenter.contentSize.height)/2 | |
| topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect | |
| textViewToCenter.contentOffset = CGPoint(x: 0, y: -topCorrect) | |
| } | |
| // GETTING THE BIGGEST POSSIBLE VALUE FOR UINT64 FOR EXAMPLE | |
| var maxID:NSNumber = NSNumber(unsignedLongLong: UINT64_MAX) | |
| // MAX FUNCTION EMBEDDED IN SWIFT | |
| let numbers = [ 1, 42, 5, 21 ] | |
| var maxNumber = 0 | |
| for number in numbers { | |
| maxNumber = max(maxNumber, number as Int) | |
| } | |
| print("the max number is \(maxNumber)") // will be 42 | |
| // TO GET A TABLE TO BEHAVE WHEN DISPLAYING DIFFERENT ROW HEIGHTS AND SEGUEING TO OTHER VIEWS | |
| http://stackoverflow.com/questions/27684525/is-there-a-way-to-make-estimated-row-heights-with-uitableview-actually-work-with/28931606#28931606 | |
| TO RETRIEVE A PICTURE FROM AN URL | |
| let url = NSURL(string: image.url) | |
| let data = NSData(contentsOfURL: url!) //make sure your image in this url does exist, otherwise unwrap in an if let check | |
| imageURL.image = UIImage(data: data!) | |
| FOR THE LIST OF POTENTIAL DATE FORMATTER PATTERNS, CHECK OUT THIS LINK | |
| http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns | |
| TO ADD AN ARRAY AT THE BEGINNING OF ANOTHER ONE | |
| anArray.splice(["So", "Many", "Strings"], atIndex: 0) | |
| IF AN APP STORES A LOT OF DATA IN CORE DATA: | |
| CHECK THE "STORE IN EXTERNAL RECORD" BOX FOR THAT SPECIFIC ATTRIBUTE IN CORE DATA. THIS WAY THE APP WON'T SHOW AS MUCH DATA USAGE IN ICLOUD > STORAGE > MANAGE STORAGE | |
| TO DISABLE THE AUTOMATIC ICLOUD BACKUP OF SOME DATA: | |
| func addSkipBackupAttributeToItemAtURL(URL: NSURL!) -> Bool{ | |
| assert(NSFileManager.defaultManager().fileExistsAtPath(URL.path!)) | |
| var err : NSError? = nil | |
| var success : Bool! = URL.setResourceValue(NSNumber(bool:true), forKey: NSURLIsExcludedFromBackupKey, error: &err) | |
| if(!success){ | |
| println("Error excluding \(URL.lastPathComponent) from backup\(err) ") | |
| } | |
| else { | |
| println("Excluded \(URL.lastPathComponent) from backup :)") | |
| } | |
| return success | |
| } | |
| TO ROUND ONLY 1 OR 2 CORNERS OF A UIVIEW | |
| autoHashtagsBG = UIView(frame: frame) | |
| autoHashtagsBG?.backgroundColor = UIColor.blackColor() | |
| let maskLayer = CAShapeLayer() | |
| maskLayer.path = UIBezierPath(roundedRect: autoHashtagsBG!.bounds, byRoundingCorners: [.TopRight, .TopLeft], cornerRadii: CGSize(width: 20.0, height: 20.0)).CGPath | |
| autoHashtagsBG!.layer.mask = maskLayer | |
| BACKGROUND/FOREGROUND THREADS (DO NOT PUT OPTIONALS INSIDE THE CLOSURE) | |
| let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT | |
| dispatch_async(dispatch_get_global_queue(priority, 0)) { | |
| // Do some background stuff | |
| dispatch_async(dispatch_get_main_queue()) { | |
| // Update some UI | |
| } | |
| } | |
| THIS IS HOW TO USE TUPLES | |
| var tuple = (title:String, message:String) | |
| tuple.title = "This is a tuple" | |
| tuple.message = "And its accompanying message" | |
| let extractedTitle = tuple.title | |
| TO ADD AN ELEMENT IN CORE DATA AND DO A LIGHT MIGRATION | |
| http://jamesonquave.com/blog/core-data-migrations-swift-tutorial/ | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment