I would like to sort my data by date from newest down to oldest. I am getting Transaction objects from Firestore in the form of "2020-12-29". I have seen previous answers on how to sort arrays by date but I am unsure how I can sort it with my current object structure.
func loadTransactions(){
if let catId = self.categoryId{
guard let user = Auth.auth().currentUser?.uid else { return }
db.collection("users").document(user).collection("Transactions")
.whereField("catId", isEqualTo: catId)
.getDocuments() {
snapshot, error in
if let error = error {
print("\(error.localizedDescription)")
} else {
self.budgetData.removeAll()
for document in snapshot!.documents {
let data = document.data()
let title = data["name"] as? String ?? ""
let date = data["date"] as? String ?? ""
let amount = data["amount"] as? Double ?? 0
let id = data["transId"] as? String ?? ""
let absolute = abs(amount)
let trans = Transaction(transId: id, catId:catId,title: title, dateInfo: date, image: UIImage.grocIcon, amount: absolute)
self.budgetData.append(trans)
// let testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", //"2 Jul, 2016"]
// var convertedArray: [Date] = []
// var dateFormatter = DateFormatter()
// dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"
// for dat in testArray {
// let date = dateFormatter.date(from: dat)
// if let date = date {
// convertedArray.append(date)
// }
// }
// var ready = convertedArray.sorted(by: { $0.compare($1) == .orderedDescending })
var tranSet = Set<Transaction>()
self.budgetData = self.budgetData.filter { (transaction) -> Bool in
if !tranSet.contains(transaction){
tranSet.insert(transaction)
return true
}
return false
}
DispatchQueue.main.async {
self.setTotalAmountOfCats()
self.tableView.reloadData()
}
}
}
}
}
}
You can sort the data in your Firebase query using order(by:): https://firebase.google.com/docs/firestore/query-data/order-limit-data
In your example, it'll probably look like:
db.collection("users").document(user).collection("Transactions")
.whereField("catId", isEqualTo: catId)
.order(by: "date")
If you implemented this, you could get rid of your tranSet and just append the Transactions in order (this is out of scope of the question, but I'd probably look at compactMap to transform snapshot.documents instead of appending them in order).
This assumes that your dates are in the format you listed (YYYY-MM-DD), which will alphabetize correctly, even though they aren't actually date/timestamp objects. If your data is in the format in your commented-out testArray section, than a different method would have to be used.
Related
Essentially I have a tableview populated using JSON data, the tableview contains sections that groups the data using allowdate from the JSON.
allowdate as seen below is contains a date but is not formatted numerically instead looks like: March 26th 2020 so it makes difficult to control the order it is displayed in the tableview.
In the function fetchJSON I do:
self.structure.sort { $1. allowdate < $0.allowdate }
But this does not work correctly, and fails to put a date for example in January above one in March.
var sections = [TableSection]()
var structure = [TableStructure]()
private func fetchJSON() {
guard let url = URL(string: "\(URL.url)example"),
let value = name.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)
else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = "item1=\(value)&item2=\(value)".data(using: .utf8)
URLSession.shared.dataTask(with: request) { data, _, error in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
self.structure.sort { $1. allowdate < $0.allowdate }
let res = try decoder.decode([TableStructure].self, from: data)
let grouped = Dictionary(grouping: res, by: { $0. allowdate })
let keys = grouped.keys.sorted()
self.sections = keys.map({TableSection(date: $0, items: grouped[$0]!)})
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch {
print(error)
}
}.resume()
}
JSON:
[
{
"person": "Jack",
"allowdate": "March 26th 2020",
"ready_time": "10:00 am"
}
]
To decode this JSON I am using the following structure:
struct TableSections {
let date : String
var items : [TableStructure]
}
struct TableStructure: Decodable {
let person: String
let allowdate: String
let ready_time: String
enum CodingKeys : String, CodingKey {
case person, allowdate, ready_time
}
}
Check this URL:
https://nsdateformatter.com
It will help you you to try different DateFormatter.
Now for your scenario, Try changing the struct like this:
struct TableStructure: Decodable {
let person: String
let allowdate: Date?
let ready_time: String
enum CodingKeys : String, CodingKey {
case person, allowdate, ready_time
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.person = try values.decode(String.self, forKey: .person)
self.ready_time = try values.decode(String.self, forKey: .ready_time)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM d'th',yyyy"
let allowDateStringValue = try values.decode(String.self, forKey: .allowdate)
self.allowdate = dateFormatter.date(from: allowDateStringValue)
}
}
and you can sort the array as:
structure.sort { (firstStructure, secondStructure) -> Bool in
if let firstDate = firstStructure.allowDate, let secondDate = secondStructure.allowDate {
return firstDate.timeIntervalSince1970 < secondDate.timeIntervalSince1970
}
return false
}
If you don't want to change your struct format then you can go like this:
struct TableStructure: Decodable {
let person: String
let allowdate: String
let ready_time: String
enum CodingKeys : String, CodingKey {
case person, allowdate, ready_time
}
}
and while sorting :
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM d'th',yyyy"
structure.sort { (firstStructure, secondStructure) -> Bool in
if let firstDate = dateFormatter.date(from: firstStructure.allowDate),
let secondDate = dateFormatter.date(from: secondStructure.allowDate) {
return firstDate.timeIntervalSince1970 < secondDate.timeIntervalSince1970
}
return false
}
I tried this in a playground. It seems to work with different ordinals:
import UIKit
let json = """
[
{
"person": "Jack",
"allowdate": "March 26th 2020",
"ready_time": "10:00 am"
},
{
"person": "Jill",
"allowdate": "January 1st 2020",
"ready_time": "1:00 pm"
},
{
"person": "Don",
"allowdate": "January 10th 2020",
"ready_time": "1:25 pm"
}
]
"""
struct TableStructure: Decodable {
// These first three come frm the json
let person: String
let allowdate: String
let readyTime: String
// We'll calculate this one later
let compareDate: Date
// This date formatter will read in dates like "January 10th 2020"
// So to use this, we will need to pull the ordinal letters off first
static let dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd yyyy"
return dateFormatter
}()
enum DecodeError: Error {
case compareDateError
}
enum CodingKeys: String, CodingKey {
case person
case allowdate
case readyTime
}
// We decode the three key/values that are passed down, and we calculate a date that we can use to compare
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
person = try values.decode(String.self, forKey: .person)
readyTime = try values.decode(String.self, forKey: .readyTime)
allowdate = try values.decode(String.self, forKey: .allowdate)
if let date = TableStructure.comparingDate(from: allowdate) {
compareDate = date
} else {
throw DecodeError.compareDateError
}
}
// We pull the ordinal letters off of the date, and are left with something cleaner
// A regex could make this much simpler, but me and regex's, we don't get along so great
static func comparingDate(from dateString: String) -> Date? {
var datePurgedArray = dateString.split(separator: " ")
if datePurgedArray.count == 3 {
datePurgedArray[1] = datePurgedArray[1].filter("0123456789.".contains)
let newDateString = datePurgedArray.joined(separator:" ")
print(newDateString)
return TableStructure.dateFormatter.date(from: newDateString)
} else {
return nil
}
}
}
if let jsonData = json.data(using: .utf8) {
print("json Data is \(jsonData)")
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let array = try decoder.decode([TableStructure].self, from: jsonData).sorted { $0.compareDate < $1.compareDate }
print("array is \(array)")
} catch {
print(error.localizedDescription + "could not decode array")
}
} else {
print("could not get data from json")
}
The string date format cannot be sorted reliably.
You have to decode the date string as Date. That's what the date decoding strategies are designed for.
There is one problem: DateFormatter doesn't support literal ordinal date strings like 1st, you have to remove st, nd, rd, th. The most efficient way is replacingOccurrences with regularExpression option.
Declare the struct (once again the CodingKeys are not needed and name the struct members camelCased)
struct TableStructure: Decodable {
let person: String
let allowdate: Date
let readyTime: String
}
and add the strategy
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .custom({ decoder -> Date in
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
let trimmedString = dateString.replacingOccurrences(of: "(st|nd|rd|th) ", with: " ", options: .regularExpression)
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "MMMM dd yyyy"
guard let result = formatter.date(from: trimmedString) else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "Wrong date format")}
return result
})
self.structure.sort { $1. allowdate < $0.allowdate }
let res = try decoder.decode([TableStructure].self, from: data)
let grouped = Dictionary(grouping: res, by: { $0. allowdate })
let keys = grouped.keys.sorted()
self.sections = keys.map({TableSection(date: $0, items: grouped[$0]!)})
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Consider that a Date is printed with a default date format. If you need a custom date format you have to add a second date formatter
I am trying to map my data to Model.
Where I am using Firestore snapshot listener, to get data.
here, I am getting data and mapping to "User" model that;
do{
let user = try User(dictionary: tempUserDic)
print("\(user.firstName)")
}
catch{
print("error occurred")
}
Here is my Model:
struct User {
let firstName: String
// var lon: Double = 0.0
// var refresh:Int = 0
// var createdOn: Timestamp = Timestamp()
}
//Testing Codable
extension User: Codable {
init(dictionary: [String: Any]) throws {
self = try JSONDecoder().decode(User.self, from: JSONSerialization.data(withJSONObject: dictionary))
}
private enum CodingKeys: String, CodingKey {
case firstName = "firstName"
}
}
Correct me if I am wrong.
Crashing because I am getting "Timestamp" in data.
Data getting from listener :
User Dictionary:
[\"firstName\": Ruchira,
\"lastInteraction\": FIRTimestamp: seconds=1576566738 nanoseconds=846000000>]"
How to map "Timestamp" to Model?
Tried "CodableFirstore" https://github.com/alickbass/CodableFirebase
An approach is to create an extension to type Dictionary that coverts a dictionary to any other type, but automatically modifies Date and Timestamp types to writeable JSON strings.
This is the code:
extension Dictionary {
func decodeTo<T>(_ type: T.Type) -> T? where T: Decodable {
var dict = self
// This block will change any Date and Timestamp type to Strings
dict.filter {
$0.value is Date || $0.value is Timestamp
}.forEach {
if $0.value is Date {
let date = $0.value as? Date ?? Date()
dict[$0.key] = date.timestampString as? Value
} else if $0.value is Timestamp {
let date = $0.value as? Timestamp ?? Timestamp()
dict[$0.key] = date.dateValue().timestampString as? Value
}
}
let jsonData = (try? JSONSerialization.data(withJSONObject: dict, options: [])) ?? nil
if let jsonData {
return (try? JSONDecoder().decode(type, from: jsonData)) ?? nil
} else {
return nil
}
}
}
The .timestampString method is also declared in an extension for type Date:
extension Date {
var timestampString: String {
Date.timestampFormatter.string(from: self)
}
static private var timestampFormatter: DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = TimeZone(identifier: "UTC")
return dateFormatter
}
}
Usage, like in the case of the question:
let user = tempUserDict.decodeTo(User.self)
I solved this by converting the FIRTimestamp fields to Double (seconds) so the JSONSerialization could parse it accordingly.
let items: [T] = documents.compactMap { query in
var data = query.data() // get a copy of the data to be modified.
// If any of the fields value is a `FIRTimestamp` we replace it for a `Double`.
if let index = (data.keys.firstIndex{ data[$0] is FIRTimestamp }) {
// Convert the field to `Timestamp`
let timestamp: Timestamp = data[data.keys[index]] as! Timestamp
// Get the seconds of it and replace it on the `copy` of `data`.
data[data.keys[index]] = timestamp.seconds
}
// This should not complain anymore.
guard let data = try? JSONSerialization.data(
withJSONObject: data,
options: .prettyPrinted
) else { return nil }
// Make sure your decoder setups the decoding strategy to `. secondsSince1970` (see timestamp.seconds documentation).
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
return try? decoder.decode(T.self, from: data)
}
// Use now your beautiful `items`
return .success(items)
Basically, I have an app on Firebase. The thing is, when Firebase sorts the data, instead of a chronological order, it muddles the data.
When I went online and search why, I found that it was because I was using the snapshot.value instead of snapshot.children.
However, I'm not completely sure how to change the code accordingly, could someone help?
Here is the code:
func retrieveChatLog() {
FIRDatabase.database().reference().child("chats").child(chatID).observe(.value, with: {(snapshot) in
let chats = snapshot.value as! [String : AnyObject]
self.messages.removeAll()
for (_, value) in chats {
if let sender = value["sender"], let message = value["message"], let senderID = value["senderUID"], let date = value["date"] {
let messageToShow = Message()
messageToShow.message = message as! String
messageToShow.sender = sender as! String
messageToShow.senderUID = senderID as! String
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
let curDate = formatter.date(from: date as! String)
messageToShow.date = curDate as! Date
if messageToShow.senderUID != "" {
self.messages.append(messageToShow)
}
}
}
self.tableView.reloadData()
})
FIRDatabase.database().reference().removeAllObservers()
}
The problem isn't because you use snapshot.value. You can use .value or .childAdded. The problem is, if you use .value, you don't want to cast the snapshots to a dictionary because dictionaries don't preserve order. Instead, you're going to want to cast to an array to preserve order. Here's one way you could resolve this:
FIRDatabase.database().reference().child("chats").child(chatID).observe(.value, with: {(snapshot) in
let chats = snapshot.children.allObjects as! [FIRDataSnapshot]
self.messages.removeAll()
for chat in chats {
if let value = chat.value as? [String: AnyObject] {
if let sender = value["sender"], let message = value["message"], let senderID = value["senderUID"], let date = value["date"] {
let messageToShow = Message()
messageToShow.message = message as! String
messageToShow.sender = sender as! String
messageToShow.senderUID = senderID as! String
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
let curDate = formatter.date(from: date as! String)
messageToShow.date = curDate as! Date
if messageToShow.senderUID != "" {
self.messages.append(messageToShow)
}
}
}
}
self.tableView.reloadData()
})
FIRDatabase.database().reference().removeAllObservers()
}
Change this line
FIRDatabase.database().reference().child("chats").child(chatID).observe(.value, with: {(snapshot) in...
To this
FIRDatabase.database().reference().child("chats").child(chatID).observe(.childAdded, with: {(snapshot) in
There is an accepted answer but I wanted to provide another solution that may be a bit tighter and more expandable.
It starts with a class to hold the messages. In this case I am keeping just the firebase key and timestamp but other vars could easily be added. You'll note the timestamp var that is read from Firebase in the same format: dd.mm.yy. This would be useful for sorting if needed. Also note that if you want to display a nicely formatted mm/dd/yyyy format, it's available though the formattedDate computed property.
The messagesArray is an array of MessageClass objects which can be used as a datasource for a tableView for example.
Finally, the loadMessages function to load in all of the messages. As mentioned in the other answer, casting the Snapshot to a dictionary loses ordering guarantee. However, if we iterate over the snapshot directly, the ordering stays intact.
class MessageClass {
var timestamp: String
var fbKey: String
var formattedDate: String {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
let d = formatter.date(from: timestamp)
let outputFormattter = DateFormatter()
outputFormattter.dateFormat = "MM/dd/yyyy"
let finalDate = outputFormattter.string(from: d!)
return finalDate
}
init(withSnap: DataSnapshot ) {
let snapDict = withSnap.value as! [String: AnyObject]
self.timestamp = snapDict["timestamp"] as! String
self.fbKey = withSnap.key
}
}
var messagesArray = [MessageClass]()
func doButton0Action() {
let messagesRef = self.ref.child("messages")
messagesRef.observe(.value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let m = MessageClass(withSnap: snap)
self.messagesArray.append(m)
}
for msg in self.messagesArray { //test code to print the array once loaded
print("key: \(msg.fbKey) date: \(msg.formattedDate)")
}
})
}
This code is very verbose and could be condensed considerably but it's very readable. (it needs guards and error checking as well).
I would strongly encourage you to store your timestamps in a
yyyymmddhhmmss
format in firebase. It lends itself to sorting / querying
Also, as a side-note, instead of relying on the date the node was created (by key) to keep your ordering, consider leveraging the timestamp when reading in the nodes using .order(by: timestamp). That will guarantee they are always in the correct order even if messages are changed around or the keys are modified.
In my Application I create an array of "NSDate" in order to send local notifications.
The values saved are "UUID" and "deadline" and they are saved using let gameDictionary = NSUserDefaults.standardUserDefaults().dictionaryForKey(GAME_INFO) ?? [:]
The result is somenting similar to this:
[{
UUID = "546C5E4D-CFEE-42F3-9010-9936753D17D85";
deadline = "2015-12-25 15:44:26 +0000";
}, {
UUID = "7C030614-C93C-4EB9-AD0A-93096848FDC7A";
deadline = "2015-12-25 15:43:15 +0000";
}]
What I am trying to achieve is to compare the "deadline" values with the current date and if the deadline is before than current date the values need to be removed from the array.
func compareDeadline() {
let gameDictionary = NSUserDefaults.standardUserDefaults().dictionaryForKey(GAME_INFO) ?? [:]
var items = Array(gameDictionary.values)
for i in 0..<items.count {
let dateNotification = items[i]["deadline"]!! as! NSDate
print(dateNotification)
var isOverdue: Bool {
return (NSDate().compare(dateNotification) == NSComparisonResult.OrderedDescending) // deadline is earlier than current date
}
print(isOverdue)
if (isOverdue == true){
items.removeAtIndex(i)
}
}
}
When I try to remove the values from the array I get Fatal Error: Array index out of range
Any Idea How can I solve this?
You should use the .filter method on the array to remove anything that you don't want in that array. The result is a new array with just the filtered results.
.filter requires you to set the filter criteria in a closure that you send into it
Here is a good article on how to use it
You can use filter method of swift array
For example to filter even numbers in array:
func isEven(number: Int) -> Bool {
return number % 2 == 0
}
evens = Array(1...10).filter(isEven)
println(evens)
There are a few problems. The reason you are getting an error is because you cannot remove elements while iterating inside for-in block. You can filter the items with the following code:
func compareDeadline() {
let gameDictionary = NSUserDefaults.standardUserDefaults().dictionaryForKey(GAME_INFO) ?? [:]
let items = Array(gameDictionary.values)
let currentDate = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZ"
let filteredItems = items.flatMap({
guard let stringDeadline = $0["deadline"] as? String, let deadline = dateFormatter.dateFromString(stringDeadline) else {
return nil
}
return deadline
}).filter({
currentDate.compare($0) == .OrderedDescending
})
}
I have a bunch of users on my message app, fetching my "messages" class I need to get sender's first and last name and profile image from their Parse profile on my app in order to show them in each message on the tableView.
I just want to show in tableView the name of users in class "messages" contained in the column "sender" wich contains pointers to PFUsers (of which I need "first_name", "last_name", "profile_picture")
my users class
my message class
update!
can't get where is the problem, if I downCast something, something else must be changed. here the updated code:
findTimeLineDataQuery.includeKey("sender")
findTimeLineDataQuery.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) in
if let objects = objects where error == nil {
var chats:(timelinechatsData: [String], chatsDate: [NSDate]) = ([], []) //date might be NSDate
var message: (messageObjts: [String], messageSender: [String]) = ([], [])
var datesToString: [String] {
get {
var stringDates:[String] = []
let formatter = NSDateFormatter()
formatter.dateFormat = "dd-MM-yyyy" //change the format as you wish
for date in dates {
stringDates.append(formatter.stringFromDate(date))
}
return stringDates
}
}
for singleObject in objects {
if let user = singleObject["sender"] as? PFObject {
let first_name = user["first_name"] as! String
let last_name = user["last_name"] as! String
//Cast it to how you saved it. I can't see it from the picture so I assumed you saved it as NSData
let picture = user["picture"] as! NSData
self.picturesProfilesArray.append(picture)
//once you fetch the user data, you can save it in a dictionary or however you want and later call it from cellForRowAtIndex
}
if let stringData = singleObject["message"] as? String {
chats.timelinechatsData.append(stringData)
if let messageDate = singleObject.createdAt {
chats.chatsDate.append(messageDate!)
}
}
//new
if let messageObject = singleObject["messageObject"] as? String {
message.messageObjts.append(messageObject)
}
//new senderNickname
if let messageSender = singleObject["senderNickname"] as? String {
message.messageSender.append(messageSender)
}
}
//update self
dispatch_async(dispatch_get_main_queue()) {
self.timelineChatsDataArray += chats.timelinechatsData
self.chatsDateArray += datesToString
self.messageObjectArray += message.messageObjts
self.messageSenderArray += message.messageSender
self.tableView.reloadData()
}
}
})
changes
so my
var chatsDateArray : [NSDate] = []
and
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy HH:mm"
let useDate = dateFormatter.stringFromDate(self.chatsDateArray[indexPath.row])
cell.dateMessageLabel.text = useDate
should become
var chatsDateArray : [String] = []
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy HH:mm"
let useDate = String(self.chatsDateArray[indexPath.row])
cell.dateMessageLabel.text = useDate
but this causes:
Initialization of immutable value 'first_name' was never used; consider replacing with assignment to '_' or removing it
Initialization of immutable value 'last_name' was never used; consider replacing with assignment to '_' or removing it
this disappears by changing var chat (chatsDate) back to string
, but this causes
Cannot convert value of type 'NSDate' to expected argument type 'String'
on
if let messageDate = singleObject.createdAt {
chats.chatsDate.append(messageDate!)
}
}
You can use 'includeKey' to access pointer values of related classes
findTimeLineDataQuery.includeKey("sender")
findTimeLineDataQuery.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) in
if let objects = objects where error == nil {
var chats:(timelinechatsData: [String], chatsDate: [NSDate]) = ([], []) //date might be NSDate
var message: (messageObjts: [String], messageSender: [String]) = ([], [])
var datesToString: [String] {
get {
var stringDates:[String] = []
let formatter = NSDateFormatter()
formatter.dateFormat = "dd-MM-yyyy" //change the format as you wish
for date in dates {
stringDates.append(formatter.stringFromDate(date))
}
return stringDates
}
}
for singleObject in objects {
if let user = singleObject["sender"] as! PFObject {
let first_name = user["first_name"] as! String
let last_name = user["last_name"] as! String
//Cast it to how you saved it. I can't see it from the picture so I assumed you saved it as NSData
let picture = user["picture"] as! NSData
picturesProfilesArray.append(picture)
//once you fetch the user data, you can save it in a dictionary or however you want and later call it from cellForRowAtIndex
}
if let stringData = singleObject["message"] as? String {
chats.timelinechatsData.append(stringData)
if let messageDate = singleObject.createdAt {
chats.chatsDate.append(messageDate)
}
}
//new
if let messageObject = singleObject["messageObject"] as? String {
message.messageObjts.append(messageObject)
}
//new senderNickname
if let messageSender = singleObject["senderNickname"] as? String {
message.messageSender.append(messageSender)
}
}
//update self
dispatch_async(dispatch_get_main_queue()) {
self.timelineChatsDataArray += chats.timelinechatsData
self.chatsDateArray += datesToString
self.messageObjectArray += message.messageObjts
self.messageSenderArray += message.messageSender
self.tableView.reloadData()
}
}
})