he always draws a big crowd! Orta was the co-speaker at my first iOSoho in 2014. This photo taken Jan 26, 2015 - the day a huge blizzard was predicted. You can see flurries out the window. It took me 4 hours to get home to NJ. The PATH and NJ Transit trains were overflowing. NYC shut the subway down. In the end, NYC barely got any snow at all!
tools to solve problems: 1) Think about what you need to do before you code! Plan! So important!!! 2) Not sure what to do? Then take a walk and mull on it. You’d be amazed at what comes to mind on a solitary walk.
feature Time needed for a new dev to understand this class Time needed to find all parts of a feature 10 If it takes a long time to add something (because you cannot figure out what methods you can use to help), you have a problem. If a new person gag when asked to learn this class? Give one feature provided by the class, how easy is it to find all the relative pieces?
the code right in front of you, you don't have to think about how the rest of your code interacts with that one [thing].” Protocol and Value Oriented Programming in UIKit Apps WWDC2016 Session 419 –Be like Crusty 11
NSObject based helpers Big Swift classes: many many options 13 Using Swift from ObjectiveC has worked well from Day 1. Objective C cannot deal with Swift structures.
to satisfy a consuming receiver Uses structs as lightweight helpers to offload specific tasks Use structs to provide backing data for table cells 14 Advanced: Watch “dotSwift 2016 - Rob Napier - Beyond Crusty: Real-World Protocols” Swift structs can hold Objective C objects, Swift class objects, and Swift value types such as Ints and structs. Rob Napier gave a talk recently on his journey to solve a problem with Swift Protocols, structs, and functions.
private let title: String private let label: UILabel private let underline: UIView private var position: Int func bottomAnchor() -> NSLayoutAnchor { return box.bottomAnchor } func constrainTopToAnchor(anchor: NSLayoutAnchor) { box.topAnchor.constraintEqualToAnchor(anchor).active = true } mutating func updateState(state: TitleItemState) { label.text = title switch state { case .Normal: label.alpha = 1 underline.alpha = 0 case .Selected: label.alpha = 1 underline.alpha = 1 case .Dimmed: label.alpha = dimText underline.alpha = 0 } } } 15 The circled items are backed by an array of “TitleItem” structs. Note the mix of objects (UIViews) and constants (Ints) as well as helper methods.
titleView: UILabel! {get set} var titleTextView: UITextView! {get set} var formView: UIView! {get set} var closeBox: UIStackView! {get set} var boxes: [TitleItem] {get set} var formContentView: UIView {get set} var triangleView: SBTrianglePointerView! {get set} var submitButton: UIButton {get} var backButton: UIButton {get} func buttonSelector() -> Selector func closeButtonSelector() -> Selector func label(lines lines: Int, textSize: Int, bold: Bool) -> UILabel func checkWidth() -> CGFloat } 2) Use Protocols 18 This struct was created in the hour I spent separating the view construction from my View Controller. Reduced the View Controller from 1000+ lines to 740. Process: - grab big chunk of code and copy it into a new file. Comment out the original code in the VC - create a new protocol, make the VC adopt it. - try to build, and add items to the protocol until I can build. - test! Must use “class” because the using the adopter as a button target.
structs) Lots of local protocols between helpers and core View Controller Resulting File line length: - 13 files (in their own directory) - max: 730 - min: 95 - avg: 279 19
key: String) -> String? func updateDataFor(key key: String, data: String?) func updateUI(incrementSelectedGroup incrementSelectedGroup : Int) func itemWithID(id: Int) -> SBFormItem func theSelectedGroup() -> SBFormGroup func sendSubmit() func isFormDone() -> Bool func ppText() -> String? func tosText() -> String? func displayText(text: String, title: String) func presentViewController(viewController: UIViewController, byTextField: UITextField) func temporarilySuppressKeyboardChanges() } 3) Use Helpers final class SBFormControlsDelegate: NSObject { private weak var delegate: SBFormControls! private var currentLocale: NSLocale private var dateFormatter: SBFormValidateDate private var phoneFormatter: SBFormValidatePhone private var postalFormatter: SBFormValidatePostcode private var dataToLocale: [SBFormDataType: String] = [:] private var localeChanged = false // MARK: - Methods init(delegate: SBFormControls) { extension SBFormControlsDelegate: UITextFieldDelegate { 20 One class handles delegate methods: UITextView, UITextField, UIButton, SBFormItem Each set of delegate methods in its own extension. Delegates do NOT need to be weak if you create a structure, use it, then discard it. Good ideas here: http://blog.flaviocaetano.com/post/a-better-way-to-organize-swift-classes/
View Refresh func updateUI(animated: Bool) { button.enabled = … // lots more - all your view logic // including visible cells for cell in tableView.visibleCells { updateCell(cell, atIndex: tableView.indexPathForCell(cell)) } } // Cell creation func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("List", forIndexPath: indexPath) // add/change visible elements, backgrounds, etc cell.backgroundColor = UIColor.blueColor() updateCell(cell, atIndex: indexPath) // code in one method return cell } // Single place where cell elements refreshed func updateCell(cell: UITableViewCell, atIndex indexPath: NSIndexPath) { // use indexPath to get appropriate data cell.textLabel?.text = “Hi” + String(indexPath.row) } 21 Only ever update the UI from one place. Call it after viewDidLoad (or viewWillAppear) to to the initial setup, then whenever something changes post a message in a dispatchBlock.
put all views into the container view, or swap them in and out Container view controllers can use xibs or storyboard Use a protocol to connect the children to the parent 22 Apple provides several container View Controllers as standard UIKit components. Developers can easily create their own in IB or in code (Matt Neuburg’s book has a nice section on the latter).
I put this together using Xcode 7 in about 15 minutes (I hadn’t done it in IB before!) Note the garish colors - when designing UIs, its often nice to know exactly where views extend, and their stacking order.
not full knowledge of all classes 3. Use helpers—lots of helpers! Might want to locate in one directory. 4. Localize UI Changes 5. Container view controllers: complex views with simpler code Adding Swift code to older Objective C projects works GREAT!!! 24 Start adding Swift to your Objective C apps NOW! Take small steps - when you get comfortable take bigger steps.
You can schematize a complex interaction (login, update, etc), use actual class and method names, then insure your code does each transition as you believe it does.
5-star ratings, 2 4-star Since I use the mouse with my left hand, this is invaluable. However, I’m sure its a valuable tool for anyone. * Swap current selection with Clipboard * Append current selection to the Clipboard Write you own extensions!
lively, this new mother never sleeps!) Natasha `The Robot’: http:/ /natashatherobot.com Swift Conference (in NYC!, Sept 1-2): https:/ /www.tryswiftnyc.com 31 Erica Sadun must never sleep: mother, writer, blogger, very active on Swift migrations: http://ericasadun.com http://natashatherobot.com Only a few seats left for Try Swift: https://www.tryswiftnyc.com
SpeakerDeck: https:/ / speakerdeck.com/ dhoerl Just google SpeakerDeck and dhoerl to find it! 32 https://medium.freecodecamp.com/coding-explained-in-25-profound-comics-8847ea03819c#.u4orsnuri Author: Randall Munroe