1

I’ve got an array of Transaction objects:

var transactions = [Transaction]()

Transaction class:

class Transaction {
    var description : String = ""
    var post_transaction_balance : Double = 0
    var settlement_date : NSDate?
    var dateOnly : NSDate?
 }

I need to create a UITableView with sections and each section represents transactions made on particular day

An example of how table structure should look like:

— section header: dateOnly—

transaction [0] title

transaction [3] title

— section header: dateOnly—

transaction [2] title

transaction [7] title

Example of dateOnly value:

dateOnly = (NSDate?) 2016-01-22 00:00:00 UTC

I am not sure how to iterate through the array of objects and get the data into the section headers and the cells. I would greatly appreciate any help.

2
  • All date contain same time 00:00:00 UTC ? Commented Sep 12, 2016 at 15:28
  • @NDoc yes, thank you Commented Sep 12, 2016 at 15:50

3 Answers 3

5

Preview of the result:

enter image description here

Note: I have used Swift 3.

ViewController:

class ViewController: UIViewController {
  @IBOutlet weak private var tableView: UITableView!
  var transactionsGroupedByDate = [(String,Array<Transaction>)]()

  override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    getTransactions()
  }

  // Getting transactions
  private func getTransactions() {
    let transactions = makeTransactions()
    self.transactionsGroupedByDate = groupByDate(transactions: transactions)

    tableView.reloadData()
  }

  // Grouping the transactions by their date
  private func groupByDate(transactions: [Transaction]) -> [(String,Array<Transaction>)] {
    var transactionsGroupedByDate = Dictionary<String, Array<Transaction>>()

    // Looping the Array of transactions
    for transaction in transactions {

      // Converting the transaction's date to String
      let date = convertDateToString(date: transaction.date!)

      // Verifying if the array is nil for the current date used as a
      // key in the dictionary, if so the array is initialized only once
      if transactionsGroupedByDate[date] == nil {
        transactionsGroupedByDate[date] = Array<Transaction>()
      }

      // Adding the transaction in the dictionary to the key that is the date
      transactionsGroupedByDate[date]?.append(transaction)
    }

    // Sorting the dictionary to descending order and the result will be
    // an array of tuples with key(String) and value(Array<Transaction>)
    return transactionsGroupedByDate.sorted { $0.0 > $1.0 }
  }
}

Helper Methods:

extension ViewController {
  // Helper to create a date formatter
  func createDateFormatter() -> DateFormatter {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    dateFormatter.timeZone = TimeZone(identifier: "UTC")

    return dateFormatter
  }

  // Helper to convert date to string
  func convertDateToString(date: Date) -> String {
    let dateFormatter = createDateFormatter()

    return dateFormatter.string(from: date)
  }

  // Mocking the transactions
  func makeTransactions() -> [Transaction] {
    var transactions = [Transaction]()

    let dateFormatter = createDateFormatter()

    let date1 = dateFormatter.date(from: "2016-01-22 00:00:00")
    let transaction1 = Transaction(title: "transaction 1", date: date1)

    let date2 = dateFormatter.date(from: "2016-01-22 00:00:00")
    let transaction2 = Transaction(title: "transaction 2", date: date2)

    let date3 = dateFormatter.date(from: "2016-01-23 00:00:00")
    let transaction3 = Transaction(title: "transaction 3", date: date3)

    let date4 = dateFormatter.date(from: "2016-01-24 00:00:00")
    let transaction4 = Transaction(title: "transaction 4", date: date4)

    let date5 = dateFormatter.date(from: "2016-01-24 00:00:00")
    let transaction5 = Transaction(title: "transaction 5", date: date5)

    let date6 = dateFormatter.date(from: "2016-01-25 00:00:00")
    let transaction6 = Transaction(title: "transaction 6", date: date6)

    transactions.append(transaction1)
    transactions.append(transaction2)
    transactions.append(transaction3)
    transactions.append(transaction4)
    transactions.append(transaction5)
    transactions.append(transaction6)

    return transactions
  }
}

UITableViewDelegate, UITableViewDataSource methods:

extension ViewController: UITableViewDelegate, UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return transactionsGroupedByDate[section].1.count
  }

  func numberOfSections(in tableView: UITableView) -> Int {
    return transactionsGroupedByDate.count
  }

  func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return transactionsGroupedByDate[section].0
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    let transaction = transactionsGroupedByDate[indexPath.section].1[indexPath.row]

    cell.textLabel?.text = transaction.title

    return cell
  }
}

Transaction struct:

struct Transaction {
  var title: String?
  var date: Date?
}
Sign up to request clarification or add additional context in comments.

Comments

0

Why not reorganize the array to a dictionary.

You can enumerate the transaction array and save it as [String: Transaction]. The key could be your particular day's description.

Comments

0

You need to have a section array (i.e. [Int:NSDate]) containing the starting index of each section & date value (section title) of each section.

You can define a func filling the section array and might do the following in it:

  1. Reorder your transactions array according to dateOnly objects in it, so that the Transaction object with the closest date will be at top.

  2. Iterate the sorted array to find dateOnly objects that are different from that of previous object in the array and put these dateOnly objects in section array.

Now, you have a section array containing the dateOnly objects, and a sorted Transaction array. You can easily use these for populating the tableView.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.