Gold, Silver, Bronze, and Chapter 8 in Swift


#1

Please let me know of any improvements I could make!

AppDelegate.swift

[code]//
// AppDelegate.swift
// Homepwner
//
// Created by adam on 6/18/14.
// Copyright © 2014 Adam Schoonmaker. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    // Override point for customization after application launch.
    
    // Create a ItemsViewController
    let itemsViewController = ItemsViewController()
    
    // Place ItemsViewController's table view in the windoe hierarchy
    window!.rootViewController = itemsViewController
    
    self.window!.backgroundColor = UIColor.whiteColor()
    self.window!.makeKeyAndVisible()
    return true
}

}
[/code]

ItemsViewController.swift

[code]//
// ItemsViewController.swift
// Homepwner
//
// Created by adam on 6/18/14.
// Copyright © 2014 Adam Schoonmaker. All rights reserved.
//

import UIKit

class ItemsViewController: UITableViewController, UITableViewDataSource,
UITableViewDelegate {

// All instances of TableViewController should use UITableViewStyle.Plain
// and this initializer
convenience init() {
    self.init(style: UITableViewStyle.Grouped)
    
    // Initialize the ItemStore to have 5 random items
    for _ in 0..10 {
        ItemStore.sharedStore.createItem()
    }
}
/*
// should be using this, but use of UITableViewController.init(style:) has a
// bug where it accidentally calls "unimplemented initializer 'init(nibName:bundle:)"
init() {
    super.init(style: UITableViewStyle.Plain)
}*/


// Register the UITableViewCell class for reuse within the table
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.backgroundView = UIImageView(image: UIImage(named: "galaxy.jpg"))
    tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell")
}



// UITableViewDataSource protocol functions
override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
    return 2
}

override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        return ItemStore.sharedStore.allItemsMoreThanFifty().count + 1
    } else if section == 1 {
        return ItemStore.sharedStore.allItemsLessThanOrEqualToFifty().count + 1
    } else {
        return 0
    }
}

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    // Create an instance of UITableViewCell, with default appearance
    // NOTE: THIS DOES NOT REUSE CELLS
    //let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "UITableViewCell")
    
    // Get a new or recycled cell
    // By convention, the reuse identifier is typically the name of the cell class
    // For this to work, the table view must know which kind of cell to instantiate
    // if there are no cells in the pool, done in viewDidLoad...
    let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath) as UITableViewCell
    
    
    // Set the text on the cell with the description of the item that is at the
    // nth index of items, when n = "row this cell will appear in on the tableview"
    let itemsOverFifty = ItemStore.sharedStore.allItemsMoreThanFifty()
    let itemsEqualOrBelowFifty = ItemStore.sharedStore.allItemsLessThanOrEqualToFifty()
    
    var item = Item()
    
    if indexPath.section == 0 {
        
        if indexPath.row < (itemsOverFifty.count) {
            item = itemsOverFifty[indexPath.row]
            cell.textLabel.text = item.description
            cell.textLabel.font = UIFont.systemFontOfSize(20.0)
        } else {
            cell.textLabel.text = "No more items!"
            cell.textLabel.font = UIFont.systemFontOfSize(14.0)
        }
    } else if indexPath.section == 1 {
        
        if indexPath.row < (itemsEqualOrBelowFifty.count) {
            item = itemsEqualOrBelowFifty[indexPath.row]
            cell.textLabel.text = item.description
            cell.textLabel.font = UIFont.systemFontOfSize(20.0)
        } else {
            cell.textLabel.text = "No more items!"
            cell.textLabel.font = UIFont.systemFontOfSize(14.0)
        }
    }
    
    return cell
}

// Set the title for the section headers
override func tableView(tableView: UITableView!, titleForHeaderInSection section: Int) -> String! {
    if section == 0 {
        return "Items Over $50"
    } else {
        return "Items Below or Equal to $50"
    }
}

// Set the height for the rows. All but the last rows will be 60.0pt, last
// row for each section will be 44.0pt
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
    let itemsOverFifty = ItemStore.sharedStore.allItemsMoreThanFifty()
    let itemsEqualOrBelowFifty = ItemStore.sharedStore.allItemsLessThanOrEqualToFifty()
    
    if indexPath.section == 0 {
        if indexPath.row < (itemsOverFifty.count) {
            return 60.0
        } else {
            return 44.0
        }
    } else {
        if indexPath.row < (itemsEqualOrBelowFifty.count) {
            return 60.0
        } else {
            return 44.0
        }
    }
}

}
[/code]

ItemStore.swift

[code]//
// ItemStore.swift
// Homepwner
//
// Created by adam on 6/18/14.
// Copyright © 2014 Adam Schoonmaker. All rights reserved.
//

import Foundation

// lazily initiated, thread-safe from "let"
let _GlobalItemStoreSharedInstance = ItemStore()

class ItemStore : NSObject {

class var sharedStore : ItemStore {
    return _GlobalItemStoreSharedInstance
}

// Common design pattern for a class that wants strict control over its
// internal data:
// Internally, ItemStore needs to be able to mutate the array and add new 
// Items (and remove and reorder them)
var _privateItems = Item[]()
// The allItems property can't be changed by other objects
var allItems: Item[] {
    return _privateItems
}

func allItemsMoreThanFifty() -> Item[] {
    return _privateItems.filter({ $0.valueInDollars > 50 })
}

func allItemsLessThanOrEqualToFifty() -> Item[] {
    return _privateItems.filter({ $0.valueInDollars <= 50 })
}

func createItem() -> Item {
    let item = Item.randomItem()
    _privateItems.append(item)
    return item
}

}[/code]

Item.swift

[code]//
// Item.swift
// Homepwner
//
// Created by adam on 6/18/14.
// Copyright © 2014 Adam Schoonmaker. All rights reserved.
//

import Foundation

class Item : NSObject {

var itemName: String
var serialNumber: String
var valueInDollars: Int
var dateCreated: NSDate

override var description: String {
    return "\(itemName) (\(serialNumber)): Worth \(valueInDollars), recorded on \(dateCreated)"
}

init(itemName name: String, valueInDollars value: Int, serialNumber sNumber: String) {
    // Give the instance variables initial values
    itemName = name
    serialNumber = sNumber
    valueInDollars = value
    dateCreated = NSDate()
    
    super.init()
}

convenience init(itemName name: String) {
    self.init(itemName: name, valueInDollars: 0, serialNumber: "")
}

convenience init() {
    self.init(itemName: "", valueInDollars: 0, serialNumber: "")
}

// A class method for the type Item itself, not Item instances
class func randomItem() -> Item {
    let randomAdjectiveList = ["Fluffy", "Rusty", "Shiny"]
    let randomNounList = ["Bear", "Spork", "Mac"]
    
    // Get the index of a random adjective/noun from the lists
    let adjectiveIndex = Int(arc4random() % UInt32(randomAdjectiveList.count))
    let nounIndex = Int(arc4random() % UInt32(randomNounList.count))
    
    let randomName = "\(randomAdjectiveList[adjectiveIndex]) \(randomNounList[nounIndex])"
    
    let randomValue = Int(arc4random() % 100)
    
    //let randomSerialNumber = "0\(arc4random() % 10)A\(arc4random() % 26)0\(arc4random() % 10)A\(arc4random() % 26)0\(arc4random() % 10)"
    // shorter version
    let randomSerialNumber = "0\(arc4random() % 10)A\(arc4random() % 26)0\(arc4random() % 10)"
    
    return Item(itemName: randomName, valueInDollars: randomValue, serialNumber: randomSerialNumber)
}

}
[/code]


#2

Thanks SchoonSauce.

I’ve been racking my head on completing this chapter via swift. The singleton concept started the downward spiral of confusion and after a while I could not distinguish up from down.

Thanks again.