-1

I'm trying to display a section header with the month and year the cell was created as the text in the section header. This is my code but it only displays one section header like so. Any idea why and how I can get it to display the year and month the cell was created?

  import UIKit


class PRViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var tblTasks : UITableView!

    //For persisting data
    let defaults = NSUserDefaults.standardUserDefaults()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tblTasks.reloadData()
         tblTasks.registerNib(UINib(nibName: "PRTableViewCell", bundle: nil), forCellReuseIdentifier: "PRTableCell")
        tblTasks.tableFooterView = UIView()

    }

    override func viewWillAppear(animated: Bool) {
        self.tblTasks.reloadData()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{



        return 1

    }


    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "Your PR's"
    }

    //Define how our cells look - 2 lines a heading and a subtitle
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
        let identifier = "PRTableCell"
        var cell: PRTableViewCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? PRTableViewCell

        if cell == nil {
            tableView.registerNib(UINib(nibName: "PRTableViewCell", bundle: nil), forCellReuseIdentifier: identifier)
            cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? PRTableViewCell
        }


//        Assign the contents of our var "items" to the textLabel of each cell
//        cell.textLabel!.text = taskMgr.tasks[indexPath.row].name
//        cell.detailTextLabel!.text = taskMgr.tasks[indexPath.row].desc

        cell.PRLabel.text = taskMgr.tasks[indexPath.row].name
        cell.NotesLabel.text = taskMgr.tasks[indexPath.row].desc
        cell.WeightLabel.text = taskMgr.tasks[indexPath.row].weight + "lb"






        return cell



    }

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){

        if (editingStyle == UITableViewCellEditingStyle.Delete){

            taskMgr.removeTask(indexPath.row)
            tblTasks.reloadData()
        }


         func numberOfSectionsInTableView(tableView: UITableView) -> Int {

            // #warning Incomplete implementation, return the number of sections

            let numberOfSections = taskMgr.tasks.count



            return numberOfSections
        }





    }
Nate Grant
  • 13
  • 2
  • 5
  • You only get one section header per section. The image you have linked appears to show two cells in a single section hence only one section header. To display a date you need to retrieve a date that represents all the cells in that section from your data source. Then use `NSDateFormatter` to create a `String` and then return that `String`. Similar to something like this: `let formatter = NSDateFormatter(); formatter.dateStyle = .ShortStyle; formatter.timeStyle = .NoStyle ; let dateString = formatter.stringFromDate(sectionHeaderDate); return dateString` – Robotic Cat May 15 '16 at 19:03
  • @RoboticCat I want to display each cell in a separate section. then use the date the cell was added as the section header text? Would I put that in an override func method? – Nate Grant May 15 '16 at 19:08
  • Return the correct number of "sections" (from your model) in `numberOfSectionsInTableView:` and return `1` in `tableView:numberOfRowsInSection:`. Then set the correct information for each cell in `tableView:cellForRowAtIndexPath:`. Finally in `tableView:titleForHeaderInSection:` get the date of creation for that "section" and format it as I described above. – Robotic Cat May 15 '16 at 19:18
  • If you want more assistance then edit your question to include your `tableView:cellForRowAtIndexPath:` method. – Robotic Cat May 15 '16 at 19:20
  • @RoboticCat I set all of this up but now it won't add a new cell with a new section each time I add a new cell. I'll update the post with my code. – Nate Grant May 15 '16 at 20:25

2 Answers2

0

Here's one way to do it. Note that this code assumes your cell data is in an array called "cellArray". It displays a date that starts with today and goes back one day for each section. Obviously you'll need to substitute your dates.

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.cellArray.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)

    // TODO: configure cell for display using self.cellArray[indexPath.section]

    return cell
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let df = NSDateFormatter()
    df.dateStyle = .MediumStyle
    df.timeStyle = .NoStyle

    // TODO: determine the actual date
    let displayDate = NSDate().dateByAddingTimeInterval(Double(section * -86400))

    return df.stringFromDate(displayDate)
}
Wayne
  • 56
  • 2
  • 2
0

So example code is below (code not tested obviously). I have assumed that there is a dateCreated property containing an NSDate in the objects held in your tasks array.

Example code:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return 1
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

    let formatter = NSDateFormatter() // This is slightly inefficient for a large number of rows because setting up NSDateFormatter is expensive. You could make this a property. 
    formatter.dateStyle = .ShortStyle
    formatter.timeStyle = .NoStyle

    let sectionHeaderDate = taskMgr.tasks[section].dateCreated

    let dateString = formatter.stringFromDate(sectionHeaderDate)
    return dateString
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let identifier = "PRTableCell"
    var cell: PRTableViewCell! = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath:idx) as? PRTableViewCell // You must register a class or nib file using the registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier: method before calling this method (http://stackoverflow.com/q/12737860/558933).

    cell.PRLabel.text = taskMgr.tasks[indexPath.row].name
    cell.NotesLabel.text = taskMgr.tasks[indexPath.row].desc
    cell.WeightLabel.text = taskMgr.tasks[indexPath.row].weight + "lb" // Note iOS 9 allows you to localise weights rather than hard-coding "lb" or "kg". You should look at the documentation.

    return cell
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    let numberOfSections = taskMgr.tasks.count
    return numberOfSections
}

To add a new "section" to the UITableView you must add the new data to the array taskMgr.tasks and then either reload the table or update just the added rows. Wrap these lines of code in tblTasks.beginUpdates and tblTasks.endUpdates. Similarly for deleting.

Robotic Cat
  • 5,899
  • 4
  • 41
  • 58
  • Ok. I've implemented the code you have given me and understand how that works and how I need to plug it in with my core data. Now I am new to working with NSDate. If I understand correctly I need to make a dateCreated property that holds the current date in months/year as the NSDate and store it in my tasks array so when it is called it will add the dateCreated NSDate as the section header text? Thanks for all the help! – Nate Grant May 16 '16 at 01:14
  • Basically yes. You need a new `dateCreated` property in your objects in your array (and in your Core Data model). When you create the object in Core Date (or the array depending on how you've coded this) you need to set `dateCreated` to the current date (e.g. `newObject.dateCreated = NSDate()`). – Robotic Cat May 16 '16 at 01:33
  • My question is where do I put the code newObject.dateCreated = NSDate() ? In my viewdidload for the viewcontroller or in the class that manages all of my core data? – Nate Grant May 16 '16 at 12:11
  • I don't understand the question - you need to update your model to have the new `dateCreated` property. You have a `tasks` array that contains objects that you are using to populate the table view cells. You need to update that object to have a `dateCreated` property (which is in your Core Data model if you are using Core Data) and then when you create a new bit of data you need to set the `dateCreated` property at the same time as you set the `.name`, `.weight` and `.desc` properties. This then needs to be saved to your Core Data model as per normal. This should be obvious. – Robotic Cat May 16 '16 at 14:03
  • Yep. So I would set it as a string just like the others or date? That's what I was just trying to confirm. Thanks – Nate Grant May 16 '16 at 15:55
  • You set it as a `Date` using `NSDate()`. It's not a `String` type but an `NSDate` type: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/ . The formatter then handles the conversion to an appropriate string based on the users settings. – Robotic Cat May 16 '16 at 16:19
  • I mean in my core data model do i set the Type to date? And if not where would I set it to be theNSDate()? Because it's not an array. Just core data. – Nate Grant May 16 '16 at 17:46
  • Yes - in your Core Data model set the type to `Date` – Robotic Cat May 16 '16 at 20:58
  • Ok. Now I get the error, "cannot convert calue of type string to expected argument type nsdate" – Nate Grant May 16 '16 at 23:23
  • That's not enough info for anyone to help. I suggest you post a new question with the relevant code highlighting the line with the error. – Robotic Cat May 17 '16 at 00:21