Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building TableViews with Swift and iOS8

Building TableViews with Swift and iOS8

Presented at the SLUG Meetup on 09/10/2014: http://www.meetup.com/swift-language/events/201151762/

Source Code: https://github.com/NatashaTheRobot/SeinfeldQuotes

TableViews are the foundation of most (non-gaming) iOS applications, and Swift provides several unexplored patterns for approaching TableViews moving forward. Experienced Objective-C programmers will learn how to apply "Swift-thinking" when approaching an iOS8 TableView. New iOS developers will learn the basics of TableViews and how to use them in their own iOS projects.

Natasha Murashev

September 10, 2014
Tweet

More Decks by Natasha Murashev

Other Decks in Programming

Transcript

  1. Self Sizing Table View Cell import UIKit class QuotesTableViewController: UITableViewController

    { /*...*/ override func viewDidLoad() { super.viewDidLoad() tableView.estimatedRowHeight = 89 tableView.rowHeight = UITableViewAutomaticDimension } /*...*/ }
  2. import UIKit class TwoLabelTableViewCell: UITableViewCell { @IBOutlet weak private var

    headerLabel: UILabel! @IBOutlet weak private var subheadLabel: UILabel! func configure(#headerText: String, subheadText: String) { headerLabel.text = headerText headerLabel.accessibilityLabel = headerText subheadLabel.text = "- \(subheadText)" subheadLabel.accessibilityLabel = subheadText } }
  3. class QuotesTableViewController: UITableViewController { private let quotes = Quote.allQuotes() private

    let quoteCellIdentifier = "quoteCell" override func viewDidLoad() { super.viewDidLoad() tableView.estimatedRowHeight = 89 tableView.rowHeight = UITableViewAutomaticDimension } // MARK: - Table view data source override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return quotes.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(quoteCellIdentifier) as TwoLabelTableViewCell let quote = quotes[indexPath.row] cell.configure(headerText: quote.content, subheadText: quote.scene) return cell } }
  4. Dynamic Type class TwoLabelTableViewCell: UITableViewCell { @IBOutlet weak private var

    headerLabel: UILabel! @IBOutlet weak private var subheadLabel: UILabel! func configure(#headerText: String, subheadText: String) { headerLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline) subheadLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline) /*...*/ } /*...*/ }
  5. Hide Navigation Bar on Scroll class QuotesTableViewController: UITableViewController { //

    ** // override func viewDidLoad() { super.viewDidLoad() navigationController?.hidesBarsOnSwipe = true // ** // } // ** // }
  6. Default Parameter Values func configure(#headerText: String, subheadText: String, textColor: UIColor

    = UIColor.blackColor()) { headerLabel.textColor = textColor subheadLabel.textColor = textColor /* ... */ }
  7. MVVM Model View ViewModel class Quote { let content: String

    let scene: String /* ... */ init(content: String, scene: String) { self.content = content self.scene = scene } }
  8. View Model class QuoteViewModel { var quoteContent: String? var quoteScene:

    String? let quoteContentPlaceholder = "Quote Content" let quoteScenePlaceholder = "Scene Description" init(quoteContent: String? = nil, quoteScene: String? = nil) { self.quoteContent = quoteContent self.quoteContent = quoteScene } }
  9. class CreateQuoteTableViewController: UITableViewController { private let quoteViewModel = QuoteViewModel() /*

    ... */ private enum QuoteField: Int { case Content, Scene func placeholder(#quoteViewModel: QuoteViewModel) -> String { switch self { case .Content: return quoteViewModel.quoteContentPlaceholder case .Scene: return quoteViewModel.quoteScenePlaceholder } } func text(#quoteViewModel: QuoteViewModel) -> String? { switch self { case .Content: return quoteViewModel.quoteContent case .Scene: return quoteViewModel.quoteScene } } func updateQuoteWithText(text: String, quoteViewModel: QuoteViewModel) { switch self { case .Content: quoteViewModel.quoteContent = text case .Scene: quoteViewModel.quoteScene = text } } /* ... */ }
  10. Using Enums override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->

    UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier) as TextInputTableViewCell if let quoteField = QuoteField.fromRaw(indexPath.row) { let text = quoteField.text(quoteViewModel: quoteViewModel) let placeholder = quoteField.placeholder(quoteViewModel: quoteViewModel) /* ... */ } return cell }
  11. Using Closures import UIKit class TextInputTableViewCell: UITableViewCell, UITextFieldDelegate { @IBOutlet

    weak private var textField: UITextField! typealias textFieldChangedHandlerType = (String) -> Void private var textFieldChangedHander: textFieldChangedHandlerType? override func awakeFromNib() { textField.delegate = self } func configure(#text: String?, placeholder: String, textFieldChangedHandler: textFieldChangedHandlerType?) { textField.placeholder = placeholder textField.text = text textField.accessibilityLabel = placeholder textField.accessibilityValue = text self.textFieldChangedHander = textFieldChangedHandler } // MARK: Text Field Delegate func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if let textFieldChangedHandler = textFieldChangedHander { textFieldChangedHandler(textField.text) } return true } }
  12. Using Closures override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->

    UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier) as TextInputTableViewCell if let quoteField = QuoteField.fromRaw(indexPath.row) { let text = quoteField.text(quoteViewModel: quoteViewModel) let placeholder = quoteField.placeholder(quoteViewModel: quoteViewModel) cell.configure(text: text, placeholder: placeholder, textFieldChangedHandler: { [weak self] (newText) in if let strongSelf = self { quoteField.updateQuoteWithText(newText, quoteViewModel: strongSelf.quoteViewModel) } }) } return cell }
  13. A Swift Summary iOS8 Features — Self Sizing Table View

    Cells — Dynamic Type — Hide Navigation Bar