Full Code of rlopezdiez/RLDTableViewSwift for AI

master 1bad87913779 cached
61 files
221.2 KB
59.4k tokens
1 requests
Download .txt
Showing preview only (242K chars total). Download the full file or copy to clipboard to get everything.
Repository: rlopezdiez/RLDTableViewSwift
Branch: master
Commit: 1bad87913779
Files: 61
Total size: 221.2 KB

Directory structure:
gitextract_uxx7488s/

├── .gitignore
├── Classes/
│   ├── RLDHandledViewProtocol.swift
│   ├── RLDTableViewController.swift
│   ├── RLDTableViewDataSource.swift
│   ├── RLDTableViewDelegate.swift
│   ├── RLDTableViewEventHandler.swift
│   ├── RLDTableViewEventHandlerProvider.swift
│   └── RLDTableViewModel.swift
├── LICENSE
├── README.md
├── RLDTableViewSwift.podspec
├── Sample app/
│   ├── TableViewPrototype/
│   │   ├── AppDelegate.swift
│   │   ├── Event handlers/
│   │   │   ├── RLDGenericTableViewCellEventHandler.swift
│   │   │   └── RLDTableViewHeaderViewEventHandler.swift
│   │   ├── Info.plist
│   │   ├── Models/
│   │   │   ├── RLDBigPictureTableViewCellModel.swift
│   │   │   ├── RLDCommentTableViewCellModel.swift
│   │   │   ├── RLDGenericTableViewCellModel.swift
│   │   │   ├── RLDSimpleTableViewCellModel.swift
│   │   │   ├── RLDTableViewHeaderViewModel.swift
│   │   │   └── RLDTableViewModelProvider.swift
│   │   ├── RLDTableViewSwift-Info.plist
│   │   ├── Resources/
│   │   │   ├── Images.xcassets/
│   │   │   │   ├── 0_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 1_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 2_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 2_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 3_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 4_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 5_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 6_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 7_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 8_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 9_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── AppIcon.appiconset/
│   │   │   │       └── Contents.json
│   │   │   ├── LaunchScreen.xib
│   │   │   ├── Main.storyboard
│   │   │   ├── RLDTableViewHeaderView.xib
│   │   │   └── viewModelData.plist
│   │   ├── View controllers/
│   │   │   ├── RLDMasterViewController.swift
│   │   │   └── RLDWebViewController.swift
│   │   └── Views/
│   │       ├── RLDBigPictureTableViewCell.swift
│   │       ├── RLDCommentTableViewCell.swift
│   │       ├── RLDGenericTableViewCell.swift
│   │       ├── RLDSimpleTableViewCell.swift
│   │       └── RLDTableViewHeaderView.swift
│   └── TableViewPrototype.xcodeproj/
│       ├── project.pbxproj
│       ├── project.xcworkspace/
│       │   ├── contents.xcworkspacedata
│       │   └── xcshareddata/
│       │       └── TableViewPrototype.xccheckout
│       └── xcuserdata/
│           └── rhocassiopeiae.xcuserdatad/
│               └── xcschemes/
│                   ├── RLDTableViewSwift.xcscheme
│                   ├── TableViewPrototype.xcscheme
│                   └── xcschememanagement.plist
└── Tests/
    ├── Tests/
    │   ├── Info.plist
    │   ├── RLDTableViewDataSourceTests.swift
    │   ├── RLDTableViewDelegateTests.swift
    │   ├── RLDTableViewEventHandlerProviderTests.swift
    │   ├── RLDTableViewModelTests.swift
    │   └── TestHelpers.swift
    └── Tests.xcodeproj/
        ├── project.pbxproj
        ├── project.xcworkspace/
        │   ├── contents.xcworkspacedata
        │   └── xcshareddata/
        │       └── Tests.xccheckout
        └── xcshareddata/
            └── xcschemes/
                └── Tests.xcscheme

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
Sample app/TableViewPrototype.xcodeproj/project.xcworkspace/xcuserdata


================================================
FILE: Classes/RLDHandledViewProtocol.swift
================================================
import UIKit

public protocol RLDHandledViewProtocol:class {
    var eventHandler:RLDTableViewEventHandler? {get set}
}

================================================
FILE: Classes/RLDTableViewController.swift
================================================
import UIKit
import RLDTableViewSwift

// MARK: UIView extension to find the first responder

private extension UIView {
    private weak static var _firstResponder:UIView?
    
    class func rld_firstResponder() -> UIView? {
        UIApplication.sharedApplication().sendAction(Selector("setFirstResponder"), to:nil, from:nil, forEvent:nil)
        return _firstResponder
    }
    
    func setFirstResponder() {
        UIView._firstResponder = self
    }
}

// MARK: UITableView extension to scroll to the first responder cell

private extension UITableView {
    func scrollToFirstResponder(animated:Bool) {
        if let firstResponder = UIView.rld_firstResponder() {
            let firstResponderFrame = firstResponder.convertRect(firstResponder.bounds, toView:self)
            self.scrollRectToVisible(firstResponderFrame, animated:animated)
        }
    }
}

// MARK: UITableView extension to know wether multiple selection is enabled

private extension UITableView {
    var multipleSelectionModeEnabled: Bool {
        return (self.editing
            ? self.allowsMultipleSelectionDuringEditing
            : self.allowsMultipleSelection)
    }
}

// MARK: RLDTableViewController class

public class RLDTableViewController:UIViewController {
    
    // MARK: Initialization
    required public init(style: UITableViewStyle) {
        super.init(nibName:nil, bundle:nil)
        tableView = UITableView(frame:CGRectZero, style:style)
    }
    
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder:aDecoder)
    }
    
    // MARK: Data source and delegate configuration
    private var tableViewDataSource:RLDTableViewDataSource?
    private var tableViewDelegate:RLDTableViewDelegate?
    
    public var tableViewModel:RLDTableViewModel? {
        didSet {
            if let tableViewModel = tableViewModel {
                tableViewDataSource = RLDTableViewDataSource(tableViewModel:tableViewModel)
                tableViewDelegate = RLDTableViewDelegate(tableViewModel:tableViewModel)
                
                tableView?.dataSource = tableViewDataSource
                tableView?.delegate = tableViewDelegate
                tableView?.reloadData()
            }
        }
    }
    
    // MARK: View management
    lazy public var tableView: UITableView? = {
        return UITableView(frame:CGRectZero)
        }()
    
    override public var view: UIView! {
        get {
            return super.view
        }
        set {
            if let tableView = newValue as? UITableView {
                self.tableView = tableView
                super.view = tableView
            } else {
                fatalError("The view must be an UITableView")
            }
        }
    }
    
    var clearsSelectionOnViewWillAppear: Bool = true
    var refreshControl: UIRefreshControl? {
        didSet {
            if let refreshControl = refreshControl {
                self.tableView!.insertSubview(refreshControl, atIndex:0)
            }
        }
    }
    
    override public func viewWillAppear(animated:Bool) {
        startObservingKeyboardNotifications()
        
        if clearsSelectionOnViewWillAppear {
            clearTableViewSelection(animated)
        }
        
        super.viewWillAppear(animated)
    }
    
    override public func viewWillDisappear(animated:Bool) {
        super.viewWillDisappear(animated)
        
        stopObservingKeyboardNotifications()
    }
    
    override public func viewDidAppear(animated:Bool) {
        super.viewDidAppear(animated)
        
        tableView!.flashScrollIndicators()
    }
    
    override public func setEditing(editing:Bool, animated:Bool) {
        super.setEditing(editing, animated:animated)
        
        tableView!.setEditing(editing, animated:animated)
    }
    
    // MARK: Keyboard notifications handling
    private func startObservingKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(RLDTableViewController.keyboardWillShowWithKeyboardChangeNotification(_:)), name:UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(RLDTableViewController.keyboardWillHideWithKeyboardChangeNotification(_:)), name:UIKeyboardWillHideNotification, object: nil)
    }
    
    private func stopObservingKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
    func keyboardWillShowWithKeyboardChangeNotification(notification:NSNotification) {
        synchronizeAnimationWithKeyboardChangeNotification(notification,
            animations: { () -> Void in
                self.tableView!.frame = CGRect(x:self.tableView!.frame.origin.x,
                    y:self.tableView!.frame.origin.y,
                    width:self.tableView!.frame.size.width,
                    height:self.tableView!.superview!.bounds.size.height - self.keyboardHeightWithKeyboardNotification(notification))
                
                self.tableView?.scrollToFirstResponder(false)
        })
    }
    
    func keyboardWillHideWithKeyboardChangeNotification(notification:NSNotification) {
        synchronizeAnimationWithKeyboardChangeNotification(notification,
            animations: { () -> Void in
                self.tableView!.frame = self.tableView!.superview!.bounds
        })
    }
    
    private func synchronizeAnimationWithKeyboardChangeNotification(notification:NSNotification, animations:(()->Void)?) {
        if let animations = animations,
            let userInfo = notification.userInfo as? [String:AnyObject] {
                
                let animationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
                
                if (animationDuration == 0) {
                    animations()
                } else {
                    let animationCurve = UIViewAnimationCurve(rawValue:(userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).integerValue)!
                    
                    UIView.beginAnimations(nil, context:nil)
                    UIView.setAnimationDuration(animationDuration)
                    UIView.setAnimationCurve(animationCurve)
                    UIView.setAnimationBeginsFromCurrentState(true)
                    animations()
                    
                    UIView.commitAnimations()
                }
        }
    }
    
    private func keyboardHeightWithKeyboardNotification(notification:NSNotification) -> CGFloat {
        let keyboardBounds = keyboardBoundsWithKeyboardNotification(notification)
        return keyboardBounds.size.height
    }
    
    private func keyboardBoundsWithKeyboardNotification(notification:NSNotification) -> CGRect {
        if let userInfo = notification.userInfo as? [String:NSValue],
            let keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] {
                return keyboardFrameValue.CGRectValue()
        }
        return CGRectZero
    }
    
    // MARK: Selection clearing
    private func clearTableViewSelection(animated:Bool) {
        if !tableView!.multipleSelectionModeEnabled {
            if let indexPathForSelectedRow = tableView?.indexPathForSelectedRow {
                synchronizeDeselectionAnimationOfRow(indexPathForSelectedRow, animated:animated)
            }
        }
    }
    
    private func synchronizeDeselectionAnimationOfRow(indexPathForSelectedRow:NSIndexPath, animated:Bool) {
        if let transitionCoordinator = transitionCoordinator() {
            transitionCoordinator.animateAlongsideTransitionInView(tableView,
                animation: { (context:UIViewControllerTransitionCoordinatorContext!) -> Void in
                    self.tableView!.deselectRowAtIndexPath(indexPathForSelectedRow, animated:animated)
                }, completion: { (context:UIViewControllerTransitionCoordinatorContext!) -> Void in
                    if context.isCancelled() {
                        self.tableView!.selectRowAtIndexPath(indexPathForSelectedRow, animated:false, scrollPosition:UITableViewScrollPosition.None)
                    }
            })
        }
    }
}

================================================
FILE: Classes/RLDTableViewDataSource.swift
================================================
import UIKit

public class RLDTableViewDataSource:NSObject, UITableViewDataSource {
    
    // MARK: Initialization
    private(set) var tableViewModel:RLDTableViewModel?
    required public init(tableViewModel:RLDTableViewModel) {
        self.tableViewModel = tableViewModel
    }
    
    // MARK: Cell generation
    public func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
        let cellModel = self.cellModel(indexPath)
        return tableView.dequeueReusableCellWithIdentifier(cellModel.reuseIdentifier, forIndexPath:indexPath) 
    }
    
    // MARK: Sections
    public func numberOfSectionsInTableView(tableView:UITableView) -> Int {
        return tableViewModel!.sectionModels.count
    }
    
    public func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
        let sectionModel = tableViewModel!.sectionModels[section]
        return sectionModel.cellModels.count
    }
    
    public func tableView(tableView:UITableView, titleForHeaderInSection section:Int) -> String? {
        return title(forSection:section, sectionAccessoryViewModel:{ (sectionModel) -> RLDTableViewSectionAccessoryViewModel? in
            return sectionModel.header
        })
    }
    
    public func tableView(tableView:UITableView, titleForFooterInSection section:Int) -> String? {
        return title(forSection:section, sectionAccessoryViewModel:{ (sectionModel) -> RLDTableViewSectionAccessoryViewModel? in
            return sectionModel.footer
        })
    }
    
    private func title(forSection section:Int, sectionAccessoryViewModel:((sectionModel:RLDTableViewSectionModel)->RLDTableViewSectionAccessoryViewModel?)) -> String? {
        let sectionModel = tableViewModel!.sectionModels[section]
        if let sectionAccessoryViewModel = sectionAccessoryViewModel(sectionModel:sectionModel) {
            return sectionAccessoryViewModel.title
        }
        return nil
    }
    
    // MARK: Sections index titles
    public func sectionIndexTitlesForTableView(tableView:UITableView) -> [String]? {
        return tableViewModel!.sectionIndexTitles
    }
    
    public func tableView(tableView:UITableView, sectionForSectionIndexTitle title:String, atIndex index:Int) -> Int {
        for (index, sectionModel) in tableViewModel!.sectionModels.enumerate() {
            if let indexTitle = sectionModel.indexTitle {
                if indexTitle == title {
                    return index
                }
            }
        }
        return 0
    }
    
    // MARK: Data source edition
    public func tableView(tableView:UITableView, canEditRowAtIndexPath indexPath:NSIndexPath) -> Bool {
        let cellModel = self.cellModel(indexPath)
        if let editable = cellModel.editable {
            return editable
        }
        return false
    }
    
    public func tableView(tableView:UITableView, canMoveRowAtIndexPath indexPath:NSIndexPath) -> Bool {
        let cellModel = self.cellModel(indexPath)
        if let movable = cellModel.movable {
            return movable
        }
        return false
    }
    
    public func tableView(tableView:UITableView, commitEditingStyle editingStyle:UITableViewCellEditingStyle, forRowAtIndexPath indexPath:NSIndexPath) {
        switch editingStyle {
        case .Insert:
            self.tableView(tableView, commitInsertionForRowAtIndexPath:indexPath)
        case .Delete:
            self.tableView(tableView, commitDeletionForRowAtIndexPath:indexPath)
        case .None:
            break
        }
    }
    
    public func tableView(tableView:UITableView, moveRowAtIndexPath sourceIndexPath:NSIndexPath, toIndexPath destinationIndexPath:NSIndexPath) {
        let sourceSectionModel = tableViewModel!.sectionModels[sourceIndexPath.section]
        let destinationSectionModel = tableViewModel!.sectionModels[destinationIndexPath.section]
        let cellModel = sourceSectionModel.cellModels[sourceIndexPath.row]
        
        sourceSectionModel.remove(cellModel)
        destinationSectionModel.insert(cellModel, atIndex:destinationIndexPath.row)
    }
    
    private func tableView(tableView:UITableView, commitInsertionForRowAtIndexPath indexPath:NSIndexPath) {
        let sectionModel = tableViewModel!.sectionModels[indexPath.section]
        if let defaultCellModelClassForInsertions = sectionModel.defaultCellModelClassForInsertions {
            let cellModelType = NSClassFromString(defaultCellModelClassForInsertions) as! RLDTableViewCellModel.Type
            let cellModel = cellModelType.init()
            
            sectionModel.insert(cellModel, atIndex:indexPath.row)
            tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation:UITableViewRowAnimation.Automatic)
        }
    }
    
    private func tableView(tableView:UITableView, commitDeletionForRowAtIndexPath indexPath:NSIndexPath) {
        let sectionModel = tableViewModel!.sectionModels[indexPath.section]
        let cellModel = sectionModel.cellModels[indexPath.row]
        
        sectionModel.remove(cellModel)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation:UITableViewRowAnimation.Automatic)
    }
    
    // MARK: Model accessors
    private func cellModel(indexPath:NSIndexPath) -> RLDTableViewCellModel {
        let sectionModel = tableViewModel!.sectionModels[indexPath.section]
        return sectionModel.cellModels[indexPath.row]
    }
    
}

================================================
FILE: Classes/RLDTableViewDelegate.swift
================================================
import UIKit

public class RLDTableViewDelegate:NSObject, UITableViewDelegate {
    // Initialization
    private var tableViewModel:RLDTableViewModel
    required public init(tableViewModel:RLDTableViewModel) {
        self.tableViewModel = tableViewModel
    }
    
    // MARK: Display customization
    public func tableView(tableView:UITableView, willDisplayCell cell:UITableViewCell, forRowAtIndexPath indexPath:NSIndexPath) {
        link(eventHandler(tableView, indexPath:indexPath, cell:cell),
            view:cell,
            andExecute:{ (eventHandler) -> Void in
                eventHandler.willDisplayView()
        })
    }
    
    public func tableView(tableView:UITableView, willDisplayHeaderView view:UIView, forSection section:Int) {
        self.tableView(tableView, willDisplayHeaderFooterView:view, model:tableViewModel.sectionModels[section].header)
    }
    
    public func tableView(tableView:UITableView, willDisplayFooterView view:UIView, forSection section:Int) {
        self.tableView(tableView, willDisplayHeaderFooterView:view, model:tableViewModel.sectionModels[section].footer)
    }
    
    private func tableView(tableView:UITableView, willDisplayHeaderFooterView view:UIView, model:RLDTableViewSectionAccessoryViewModel?) {
        if let model = model {
            link(eventHandler(tableView, viewModel:model, view:view),
                view:view,
                andExecute:{ (eventHandler) -> Void in
                    eventHandler.willDisplayView()
            })
        }
    }
    
    private func link(eventHandler:RLDTableViewEventHandler, view:UIView, andExecute closure:(eventHandler:RLDTableViewEventHandler)->Void) {
        if let view = view as? RLDHandledViewProtocol {
            view.eventHandler = eventHandler
        }
        closure(eventHandler:eventHandler)
    }
    
    public func tableView(tableView:UITableView, didEndDisplayingCell cell:UITableViewCell, forRowAtIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath, cell:cell).didEndDisplayingView()
    }
    
    public func tableView(tableView:UITableView, didEndDisplayingHeaderView view:UIView, forSection section:Int) {
        if let headerViewModel = tableViewModel.sectionModels[section].header {
            eventHandler(tableView, viewModel:headerViewModel, view:view).didEndDisplayingView()
        }
    }
    
    public func tableView(tableView:UITableView, didEndDisplayingFooterView view:UIView, forSection section:Int) {
        if let footerViewModel = tableViewModel.sectionModels[section].footer {
            eventHandler(tableView, viewModel:footerViewModel, view:view).didEndDisplayingView()
        }
    }
    
    // MARK: Variable height support
    public func tableView(tableView:UITableView, heightForRowAtIndexPath indexPath:NSIndexPath) -> CGFloat {
        if let height = cellModel(indexPath).height {
            return height
        }
        return UITableViewAutomaticDimension
    }
    
    public func tableView(tableView:UITableView, heightForHeaderInSection section:Int) -> CGFloat {
        if let height = tableViewModel.sectionModels[section].header?.height {
            return height
        }
        return UITableViewAutomaticDimension
    }
    
    public func tableView(tableView:UITableView, heightForFooterInSection section:Int) -> CGFloat {
        if let height = tableViewModel.sectionModels[section].footer?.height {
            return height
        }
        return UITableViewAutomaticDimension
    }
    
    public func tableView(tableView:UITableView, estimatedHeightForRowAtIndexPath indexPath:NSIndexPath) -> CGFloat {
        if let estimatedHeight = cellModel(indexPath).estimatedHeight {
            return estimatedHeight
        }
        return UITableViewAutomaticDimension
    }
    
    public func tableView(tableView:UITableView, estimatedHeightForHeaderInSection section:Int) -> CGFloat {
        if let estimatedHeight = tableViewModel.sectionModels[section].header?.estimatedHeight {
            return estimatedHeight
        }
        return UITableViewAutomaticDimension
    }
    
    public func tableView(tableView:UITableView, estimatedHeightForFooterInSection section:Int) -> CGFloat {
        if let estimatedHeight = tableViewModel.sectionModels[section].footer?.estimatedHeight {
            return estimatedHeight
        }
        return UITableViewAutomaticDimension
    }
    
    // MARK: Section header and footer
    public func tableView(tableView:UITableView, viewForHeaderInSection section:Int) -> UIView? {
        if let reuseIdentifier = tableViewModel.sectionModels[section].header?.reuseIdentifier {
            return tableView.dequeueReusableHeaderFooterViewWithIdentifier(reuseIdentifier)
        }
        return nil
    }
    
    public func tableView(tableView:UITableView, viewForFooterInSection section:Int) -> UIView? {
        if let reuseIdentifier = tableViewModel.sectionModels[section].footer?.reuseIdentifier {
            return tableView.dequeueReusableHeaderFooterViewWithIdentifier(reuseIdentifier)
        }
        return nil
    }
    
    // MARK: Accessories (disclosures)
    public func tableView(tableView:UITableView, accessoryButtonTappedForRowWithIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath).accessoryButtonTapped()
    }
    
    // MARK: Selection
    public func tableView(tableView:UITableView, shouldHighlightRowAtIndexPath indexPath:NSIndexPath) -> Bool {
        return eventHandler(tableView, indexPath:indexPath).shouldHighlightView()
    }
    
    public func tableView(tableView:UITableView, didHighlightRowAtIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath).didHighlightView()
    }
    
    public func tableView(tableView:UITableView, didUnhighlightRowAtIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath).didUnhighlightView()
    }
    
    public func tableView(tableView:UITableView, willSelectRowAtIndexPath indexPath:NSIndexPath) -> NSIndexPath? {
        let selectedIndexPath = eventHandler(tableView, indexPath:indexPath).willSelectView()
        return (selectedIndexPath != nil ? selectedIndexPath : indexPath)
    }
    
    public func tableView(tableView:UITableView, willDeselectRowAtIndexPath indexPath:NSIndexPath) -> NSIndexPath? {
        let deselectedIndexPath = eventHandler(tableView, indexPath:indexPath).willDeselectView()
        return (deselectedIndexPath != nil ? deselectedIndexPath : indexPath)
    }
    
    public func tableView(tableView:UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath).didSelectView()
    }
    
    public func tableView(tableView:UITableView, didDeselectRowAtIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath).didDeselectView()
    }
    
    // MARK: Editing
    public func tableView(tableView:UITableView, editingStyleForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCellEditingStyle {
        if let editingStyle = cellModel(indexPath).editingStyle {
            return editingStyle
        }
        return UITableViewCellEditingStyle.None
    }
    
    public func tableView(tableView:UITableView, titleForDeleteConfirmationButtonForRowAtIndexPath indexPath:NSIndexPath) -> String? {
        if let titleForDeleteConfirmationButton = cellModel(indexPath).titleForDeleteConfirmationButton {
            return titleForDeleteConfirmationButton
        }
        return ""
    }
    
    public func tableView(tableView:UITableView, editActionsForRowAtIndexPath indexPath:NSIndexPath) -> [UITableViewRowAction]? {
        return eventHandler(tableView, indexPath:indexPath).editActions()
    }
    
    public func tableView(tableView:UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath:NSIndexPath) -> Bool {
        if let shouldIndentWhileEditing = cellModel(indexPath).shouldIndentWhileEditing {
            return shouldIndentWhileEditing
        }
        return false
    }
    
    public func tableView(tableView:UITableView, willBeginEditingRowAtIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath).willBeginEditing()
    }
    
    public func tableView(tableView:UITableView, didEndEditingRowAtIndexPath indexPath:NSIndexPath) {
        eventHandler(tableView, indexPath:indexPath).didEndEditing()
    }
    
    // MARK: Moving and reordering
    public func tableView(tableView:UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath:NSIndexPath, toProposedIndexPath proposedDestinationIndexPath:NSIndexPath) -> NSIndexPath {
        return proposedDestinationIndexPath
    }
    
    // MARK: Indentation
    public func tableView(tableView:UITableView, indentationLevelForRowAtIndexPath indexPath:NSIndexPath) -> Int {
        if let indentationLevel = cellModel(indexPath).indentationLevel {
            return indentationLevel
        }
        return 0
    }
    
    // MARK: Copy and Paste
    public func tableView(tableView:UITableView, shouldShowMenuForRowAtIndexPath indexPath:NSIndexPath) -> Bool {
        if let shouldShowMenu = cellModel(indexPath).shouldShowMenu {
            return shouldShowMenu
        }
        return false
    }
    
    public func tableView(tableView:UITableView, canPerformAction action:Selector, forRowAtIndexPath indexPath:NSIndexPath, withSender sender:AnyObject?) -> Bool {
        return eventHandler(tableView, indexPath:indexPath).canPerform(action, withSender:sender!)
    }
    
    public func tableView(tableView:UITableView, performAction action:Selector, forRowAtIndexPath indexPath:NSIndexPath, withSender sender:AnyObject?) {
        return eventHandler(tableView, indexPath:indexPath).performAction(action, withSender:sender!)
    }
    
    // MARK: Event handler generation
    private func eventHandler(tableView:UITableView, indexPath:NSIndexPath) -> RLDTableViewCellEventHandler {
        let cellModel = self.cellModel(indexPath)
        tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.None, animated:false)
        let cell = tableView.cellForRowAtIndexPath(indexPath)!
        return eventHandler(tableView, indexPath:indexPath, cell:cell)
    }
    
    private func eventHandler(tableView:UITableView, indexPath:NSIndexPath, cell:UITableViewCell) -> RLDTableViewCellEventHandler {
        let cellModel = self.cellModel(indexPath)
        return eventHandler(tableView, viewModel:cellModel, view:cell) as! RLDTableViewCellEventHandler
    }
    
    private func eventHandler(tableView:UITableView, viewModel:RLDTableViewReusableViewModel, view:UIView) -> RLDTableViewEventHandler {
        if let eventHandler = reusableEventHandler(tableView, viewModel:viewModel, view:view) {
            eventHandler.tableView = tableView
            eventHandler.viewModel = viewModel
            eventHandler.view = view
            return eventHandler
        } else {
            let eventHandler = RLDTableViewEventHandlerProvider.eventHandler(tableView, viewModel:viewModel, view:view)
            assert(eventHandler != nil, "Unable to find suitable event hander for \ntableView: \(tableView)\nviewModel: \(viewModel)\nview: \(view)")
            return eventHandler!
        }
    }
    
    private func reusableEventHandler(tableView:UITableView, viewModel:RLDTableViewReusableViewModel, view:UIView) -> RLDTableViewEventHandler? {
        if let handledView = view as? RLDHandledViewProtocol, let eventHandler = handledView.eventHandler {
            let eventHandlerClass = eventHandler.dynamicType
            if eventHandlerClass.canHandle(tableView, viewModel:viewModel, view:view) {
                return eventHandler
            }
        }
        return nil
    }
    
    // MARK: Model accessors
    private func cellModel(indexPath:NSIndexPath) -> RLDTableViewCellModel {
        let sectionModel = tableViewModel.sectionModels[indexPath.section]
        return sectionModel.cellModels[indexPath.row]
    }
}

================================================
FILE: Classes/RLDTableViewEventHandler.swift
================================================
import UIKit

// MARK: RLDTableViewEventHandler class

public class RLDTableViewEventHandler {
    // MARK: Event handler registration
    public class func register() {
        RLDTableViewEventHandlerProvider.register(self)
    }
    
    // MARK: Suitability checking
    public class func canHandle(tableView:UITableView, viewModel:RLDTableViewReusableViewModel, view:UIView) -> Bool {
        return false
    }
    
    // MARK: Initialization and dependencies
    public var tableView:UITableView
    public var viewModel:RLDTableViewReusableViewModel
    public var view:UIView
    required public init(tableView:UITableView, viewModel:RLDTableViewReusableViewModel, view:UIView) {
        self.tableView = tableView
        self.viewModel = viewModel
        self.view = view
    }
    
    // MARK: Display customization
    public func willReuseView() {}
    public func willDisplayView() {}
    public func didEndDisplayingView() {}
}

// MARK: RLDTableViewCellEventHandler class

public class RLDTableViewCellEventHandler:RLDTableViewEventHandler {
    
    // MARK: Accessories (disclosures)
    public func accessoryButtonTapped() {}
    
    // MARK: Selection
    public func shouldHighlightView() -> Bool { return false }
    public func didHighlightView() {}
    public func didUnhighlightView() {}
    public func willSelectView() -> NSIndexPath? { return nil }
    public func willDeselectView() -> NSIndexPath? { return nil }
    public func didSelectView() {}
    public func didDeselectView() {}
    
    // MARK: Editing
    public func willBeginEditing() {}
    public func didEndEditing() {}
    public func editActions() -> [UITableViewRowAction]? { return nil }
    
    // MARK: Copy and Paste
    public func canPerform(action:Selector, withSender sender:AnyObject) -> Bool { return false }
    public func performAction(action:Selector, withSender sender:AnyObject) {}
}

// MARK: RLDTableViewSectionAccessoryViewEventHandler class

public class RLDTableViewSectionAccessoryViewEventHandler:RLDTableViewEventHandler {
}

================================================
FILE: Classes/RLDTableViewEventHandlerProvider.swift
================================================
import UIKit

class RLDTableViewEventHandlerProvider {
    private static var availableEventHanlderClasses:[RLDTableViewEventHandler.Type] = []
    
    class func register(eventHandlerClass:RLDTableViewEventHandler.Type) {
        availableEventHanlderClasses.append(eventHandlerClass)
    }
    
    class func eventHandler(tableView:UITableView, viewModel:RLDTableViewReusableViewModel, view:UIView) -> RLDTableViewEventHandler? {
        for eventHandler in availableEventHanlderClasses {
            if eventHandler.canHandle(tableView, viewModel:viewModel, view:view) {
                return eventHandler.init(tableView:tableView, viewModel:viewModel, view:view)
            }
        }
        return nil
    }
}

================================================
FILE: Classes/RLDTableViewModel.swift
================================================
//
//  RLDNavigation
//
//  Copyright (c) 2015 Rafael Lopez Diez. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

import UIKit

// MARK: RLDTableViewReusableViewModel class

public class RLDTableViewReusableViewModel {
    // MARK: Initialization
    required public init() {
        reuseIdentifier = NSStringFromClass(self.dynamicType)
    }
    
    // MARK: Parent linking
    weak private(set) var sectionModel:RLDTableViewSectionModel?
    public func set(sectionModel newSectionModel:RLDTableViewSectionModel) {
        sectionModel = newSectionModel
    }
    
    // MARK: Reuse identifier
    public var reuseIdentifier:String
    
    // MARK: Variable height support
    public var height:CGFloat?
    public var estimatedHeight:CGFloat?
}

// MARK: RLDTableViewCellModel class

public class RLDTableViewCellModel:RLDTableViewReusableViewModel {
    // MARK: Indentation
    public var indentationLevel:NSInteger?
    
    // MARK: Editing
    public var editable:Bool?
    public var movable:Bool?
    public var shouldIndentWhileEditing:Bool?
    public var editingStyle:UITableViewCellEditingStyle?
    public var titleForDeleteConfirmationButton:String?
    
    // MARK: Copy and Paste
    public var shouldShowMenu:Bool?
}

// MARK: RLDTableViewSectionAccessoryViewModel class

public class RLDTableViewSectionAccessoryViewModel:RLDTableViewReusableViewModel {
    // MARK: Title
    public var title:String?
}

// MARK: RLDTableViewSectionModel class

public class RLDTableViewSectionModel:Equatable {
    // MARK: Parent linking
    weak private(set) var tableModel:RLDTableViewModel?
    public func set(tableModel newTableModel:RLDTableViewModel) {
        tableModel = newTableModel
    }
    
    // Listing cell models
    private(set) var cellModels:[RLDTableViewCellModel] = []
    
    // MARK: Insertions
    public var defaultCellModelClassForInsertions:String?
    
    public func add(cellModel:RLDTableViewCellModel) {
        cellModel.set(sectionModel:self)
        cellModels.append(cellModel)
    }
    
    public func insert(cellModel:RLDTableViewCellModel, atIndex index:Int) {
        cellModel.set(sectionModel:self)
        cellModels.insert(cellModel, atIndex:index)
    }
    
    // MARK: Deletions
    public func remove(cellModel:RLDTableViewCellModel) {
        cellModel.set(sectionModel:self)
        cellModels = cellModels.filter( {!($0 === cellModel)} )
    }
    
    // MARK: Index title
    public var indexTitle:String?
    
    // MARK: Section header and footer
    public var header:RLDTableViewSectionAccessoryViewModel? {
        didSet {
            header?.set(sectionModel:self)
        }
    }
    
    public var footer:RLDTableViewSectionAccessoryViewModel? {
        didSet {
            footer?.set(sectionModel:self)
        }
    }
}

// MARK: RLDTableViewSectionModel equality operator

public func == (lhs:RLDTableViewSectionModel, rhs:RLDTableViewSectionModel) -> Bool {
    return lhs === rhs
}

// MARK: RLDTableViewModel class

public class RLDTableViewModel {
    
    public init() {
        // XCode Version 6.3 (6D570) forces me to add this initializer
    }
    
    // MARK: Listing section models
    private(set) var sectionModels:[RLDTableViewSectionModel] = []
    
    // MARK: Adding section models
    public func addNewSectionModel() -> RLDTableViewSectionModel {
        let newSectionModel = RLDTableViewSectionModel()
        add(newSectionModel)
        return newSectionModel
    }
    
    private func add(sectionModel:RLDTableViewSectionModel) {
        sectionModel.set(tableModel:self)
        sectionModels.append(sectionModel)
    }
    
    // MARK: Adding cell models
    public func add(cellModel:RLDTableViewCellModel) {
        if sectionModels.count == 0 {
            addNewSectionModel()
        }
        add(cellModel, toSectionModel:sectionModels.last!)
    }
    
    public func add(cellModel:RLDTableViewCellModel, toSectionModel sectionModel:RLDTableViewSectionModel) {
        if !sectionModels.contains(sectionModel) {
            add(sectionModel)
        }
        sectionModel.add(cellModel)
    }
    
    // MARK: Section index titles
    private var _sectionIndexTitles:[String]?
    public var sectionIndexTitles:[String]? {
        set {
            _sectionIndexTitles = newValue
        }
        get {
            if (_sectionIndexTitles == nil) {
                var indexTitles:[String] = []
                
                for sectionModel in sectionModels {
                    if let indexTitle = sectionModel.indexTitle {
                        indexTitles.append(indexTitle)
                    }
                }
                
                if indexTitles.count > 0 {
                    _sectionIndexTitles = indexTitles
                }
            }
            return _sectionIndexTitles
        }
    }
}

================================================
FILE: LICENSE
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

================================================
FILE: README.md
================================================
# RLDTableViewSwift

The ubiquitous `UITableView`, with its required data source and delegate, is one of the main sources of badly architected solutions in the iOS platform. SDK classes, as `UITableViewController`, enforce bad design practices, and lead you to the problem of the Massive View Controller, where the single responsibility principle is completely missed.

`RLDTableViewSwift` is a set of ready-to-use Swift classes that will get you back in track, helping you to refine the shape of your app. They enforce the SOLID principles, with an adaptation of the Model-View-Presenter pattern.

![RLDTableViewSwift sample app](https://raw.githubusercontent.com/rlopezdiez/RLDTableViewSwift/master/README.jpg)

> [Objective-C version](https://github.com/rlopezdiez/RLDTableViewSuite) also available.

## Foundations

### RLDTableViewDataSource and RLDTableViewDelegate

These are reusable components for the data source and delegate of all your table views. With them, you won't need to write the same boilerplate code again and again –they will just use your table view model and event handlers to be able to manage any `UITableView`. 

They fully implement the `UITableViewDataSource` and `UITableViewDelegate` protocols, and keep synchronized between themselves, giving you all the `UITableView` features with little effort from your side:
- Display customization
- Variable height support
- Sections, with headers and footers
- Sections index titles
- Cell accessories (disclosures)
- Highlighting and selection of cells
- Editing, moving and reordering cells
- Indentation
- Copy and Paste


### Table view model

The table view model defines the state, look and feel of the views in your table view, and the relationships between them. You can use the provided generic implementations, or subclass them to tailor them to yor needs:

- `RLDTableViewCellModel`, for cells,
- `RLDTableViewSectionModel`, for table sections,
- `RLDTableViewSectionAccessoryViewModel`, for section headers and footers, and
- `RLDTableViewModel`, for the table view itself.

### Event handlers

Every view in your table view (like cells, section headers and section footers) should be managed by an event handler. It will receive all the view related actions from the table view delegate and react to user generated events on the view. 

Event handlers are short-lived objects that will be instantiated on demand and destroyed once the event that caused its creation has been handled or when the view they manage is deallocated. They should not store state *(because we have a model, right?)* and they can either configure the look of the view by themselves, or pass the view model to the view, so it can autoconfigure. The provided sample app uses the latest approach.

You have two event handlers classes that you can subclass:
- `RLDTableViewCellEventHandler`, for table view cells, and
- `RLDTableViewSectionAccessoryViewEventHandler`, for section headers and footers.

Although it is not mandatory, if the handled view conforms to the `RLDHandledViewProtocol` it will receive an event handler just before the view is displayed for the first time. The view will retain this event handler during all its lifecycle to be able to react to the user generated events on the view. This retained event handler will be reused together with the cell, improving the performance.

### Event handler provider

In order to create the best suited event handler on demand, `RLDTableViewDelegate` will need an event handler provider to find the first event handler which supports a certain combination of table view, view and view model.

To make your event handlers available to the provider, you must register them using their  `register()` class method. 

The best way to make sure all your classes are ready when needed is registering them in the same place. You can use a registar class with a function that is called once when the application has finished launching, or register them just before their first use. The included sample app uses this approach.

### RLDTableViewController 

This class is a drop-in replacement of `UITableViewController`. It just requires a table view model to be able to configure your table view. Internally, it uses the default implementations of `RLDTableViewDataSource`, `RLDTableViewDelegate` and `RLDTableViewEventHandlerProvider`, so it's the easiest way to use `RLDTableViewSwift` without worrying about its internals, while getting the most of having a proper architecture.

## Installing

### Using CocoaPods

To use the latest stable release of `RLDTableViewSwift`, just add the following to your project `Podfile`:

```
pod 'RLDTableViewSwift', '~> 0.2.1' 
```

If you like to live on the bleeding edge, you can use the `master` branch with:

```
pod 'RLDTableViewSwift', :git => 'https://github.com/rlopezdiez/RLDTableViewSwift'
```

### Manually

1. Clone, add as a submodule or [download.](https://github.com/rlopezdiez/RLDTableViewSwift/zipball/master)
2. Add all the files under `Classes` to your project.
3. Enjoy.

## License

`RLDTableViewSwift` is available under the Apache License, Version 2.0. See LICENSE file for more info.

This README has been made with [(GitHub-Flavored) Markdown Editor](http://jbt.github.io/markdown-editor)

================================================
FILE: RLDTableViewSwift.podspec
================================================
Pod::Spec.new do |s|
  s.name         = 'RLDTableViewSwift'
  s.version      = '0.2.1'
  s.homepage     = 'https://github.com/rlopezdiez/RLDTableViewSwift.git'
  s.summary      = 'Reusable table view controller, data source and delegate for all your UITableView needs in Swift'
  s.authors      = { 'Rafael Lopez Diez' => 'https://www.linkedin.com/in/rafalopezdiez' }
  s.source       = { :git => 'https://github.com/rlopezdiez/RLDTableViewSwift.git', :tag => s.version.to_s }
  s.source_files = 'Classes/*.swift'
  s.license      = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' }
  s.platform     = :ios, '8.0'
  s.requires_arc = true
end


================================================
FILE: Sample app/TableViewPrototype/AppDelegate.swift
================================================
import UIKit

@UIApplicationMain
class AppDelegate:UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    
    func application(application:UIApplication, didFinishLaunchingWithOptions launchOptions:[NSObject:AnyObject]?) -> Bool {
        return true
    }
}

================================================
FILE: Sample app/TableViewPrototype/Event handlers/RLDGenericTableViewCellEventHandler.swift
================================================
import UIKit
import RLDTableViewSwift

class RLDGenericTableViewCellEventHandler:RLDTableViewCellEventHandler {
    // MARK: Suitability checking
    override class func canHandle(tableView:UITableView, viewModel:RLDTableViewReusableViewModel, view:UIView) -> Bool {
        if let viewModel = viewModel as? RLDGenericTableViewCellModel,
            let view = view as? RLDGenericTableViewCell {
                return true
        }
        
        return false
    }
    
    // MARK: Cell customization
    override func willDisplayView() {
        if let view = view as? RLDGenericTableViewCell {
            view.model = (viewModel as! RLDGenericTableViewCellModel)
        }
    }
    
    // MARK: View highlighting
    override func shouldHighlightView() -> Bool {
        return true
    }
    
    override func didHighlightView() {
        if let view = view as? RLDGenericTableViewCell {
            view.viewToHighlight.backgroundColor = UIColor(red:0.8, green:0.92, blue:1, alpha:1)
        }
        view.alpha = 0.75
    }
    
    override func didUnhighlightView() {
        if let view = view as? RLDGenericTableViewCell {
            view.viewToHighlight.backgroundColor = UIColor.whiteColor()
        }
        view.alpha = 1
    }
    
    // MARK: Cell interactions
    override func didSelectView() {
        if let viewModel = viewModel as? RLDGenericTableViewCellModel {
            open(viewModel.imageURL, title: viewModel.title)
        }
    }
    
    func didTapCategoryButton() {
        if let viewModel = viewModel as? RLDGenericTableViewCellModel {
            open(viewModel.categoryURL, title: viewModel.category)
        }
    }
    
    private func open(url:String, title:String) {
        /*
        This way of navigating to another view controller is good enough for a sample app,
        but in a real life situation you should consider moving navigation code elsewhere.
        You can use flow controllers, routers or some kind of view model propagation.
        You might want to use my navigation library, which is a good complement to this one:
        https://github.com/rlopezdiez/RLDNavigationSwift
        */
        if let navigationController = navigationController() {
            let storyboard = UIStoryboard(name:"Main", bundle:nil)
            let detailViewController = storyboard.instantiateViewControllerWithIdentifier("RLDWebViewController") as! RLDWebViewController
            detailViewController.title = title
            detailViewController.url = url
            navigationController.pushViewController(detailViewController, animated:true)
        }
    }
    
    private func navigationController() -> UINavigationController? {
        for var nextView:UIView? = view.superview; nextView != nil; nextView = nextView!.superview {
            if let nextResponder = nextView?.nextResponder() as? UINavigationController {
                return nextResponder
            }
        }
        return nil
    }
}

================================================
FILE: Sample app/TableViewPrototype/Event handlers/RLDTableViewHeaderViewEventHandler.swift
================================================
import UIKit
import RLDTableViewSwift

class RLDTableViewHeaderViewEventHandler:RLDTableViewSectionAccessoryViewEventHandler {
    // MARK: Suitability checking
    override class func canHandle(tableView:UITableView, viewModel:RLDTableViewReusableViewModel, view:UIView) -> Bool {
        if let viewModel = viewModel as? RLDTableViewHeaderViewModel,
            let view = view as? RLDTableViewHeaderView {
                return true
        }
        
        return false
    }
    
    // MARK: View customization
    override func willDisplayView() {
        if let view = view as? RLDTableViewHeaderView {
            view.model = (viewModel as! RLDTableViewHeaderViewModel)
        }
    }
}

================================================
FILE: Sample app/TableViewPrototype/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: Sample app/TableViewPrototype/Models/RLDBigPictureTableViewCellModel.swift
================================================
class RLDBigPictureTableViewCellModel:RLDGenericTableViewCellModel {
    required init() {
        super.init()
        reuseIdentifier = "RLDBigPictureTableViewCell"
    }
}

================================================
FILE: Sample app/TableViewPrototype/Models/RLDCommentTableViewCellModel.swift
================================================
class RLDCommentTableViewCellModel:RLDGenericTableViewCellModel {
    
    var comment:String = ""
    
    required init() {
        super.init()
        reuseIdentifier = "RLDCommentTableViewCell"
    }
}

================================================
FILE: Sample app/TableViewPrototype/Models/RLDGenericTableViewCellModel.swift
================================================
import RLDTableViewSwift

class RLDGenericTableViewCellModel:RLDTableViewCellModel {
    var title:String = ""
    var date:String = ""
    var category:String = ""
    var categoryURL:String = ""
    var imageName:String = ""
    var imageURL:String = ""
}

================================================
FILE: Sample app/TableViewPrototype/Models/RLDSimpleTableViewCellModel.swift
================================================
class RLDSimpleTableViewCellModel:RLDGenericTableViewCellModel {
    required init() {
        super.init()
        reuseIdentifier = "RLDSimpleTableViewCell"
    }
}

================================================
FILE: Sample app/TableViewPrototype/Models/RLDTableViewHeaderViewModel.swift
================================================
import RLDTableViewSwift

class RLDTableViewHeaderViewModel:RLDTableViewSectionAccessoryViewModel {
    required init() {
        super.init()
        reuseIdentifier = "RLDTableViewHeaderView"
        height = 60
        estimatedHeight = height
    }
}

================================================
FILE: Sample app/TableViewPrototype/Models/RLDTableViewModelProvider.swift
================================================
import RLDTableViewSwift
import UIKit

class RLDTableViewModelProvider {
    
    static private let DataPlistFileName = "viewModelData"
    static private let DictionaryTitleKey = "title"
    static private let DictionaryCellsKey = "cells"
    static private let DictionaryClassKey = "class"
    static private let TableViewCellTitleForDeleteConfirmationButton = "Delete"
    static private let TableViewHeaderViewReuseIdentifier = "RLDTableViewHeaderView"
    
    var headerFooterReuseIdentifiersToNibNames = [RLDTableViewModelProvider.TableViewHeaderViewReuseIdentifier:RLDTableViewModelProvider.TableViewHeaderViewReuseIdentifier]
    lazy var tableViewModel:RLDTableViewModel = {
        let modelArray = self.modelArray()
        let tableViewModel = RLDTableViewModel()
        for sectionDictionary in modelArray {
            self.tableViewModel(tableViewModel, addSectionWithSectionDictionary:sectionDictionary)
        }
        return tableViewModel
        }()
    
    
    private func modelArray() -> [[String:AnyObject]] {
        return NSArray(contentsOfFile:NSBundle.mainBundle().pathForResource(RLDTableViewModelProvider.DataPlistFileName, ofType:"plist")!)! as! [[String:AnyObject]]
    }
    
    private func tableViewModel(tableViewModel:RLDTableViewModel, addSectionWithSectionDictionary sectionDictionary:[String:AnyObject]) {
        let sectionModel = tableViewModel.addNewSectionModel()
        
        if let headerTitle = sectionDictionary[RLDTableViewModelProvider.DictionaryTitleKey] as? String {
            let headerModel = RLDTableViewHeaderViewModel()
            headerModel.title = headerTitle
            sectionModel.header = headerModel
        }
        
        for cellDictionary in sectionDictionary[RLDTableViewModelProvider.DictionaryCellsKey] as! [[String:AnyObject]] {
            self.tableViewModel(tableViewModel, addCellWithCellDictionary:cellDictionary)
        }
    }
    
    private func tableViewModel(tableViewModel:RLDTableViewModel, addCellWithCellDictionary cellDictionary:[String:AnyObject]) {
        let cellModel = RLDGenericTableViewCellModel.cellModelForClass(cellDictionary[RLDTableViewModelProvider.DictionaryClassKey] as! String)
        
        for (key, value) in cellDictionary {
            cellModel.setValue(value, forKey:key)
        }
        
        cellModel.titleForDeleteConfirmationButton = RLDTableViewModelProvider.TableViewCellTitleForDeleteConfirmationButton
        
        tableViewModel.add(cellModel)
    }
    
}

extension RLDGenericTableViewCellModel {
    
    class func cellModelForClass(cellModelClass:String) -> RLDGenericTableViewCellModel {
        switch cellModelClass {
        case "RLDBigPictureTableViewCellModel":
            return RLDBigPictureTableViewCellModel()
        case "RLDCommentTableViewCellModel":
            return RLDCommentTableViewCellModel()
        case "RLDSimpleTableViewCellModel":
            return RLDSimpleTableViewCellModel()
        default:
            fatalError("Unable to find class for \(cellModelClass)")
        }
    }
    
    func setValue(value:AnyObject, forKey key:String) {
        switch key {
        case "category":
            category = value as! String
        case "categoryURL":
            categoryURL = value as! String
        case "comment":
            (self as! RLDCommentTableViewCellModel).comment = value as! String
        case "date":
            date = value as! String
        case "editable":
            editable = (value as! Bool)
        case "editingStyle":
            editingStyle = (value as! Int == 1
                ? UITableViewCellEditingStyle.Delete
                : UITableViewCellEditingStyle.None)
        case "imageName":
            imageName = value as! String
        case "imageURL":
            imageURL = value as! String
        case "movable":
            movable = (value as! Bool)
        case "title":
            title = value as! String
        case "class":
            break
        default:
            fatalError("Unable to set the value for \(key)")
        }
    }
}

================================================
FILE: Sample app/TableViewPrototype/RLDTableViewSwift-Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>0.2.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>NSPrincipalClass</key>
	<string></string>
</dict>
</plist>


================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/0_small.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "0_small.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/1_small.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "1_small.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/2_big.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "2_big.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/2_small.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "2_small.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/3_small.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "3_small.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/4_big.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "4_big.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/5_small.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "5_small.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/6_big.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "6_big.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/7_big.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "7_big.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/8_small.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "8_small.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/9_small.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x",
      "filename" : "9_small.jpg"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Sample app/TableViewPrototype/Resources/LaunchScreen.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7531" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7520"/>
        <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view contentMode="scaleToFill" id="iN0-l3-epB">
            <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="RLDTableViewSwift" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
                    <rect key="frame" x="20" y="140" width="441" height="43"/>
                    <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                    <nil key="highlightedColor"/>
                </label>
                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sample app" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
                    <rect key="frame" x="20" y="191" width="441" height="21"/>
                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                    <nil key="highlightedColor"/>
                </label>
            </subviews>
            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
            <constraints>
                <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
                <constraint firstItem="8ie-xW-0ye" firstAttribute="top" secondItem="kId-c2-rCX" secondAttribute="bottom" constant="8" id="Ael-S7-PCG"/>
                <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
                <constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
                <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
                <constraint firstItem="8ie-xW-0ye" firstAttribute="width" secondItem="kId-c2-rCX" secondAttribute="width" id="ula-XA-QNb"/>
            </constraints>
            <nil key="simulatedStatusBarMetrics"/>
            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
            <point key="canvasLocation" x="548" y="455"/>
        </view>
    </objects>
</document>


================================================
FILE: Sample app/TableViewPrototype/Resources/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7531" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="Ncx-uH-Jsh">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7520"/>
        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
    </dependencies>
    <scenes>
        <!--RLDMasterViewController-->
        <scene sceneID="Kjn-h9-4al">
            <objects>
                <tableViewController title="RLDTableViewSuite" id="9Ww-mV-ZtW" userLabel="RLDMasterViewController" customClass="RLDMasterViewController" customModule="TableViewPrototype" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="onDrag" dataMode="prototypes" style="plain" separatorStyle="none" showsSelectionImmediatelyOnTouchBegin="NO" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="Fvc-Gm-gkE">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="890"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="0.87450980389999999" green="0.87450980389999999" blue="0.87450980389999999" alpha="1" colorSpace="calibratedRGB"/>
                        <view key="tableFooterView" contentMode="scaleToFill" id="dQs-WQ-sFE" userLabel="Footer view">
                            <rect key="frame" x="0.0" y="0.0" width="414" height="60"/>
                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                            <subviews>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Source code available under the Apache License, Version 2.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ICO-EO-gob" userLabel="Title">
                                    <rect key="frame" x="8" y="23" width="398" height="15"/>
                                    <fontDescription key="fontDescription" type="system" weight="light" pointSize="12"/>
                                    <nil key="highlightedColor"/>
                                </label>
                            </subviews>
                            <constraints>
                                <constraint firstItem="ICO-EO-gob" firstAttribute="leading" secondItem="dQs-WQ-sFE" secondAttribute="leadingMargin" id="1eE-oO-pgw"/>
                                <constraint firstAttribute="centerY" secondItem="ICO-EO-gob" secondAttribute="centerY" id="C7M-Nc-WO8"/>
                                <constraint firstItem="ICO-EO-gob" firstAttribute="trailing" secondItem="dQs-WQ-sFE" secondAttribute="trailingMargin" id="gaJ-5t-RfY"/>
                                <constraint firstAttribute="height" constant="60" id="paV-4F-UaT"/>
                            </constraints>
                        </view>
                        <prototypes>
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="RLDSimpleTableViewCell" rowHeight="116" id="WqJ-bQ-aqm" customClass="RLDSimpleTableViewCell" customModule="TableViewPrototype">
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WqJ-bQ-aqm" id="4h3-wr-OdE">
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kX2-q5-VLD" userLabel="Frame">
                                            <rect key="frame" x="8" y="8" width="398" height="108"/>
                                            <subviews>
                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="f8f-tL-siP" userLabel="Image">
                                                    <rect key="frame" x="0.0" y="1" width="145" height="106"/>
                                                    <color key="backgroundColor" red="0.52831865649999998" green="0.70838541109999997" blue="0.84556502529999999" alpha="1" colorSpace="calibratedRGB"/>
                                                    <constraints>
                                                        <constraint firstAttribute="width" constant="145" id="Rdz-lb-h1f"/>
                                                        <constraint firstAttribute="height" constant="106" id="qpm-qv-a9c"/>
                                                    </constraints>
                                                </imageView>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Lorem ipsum dolor sit er elit consectetaur" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="237" translatesAutoresizingMaskIntoConstraints="NO" id="Qp9-EF-CBv" userLabel="Title">
                                                    <rect key="frame" x="153" y="6" width="237" height="46"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="19"/>
                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Loren" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3ef-5V-urY" userLabel="Timestamp">
                                                    <rect key="frame" x="153" y="82" width="37" height="18"/>
                                                    <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                    <color key="textColor" red="0.3912036263" green="0.3912036263" blue="0.3912036263" alpha="1" colorSpace="calibratedRGB"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="|" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fff-4o-qCJ" userLabel="Separator">
                                                    <rect key="frame" x="196" y="82" width="4" height="18"/>
                                                    <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                    <color key="textColor" red="0.3912036263" green="0.3912036263" blue="0.3912036263" alpha="1" colorSpace="calibratedRGB"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gTO-00-yFQ" userLabel="Section">
                                                    <rect key="frame" x="206" y="76" width="40" height="30"/>
                                                    <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                    <state key="normal" title="Ipsum">
                                                        <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
                                                    </state>
                                                    <connections>
                                                        <action selector="categoryButtonTapped" destination="WqJ-bQ-aqm" eventType="touchUpInside" id="Tdu-gn-oC1"/>
                                                    </connections>
                                                </button>
                                            </subviews>
                                            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="bottom" secondItem="3ef-5V-urY" secondAttribute="bottom" constant="8" id="0sb-Aq-0o8"/>
                                                <constraint firstItem="Qp9-EF-CBv" firstAttribute="top" secondItem="kX2-q5-VLD" secondAttribute="top" constant="6" id="BUx-Ib-ASU"/>
                                                <constraint firstItem="Qp9-EF-CBv" firstAttribute="leading" secondItem="f8f-tL-siP" secondAttribute="trailing" constant="8" id="DGd-I9-tik"/>
                                                <constraint firstAttribute="centerY" secondItem="f8f-tL-siP" secondAttribute="centerY" id="E86-Qt-eu3"/>
                                                <constraint firstItem="gTO-00-yFQ" firstAttribute="leading" secondItem="fff-4o-qCJ" secondAttribute="trailing" constant="6" id="Gqh-Gn-exs"/>
                                                <constraint firstItem="f8f-tL-siP" firstAttribute="leading" secondItem="kX2-q5-VLD" secondAttribute="leading" id="I7e-Jw-c7A"/>
                                                <constraint firstAttribute="trailing" secondItem="Qp9-EF-CBv" secondAttribute="trailing" constant="8" id="Xy7-yt-cp8"/>
                                                <constraint firstItem="fff-4o-qCJ" firstAttribute="leading" secondItem="3ef-5V-urY" secondAttribute="trailing" constant="6" id="Yyb-W5-g9A"/>
                                                <constraint firstAttribute="height" priority="750" constant="106" id="i5p-uU-Rg2"/>
                                                <constraint firstItem="3ef-5V-urY" firstAttribute="leading" secondItem="f8f-tL-siP" secondAttribute="trailing" constant="8" id="lb5-kp-9WA"/>
                                                <constraint firstItem="fff-4o-qCJ" firstAttribute="top" relation="greaterThanOrEqual" secondItem="kX2-q5-VLD" secondAttribute="top" constant="4" id="peY-zz-xco"/>
                                                <constraint firstAttribute="bottom" secondItem="gTO-00-yFQ" secondAttribute="bottom" constant="2" id="tIh-a7-uQA"/>
                                                <constraint firstAttribute="bottom" secondItem="fff-4o-qCJ" secondAttribute="bottom" constant="8" id="tkf-xA-3XY"/>
                                            </constraints>
                                        </view>
                                    </subviews>
                                    <color key="backgroundColor" red="0.87450980392156863" green="0.87450980392156863" blue="0.87450980392156863" alpha="1" colorSpace="calibratedRGB"/>
                                    <constraints>
                                        <constraint firstItem="kX2-q5-VLD" firstAttribute="top" secondItem="4h3-wr-OdE" secondAttribute="top" constant="8" id="BNC-Ug-R3e"/>
                                        <constraint firstItem="kX2-q5-VLD" firstAttribute="leading" secondItem="4h3-wr-OdE" secondAttribute="leading" constant="8" id="Rle-Ak-bUc"/>
                                        <constraint firstAttribute="bottom" secondItem="kX2-q5-VLD" secondAttribute="bottom" id="mMO-1U-M9P"/>
                                        <constraint firstAttribute="trailing" secondItem="kX2-q5-VLD" secondAttribute="trailing" constant="8" id="maW-l8-KVX"/>
                                    </constraints>
                                </tableViewCellContentView>
                                <color key="backgroundColor" red="0.87450980389999999" green="0.87450980389999999" blue="0.87450980389999999" alpha="1" colorSpace="calibratedRGB"/>
                                <connections>
                                    <outlet property="category" destination="gTO-00-yFQ" id="cXP-Ad-qtA"/>
                                    <outlet property="date" destination="3ef-5V-urY" id="H2E-za-zqx"/>
                                    <outlet property="picture" destination="f8f-tL-siP" id="alf-As-w01"/>
                                    <outlet property="title" destination="Qp9-EF-CBv" id="RoZ-jj-7KC"/>
                                    <outlet property="viewToHighlight" destination="kX2-q5-VLD" id="2dt-6e-hxE"/>
                                </connections>
                            </tableViewCell>
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="RLDCommentTableViewCell" rowHeight="317" id="fPA-ug-cX0" userLabel="RLDCommentTableViewCell" customClass="RLDCommentTableViewCell" customModule="TableViewPrototype">
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fPA-ug-cX0" id="TqF-TS-Zj0">
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="zaf-SL-8EC" userLabel="Image">
                                            <rect key="frame" x="0.0" y="0.0" width="414" height="205"/>
                                            <color key="backgroundColor" red="0.52831865649999998" green="0.70838541109999997" blue="0.84556502529999999" alpha="1" colorSpace="calibratedRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="height" constant="205" id="4eD-Es-qn2"/>
                                            </constraints>
                                        </imageView>
                                        <view alpha="0.40000000000000002" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8sm-sU-eZq" userLabel="Veil">
                                            <rect key="frame" x="0.0" y="155" width="414" height="50"/>
                                            <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
                                            <constraints>
                                                <constraint firstAttribute="height" constant="50" id="zAc-U4-h8B"/>
                                            </constraints>
                                        </view>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Excepteur sint occaecat" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gst-02-5DO" userLabel="Title">
                                            <rect key="frame" x="10" y="169" width="394" height="28"/>
                                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="23"/>
                                            <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Comment, tap to edit" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iCh-9Q-VvL" userLabel="Comment title">
                                            <rect key="frame" x="8" y="213" width="139" height="18"/>
                                            <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                            <color key="textColor" red="0.3912036263" green="0.3912036263" blue="0.3912036263" alpha="1" colorSpace="calibratedRGB"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" bounces="NO" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZCe-oO-5gl" userLabel="Comment text">
                                            <rect key="frame" x="8" y="237" width="398" height="70"/>
                                            <color key="backgroundColor" red="0.94446719028520498" green="0.94446719028520498" blue="0.94446719028520498" alpha="1" colorSpace="calibratedRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="height" constant="70" id="Ute-8s-4m1"/>
                                            </constraints>
                                            <string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</string>
                                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                            <textInputTraits key="textInputTraits" autocapitalizationType="sentences" spellCheckingType="no" enablesReturnKeyAutomatically="YES"/>
                                            <connections>
                                                <outlet property="delegate" destination="fPA-ug-cX0" id="ecl-du-YAW"/>
                                            </connections>
                                        </textView>
                                    </subviews>
                                    <constraints>
                                        <constraint firstItem="8sm-sU-eZq" firstAttribute="leading" secondItem="Gst-02-5DO" secondAttribute="leading" constant="-10" id="2Qa-4k-hHn"/>
                                        <constraint firstItem="zaf-SL-8EC" firstAttribute="bottom" secondItem="8sm-sU-eZq" secondAttribute="bottom" id="7hY-sf-Zt5"/>
                                        <constraint firstItem="zaf-SL-8EC" firstAttribute="leading" secondItem="8sm-sU-eZq" secondAttribute="leading" id="C4z-1S-AdS"/>
                                        <constraint firstAttribute="trailing" secondItem="zaf-SL-8EC" secondAttribute="trailing" id="Ik8-0l-zrq"/>
                                        <constraint firstItem="ZCe-oO-5gl" firstAttribute="top" secondItem="8sm-sU-eZq" secondAttribute="top" constant="82" id="WyV-a3-Myc"/>
                                        <constraint firstAttribute="trailing" secondItem="ZCe-oO-5gl" secondAttribute="trailing" constant="8" id="boc-FL-bSu"/>
                                        <constraint firstItem="zaf-SL-8EC" firstAttribute="leading" secondItem="TqF-TS-Zj0" secondAttribute="leading" id="bop-sa-fAA"/>
                                        <constraint firstItem="iCh-9Q-VvL" firstAttribute="top" secondItem="8sm-sU-eZq" secondAttribute="bottom" constant="8" id="eJs-qa-bgM"/>
                                        <constraint firstItem="zaf-SL-8EC" firstAttribute="top" secondItem="TqF-TS-Zj0" secondAttribute="top" id="m6K-wy-bxg"/>
                                        <constraint firstItem="8sm-sU-eZq" firstAttribute="bottom" secondItem="Gst-02-5DO" secondAttribute="bottom" constant="8" id="p57-BQ-ELc"/>
                                        <constraint firstItem="ZCe-oO-5gl" firstAttribute="leading" secondItem="TqF-TS-Zj0" secondAttribute="leading" constant="8" id="q1B-8G-CyR"/>
                                        <constraint firstItem="zaf-SL-8EC" firstAttribute="trailing" secondItem="8sm-sU-eZq" secondAttribute="trailing" id="qpZ-80-TRU"/>
                                        <constraint firstItem="8sm-sU-eZq" firstAttribute="trailing" secondItem="Gst-02-5DO" secondAttribute="trailing" constant="10" id="tM8-Xs-RPI"/>
                                        <constraint firstAttribute="bottom" secondItem="ZCe-oO-5gl" secondAttribute="bottom" constant="10" id="tNN-3C-Mjz"/>
                                        <constraint firstItem="iCh-9Q-VvL" firstAttribute="leading" secondItem="TqF-TS-Zj0" secondAttribute="leading" constant="8" id="uyU-zh-JHg"/>
                                    </constraints>
                                </tableViewCellContentView>
                                <connections>
                                    <outlet property="comment" destination="ZCe-oO-5gl" id="mq1-Wv-tyf"/>
                                    <outlet property="picture" destination="zaf-SL-8EC" id="XxF-ZC-a82"/>
                                    <outlet property="title" destination="Gst-02-5DO" id="7F8-zo-x2u"/>
                                    <outlet property="viewToHighlight" destination="TqF-TS-Zj0" id="kLj-k0-y8i"/>
                                </connections>
                            </tableViewCell>
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="RLDBigPictureTableViewCell" rowHeight="310" id="Onf-RL-efg" userLabel="RLDBigPictureTableViewCell" customClass="RLDBigPictureTableViewCell" customModule="TableViewPrototype">
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Onf-RL-efg" id="HoN-kJ-6R4">
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="L05-sr-ilM" userLabel="Image">
                                            <rect key="frame" x="0.0" y="0.0" width="414" height="205"/>
                                            <color key="backgroundColor" red="0.52831865653999721" green="0.70838541114296383" blue="0.84556502525252519" alpha="1" colorSpace="calibratedRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="height" constant="205" id="Cxe-Rw-JHj"/>
                                            </constraints>
                                        </imageView>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Illium adipisicing pecu, sed eiusmod tempor" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0tY-gY-zvz" userLabel="Title">
                                            <rect key="frame" x="8" y="208" width="398" height="72"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="29"/>
                                            <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="|" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZYr-2N-4SK" userLabel="Separator">
                                            <rect key="frame" x="51" y="284" width="4" height="18"/>
                                            <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                            <color key="textColor" red="0.3912036263" green="0.3912036263" blue="0.3912036263" alpha="1" colorSpace="calibratedRGB"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lIN-5o-URb" userLabel="Section">
                                            <rect key="frame" x="61" y="278" width="40" height="30"/>
                                            <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                            <state key="normal" title="Ipsum">
                                                <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
                                            </state>
                                            <connections>
                                                <action selector="categoryButtonTapped" destination="Onf-RL-efg" eventType="touchUpInside" id="qKA-wr-bfp"/>
                                            </connections>
                                        </button>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Loren" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MTb-6D-D5K" userLabel="Timestamp">
                                            <rect key="frame" x="8" y="284" width="37" height="18"/>
                                            <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                            <color key="textColor" red="0.39120362633689854" green="0.39120362633689854" blue="0.39120362633689854" alpha="1" colorSpace="calibratedRGB"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                    </subviews>
                                    <constraints>
                                        <constraint firstAttribute="trailing" secondItem="L05-sr-ilM" secondAttribute="trailing" id="3Sj-Py-3Cf"/>
                                        <constraint firstItem="MTb-6D-D5K" firstAttribute="leading" secondItem="HoN-kJ-6R4" secondAttribute="leading" constant="8" id="3mO-hN-Yoj"/>
                                        <constraint firstItem="L05-sr-ilM" firstAttribute="top" secondItem="HoN-kJ-6R4" secondAttribute="top" id="9tk-KY-Mfe"/>
                                        <constraint firstItem="0tY-gY-zvz" firstAttribute="bottom" secondItem="lIN-5o-URb" secondAttribute="top" constant="2" id="Sdd-92-fWM"/>
                                        <constraint firstAttribute="bottom" secondItem="ZYr-2N-4SK" secondAttribute="bottom" constant="8" id="UGd-bT-XGG"/>
                                        <constraint firstItem="MTb-6D-D5K" firstAttribute="top" secondItem="0tY-gY-zvz" secondAttribute="bottom" constant="4" id="Ue4-AJ-2nR"/>
                                        <constraint firstItem="lIN-5o-URb" firstAttribute="leading" secondItem="ZYr-2N-4SK" secondAttribute="trailing" constant="6" id="W87-dT-cAC"/>
                                        <constraint firstAttribute="trailing" secondItem="0tY-gY-zvz" secondAttribute="trailing" constant="8" id="Wyz-lY-vih"/>
                                        <constraint firstAttribute="bottom" secondItem="0tY-gY-zvz" secondAttribute="bottom" constant="30" id="bRH-XL-TrG"/>
                                        <constraint firstAttribute="bottomMargin" secondItem="lIN-5o-URb" secondAttribute="bottom" constant="-6" id="cBY-Aw-iIr"/>
                                        <constraint firstItem="0tY-gY-zvz" firstAttribute="top" secondItem="L05-sr-ilM" secondAttribute="bottom" constant="3" id="du2-LK-sxd"/>
                                        <constraint firstItem="0tY-gY-zvz" firstAttribute="leading" secondItem="HoN-kJ-6R4" secondAttribute="leading" constant="8" id="qlo-C8-HqO"/>
                                        <constraint firstItem="ZYr-2N-4SK" firstAttribute="leading" secondItem="MTb-6D-D5K" secondAttribute="trailing" constant="6" id="sXg-K5-NpL"/>
                                        <constraint firstItem="L05-sr-ilM" firstAttribute="leading" secondItem="HoN-kJ-6R4" secondAttribute="leading" id="tmr-e9-mAU"/>
                                        <constraint firstItem="ZYr-2N-4SK" firstAttribute="top" secondItem="0tY-gY-zvz" secondAttribute="bottom" constant="4" id="uke-Ix-HbN"/>
                                        <constraint firstItem="MTb-6D-D5K" firstAttribute="bottom" secondItem="HoN-kJ-6R4" secondAttribute="bottom" constant="-8" id="wkT-ub-eXw"/>
                                    </constraints>
                                </tableViewCellContentView>
                                <connections>
                                    <outlet property="category" destination="lIN-5o-URb" id="mGH-KO-Iyl"/>
                                    <outlet property="date" destination="MTb-6D-D5K" id="Bnx-uK-h5T"/>
                                    <outlet property="picture" destination="L05-sr-ilM" id="0Vq-FI-9f6"/>
                                    <outlet property="title" destination="0tY-gY-zvz" id="6dn-Pd-Vsk"/>
                                    <outlet property="viewToHighlight" destination="HoN-kJ-6R4" id="c6e-C1-xKA"/>
                                </connections>
                            </tableViewCell>
                        </prototypes>
                    </tableView>
                    <navigationItem key="navigationItem" title="RLDTableViewSwift" id="o3E-jY-00A"/>
                    <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
                    <size key="freeformSize" width="414" height="890"/>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="7B2-LV-31Y" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1223" y="326"/>
        </scene>
        <!--RLDWebViewController-->
        <scene sceneID="ZWB-jG-Egi">
            <objects>
                <viewController storyboardIdentifier="RLDWebViewController" id="iCO-A2-0sZ" userLabel="RLDWebViewController" customClass="RLDWebViewController" customModule="TableViewPrototype" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="5AO-cQ-aQP"/>
                        <viewControllerLayoutGuide type="bottom" id="RCV-Nf-Zau"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="FGT-6P-mBu" customClass="UIWebView">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                    </view>
                    <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
                    <size key="freeformSize" width="414" height="600"/>
                    <connections>
                        <outlet property="view" destination="FGT-6P-mBu" id="qEz-So-eOV"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="OBa-tC-sBZ" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1851" y="326"/>
        </scene>
        <!--Navigation Controller-->
        <scene sceneID="JeG-hF-Op9">
            <objects>
                <navigationController automaticallyAdjustsScrollViewInsets="NO" hidesBarsOnSwipe="YES" hidesBarsWhenVerticallyCompact="YES" id="Ncx-uH-Jsh" sceneMemberID="viewController">
                    <toolbarItems/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="PQC-QZ-zjp">
                        <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <nil name="viewControllers"/>
                    <toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="dsV-TP-fCC">
                        <autoresizingMask key="autoresizingMask"/>
                    </toolbar>
                    <connections>
                        <segue destination="9Ww-mV-ZtW" kind="relationship" relationship="rootViewController" id="2fw-sk-8B8"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="BTf-ZW-WC8" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="411" y="326"/>
        </scene>
    </scenes>
</document>


================================================
FILE: Sample app/TableViewPrototype/Resources/RLDTableViewHeaderView.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7531" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7520"/>
        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view contentMode="scaleToFill" id="43X-QC-Slb" userLabel="RLDTableViewHeaderView" customClass="RLDTableViewHeaderView" customModule="TableViewPrototype">
            <rect key="frame" x="0.0" y="0.0" width="414" height="60"/>
            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
            <subviews>
                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6yK-8V-tMD" userLabel="Content View">
                    <rect key="frame" x="0.0" y="0.0" width="414" height="60"/>
                    <subviews>
                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="In Picteris Luxum" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gMF-YT-BCB" userLabel="Title">
                            <rect key="frame" x="8" y="23" width="398" height="32"/>
                            <fontDescription key="fontDescription" type="system" weight="light" pointSize="26"/>
                            <nil key="highlightedColor"/>
                        </label>
                    </subviews>
                    <color key="backgroundColor" red="0.84313725490196079" green="0.84313725490196079" blue="0.84313725490196079" alpha="0.5" colorSpace="calibratedRGB"/>
                    <constraints>
                        <constraint firstItem="gMF-YT-BCB" firstAttribute="top" relation="lessThanOrEqual" secondItem="6yK-8V-tMD" secondAttribute="top" constant="26" id="4Nl-Qx-3t9"/>
                        <constraint firstItem="gMF-YT-BCB" firstAttribute="trailing" secondItem="6yK-8V-tMD" secondAttribute="trailingMargin" id="L8J-Bt-wxI"/>
                        <constraint firstAttribute="bottom" secondItem="gMF-YT-BCB" secondAttribute="bottom" constant="5" id="afn-5o-8Oz"/>
                        <constraint firstItem="gMF-YT-BCB" firstAttribute="leading" secondItem="6yK-8V-tMD" secondAttribute="leadingMargin" id="qPe-wJ-Qxd"/>
                    </constraints>
                </view>
            </subviews>
            <constraints>
                <constraint firstItem="6yK-8V-tMD" firstAttribute="top" secondItem="43X-QC-Slb" secondAttribute="top" id="LRR-gq-7JM"/>
                <constraint firstAttribute="trailing" secondItem="6yK-8V-tMD" secondAttribute="trailing" id="cpZ-Fg-hS3"/>
                <constraint firstAttribute="bottom" secondItem="6yK-8V-tMD" secondAttribute="bottom" id="sOR-aP-Y5p"/>
                <constraint firstItem="6yK-8V-tMD" firstAttribute="leading" secondItem="43X-QC-Slb" secondAttribute="leading" id="wRI-m9-jnF"/>
            </constraints>
            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
            <connections>
                <outlet property="text" destination="gMF-YT-BCB" id="14f-n1-X38"/>
            </connections>
            <point key="canvasLocation" x="418" y="363"/>
        </view>
    </objects>
</document>


================================================
FILE: Sample app/TableViewPrototype/Resources/viewModelData.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>cells</key>
		<array>
			<dict>
				<key>category</key>
				<string>Moscow</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157602083268883/</string>
				<key>class</key>
				<string>RLDBigPictureTableViewCellModel</string>
				<key>date</key>
				<string>2 years ago</string>
				<key>imageName</key>
				<string>6_big.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/1406925773/in/set-72157602083268883</string>
				<key>title</key>
				<string>The colorful Cathedral of Vasily the Blessed</string>
			</dict>
			<dict>
				<key>category</key>
				<string>Amsterdam</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157603544030165/</string>
				<key>class</key>
				<string>RLDSimpleTableViewCellModel</string>
				<key>date</key>
				<string>4 years ago</string>
				<key>imageName</key>
				<string>3_small.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/2135948414/in/set-72157603544030165</string>
				<key>title</key>
				<string>Quiet canals in the “Venice of the North”</string>
				<key>editable</key>
				<true/>
				<key>editingStyle</key>
				<integer>1</integer>
			</dict>
			<dict>
				<key>category</key>
				<string>London</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157594446615513/</string>
				<key>class</key>
				<string>RLDSimpleTableViewCellModel</string>
				<key>date</key>
				<string>Today</string>
				<key>imageName</key>
				<string>9_small.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/337540114/in/set-72157594446615513</string>
				<key>title</key>
				<string>Tower Bridge, one of the most iconic bridges in the world</string>
				<key>editable</key>
				<true/>
				<key>editingStyle</key>
				<integer>1</integer>
			</dict>
		</array>
	</dict>
	<dict>
		<key>cells</key>
		<array>
			<dict>
				<key>category</key>
				<string>Kuramathi</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157627990642402/</string>
				<key>class</key>
				<string>RLDBigPictureTableViewCellModel</string>
				<key>date</key>
				<string>3 weeks ago</string>
				<key>imageName</key>
				<string>4_big.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/6286531716/in/set-72157627990642402</string>
				<key>title</key>
				<string>Sea Salt&apos;s crab unwinding in the beach</string>
			</dict>
			<dict>
				<key>category</key>
				<string>Rasdhoo</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157627991759766/</string>
				<key>class</key>
				<string>RLDSimpleTableViewCellModel</string>
				<key>date</key>
				<string>Today</string>
				<key>imageName</key>
				<string>1_small.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/6286903694/in/set-72157627990642402</string>
				<key>title</key>
				<string>The Maldives, home of beautiful beaches</string>
				<key>editable</key>
				<true/>
				<key>movable</key>
				<true/>
			</dict>
			<dict>
				<key>category</key>
				<string>Swiss Alps</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157625889560426/</string>
				<key>class</key>
				<string>RLDSimpleTableViewCellModel</string>
				<key>date</key>
				<string>7 years ago</string>
				<key>imageName</key>
				<string>0_small.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/5384467483/in/set-72157625889560426</string>
				<key>title</key>
				<string>Picturesque peak covered with snow</string>
				<key>editable</key>
				<true/>
				<key>movable</key>
				<true/>
			</dict>
			<dict>
				<key>category</key>
				<string>Tenerife</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157594446322517/</string>
				<key>class</key>
				<string>RLDSimpleTableViewCellModel</string>
				<key>date</key>
				<string>Yesterday</string>
				<key>imageName</key>
				<string>8_small.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/3556768497/in/set-72157594446322517</string>
				<key>title</key>
				<string>Mount Teide, a 3,718 meter high vulcano</string>
				<key>editable</key>
				<true/>
				<key>movable</key>
				<true/>
			</dict>
		</array>
		<key>title</key>
		<string>Magnificent scenery</string>
	</dict>
	<dict>
		<key>cells</key>
		<array>
			<dict>
				<key>class</key>
				<string>RLDCommentTableViewCellModel</string>
				<key>comment</key>
				<string>This building is the seat of the National Assembly of Hungary, and one of the most awesome constructions in Budapest</string>
				<key>imageName</key>
				<string>7_big.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/336410485/in/set-72157594444731896</string>
				<key>title</key>
				<string>The Hungarian Parliament</string>
			</dict>
			<dict>
				<key>category</key>
				<string>Rome</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157594444449793/</string>
				<key>class</key>
				<string>RLDSimpleTableViewCellModel</string>
				<key>date</key>
				<string>3 weeks ago</string>
				<key>imageName</key>
				<string>5_small.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/188286231/in/set-72157594444449793</string>
				<key>title</key>
				<string>Coliseum, or Flavian Amphitheatre</string>
			</dict>
			<dict>
				<key>category</key>
				<string>Paris</string>
				<key>categoryURL</key>
				<string>https://www.flickr.com/photos/keoki/sets/72157594444442779/</string>
				<key>class</key>
				<string>RLDSimpleTableViewCellModel</string>
				<key>date</key>
				<string>1 month ago</string>
				<key>imageName</key>
				<string>2_small.jpg</string>
				<key>imageURL</key>
				<string>https://www.flickr.com/photos/keoki/188266460/in/set-72157594444442779</string>
				<key>title</key>
				<string>The Basilica of the Sacré-Cœur of Paris</string>
			</dict>
		</array>
		<key>title</key>
		<string>Singular buildings</string>
	</dict>
</array>
</plist>


================================================
FILE: Sample app/TableViewPrototype/View controllers/RLDMasterViewController.swift
================================================
import UIKit

class RLDMasterViewController: RLDTableViewController {
    
    let modelProvider = RLDTableViewModelProvider()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        registerNibs()
        registerEventHandlers()
        setTableViewModel()
        attachEditButton()
    }
    
    private func registerNibs() {
        for (reuseIdentifier, nibName) in modelProvider.headerFooterReuseIdentifiersToNibNames {
            let nib = UINib(nibName:reuseIdentifier, bundle:nil)
            tableView?.registerNib(nib, forHeaderFooterViewReuseIdentifier:nibName)
        }
    }
    
    private func registerEventHandlers() {
        RLDGenericTableViewCellEventHandler.register()
        RLDTableViewHeaderViewEventHandler.register()
    }
    
    private func setTableViewModel() {
        tableViewModel = modelProvider.tableViewModel
    }
    
    private func attachEditButton() {
        navigationItem.rightBarButtonItem = self.editButtonItem()
    }
    
    override func setEditing(editing:Bool, animated:Bool) {
        super.setEditing(editing, animated:animated)
        
        navigationController?.hidesBarsOnSwipe = !editing
        navigationController?.hidesBarsWhenVerticallyCompact = !editing
    }
    
    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}

================================================
FILE: Sample app/TableViewPrototype/View controllers/RLDWebViewController.swift
================================================
import UIKit

class RLDWebViewController: UIViewController {
    var url:String = "" {
        didSet {
            if let view = view as? UIWebView {
                let urlRequest = NSURLRequest(URL:NSURL(string:url)!)
                view.loadRequest(urlRequest)
            }
        }
    }
}

================================================
FILE: Sample app/TableViewPrototype/Views/RLDBigPictureTableViewCell.swift
================================================
class RLDBigPictureTableViewCell:RLDGenericTableViewCell {
}

================================================
FILE: Sample app/TableViewPrototype/Views/RLDCommentTableViewCell.swift
================================================
import UIKit

class RLDCommentTableViewCell:RLDGenericTableViewCell {
    @IBOutlet weak var comment:UITextView!
    
    override var model:RLDGenericTableViewCellModel? {
        didSet {
            if let model = model as? RLDCommentTableViewCellModel {
                comment.text = model.comment
            }
        }
    }
}

================================================
FILE: Sample app/TableViewPrototype/Views/RLDGenericTableViewCell.swift
================================================
import UIKit
import RLDTableViewSwift

class RLDGenericTableViewCell:UITableViewCell, RLDHandledViewProtocol {
    @IBOutlet weak var title:UILabel!
    @IBOutlet weak var date:UILabel?
    @IBOutlet weak var category:UIButton?
    @IBOutlet weak var picture:UIImageView!
    @IBOutlet weak var viewToHighlight:UIView!
    
    var eventHandler:RLDTableViewEventHandler? = nil
    
    var model:RLDGenericTableViewCellModel? {
        didSet {
            if let model = model {
                title.text = model.title
                picture.image = UIImage(named:model.imageName)
                if let date = date {
                    date.text = model.date
                }
                if let category = category {
                    category.setTitle(model.category, forState:UIControlState.Normal)
                }
            }
        }
    }
    
    @IBAction func categoryButtonTapped() {
        if let eventHandler = eventHandler as? RLDGenericTableViewCellEventHandler {
            eventHandler.didTapCategoryButton()
        }
    }
}

================================================
FILE: Sample app/TableViewPrototype/Views/RLDSimpleTableViewCell.swift
================================================
class RLDSimpleTableViewCell:RLDGenericTableViewCell {
}

================================================
FILE: Sample app/TableViewPrototype/Views/RLDTableViewHeaderView.swift
================================================
import UIKit
import RLDTableViewSwift

class RLDTableViewHeaderView:UITableViewHeaderFooterView, RLDHandledViewProtocol {
    @IBOutlet weak var text:UILabel!
    
    var eventHandler:RLDTableViewEventHandler? = nil
    
    var model:RLDTableViewHeaderViewModel? {
        didSet {
            text.text = model!.title
        }
    }
}

================================================
FILE: Sample app/TableViewPrototype.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		454E32001AF008BF00AB44BC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454E31FF1AF008BF00AB44BC /* AppDelegate.swift */; };
		457D00661AF0104E00AE3D52 /* RLDTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D00651AF0104E00AE3D52 /* RLDTableViewController.swift */; };
		457D7CF81AF009EA00388423 /* RLDMasterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D7CF71AF009EA00388423 /* RLDMasterViewController.swift */; };
		457D7CFF1AF009F300388423 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 457D7CFA1AF009F300388423 /* Images.xcassets */; };
		457D7D001AF009F300388423 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 457D7CFB1AF009F300388423 /* LaunchScreen.xib */; };
		457D7D011AF009F300388423 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 457D7CFC1AF009F300388423 /* Main.storyboard */; };
		457D7D021AF009F300388423 /* RLDTableViewHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 457D7CFD1AF009F300388423 /* RLDTableViewHeaderView.xib */; };
		457D7D031AF009F300388423 /* viewModelData.plist in Resources */ = {isa = PBXBuildFile; fileRef = 457D7CFE1AF009F300388423 /* viewModelData.plist */; };
		457D7D451AF00AB700388423 /* RLDTableViewSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 457D7D2E1AF00AB700388423 /* RLDTableViewSwift.framework */; };
		457D7D461AF00AB700388423 /* RLDTableViewSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 457D7D2E1AF00AB700388423 /* RLDTableViewSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		45886C1A1AF177860085F7A4 /* RLDWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45886C191AF177860085F7A4 /* RLDWebViewController.swift */; };
		4596815E1AF031F300EC4B52 /* RLDTableViewModelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4596815D1AF031F300EC4B52 /* RLDTableViewModelProvider.swift */; };
		459681601AF0321000EC4B52 /* RLDGenericTableViewCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4596815F1AF0321000EC4B52 /* RLDGenericTableViewCellModel.swift */; };
		459681621AF0324E00EC4B52 /* RLDSimpleTableViewCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 459681611AF0324E00EC4B52 /* RLDSimpleTableViewCellModel.swift */; };
		459681641AF0327000EC4B52 /* RLDBigPictureTableViewCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 459681631AF0327000EC4B52 /* RLDBigPictureTableViewCellModel.swift */; };
		459681661AF0328D00EC4B52 /* RLDCommentTableViewCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 459681651AF0328D00EC4B52 /* RLDCommentTableViewCellModel.swift */; };
		459681681AF032AE00EC4B52 /* RLDTableViewHeaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 459681671AF032AE00EC4B52 /* RLDTableViewHeaderViewModel.swift */; };
		45AC03931AF16D2900944DB7 /* RLDGenericTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AC03921AF16D2900944DB7 /* RLDGenericTableViewCell.swift */; };
		45AC03951AF170FD00944DB7 /* RLDSimpleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AC03941AF170FD00944DB7 /* RLDSimpleTableViewCell.swift */; };
		45AC03971AF1711D00944DB7 /* RLDBigPictureTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AC03961AF1711D00944DB7 /* RLDBigPictureTableViewCell.swift */; };
		45AC03991AF1713800944DB7 /* RLDCommentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AC03981AF1713800944DB7 /* RLDCommentTableViewCell.swift */; };
		45AC039B1AF1715700944DB7 /* RLDTableViewHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AC039A1AF1715700944DB7 /* RLDTableViewHeaderView.swift */; };
		45AC039D1AF172D900944DB7 /* RLDGenericTableViewCellEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AC039C1AF172D900944DB7 /* RLDGenericTableViewCellEventHandler.swift */; };
		45AC039F1AF1731E00944DB7 /* RLDTableViewHeaderViewEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AC039E1AF1731E00944DB7 /* RLDTableViewHeaderViewEventHandler.swift */; };
		45F6AEC11AF00DEB007F7AF5 /* RLDHandledViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F6AEBB1AF00DEB007F7AF5 /* RLDHandledViewProtocol.swift */; };
		45F6AEC21AF00DEB007F7AF5 /* RLDTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F6AEBC1AF00DEB007F7AF5 /* RLDTableViewDataSource.swift */; };
		45F6AEC31AF00DEB007F7AF5 /* RLDTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F6AEBD1AF00DEB007F7AF5 /* RLDTableViewDelegate.swift */; };
		45F6AEC41AF00DEB007F7AF5 /* RLDTableViewEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F6AEBE1AF00DEB007F7AF5 /* RLDTableViewEventHandler.swift */; };
		45F6AEC51AF00DEB007F7AF5 /* RLDTableViewEventHandlerProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F6AEBF1AF00DEB007F7AF5 /* RLDTableViewEventHandlerProvider.swift */; };
		45F6AEC61AF00DEB007F7AF5 /* RLDTableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F6AEC01AF00DEB007F7AF5 /* RLDTableViewModel.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		457D7D431AF00AB700388423 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 454E31F21AF008BF00AB44BC /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 457D7D2D1AF00AB700388423;
			remoteInfo = RLDTableViewSwift;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
		457D7D251AF00A2A00388423 /* Embed Frameworks */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "";
			dstSubfolderSpec = 10;
			files = (
				457D7D461AF00AB700388423 /* RLDTableViewSwift.framework in Embed Frameworks */,
			);
			name = "Embed Frameworks";
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		454E31FA1AF008BF00AB44BC /* TableViewPrototype.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TableViewPrototype.app; sourceTree = BUILT_PRODUCTS_DIR; };
		454E31FE1AF008BF00AB44BC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		454E31FF1AF008BF00AB44BC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		457D00651AF0104E00AE3D52 /* RLDTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewController.swift; sourceTree = "<group>"; };
		457D7CF71AF009EA00388423 /* RLDMasterViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDMasterViewController.swift; sourceTree = "<group>"; };
		457D7CFA1AF009F300388423 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
		457D7CFB1AF009F300388423 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = "<group>"; };
		457D7CFC1AF009F300388423 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
		457D7CFD1AF009F300388423 /* RLDTableViewHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RLDTableViewHeaderView.xib; sourceTree = "<group>"; };
		457D7CFE1AF009F300388423 /* viewModelData.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = viewModelData.plist; sourceTree = "<group>"; };
		457D7D2E1AF00AB700388423 /* RLDTableViewSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RLDTableViewSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		457D7D311AF00AB700388423 /* RLDTableViewSwift-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "RLDTableViewSwift-Info.plist"; path = "../Sample app/TableViewPrototype/RLDTableViewSwift-Info.plist"; sourceTree = "<group>"; };
		45886C191AF177860085F7A4 /* RLDWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDWebViewController.swift; sourceTree = "<group>"; };
		4596815D1AF031F300EC4B52 /* RLDTableViewModelProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewModelProvider.swift; sourceTree = "<group>"; };
		4596815F1AF0321000EC4B52 /* RLDGenericTableViewCellModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDGenericTableViewCellModel.swift; sourceTree = "<group>"; };
		459681611AF0324E00EC4B52 /* RLDSimpleTableViewCellModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDSimpleTableViewCellModel.swift; sourceTree = "<group>"; };
		459681631AF0327000EC4B52 /* RLDBigPictureTableViewCellModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDBigPictureTableViewCellModel.swift; sourceTree = "<group>"; };
		459681651AF0328D00EC4B52 /* RLDCommentTableViewCellModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDCommentTableViewCellModel.swift; sourceTree = "<group>"; };
		459681671AF032AE00EC4B52 /* RLDTableViewHeaderViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewHeaderViewModel.swift; sourceTree = "<group>"; };
		45AC03921AF16D2900944DB7 /* RLDGenericTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDGenericTableViewCell.swift; sourceTree = "<group>"; };
		45AC03941AF170FD00944DB7 /* RLDSimpleTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDSimpleTableViewCell.swift; sourceTree = "<group>"; };
		45AC03961AF1711D00944DB7 /* RLDBigPictureTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDBigPictureTableViewCell.swift; sourceTree = "<group>"; };
		45AC03981AF1713800944DB7 /* RLDCommentTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDCommentTableViewCell.swift; sourceTree = "<group>"; };
		45AC039A1AF1715700944DB7 /* RLDTableViewHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewHeaderView.swift; sourceTree = "<group>"; };
		45AC039C1AF172D900944DB7 /* RLDGenericTableViewCellEventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDGenericTableViewCellEventHandler.swift; sourceTree = "<group>"; };
		45AC039E1AF1731E00944DB7 /* RLDTableViewHeaderViewEventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewHeaderViewEventHandler.swift; sourceTree = "<group>"; };
		45F6AEBB1AF00DEB007F7AF5 /* RLDHandledViewProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDHandledViewProtocol.swift; sourceTree = "<group>"; };
		45F6AEBC1AF00DEB007F7AF5 /* RLDTableViewDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewDataSource.swift; sourceTree = "<group>"; };
		45F6AEBD1AF00DEB007F7AF5 /* RLDTableViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewDelegate.swift; sourceTree = "<group>"; };
		45F6AEBE1AF00DEB007F7AF5 /* RLDTableViewEventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewEventHandler.swift; sourceTree = "<group>"; };
		45F6AEBF1AF00DEB007F7AF5 /* RLDTableViewEventHandlerProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewEventHandlerProvider.swift; sourceTree = "<group>"; };
		45F6AEC01AF00DEB007F7AF5 /* RLDTableViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLDTableViewModel.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		454E31F71AF008BF00AB44BC /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				457D7D451AF00AB700388423 /* RLDTableViewSwift.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		457D7D2A1AF00AB700388423 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		454E31F11AF008BF00AB44BC = {
			isa = PBXGroup;
			children = (
				457D7D2F1AF00AB700388423 /* RLDTableViewSwift */,
				454E31FC1AF008BF00AB44BC /* TableViewPrototype */,
				454E31FB1AF008BF00AB44BC /* Products */,
			);
			sourceTree = "<group>";
		};
		454E31FB1AF008BF00AB44BC /* Products */ = {
			isa = PBXGroup;
			children = (
				454E31FA1AF008BF00AB44BC /* TableViewPrototype.app */,
				457D7D2E1AF00AB700388423 /* RLDTableViewSwift.framework */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		454E31FC1AF008BF00AB44BC /* TableViewPrototype */ = {
			isa = PBXGroup;
			children = (
				457D7CF31AF009D200388423 /* Models */,
				457D7CF41AF009D700388423 /* Views */,
				457D7CF51AF009DD00388423 /* Event handlers */,
				457D7CF61AF009EA00388423 /* View controllers */,
				457D7CF91AF009F300388423 /* Resources */,
				454E31FD1AF008BF00AB44BC /* Supporting Files */,
			);
			path = TableViewPrototype;
			sourceTree = "<group>";
		};
		454E31FD1AF008BF00AB44BC /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				454E31FF1AF008BF00AB44BC /* AppDelegate.swift */,
				454E31FE1AF008BF00AB44BC /* Info.plist */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		457D7CF31AF009D200388423 /* Models */ = {
			isa = PBXGroup;
			children = (
				4596815D1AF031F300EC4B52 /* RLDTableViewModelProvider.swift */,
				4596815F1AF0321000EC4B52 /* RLDGenericTableViewCellModel.swift */,
				459681611AF0324E00EC4B52 /* RLDSimpleTableViewCellModel.swift */,
				459681631AF0327000EC4B52 /* RLDBigPictureTableViewCellModel.swift */,
				459681651AF0328D00EC4B52 /* RLDCommentTableViewCellModel.swift */,
				459681671AF032AE00EC4B52 /* RLDTableViewHeaderViewModel.swift */,
			);
			path = Models;
			sourceTree = "<group>";
		};
		457D7CF41AF009D700388423 /* Views */ = {
			isa = PBXGroup;
			children = (
				45AC03921AF16D2900944DB7 /* RLDGenericTableViewCell.swift */,
				45AC03941AF170FD00944DB7 /* RLDSimpleTableViewCell.swift */,
				45AC03961AF1711D00944DB7 /* RLDBigPictureTableViewCell.swift */,
				45AC03981AF1713800944DB7 /* RLDCommentTableViewCell.swift */,
				45AC039A1AF1715700944DB7 /* RLDTableViewHeaderView.swift */,
			);
			path = Views;
			sourceTree = "<group>";
		};
		457D7CF51AF009DD00388423 /* Event handlers */ = {
			isa = PBXGroup;
			children = (
				45AC039C1AF172D900944DB7 /* RLDGenericTableViewCellEventHandler.swift */,
				45AC039E1AF1731E00944DB7 /* RLDTableViewHeaderViewEventHandler.swift */,
			);
			name = "Event handlers";
			path = "TableViewPrototype/Event handlers";
			sourceTree = SOURCE_ROOT;
		};
		457D7CF61AF009EA00388423 /* View controllers */ = {
			isa = PBXGroup;
			children = (
				457D7CF71AF009EA00388423 /* RLDMasterViewController.swift */,
				45886C191AF177860085F7A4 /* RLDWebViewController.swift */,
			);
			path = "View controllers";
			sourceTree = "<group>";
		};
		457D7CF91AF009F300388423 /* Resources */ = {
			isa = PBXGroup;
			children = (
				457D7CFA1AF009F300388423 /* Images.xcassets */,
				457D7CFB1AF009F300388423 /* LaunchScreen.xib */,
				457D7CFC1AF009F300388423 /* Main.storyboard */,
				457D7CFD1AF009F300388423 /* RLDTableViewHeaderView.xib */,
				457D7CFE1AF009F300388423 /* viewModelData.plist */,
			);
			path = Resources;
			sourceTree = "<group>";
		};
		457D7D2F1AF00AB700388423 /* RLDTableViewSwift */ = {
			isa = PBXGroup;
			children = (
				45F6AEC01AF00DEB007F7AF5 /* RLDTableViewModel.swift */,
				45F6AEBC1AF00DEB007F7AF5 /* RLDTableViewDataSource.swift */,
				45F6AEBD1AF00DEB007F7AF5 /* RLDTableViewDelegate.swift */,
				45F6AEBE1AF00DEB007F7AF5 /* RLDTableViewEventHandler.swift */,
				45F6AEBF1AF00DEB007F7AF5 /* RLDTableViewEventHandlerProvider.swift */,
				45F6AEBB1AF00DEB007F7AF5 /* RLDHandledViewProtocol.swift */,
				457D00651AF0104E00AE3D52 /* RLDTableViewController.swift */,
				457D7D301AF00AB700388423 /* Supporting Files */,
			);
			name = RLDTableViewSwift;
			path = ../Classes;
			sourceTree = "<group>";
		};
		457D7D301AF00AB700388423 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				457D7D311AF00AB700388423 /* RLDTableViewSwift-Info.plist */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
		457D7D2B1AF00AB700388423 /* Headers */ = {
			isa = PBXHeadersBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXHeadersBuildPhase section */

/* Begin PBXNativeTarget section */
		454E31F91AF008BF00AB44BC /* TableViewPrototype */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 454E32191AF008BF00AB44BC /* Build configuration list for PBXNativeTarget "TableViewPrototype" */;
			buildPhases = (
				454E31F61AF008BF00AB44BC /* Sources */,
				454E31F71AF008BF00AB44BC /* Frameworks */,
				454E31F81AF008BF00AB44BC /* Resources */,
				457D7D251AF00A2A00388423 /* Embed Frameworks */,
			);
			buildRules = (
			);
			dependencies = (
				457D7D441AF00AB700388423 /* PBXTargetDependency */,
			);
			name = TableViewPrototype;
			productName = TableViewPrototype;
			productReference = 454E31FA1AF008BF00AB44BC /* TableViewPrototype.app */;
			productType = "com.apple.product-type.application";
		};
		457D7D2D1AF00AB700388423 /* RLDTableViewSwift */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 457D7D471AF00AB700388423 /* Build configuration list for PBXNativeTarget "RLDTableViewSwift" */;
			buildPhases = (
				457D7D291AF00AB700388423 /* Sources */,
				457D7D2A1AF00AB700388423 /* Frameworks */,
				457D7D2B1AF00AB700388423 /* Headers */,
				457D7D2C1AF00AB700388423 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = RLDTableViewSwift;
			productName = RLDTableViewSwift;
			productReference = 457D7D2E1AF00AB700388423 /* RLDTableViewSwift.framework */;
			productType = "com.apple.product-type.framework";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		454E31F21AF008BF00AB44BC /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastSwiftMigration = 0730;
				LastSwiftUpdateCheck = 0730;
				LastUpgradeCheck = 0730;
				ORGANIZATIONNAME = "Rafael Lopez Diez";
				TargetAttributes = {
					454E31F91AF008BF00AB44BC = {
						CreatedOnToolsVersion = 6.3;
					};
					457D7D2D1AF00AB700388423 = {
						CreatedOnToolsVersion = 6.3;
					};
				};
			};
			buildConfigurationList = 454E31F51AF008BF00AB44BC /* Build configuration list for PBXProject "TableViewPrototype" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
			);
			mainGroup = 454E31F11AF008BF00AB44BC;
			productRefGroup = 454E31FB1AF008BF00AB44BC /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				454E31F91AF008BF00AB44BC /* TableViewPrototype */,
				457D7D2D1AF00AB700388423 /* RLDTableViewSwift */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		454E31F81AF008BF00AB44BC /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				457D7D021AF009F300388423 /* RLDTableViewHeaderView.xib in Resources */,
				457D7D011AF009F300388423 /* Main.storyboard in Resources */,
				457D7D031AF009F300388423 /* viewModelData.plist in Resources */,
				457D7D001AF009F300388423 /* LaunchScreen.xib in Resources */,
				457D7CFF1AF009F300388423 /* Images.xcassets in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		457D7D2C1AF00AB700388423 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		454E31F61AF008BF00AB44BC /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				45AC039B1AF1715700944DB7 /* RLDTableViewHeaderView.swift in Sources */,
				459681641AF0327000EC4B52 /* RLDBigPictureTableViewCellModel.swift in Sources */,
				45AC039D1AF172D900944DB7 /* RLDGenericTableViewCellEventHandler.swift in Sources */,
				45AC03991AF1713800944DB7 /* RLDCommentTableViewCell.swift in Sources */,
				459681621AF0324E00EC4B52 /* RLDSimpleTableViewCellModel.swift in Sources */,
				45AC03931AF16D2900944DB7 /* RLDGenericTableViewCell.swift in Sources */,
				457D00661AF0104E00AE3D52 /* RLDTableViewController.swift in Sources */,
				457D7CF81AF009EA00388423 /* RLDMasterViewController.swift in Sources */,
				45AC03951AF170FD00944DB7 /* RLDSimpleTableViewCell.swift in Sources */,
				459681601AF0321000EC4B52 /* RLDGenericTableViewCellModel.swift in Sources */,
				45886C1A1AF177860085F7A4 /* RLDWebViewController.swift in Sources */,
				459681681AF032AE00EC4B52 /* RLDTableViewHeaderViewModel.swift in Sources */,
				45AC03971AF1711D00944DB7 /* RLDBigPictureTableViewCell.swift in Sources */,
				45AC039F1AF1731E00944DB7 /* RLDTableViewHeaderViewEventHandler.swift in Sources */,
				454E32001AF008BF00AB44BC /* AppDelegate.swift in Sources */,
				459681661AF0328D00EC4B52 /* RLDCommentTableViewCellModel.swift in Sources */,
				4596815E1AF031F300EC4B52 /* RLDTableViewModelProvider.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		457D7D291AF00AB700388423 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				45F6AEC11AF00DEB007F7AF5 /* RLDHandledViewProtocol.swift in Sources */,
				45F6AEC21AF00DEB007F7AF5 /* RLDTableViewDataSource.swift in Sources */,
				45F6AEC61AF00DEB007F7AF5 /* RLDTableViewModel.swift in Sources */,
				45F6AEC51AF00DEB007F7AF5 /* RLDTableViewEventHandlerProvider.swift in Sources */,
				45F6AEC41AF00DEB007F7AF5 /* RLDTableViewEventHandler.swift in Sources */,
				45F6AEC31AF00DEB007F7AF5 /* RLDTableViewDelegate.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		457D7D441AF00AB700388423 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 457D7D2D1AF00AB700388423 /* RLDTableViewSwift */;
			targetProxy = 457D7D431AF00AB700388423 /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
		454E32171AF008BF00AB44BC /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.1;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
			};
			name = Debug;
		};
		454E32181AF008BF00AB44BC /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.1;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		454E321A1AF008BF00AB44BC /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				INFOPLIST_FILE = TableViewPrototype/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.1;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = "com.rld.TableViewPrototype.$(PRODUCT_NAME:rfc1034identifier)";
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		454E321B1AF008BF00AB44BC /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				INFOPLIST_FILE = TableViewPrototype/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.1;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = "com.rld.TableViewPrototype.$(PRODUCT_NAME:rfc1034identifier)";
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
		457D7D481AF00AB700388423 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = 1;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				INFOPLIST_FILE = "$(SRCROOT)/TableViewPrototype/RLDTableViewSwift-Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				IPHONEOS_DEPLOYMENT_TARGET = 8.1;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.rld.RLDTableViewSwift;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SKIP_INSTALL = YES;
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
				TARGETED_DEVICE_FAMILY = "1,2";
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Debug;
		};
		457D7D491AF00AB700388423 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = 1;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				INFOPLIST_FILE = "$(SRCROOT)/TableViewPrototype/RLDTableViewSwift-Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				IPHONEOS_DEPLOYMENT_TARGET = 8.1;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.rld.RLDTableViewSwift;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SKIP_INSTALL = YES;
				TARGETED_DEVICE_FAMILY = "1,2";
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		454E31F51AF008BF00AB44BC /* Build configuration list for PBXProject "TableViewPrototype" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				454E32171AF008BF00AB44BC /* Debug */,
				454E32181AF008BF00AB44BC /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		454E32191AF008BF00AB44BC /* Build configuration list for PBXNativeTarget "TableViewPrototype" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				454E321A1AF008BF00AB44BC /* Debug */,
				454E321B1AF008BF00AB44BC /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		457D7D471AF00AB700388423 /* Build configuration list for PBXNativeTarget "RLDTableViewSwift" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				457D7D481AF00AB700388423 /* Debug */,
				457D7D491AF00AB700388423 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 454E31F21AF008BF00AB44BC /* Project object */;
}


================================================
FILE: Sample app/TableViewPrototype.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:TableViewPrototype.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: Sample app/TableViewPrototype.xcodeproj/project.xcworkspace/xcshareddata/TableViewPrototype.xccheckout
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDESourceControlProjectFavoriteDictionaryKey</key>
	<false/>
	<key>IDESourceControlProjectIdentifier</key>
	<string>4E446F4C-7F72-491A-AB8F-295366F8824F</string>
	<key>IDESourceControlProjectName</key>
	<string>TableViewPrototype</string>
	<key>IDESourceControlProjectOriginsDictionary</key>
	<dict>
		<key>B6CC70124526FB1C79E8927A505A5CB9A7F81823</key>
		<string>https://github.com/rlopezdiez/RLDNavigationSwift.git</string>
	</dict>
	<key>IDESourceControlProjectPath</key>
	<string>Sample app/TableViewPrototype.xcodeproj</string>
	<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
	<dict>
		<key>B6CC70124526FB1C79E8927A505A5CB9A7F81823</key>
		<string>../../..</string>
	</dict>
	<key>IDESourceControlProjectURL</key>
	<string>https://github.com/rlopezdiez/RLDNavigationSwift.git</string>
	<key>IDESourceControlProjectVersion</key>
	<integer>111</integer>
	<key>IDESourceControlProjectWCCIdentifier</key>
	<string>B6CC70124526FB1C79E8927A505A5CB9A7F81823</string>
	<key>IDESourceControlProjectWCConfigurations</key>
	<array>
		<dict>
			<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
			<string>public.vcs.git</string>
			<key>IDESourceControlWCCIdentifierKey</key>
			<string>B6CC70124526FB1C79E8927A505A5CB9A7F81823</string>
			<key>IDESourceControlWCCName</key>
			<string>RLDTableViewSwift</string>
		</dict>
	</array>
</dict>
</plist>


================================================
FILE: Sample app/TableViewPrototype.xcodeproj/xcuserdata/rhocassiopeiae.xcuserdatad/xcschemes/RLDTableViewSwift.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0730"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "457D7D2D1AF00AB700388423"
               BuildableName = "RLDTableViewSwift.framework"
               BlueprintName = "RLDTableViewSwift"
               ReferencedContainer = "container:TableViewPrototype.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "457D7D2D1AF00AB700388423"
            BuildableName = "RLDTableViewSwift.framework"
            BlueprintName = "RLDTableViewSwift"
            ReferencedContainer = "container:TableViewPrototype.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "457D7D2D1AF00AB700388423"
            BuildableName = "RLDTableViewSwift.framework"
            BlueprintName = "RLDTableViewSwift"
            ReferencedContainer = "container:TableViewPrototype.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: Sample app/TableViewPrototype.xcodeproj/xcuserdata/rhocassiopeiae.xcuserdatad/xcschemes/TableViewPrototype.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0730"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "454E31F91AF008BF00AB44BC"
               BuildableName = "TableViewPrototype.app"
               BlueprintName = "TableViewPrototype"
               ReferencedContainer = "container:TableViewPrototype.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "454E31F91AF008BF00AB44BC"
            BuildableName = "TableViewPrototype.app"
            BlueprintName = "TableViewPrototype"
            ReferencedContainer = "container:TableViewPrototype.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "454E31F91AF008BF00AB44BC"
            BuildableName = "TableViewPrototype.app"
            BlueprintName = "TableViewPrototype"
            ReferencedContainer = "container:TableViewPrototype.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "454E31F91AF008BF00AB44BC"
            BuildableName = "TableViewPrototype.app"
            BlueprintName = "TableViewPrototype"
            ReferencedContainer = "container:TableViewPrototype.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: Sample app/TableViewPrototype.xcodeproj/xcuserdata/rhocassiopeiae.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SchemeUserState</key>
	<dict>
		<key>RLDTableViewSwift.xcscheme</key>
		<dict>
			<key>orderHint</key>
			<integer>1</integer>
		</dict>
		<key>TableViewPrototype.xcscheme</key>
		<dict>
			<key>orderHint</key>
			<integer>0</integer>
		</dict>
	</dict>
	<key>SuppressBuildableAutocreation</key>
	<dict>
		<key>454E31F91AF008BF00AB44BC</key>
		<dict>
			<key>primary</key>
			<true/>
		</dict>
		<key>457D7D2D1AF00AB700388423</key>
		<dict>
			<key>primary</key>
			<true/>
		</dict>
	</dict>
</dict>
</plist>


================================================
FILE: Tests/Tests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>com.rld.RLDTableViewSwift</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>BNDL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
</dict>
</plist>


================================================
FILE: Tests/Tests/RLDTableViewDataSourceTests.swift
================================================
import XCTest
import UIKit

class RLDTableViewDataSourceTests:XCTestCase {
    // SUT
    let dataModel = RLDTableViewModel()
    
    // Collaborators
    lazy var dataSource:RLDTableViewDataSource = {
        return RLDTableViewDataSource(tableViewModel:self.dataModel)
        }()
    var tableView = UITableView()
    
    // MARK: Sections test cases
    func testAutomaticSectionCreation() {
        // GIVEN:
        //   A cell model
        let cellModel = RLDTableViewCellModel()
        
        // WHEN:
        //   We add the cell model to the table view model
        dataModel.add(cellModel:cellModel)
        
        // THEN:
        //   A section is automatically created in the data model
        //   The data source should return one row for the first section
        XCTAssertEqual(count(dataModel.sectionModels), 1)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 1)
    }
    
    func testAutomaticSectionConfiguration() {
        // GIVEN:
        //   A cell model
        let cellModel = RLDTableViewCellModel()
        
        // WHEN:
        //   We add the cell model to the table view model
        //   We set up the last section in the model
        //     setting up its index title
        //     setting up its header
        //     setting up its footer
        dataModel.add(cellModel:cellModel)
        
        let sectionModel = dataModel.sectionModels.last!
        sectionModel.indexTitle = "~"
        let header = RLDTableViewSectionAccessoryViewModel()
        header.title = "Header"
        sectionModel.header = header
        let footer = RLDTableViewSectionAccessoryViewModel()
        footer.title = "Footer"
        sectionModel.footer = footer
        
        // THEN:
        //   The data source should return one section
        //   The data source should return one row for the first section
        //   The first section header title must be equal to the title of the header
        //   The first section footer title must be equal to the title of the footer
        XCTAssertEqual(dataSource.numberOfSectionsInTableView(tableView), 1)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 1)
        XCTAssertEqual(dataSource.tableView(tableView, titleForHeaderInSection:0)!, header.title!)
        XCTAssertEqual(dataSource.tableView(tableView, titleForFooterInSection:0)!, footer.title!)
    }
    
    func testManualSectionAdding() {
        // GIVEN:
        //   A cell model
        //   A section created manually
        //     with its index title set up
        //     with its header set up
        //     with its footer set up
        let cellModel = RLDTableViewCellModel()
        
        let sectionModel = RLDTableViewSectionModel()
        sectionModel.indexTitle = "~"
        let header = RLDTableViewSectionAccessoryViewModel()
        header.title = "Header"
        sectionModel.header = header
        let footer = RLDTableViewSectionAccessoryViewModel()
        footer.title = "Footer"
        sectionModel.footer = footer
        
        // WHEN:
        //   We add the cell model to the table view model
        //     specifying it should be added to the manually created section
        dataModel.add(cellModel:cellModel, toSectionModel:sectionModel)
        
        // THEN:
        //   The data source should return one section
        //   The data source should return one row for the first section
        //   The first section header title must be equal to the title of the header
        //   The first section footer title must be equal to the title of the footer
        //   The fist section in the model must be equal to the manually created section
        XCTAssertEqual(dataSource.numberOfSectionsInTableView(tableView), 1)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 1)
        XCTAssertEqual(dataSource.tableView(tableView, titleForHeaderInSection:0)!, header.title!)
        XCTAssertEqual(dataSource.tableView(tableView, titleForFooterInSection:0)!, footer.title!)
        XCTAssertEqual(dataModel.sectionModels[0], sectionModel)
    }
    
    func testManualSectionAddingAfterAutomaticSectionAdded() {
        // GIVEN:
        //   A cell model
        //   A section created manually
        let cellModel = RLDTableViewCellModel()
        
        let sectionModel = RLDTableViewSectionModel()
        
        // WHEN:
        //   We add the cell model to the table view model twice
        //   We add the cell model to the table view model three times
        //     specifying it should be added to the manually created section
        repeat(2, closure:{
            self.dataModel.add(cellModel:cellModel)
        })
        repeat(3, closure:{
            self.dataModel.add(cellModel:cellModel, toSectionModel:sectionModel)
        })
        
        // THEN:
        //   The data source should return two sections
        //   The data source should return two rows for the first section
        //   The data source should return three rows for the second section
        //   The second section in the model must be equal to the manually created section
        XCTAssertEqual(dataSource.numberOfSectionsInTableView(tableView), 2)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 2)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:1), 3)
        XCTAssertEqual(dataModel.sectionModels[1], sectionModel)
    }
    
    func testMultipleManualSectionAdding() {
        // GIVEN:
        //   A cell model
        //   Two sections created manually
        let cellModel = RLDTableViewCellModel()
        
        let firstSectionModel = RLDTableViewSectionModel()
        let secondSectionModel = RLDTableViewSectionModel()
        
        // WHEN:
        //   We add the cell model to the table view model three times
        //     specifying it should be added to the first manually created section
        //   We add the cell model to the table view model three times
        //     specifying it should be added to the second manually created section
        repeat(2, closure:{
            self.dataModel.add(cellModel:cellModel, toSectionModel:firstSectionModel)
        })
        repeat(3, closure:{
            self.dataModel.add(cellModel:cellModel, toSectionModel:secondSectionModel)
        })
        
        // THEN:
        //   The data source should return two sections
        //   The data source should return two rows for the first section
        //   The data source should return three rows for the second section
        //   The first section in the model must be equal to the first manually created section
        //   The second section in the model must be equal to the second manually created section
        XCTAssertEqual(dataSource.numberOfSectionsInTableView(tableView), 2)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 2)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:1), 3)
        XCTAssertEqual(dataModel.sectionModels[0], firstSectionModel)
        XCTAssertEqual(dataModel.sectionModels[1], secondSectionModel)
    }
    
    // MARK: Section index titles test cases
    func testAutomaticSectionIndexTitles() {
        // GIVEN:
        //   A cell model
        //   Two sections created manually
        //     with its indexes titles set up
        let cellModel = RLDTableViewCellModel()
        
        let firstSectionModel = RLDTableViewSectionModel()
        firstSectionModel.indexTitle = "1"
        let secondSectionModel = RLDTableViewSectionModel()
        secondSectionModel.indexTitle = "2"
        
        // WHEN:
        //   We add the cell model to the table view model
        //     specifying it should be added to the first manually created section
        //   We add the cell model to the table view
        //     specifying it should be added to the second manually created section
        dataModel.add(cellModel:cellModel, toSectionModel:firstSectionModel)
        dataModel.add(cellModel:cellModel, toSectionModel:secondSectionModel)
        
        // THEN:
        //   The data source should return and array with two section index titles
        //   The first one must be equal to the section index title of the first manually created section
        //   The second one must be equal to the section index title of the second manually created section
        let sectionIndexTitles = dataSource.sectionIndexTitlesForTableView(tableView) as! [String]
        XCTAssertEqual(count(sectionIndexTitles), 2)
        XCTAssertEqual(sectionIndexTitles[0], firstSectionModel.indexTitle!)
        XCTAssertEqual(sectionIndexTitles[1], secondSectionModel.indexTitle!)
    }
    
    func testManualSectionIndexTitles() {
        // GIVEN:
        //   A data model
        //     with its section index titles set to numbers from 1 to 4
        //   A cell model
        //   Two sections created manually
        //     with its indexes titles set up to 1 and 2
        dataModel.sectionIndexTitles = ["1", "2", "3", "4"]
        let cellModel = RLDTableViewCellModel()
        
        let firstSectionModel = RLDTableViewSectionModel()
        firstSectionModel.indexTitle = "1"
        let secondSectionModel = RLDTableViewSectionModel()
        secondSectionModel.indexTitle = "2"
        
        // WHEN:
        //   We add the cell model to the table view model
        //     specifying it should be added to the first manually created section
        //   We add the cell model to the table view
        //     specifying it should be added to the second manually created section
        dataModel.add(cellModel:cellModel, toSectionModel:firstSectionModel)
        dataModel.add(cellModel:cellModel, toSectionModel:secondSectionModel)
        
        // THEN:
        //   The data source should return and array equal to the previously set up index title array of the data model
        let sectionIndexTitles = dataSource.sectionIndexTitlesForTableView(tableView) as! [String]
        XCTAssertEqual(sectionIndexTitles, dataModel.sectionIndexTitles!)
    }
    
    func testSectionIndexTitlesToSectionsRelationship() {
        // GIVEN:
        //   An data model
        //     with its section index titles set to numbers from 1 to 4
        //   A cell model
        //   Two sections created manually
        //     with its indexes titles set up to 1 and 4
        dataModel.sectionIndexTitles = ["1", "2", "3", "4"]
        let cellModel = RLDTableViewCellModel()
        
        let firstSectionModel = RLDTableViewSectionModel()
        firstSectionModel.indexTitle = "1"
        let secondSectionModel = RLDTableViewSectionModel()
        secondSectionModel.indexTitle = "4"
        
        // WHEN:
        //   We add the cell model to the table view model
        //     specifying it should be added to the first manually created section
        //   We add the cell model to the table view
        //     specifying it should be added to the second manually created section
        dataModel.add(cellModel:cellModel, toSectionModel:firstSectionModel)
        dataModel.add(cellModel:cellModel, toSectionModel:secondSectionModel)
        
        // THEN:
        //   The data source should return the second section when asked to provide an index for the fourth element of the section index titles array
        XCTAssertEqual(dataSource.tableView(tableView,sectionForSectionIndexTitle:"4", atIndex:3), 1)
    }
    
    // MARK: Data source edition test cases
    func testCellModelEditionPreferences() {
        // GIVEN:
        //   A table view data source
        //   A data model containing two cell models
        //     the first one being non editable
        //     the first one being editable
        let firstCellModel = RLDTableViewCellModel()
        firstCellModel.editable = true
        let secondCellModel = RLDTableViewCellModel()
        secondCellModel.editable = false
        dataModel.add(cellModel:firstCellModel)
        dataModel.add(cellModel:secondCellModel)
        
        // THEN:
        //   The data source should identify the first cell in the first section as editable
        //   The data source should identify the second cell in the first section as non editable
        XCTAssertEqual(dataSource.tableView(tableView, canEditRowAtIndexPath:NSIndexPath(forRow:0, inSection:0)), true)
        XCTAssertEqual(dataSource.tableView(tableView, canEditRowAtIndexPath:NSIndexPath(forRow:1, inSection:0)), false)
    }
    
    func testCellModelReorderingPreferences() {
        // GIVEN:
        //   A table view data source
        //   A data model containing two cell models
        //     the first one being non movable
        //     the first one being movable
        let firstCellModel = RLDTableViewCellModel()
        firstCellModel.movable = true
        let secondCellModel = RLDTableViewCellModel()
        secondCellModel.movable = false
        dataModel.add(cellModel:firstCellModel)
        dataModel.add(cellModel:secondCellModel)
        
        // THEN:
        //   The data source should identify the first cell in the first section as movable
        //   The data source should identify the second cell in the first section as non movable
        XCTAssertEqual(dataSource.tableView(tableView, canMoveRowAtIndexPath:NSIndexPath(forRow:0, inSection:0)), true)
        XCTAssertEqual(dataSource.tableView(tableView, canMoveRowAtIndexPath:NSIndexPath(forRow:1, inSection:0)), false)
    }
    
    func testCellModelInsertion() {
        // GIVEN:
        //   A table view data source
        //   A data model containing two cell models
        let sectionModel = RLDTableViewSectionModel()
        
        let expectedClassForInsertedCellModel = "Tests.RLDFirstTestCellModel"
        sectionModel.defaultCellModelClassForInsertions = expectedClassForInsertedCellModel
        
        var testCellModels:[RLDTableViewCellModel] = []
        repeat(2, closure:{
        let testCellModel = RLDSecondTestCellModel()
            testCellModels.append(testCellModel)
            self.dataModel.add(cellModel:testCellModel, toSectionModel:sectionModel)
        })
        
        // WHEN:
        //   We ask the data source to insert a new cell at the second row in the first section
        dataSource.tableView(tableView,
        commitEditingStyle:UITableViewCellEditingStyle.Insert,
        forRowAtIndexPath:NSIndexPath(forRow:1, inSection:0))
        
        // THEN:
        //   The data source must return three rows for the first section
        //   The section model must contain three cell models
        //   The second cell model must have the expected class
        //   The first cell model must be the first one added
        //   The third cell model must be the second one added
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 3)
        XCTAssertEqual(count(sectionModel.cellModels), 3)
        XCTAssertEqual(NSStringFromClass(sectionModel.cellModels[1].dynamicType), expectedClassForInsertedCellModel)
        XCTAssertTrue(sectionModel.cellModels[0] === testCellModels[0])
        XCTAssertTrue(sectionModel.cellModels[2] === testCellModels[1])
    }
    
    func testCellModelDeletion() {
        // GIVEN:
        //   A table view data source
        //     with a cell provider
        //   A data model
        //     with a section with a default cell model class for insertions
        //     containing three cell models
        var testCellModels:[RLDTableViewCellModel] = []
        repeat(3, closure:{
            let cellModel = RLDTableViewCellModel()
            testCellModels.append(cellModel)
            self.dataModel.add(cellModel:cellModel)
        })
        let sectionModel = dataModel.sectionModels.last!
        
        // WHEN:
        //   We ask the data source to delete the second row in the first section
        dataSource.tableView(tableView,
            commitEditingStyle:UITableViewCellEditingStyle.Delete,
            forRowAtIndexPath:NSIndexPath(forRow:1, inSection:0))
        
        // THEN:
        //   The data source should return two rows for the first section
        //   The section model must contain two cell models
        //   The first cell model must be the first one added
        //   The second cell model must be the third one added
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 2)
        XCTAssertEqual(count(sectionModel.cellModels), 2)
        XCTAssertTrue(sectionModel.cellModels[0] === testCellModels[0])
        XCTAssertTrue(sectionModel.cellModels[1] === testCellModels[2])
    }
    
    func testCellModelReordering() {
        // GIVEN:
        //   A table view data source
        //     with a cell provider
        //   A data model
        //     with a first section with a cell model
        //     with a second section with a cell model
        var testCellModels:[RLDTableViewCellModel] = []
        repeat(2, closure:{
            let cellModel = RLDTableViewCellModel()
            testCellModels.append(cellModel)
            self.dataModel.add(cellModel:cellModel, toSectionModel:RLDTableViewSectionModel())
        })
        let firstSectionModel = dataModel.sectionModels[0]
        let secondSectionModel = dataModel.sectionModels[1]
        
        // WHEN:
        //   We ask the data source to move the first row of the first section to the second row of the second section
        dataSource.tableView(tableView,
            moveRowAtIndexPath:NSIndexPath(forRow:0, inSection:0),
            toIndexPath:NSIndexPath(forRow:1, inSection:1))
        
        // THEN:
        //   The data source should return zero rows for the first section
        //   The data source should return two rows for the second section
        //   The data model must contain zero cell models in its first section
        //   The data model must contain two cell models in its second section
        //   The first cell model in the second section must be the second one added
        //   The second cell model in the second section must be the first one added
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:0), 0)
        XCTAssertEqual(dataSource.tableView(tableView, numberOfRowsInSection:1), 2)
        XCTAssertEqual(count(firstSectionModel.cellModels), 0)
        XCTAssertEqual(count(secondSectionModel.cellModels), 2)
        XCTAssertTrue(secondSectionModel.cellModels[0] === testCellModels[1])
        XCTAssertTrue(secondSectionModel.cellModels[1] === testCellModels[0])
    }
    
    // MARK: Test cell generation test cases
    func testCellGeneration() {
        // GIVEN:
        //   A table view
        //   A table view data source
        //     assigned to the table view
        //   A data model
        //   A cell model
        //     added to the data model
        //   A UITableViewCell subclass
        //     registered with the table view for the cell model reuse identifier
        tableView.dataSource = dataSource
        
        let cellModel = RLDTableViewCellModel()
        dataModel.add(cellModel:cellModel)
        
        let expectedCellClass = "Tests.RLDTestTableViewCell"
        tableView.registerClass(NSClassFromString(expectedCellClass), forCellReuseIdentifier:cellModel.reuseIdentifier)
        
        // WHEN:
        //  We ask the data source for a cell in the first row of the first section of the table
        let returnedCell = dataSource.tableView(tableView, cellForRowAtIndexPath:NSIndexPath(forRow:0, inSection:0))
        
        // THEN:
        //  The returned cell class must match the registered UITableViewCell subclass
        XCTAssertEqual(NSStringFromClass(returnedCell.dynamicType), expectedCellClass)
    }

    // MARK: Helper functions
    private func repeat(times:UInt, closure:(Void->Void)) {
        for var counter:UInt = 0; counter < times; counter++ {
            closure()
        }
    }
}

================================================
FILE: Tests/Tests/RLDTableViewDelegateTests.swift
================================================
import UIKit
import XCTest

class RLDTableViewDelegateTests: XCTestCase {
    
    // SUT
    var tableViewDelegate:RLDTableViewDelegate?
    
    // Collaborators
    var tableDataSource:RLDTableViewDataSource?
    let tableView = UITableView(frame:CGRect(x:0, y:0, width: 1, height:1))
    let cell = UITableViewCell()
    let view = UITableViewHeaderFooterView()
    let indexPath = NSIndexPath(forRow:0, inSection:0)
    
    override func setUp() {
        super.setUp()
        
        // GIVEN:
        //   A table view delegate
        //   An event handler
        //     capable to handle any model, table view and view
        //   A table view, a header/footer view, a cell and an index path
        let cellModel = RLDTableViewCellModel()
        let tableViewModel = RLDTableViewModel()
        tableViewModel.add(cellModel:cellModel)
        
        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier:cellModel.reuseIdentifier)
        RLDTestEventHandler.register()
        
        tableViewDelegate = RLDTableViewDelegate(tableViewModel:tableViewModel)
        tableView.delegate = tableViewDelegate
        
        tableDataSource = RLDTableViewDataSource(tableViewModel:tableViewModel)
        tableView.dataSource = tableDataSource
    }
    
    override func tearDown() {
        RLDTestEventHandler.reset()
        
        super.tearDown()
    }
    
    // MARK : Display customization test cases
    func testWillDisplayCell() {
        // WHEN:
        //   We inform the delegate that the table view will display the cell for a row at the index path
        tableViewDelegate!.tableView(tableView, willDisplayCell:cell, forRowAtIndexPath:indexPath)
        
        // THEN:
        //   The willDisplayView method of the event handler will be called
        RLDTestEventHandler.isCallRegistered("willDisplayView")
    }
    
    func testWillDisplayHeaderView() {
        // WHEN:
        //   We inform the delegate that the table view will display the header view of a section
        tableViewDelegate!.tableView(tableView, willDisplayHeaderView:view, forSection:indexPath.section)
        
        // THEN:
        //   The willDisplayView method of the event handler will be called
        RLDTestEventHandler.isCallRegistered("willDisplayView")
    }
    
    func testWillDisplayFooterView() {
        // WHEN:
        //   We inform the delegate that the table view will display the footer view of a section
        tableViewDelegate!.tableView(tableView, willDisplayFooterView:view, forSection:indexPath.section)
        
        // THEN:
        //   The willDisplayView method of the event handler will be called
        RLDTestEventHandler.isCallRegistered("willDisplayView")
    }
    
    func testDidEndDisplayingCell() {
        // WHEN:
        //   We inform the delegate that the table view did end displaying the cell for a row at the index path
        tableViewDelegate!.tableView(tableView, didEndDisplayingCell:cell, forRowAtIndexPath:indexPath)
        
        // THEN:
        //   The didEndDisplayingView method of the event handler will be called
        RLDTestEventHandler.isCallRegistered("didEndDisplayingView")
    }
    
    func testDidEndDisplayingHeaderView() {
        // WHEN:
        //   We inform the delegate that the table view did end displaying the header view of a section
        tableViewDelegate!.tableView(tableView, didEndDisplayingHeaderView:view, forSection:indexPath.section)
        
        // THEN:
        //   The didEndDisplayingView method of the event handler will be called
        RLDTestEventHandler.isCallRegistered("didEndDisplayingView")
    }
    
    func testDidEndDisplayingFooterView() {
        // WHEN:
        //   We inform the delegate that the table view did end displaying the footer view of a section
        tableViewDelegate!.tableView(tableView, didEndDisplayingFooterView:view, forSection:indexPath.section)
        
        // THEN:
        //   The didEndDisplayingView method of the event handler will be called
        RLDTestEventHandler.isCallRegistered("didEndDisplayingView")
    }
    
    // MARK : Section header and footer reusing test cases
    func testHeaderReusing() {
        // GIVEN:
        //   A table view data model
        //     with an automatically created section model
        //       with a cell model assigned to it
        //     set as the model of the table view delegate
        //   A header data model
        //     with a certain reuse identifier
        //       registered with the table view with a certain view class
        //     assigned as the header of the section model
        let dataModel = RLDTableViewModel()
        dataModel.add(cellModel:RLDTableViewCellModel())
        tableViewDelegate = RLDTableViewDelegate(tableViewModel:dataModel)
        tableView.delegate = tableViewDelegate
        
        let headerModel = RLDTableViewSectionAccessoryViewModel()
        headerModel.reuseIdentifier = "HeaderReuseIdentifier"
        tableView.registerClass(RLDTestAccessoryView.self, forHeaderFooterViewReuseIdentifier:headerModel.reuseIdentifier)
        dataModel.sectionModels.last!.header = headerModel
        
        // WHEN:
        //   We ask the delegate for a view for the header of the section
        let sectionHeader = tableViewDelegate!.tableView(tableView, viewForHeaderInSection:indexPath.section) as? RLDTestAccessoryView
        
        // THEN:
        //   The returned view class must be the same as the registered class
        //   Its reuse identifier must match the one for the header model
        XCTAssertNotNil(sectionHeader)
        XCTAssertTrue(sectionHeader!.dynamicType === RLDTestAccessoryView.self)
        XCTAssertEqual(sectionHeader!.reuseIdentifier!, headerModel.reuseIdentifier)
    }
    
    func testFooterReusing() {
        // GIVEN:
        //   A table view data model
        //     with an automatically created section model
        //       with a cell model assigned to it
        //     set as the model of the table view delegate
        //   A footer data model
        //     with a certain reuse identifier
        //       registered with the table view with a certain view class
        //     assigned as the footer of the section model
        let dataModel = RLDTableViewModel()
        dataModel.add(cellModel:RLDTableViewCellModel())
        tableViewDelegate = RLDTableViewDelegate(tableViewModel:dataModel)
        tableView.delegate = tableViewDelegate
        
        let footerModel = RLDTableViewSectionAccessoryViewModel()
        footerModel.reuseIdentifier = "FooterReuseIdentifier"
        tableView.registerClass(RLDTestAccessoryView.self, forHeaderFooterViewReuseIdentifier:footerModel.reuseIdentifier)
        dataModel.sectionModels.last!.footer = footerModel
        
        // WHEN:
        //   We ask the delegate for a view for the footer of the section
        let sectionFooter = tableViewDelegate!.tableView(tableView, viewForFooterInSection:indexPath.section) as? RLDTestAccessoryView
        
        // THEN:
        //   The returned view class must be the same as the registered class
        //   Its reuse identifier must match the one for the footer model
        XCTAssertNotNil(sectionFooter)
        XCTAssertTrue(sectionFooter!.dynamicType === RLDTestAccessoryView.self)
        XCTAssertEqual(sectionFooter!.reuseIdentifier!, footerModel.reuseIdentifier)
    }
    
    // MARK : Variable height support test cases
    func testVariableHeightForRow() {
        // GIVEN:
        //   A table view data model
        //     set as the model of the table view delegate
        //   A cell model
        //     with a certain estimated height
        //     with a certain height
        //     assigned to the table model
        let cellModel = cellModelInTableViewDataModel()
        cellModel.estimatedHeight = 1
        cellModel.height = 2
        
        // WHEN:
        //   We ask the delegate for
        //     the estimated height of a given cell for a row at the index path
        //     the height of a given cell for a row at the index path
        let estimatedHeight = tableViewDelegate!.tableView(tableView, estimatedHeightForRowAtIndexPath:indexPath)
        let height = tableViewDelegate!.tableView(tableView, heightForRowAtIndexPath:indexPath)
        
        // THEN:
        //   The returned estimated height must be equal to the height of the cell model
        //   The returned height must be equal to the height of the cell model
        XCTAssertEqual(estimatedHeight, cellModel.estimatedHeight!)
        XCTAssertEqual(height, cellModel.height!)
    }
    
    func testVariableHeightForHeader() {
        // GIVEN:
        //   A table view data model
        //     with a cell model assigned to it
        //     set as the model of the table view delegate
        //   An automatically created section model
        //   A header data model
        //     with a certain estimated height
        //     with a certain height
        //     assigned to the section model
        let dataModel = RLDTableViewModel()
        dataModel.add(cellModel:RLDTableViewCellModel())
        tableViewDelegate = RLDTableViewDelegate(tableViewModel:dataModel)
        tableView.delegate = tableViewDelegate
        
        let sectionModel = dataModel.sectionModels.last!
    
        let headerModel = RLDTableViewSectionAccessoryViewModel()
        headerModel.estimatedHeight = 1
        headerModel.height = 2
        sectionModel.header = headerModel
        
        // WHEN:
        //   We ask the delegate for
        //     the estimated height of a given cell for a row at the index path
        //     the height of a given cell for a row at the index path
        let estimatedHeight = tableViewDelegate!.tableView(tableView, estimatedHeightForHeaderInSection:indexPath.section)
        let height = tableViewDelegate!.tableView(tableView, heightForHeaderInSection:indexPath.section)
        
        // THEN:
        //   The returned estimated height must be equal to the height of the cell model
        //   The returned height must be equal to the height of the cell model
        XCTAssertEqual(estimatedHeight, headerModel.estimatedHeight!)
        XCTAssertEqual(height, headerModel.height!)
    }
    
    func testVariableHeightForFooter() {
        // GIVEN:
        //   A table view data model
        //     with a cell model assigned to it
        //     set as the model of the table view delegate
        //   An automatically created section model
        //   A footer data model
        //     with a certain estimated height
        //     with a certain height
        //     assigned to the section model
        let dataModel = RLDTableViewModel()
        dataModel.add(cellModel:RLDTableViewCellModel())
        tableViewDelegate = RLDTableViewDelegate(tableViewModel:dataModel)
        tableView.delegate = tableViewDelegate
        
        let sectionModel = dataModel.sectionModels.last!
        
        let footerModel = RLDTableViewSectionAccessoryViewModel()
        footerModel.estimatedHeight = 1
        footerModel.height = 2
        sectionModel.footer = footerModel
        
        // WHEN:
        //   We ask the delegate for
        //     the estimated height of a given cell for a row at the index path
        //     the height of a given cell for a row at the index path
        let estimatedHeight = tableViewDelegate!.tableView(tableView, estimatedHeightForFooterInSection:indexPath.section)
        let height = tableViewDelegate!.tableView(tableView, heightForFooterInSection:indexPath.section)
        
        // THEN:
        //   The returned estimated height must be equal to the height of the cell model
        //   The returned height must be equal to the height of the cell model
        XCTAssertEqual(estimatedHeight, footerModel.estimatedHeight!)
        XCTAssertEqual(height, footerModel.height!)
    }
    
    // MARK : Accessories (disclosures)
    func testAccessoryButtonTapped() {
        // WHEN:
        //   We inform the delegate that the accessory button for a row with a certain index path has been tapped
        tableViewDelegate!.tableView(tableView, accessoryButtonTappedForRowWithIndexPath:indexPath)
        
        // THEN:
        //   The accessoryButtonTapped method of the event handler will be called
        RLDTestEventHandler.isCallRegistered("accessoryButtonTapped")
    }
    
    /
Download .txt
gitextract_uxx7488s/

├── .gitignore
├── Classes/
│   ├── RLDHandledViewProtocol.swift
│   ├── RLDTableViewController.swift
│   ├── RLDTableViewDataSource.swift
│   ├── RLDTableViewDelegate.swift
│   ├── RLDTableViewEventHandler.swift
│   ├── RLDTableViewEventHandlerProvider.swift
│   └── RLDTableViewModel.swift
├── LICENSE
├── README.md
├── RLDTableViewSwift.podspec
├── Sample app/
│   ├── TableViewPrototype/
│   │   ├── AppDelegate.swift
│   │   ├── Event handlers/
│   │   │   ├── RLDGenericTableViewCellEventHandler.swift
│   │   │   └── RLDTableViewHeaderViewEventHandler.swift
│   │   ├── Info.plist
│   │   ├── Models/
│   │   │   ├── RLDBigPictureTableViewCellModel.swift
│   │   │   ├── RLDCommentTableViewCellModel.swift
│   │   │   ├── RLDGenericTableViewCellModel.swift
│   │   │   ├── RLDSimpleTableViewCellModel.swift
│   │   │   ├── RLDTableViewHeaderViewModel.swift
│   │   │   └── RLDTableViewModelProvider.swift
│   │   ├── RLDTableViewSwift-Info.plist
│   │   ├── Resources/
│   │   │   ├── Images.xcassets/
│   │   │   │   ├── 0_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 1_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 2_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 2_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 3_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 4_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 5_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 6_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 7_big.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 8_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── 9_small.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── AppIcon.appiconset/
│   │   │   │       └── Contents.json
│   │   │   ├── LaunchScreen.xib
│   │   │   ├── Main.storyboard
│   │   │   ├── RLDTableViewHeaderView.xib
│   │   │   └── viewModelData.plist
│   │   ├── View controllers/
│   │   │   ├── RLDMasterViewController.swift
│   │   │   └── RLDWebViewController.swift
│   │   └── Views/
│   │       ├── RLDBigPictureTableViewCell.swift
│   │       ├── RLDCommentTableViewCell.swift
│   │       ├── RLDGenericTableViewCell.swift
│   │       ├── RLDSimpleTableViewCell.swift
│   │       └── RLDTableViewHeaderView.swift
│   └── TableViewPrototype.xcodeproj/
│       ├── project.pbxproj
│       ├── project.xcworkspace/
│       │   ├── contents.xcworkspacedata
│       │   └── xcshareddata/
│       │       └── TableViewPrototype.xccheckout
│       └── xcuserdata/
│           └── rhocassiopeiae.xcuserdatad/
│               └── xcschemes/
│                   ├── RLDTableViewSwift.xcscheme
│                   ├── TableViewPrototype.xcscheme
│                   └── xcschememanagement.plist
└── Tests/
    ├── Tests/
    │   ├── Info.plist
    │   ├── RLDTableViewDataSourceTests.swift
    │   ├── RLDTableViewDelegateTests.swift
    │   ├── RLDTableViewEventHandlerProviderTests.swift
    │   ├── RLDTableViewModelTests.swift
    │   └── TestHelpers.swift
    └── Tests.xcodeproj/
        ├── project.pbxproj
        ├── project.xcworkspace/
        │   ├── contents.xcworkspacedata
        │   └── xcshareddata/
        │       └── Tests.xccheckout
        └── xcshareddata/
            └── xcschemes/
                └── Tests.xcscheme
Condensed preview — 61 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (244K chars).
[
  {
    "path": ".gitignore",
    "chars": 71,
    "preview": "Sample app/TableViewPrototype.xcodeproj/project.xcworkspace/xcuserdata\n"
  },
  {
    "path": "Classes/RLDHandledViewProtocol.swift",
    "chars": 119,
    "preview": "import UIKit\n\npublic protocol RLDHandledViewProtocol:class {\n    var eventHandler:RLDTableViewEventHandler? {get set}\n}"
  },
  {
    "path": "Classes/RLDTableViewController.swift",
    "chars": 8202,
    "preview": "import UIKit\nimport RLDTableViewSwift\n\n// MARK: UIView extension to find the first responder\n\nprivate extension UIView {"
  },
  {
    "path": "Classes/RLDTableViewDataSource.swift",
    "chars": 5462,
    "preview": "import UIKit\n\npublic class RLDTableViewDataSource:NSObject, UITableViewDataSource {\n    \n    // MARK: Initialization\n   "
  },
  {
    "path": "Classes/RLDTableViewDelegate.swift",
    "chars": 12106,
    "preview": "import UIKit\n\npublic class RLDTableViewDelegate:NSObject, UITableViewDelegate {\n    // Initialization\n    private var ta"
  },
  {
    "path": "Classes/RLDTableViewEventHandler.swift",
    "chars": 2051,
    "preview": "import UIKit\n\n// MARK: RLDTableViewEventHandler class\n\npublic class RLDTableViewEventHandler {\n    // MARK: Event handle"
  },
  {
    "path": "Classes/RLDTableViewEventHandlerProvider.swift",
    "chars": 720,
    "preview": "import UIKit\n\nclass RLDTableViewEventHandlerProvider {\n    private static var availableEventHanlderClasses:[RLDTableView"
  },
  {
    "path": "Classes/RLDTableViewModel.swift",
    "chars": 5399,
    "preview": "//\n//  RLDNavigation\n//\n//  Copyright (c) 2015 Rafael Lopez Diez. All rights reserved.\n//\n//  Licensed under the Apache "
  },
  {
    "path": "LICENSE",
    "chars": 10173,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "README.md",
    "chars": 5265,
    "preview": "# RLDTableViewSwift\n\nThe ubiquitous `UITableView`, with its required data source and delegate, is one of the main source"
  },
  {
    "path": "RLDTableViewSwift.podspec",
    "chars": 655,
    "preview": "Pod::Spec.new do |s|\n  s.name         = 'RLDTableViewSwift'\n  s.version      = '0.2.1'\n  s.homepage     = 'https://githu"
  },
  {
    "path": "Sample app/TableViewPrototype/AppDelegate.swift",
    "chars": 271,
    "preview": "import UIKit\n\n@UIApplicationMain\nclass AppDelegate:UIResponder, UIApplicationDelegate {\n    var window: UIWindow?\n    \n "
  },
  {
    "path": "Sample app/TableViewPrototype/Event handlers/RLDGenericTableViewCellEventHandler.swift",
    "chars": 2980,
    "preview": "import UIKit\nimport RLDTableViewSwift\n\nclass RLDGenericTableViewCellEventHandler:RLDTableViewCellEventHandler {\n    // M"
  },
  {
    "path": "Sample app/TableViewPrototype/Event handlers/RLDTableViewHeaderViewEventHandler.swift",
    "chars": 700,
    "preview": "import UIKit\nimport RLDTableViewSwift\n\nclass RLDTableViewHeaderViewEventHandler:RLDTableViewSectionAccessoryViewEventHan"
  },
  {
    "path": "Sample app/TableViewPrototype/Info.plist",
    "chars": 1205,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Sample app/TableViewPrototype/Models/RLDBigPictureTableViewCellModel.swift",
    "chars": 174,
    "preview": "class RLDBigPictureTableViewCellModel:RLDGenericTableViewCellModel {\n    required init() {\n        super.init()\n        "
  },
  {
    "path": "Sample app/TableViewPrototype/Models/RLDCommentTableViewCellModel.swift",
    "chars": 206,
    "preview": "class RLDCommentTableViewCellModel:RLDGenericTableViewCellModel {\n    \n    var comment:String = \"\"\n    \n    required ini"
  },
  {
    "path": "Sample app/TableViewPrototype/Models/RLDGenericTableViewCellModel.swift",
    "chars": 257,
    "preview": "import RLDTableViewSwift\n\nclass RLDGenericTableViewCellModel:RLDTableViewCellModel {\n    var title:String = \"\"\n    var d"
  },
  {
    "path": "Sample app/TableViewPrototype/Models/RLDSimpleTableViewCellModel.swift",
    "chars": 166,
    "preview": "class RLDSimpleTableViewCellModel:RLDGenericTableViewCellModel {\n    required init() {\n        super.init()\n        reus"
  },
  {
    "path": "Sample app/TableViewPrototype/Models/RLDTableViewHeaderViewModel.swift",
    "chars": 254,
    "preview": "import RLDTableViewSwift\n\nclass RLDTableViewHeaderViewModel:RLDTableViewSectionAccessoryViewModel {\n    required init() "
  },
  {
    "path": "Sample app/TableViewPrototype/Models/RLDTableViewModelProvider.swift",
    "chars": 4088,
    "preview": "import RLDTableViewSwift\nimport UIKit\n\nclass RLDTableViewModelProvider {\n    \n    static private let DataPlistFileName ="
  },
  {
    "path": "Sample app/TableViewPrototype/RLDTableViewSwift-Info.plist",
    "chars": 783,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/0_small.imageset/Contents.json",
    "chars": 304,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/1_small.imageset/Contents.json",
    "chars": 304,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/2_big.imageset/Contents.json",
    "chars": 302,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/2_small.imageset/Contents.json",
    "chars": 304,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/3_small.imageset/Contents.json",
    "chars": 304,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/4_big.imageset/Contents.json",
    "chars": 302,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/5_small.imageset/Contents.json",
    "chars": 304,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/6_big.imageset/Contents.json",
    "chars": 302,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/7_big.imageset/Contents.json",
    "chars": 302,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/8_small.imageset/Contents.json",
    "chars": 304,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/9_small.imageset/Contents.json",
    "chars": 304,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Images.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 585,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/LaunchScreen.xib",
    "chars": 3654,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/Main.storyboard",
    "chars": 35458,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/RLDTableViewHeaderView.xib",
    "chars": 3789,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "Sample app/TableViewPrototype/Resources/viewModelData.plist",
    "chars": 6423,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Sample app/TableViewPrototype/View controllers/RLDMasterViewController.swift",
    "chars": 1350,
    "preview": "import UIKit\n\nclass RLDMasterViewController: RLDTableViewController {\n    \n    let modelProvider = RLDTableViewModelProv"
  },
  {
    "path": "Sample app/TableViewPrototype/View controllers/RLDWebViewController.swift",
    "chars": 297,
    "preview": "import UIKit\n\nclass RLDWebViewController: UIViewController {\n    var url:String = \"\" {\n        didSet {\n            if l"
  },
  {
    "path": "Sample app/TableViewPrototype/Views/RLDBigPictureTableViewCell.swift",
    "chars": 60,
    "preview": "class RLDBigPictureTableViewCell:RLDGenericTableViewCell {\n}"
  },
  {
    "path": "Sample app/TableViewPrototype/Views/RLDCommentTableViewCell.swift",
    "chars": 334,
    "preview": "import UIKit\n\nclass RLDCommentTableViewCell:RLDGenericTableViewCell {\n    @IBOutlet weak var comment:UITextView!\n    \n  "
  },
  {
    "path": "Sample app/TableViewPrototype/Views/RLDGenericTableViewCell.swift",
    "chars": 1060,
    "preview": "import UIKit\nimport RLDTableViewSwift\n\nclass RLDGenericTableViewCell:UITableViewCell, RLDHandledViewProtocol {\n    @IBOu"
  },
  {
    "path": "Sample app/TableViewPrototype/Views/RLDSimpleTableViewCell.swift",
    "chars": 56,
    "preview": "class RLDSimpleTableViewCell:RLDGenericTableViewCell {\n}"
  },
  {
    "path": "Sample app/TableViewPrototype/Views/RLDTableViewHeaderView.swift",
    "chars": 338,
    "preview": "import UIKit\nimport RLDTableViewSwift\n\nclass RLDTableViewHeaderView:UITableViewHeaderFooterView, RLDHandledViewProtocol "
  },
  {
    "path": "Sample app/TableViewPrototype.xcodeproj/project.pbxproj",
    "chars": 30559,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Sample app/TableViewPrototype.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 163,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:TableViewProtot"
  },
  {
    "path": "Sample app/TableViewPrototype.xcodeproj/project.xcworkspace/xcshareddata/TableViewPrototype.xccheckout",
    "chars": 1548,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Sample app/TableViewPrototype.xcodeproj/xcuserdata/rhocassiopeiae.xcuserdatad/xcschemes/RLDTableViewSwift.xcscheme",
    "chars": 2943,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0730\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Sample app/TableViewPrototype.xcodeproj/xcuserdata/rhocassiopeiae.xcuserdatad/xcschemes/TableViewPrototype.xcscheme",
    "chars": 3435,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0730\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Sample app/TableViewPrototype.xcodeproj/xcuserdata/rhocassiopeiae.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 687,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Tests/Tests/Info.plist",
    "chars": 730,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Tests/Tests/RLDTableViewDataSourceTests.swift",
    "chars": 20120,
    "preview": "import XCTest\nimport UIKit\n\nclass RLDTableViewDataSourceTests:XCTestCase {\n    // SUT\n    let dataModel = RLDTableViewMo"
  },
  {
    "path": "Tests/Tests/RLDTableViewDelegateTests.swift",
    "chars": 22382,
    "preview": "import UIKit\nimport XCTest\n\nclass RLDTableViewDelegateTests: XCTestCase {\n    \n    // SUT\n    var tableViewDelegate:RLDT"
  },
  {
    "path": "Tests/Tests/RLDTableViewEventHandlerProviderTests.swift",
    "chars": 1594,
    "preview": "import XCTest\nimport UIKit\n\nclass RLDTableViewEventHandlerProviderTests: XCTestCase {\n    \n    func testFactoryMethod() "
  },
  {
    "path": "Tests/Tests/RLDTableViewModelTests.swift",
    "chars": 1889,
    "preview": "import UIKit\nimport XCTest\n\nclass RLDTableViewModelTests:XCTestCase {\n    // MARK: Section index titles test cases\n    f"
  },
  {
    "path": "Tests/Tests/TestHelpers.swift",
    "chars": 3010,
    "preview": "import UIKit\n\n// MARK: UITableViewCell subclass\nclass RLDTestTableViewCell:UITableViewCell {\n}\n\n// MARK: UITableViewHead"
  },
  {
    "path": "Tests/Tests.xcodeproj/project.pbxproj",
    "chars": 14608,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 150,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:Tests.xcodeproj"
  },
  {
    "path": "Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/Tests.xccheckout",
    "chars": 1517,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme",
    "chars": 3140,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0630\"\n   version = \"1.3\">\n   <BuildAction\n      "
  }
]

About this extraction

This page contains the full source code of the rlopezdiez/RLDTableViewSwift GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 61 files (221.2 KB), approximately 59.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!