Swift: how to get Parse's many user's name and photo - ios

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()
}
}
})

Related

Sort objects by date/Firestore

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.

iOS error 'Invalid type in JSON write (FIRTimestamp)'

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)

How can I notify client side so that a certain post does not exist anymore?

The app I made is post/thread based. Every time a client submits a post, all the other clients receive the post as they refresh the tableview. The newly received post is then saved using core data. Ultimately, for every client that refreshes, the function fetchPosts is called. fetchPost is an asynchronous function that returns a callback twice. First, when it receives posts from core data and then when server sync is finished and the live data has been received.
The problem with this function is that it will always return in the first callback all the posts, including the one that was deleted (by other clients).
What is a proper way to deal with that? Here is my code:
static func fetchPosts(lastPost:Topic?,subject:String,complition: #escaping (_ topics:[Topic?],_ newData:Bool)->()){
var topics:[Topic?] = []
//Check Ceche. FIRST PART
do {
let fetchRequest : NSFetchRequest<DPost> = DPost.fetchRequest()
fetchRequest.fetchLimit = 20
if lastPost == nil {
fetchRequest.predicate = NSPredicate(format: "created < %# AND subject = %# ", NSDate(),subject)
}else{
fetchRequest.predicate = NSPredicate(format: "created < %# AND subject = %#", argumentArray: [lastPost?.date as Any, subject])
}
let fetchedResults = try context.fetch(fetchRequest)
// _ = index
for (_, aPost) in fetchedResults.enumerated() {
topics.append(Topic(id: aPost.id!, title: aPost.title!, date: aPost.created! as Date, image: aPost.imageAddress, posterUsername: aPost.username!, posterUserid: aPost.userId!,posterImage: aPost.posterImageAddress))
//TODO: add subject id
}
}
catch {
print ("fetch task failed", error)
}
//First Callback
complition(topics,true)
//Second part
//Check server.
topics = []
var data:[String:Any] = [:]
data[K.UserInformation.sessionID] = User.currentUser!.sessionID
data[K.UserInformation.udid] = User.currentUser?.udid
if topics.last == nil {
data[K.TopicInformation.data] = "000000000000000000000000"
} else {
data[K.TopicInformation.data] = lastPost?.id
}
data[K.TopicInformation.subject] = subject
HTTPRequest.appSession.data_request(url_to_request: K.Server.domain+":8443/getPosts",method: HTTPRequest.HTTPRequestMethod.post, data: HTTPRequest.toJSON(dict: data)) { (resStr:String?) in
// return respond with information about the registrant status.
if resStr != nil{
let respond = HTTPRequest.toDict(jsonStr: resStr!)
if (respond[K.Status.success] != nil){
let postDictList = respond[K.Status.success] as! [[String:Any]]
if postDictList.count == 0 {
//Second callback
complition(topics,true)
return
}
for dict in postDictList {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
var topic:Topic? = nil
if let date = formatter.date(from: dict[K.TopicInformation.date] as! String) {
context.mergePolicy = NSOverwriteMergePolicy
let cPost = NSEntityDescription.insertNewObject(forEntityName: "CDPost", into: context) as! DPost
cPost.id = dict[K.TopicInformation.id] as? String
cPost.title = dict[K.TopicInformation.title] as? String
cPost.created = date as NSDate
cPost.imageAddress = dict[K.TopicInformation.postImageAddress] as? String
cPost.username = dict[K.TopicInformation.posterUsername] as? String
cPost.userId = dict[K.TopicInformation.posterUserid] as? String
cPost.posterImageAddress = dict[K.TopicInformation.posterImageAddress] as? String
cPost.subject = dict[K.TopicInformation.subject] as? String
do{
try context.save()
}
catch{
fatalError("Failure to save context: \(error)")
}
topic = Topic(id: dict[K.TopicInformation.id] as! String,
title: dict[K.TopicInformation.title] as! String,
date: date,
image: dict[K.TopicInformation.postImageAddress] as? String,
posterUsername: dict[K.TopicInformation.posterUsername] as! String,
posterUserid: dict[K.TopicInformation.posterUserid] as! String, posterImage: dict[K.TopicInformation.posterImageAddress] as? String)
}
topics.append(topic!)
}
complition(topics,true)
return
}
if(respond[K.Status.error] != nil){
print(respond["errmsg"] as! String)
}
}
The server side is written with NodeJS Mongodb is the database I'm using. Let me know if it's relevant so can edit out/in some tags.
If you have fetch limit, I dont think you can do it locally by compare the fetched posts and the stored posts in your CoreData, best is add an unread tag to the post and update it with your API, when fetch then can fetch both deleted and normal posts with unread tag, another idea is use last logged in time and fetch all post from that time, including deleted post

Change label with Alamofire

I want to put the information I get from the API into the corresponding Label inside, I use the Alamofire to get the API information and put the corresponding Label inside, but I found that my Label text has not been changed, would like to ask this happen What's the problem? Who can answer me for me? Thank you
Here is my Information class:
import Foundation
import Alamofire
class Information {
var account:String?
var date:String?
var name:String?
var sex:String?
var born:String?
var phoneNumber:String?
var email:String?
init(account:String,date:String,name:String,sex:String,born:String,phoneNumber:String,email:String) {
self.account = account
self.date = date
self.name = name
self.sex = sex
self.born = born
self.phoneNumber = phoneNumber
self.email = email
}
typealias DownlaodComplete = () -> ()
func downlaodInformation(completion:#escaping DownlaodComplete) {
Alamofire.request("http://163.18.22.78:81/api/Information/A1001a").responseJSON { response in
print(response)
if let json = response.result.value as? Dictionary<String,Any> {
guard let account = json["Account"] as? String ,let date = json["Date"] as? String , let name = json["Name"] as? String , let sex = json["Sex"] as? String , let born = json["Born"] as? String , let phoneNumber = json["PhoneNumber"] as? String , let email = json["Email"] as? String else {
return
}
self.account = account
self.date = date
self.name = name
self.sex = sex
self.born = born
self.phoneNumber = phoneNumber
self.email = email
completion()
}
}
}
}
And here is my ViewController:
var information:Information?
override func viewDidLoad() {
super.viewDidLoad()
if let currentInformation = information {
currentInformation.downlaodInformation {
self.accountLabel.text = currentInformation.account
self.dateLabel.text = currentInformation.date
self.nameLabel.text = currentInformation.name
self.sexLabel.text = currentInformation.sex
self.bornLabel.text = currentInformation.born
self.phoneNumberLabel.text = currentInformation.phoneNumber
self.emailLabel.text = currentInformation.email
}
}
You need to use your completion block which will be called whenever Alamofire has finished the data request. You can also improve your code a bit by for example have a onCompletion block that passes an Information object and an onError block to display if you have any errors. Example below:
func downlaodInformation(parameterOne: String, parameterTwo: Int, onCompletion: #escaping (Information) -> Void, onError: #escaping(NSError) -> Void) {
Alamofire.request("http://163.18.22.78:81/api/Information/A1001a").responseJSON { response in
if let json = response.result.value as? Dictionary<String,Any> {
let account = json["Account"] as? String
let date = json["Date"] as? String
let name = json["Name"] as? String
let sex = json["Sex"] as? String
let born = json["Born"] as? String
let phoneNumber = json["PhoneNumber"] as? String
let email = json["Email"] as? String
let information = Information(account: account, date: date, name: name, sex: sex, born: born, phoneNumber: phoneNumber, email: email)
onCompletion(information)
} else {
onError(NSError(domain: "Error while getting data", code: 0, userInfo: nil))
}
}
}
Usage:
downlaodInformation(parameterOne: "someParam", parameterTwo: 123, onCompletion: { (currentInformation) in
print(currentInformation.account)
self.accountLabel.text = currentInformation.account
self.dateLabel.text = currentInformation.date
self.nameLabel.text = currentInformation.name
self.sexLabel.text = currentInformation.sex
self.bornLabel.text = currentInformation.born
self.phoneNumberLabel.text = currentInformation.phoneNumber
self.emailLabel.text = currentInformation.email
}) { (error) in
print(error.domain)
}
Here you declare information to be an Information optional
var information:Information?
But you don't give it an initial value, meaning that it is nil
In your viewDidLoad you do the right thing and check whether information has a value:
if let currentInformation = information
But I'm guessing it hasn't, because you haven't created an instance of it. Therefore you don't end up inside your if let loop and never calls downlaodInformation
So you need to create a new instance of Information before you can use it.
However
This leads to a problem with your Information class.
If I was to instantiate an Information object, I'd need to have:
account
date
name
sex
born
phoneNumber
email
Or..since you've created them as optionals, pass nil.
But that is not what you want, is it?
I'm guessing you'd like to do something along the lines of this in your ViewController:
let information = Information()
and then in viewDidLoad
information.downloadInformation( currrentInformation in
self.accountLabel.text = currentInformation.account
....
}
To do so you could change your Information to not take parameters to its constructor and then create another struct which would hold your data.
Something like:
struct Information {
var account:String?
var date:String?
var name:String?
var sex:String?
var born:String?
var phoneNumber:String?
var email:String?
}
class InformationLoader {
func downloadInformation(completion: (Information?) -> ()) {
Alamofire.request("http://163.18.22.78:81/api/Information/A1001a").responseJSON{ response in
print(response)
if let json = response.result.value as? Dictionary<String,Any> {
guard let account = json["Account"] as? String,
let date = json["Date"] as? String,
let name = json["Name"] as? String,
let sex = json["Sex"] as? String,
let born = json["Born"] as? String,
let phoneNumber = json["PhoneNumber"] as? String,
let email = json["Email"] as? String else {
completion(nil)
return
}
let information = Information(account: account, date: date, name: name, sex: sex, born: born, phoneNumber: phoneNumber, email: email)
completion(information)
}
}
}
And you'd need to change your code in the ViewController to:
let informationLoader:InformationLoader()
In viewDidLoad
informationLoader.downloadInformation{ currentInformation in
if let currentInformation = currentInformation {
//populate your textfields
self.accountLabel.text = currentInformation.account
....
}
}
Hope that makes sense and helps you.
Your code has a lot of mistakes, so here is a working variant. Better to call an updateUI or something like that from the closure. I hope this will help:
ViewController.swift:
class ViewController: UIViewController
{
#IBOutlet weak var accountLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
var information: Information?
override func viewDidLoad()
{
super.viewDidLoad()
information = Information.init(account: "aaaa", date: "dddd", name: "nnnn", sex: "ssss", born: "bbbb", phoneNumber: "pppp", email: "eeee")
information?.downlaodInformation(completion:
{
self.updateUI()
})
}
func updateUI()
{
print("called")
self.accountLabel.text = information?.account
self.dateLabel.text = information?.date
self.nameLabel.text = information?.name
/*self.sexLabel.text = currentInformation.sex
self.bornLabel.text = currentInformation.born
self.phoneNumberLabel.text = currentInformation.phoneNumber
self.emailLabel.text = currentInformation.email*/
}
}
Information.swift:
class Information
{
var account:String?
var date:String?
var name:String?
var sex:String?
var born:String?
var phoneNumber:String?
var email:String?
typealias DownlaodComplete = () -> ()
init(account:String,date:String,name:String,sex:String,born:String,phoneNumber:String,email:String) {
self.account = account
self.date = date
self.name = name
self.sex = sex
self.born = born
self.phoneNumber = phoneNumber
self.email = email
}
func downlaodInformation(completion:#escaping DownlaodComplete) {
Alamofire.request("http://163.18.22.78:81/api/Information/A1001a").responseJSON { response in
print(response)
completion()
if let json = response.result.value as? Dictionary<String,Any>
{
print("Dictionary done")
guard
let account = json["Account"] as? String,
let date = json["Date"] as? String ,
let name = json["Name"] as? String else
{
print("Parse error!")
return
}
self.account = account
self.date = date
self.name = name
/*self.sex = sex
self.born = born
self.phoneNumber = phoneNumber
self.email = email*/
completion()
}
}
}
}
Tested, and got the following response:
SUCCESS: {
Account = A1001a;
Born = 841031;
CarParking = "";
Date = "0001/1/1 \U4e0a\U5348 12:00:00";
Email = "zxc#gmail.com";
Name = Ray;
Phone = 09361811111;
Sex = "\U7537"; } called Dictionary done called

How to use reflection with Core Data and Swift

I'm trying to use reflection in Swift with Core Data entities, but when I execute the following code, my reflected var has only a reference for a super class, it didn't have a reference for any of it's attributes.
func printProperties() {
let mirror = reflect(self)
for var i = 0; i < mirror.count; i++ {
let (propertyName, childMirror) = mirror[i]
println("property name: \(propertyName)")
println("property value: \(childMirror.value)")
}
}
Does anyone have some idea why this happens?
Update: As suggested by Anderson in his answer I tried another approach and ended up with this code:
func loadFromJson(json: JSON) {
for attributeKey in self.entity.attributesByName.keys {
let attributeDescription = self.entity.propertiesByName[attributeKey]!
as! NSAttributeDescription
let attributeClassName = attributeDescription.attributeValueClassName
let jsonValue = json[(attributeKey as! String)]
var attributeValue: AnyObject? = attributeDescription.defaultValue
if jsonValue.type != .Null && attributeClassName != nil {
if attributeClassName == "NSNumber" {
attributeValue = jsonValue.number!
} else if attributeClassName == "NSString" {
attributeValue = jsonValue.string!
}
}
setValue(attributeValue, forKey: (attributeKey as! String))
}
}
I believe that this code can help you.
I wrote this extension to make a dictionary from a NSmanagedObject and it accesses all attributes and values of the object.
extension NSManagedObject {
func toDict() -> Dictionary<String, AnyObject>! {
let attributes = self.entity.attributesByName.keys
let relationships = self.entity.relationshipsByName.keys
var dict: [String: AnyObject] = [String: AnyObject]()
var dateFormater = NSDateFormatter()
dateFormater.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
for attribute in attributes {
if self.entity.propertiesByName[attribute]!.attributeValueClassName != nil && self.entity.propertiesByName[attribute]!.attributeValueClassName == "NSDate" {
let value: AnyObject? = self.valueForKey(attribute as! String)
if value != nil {
dict[attribute as! String] = dateFormater.stringFromDate(value as! NSDate)
} else {
dict[attribute as! String] = ""
}
} else {
let value: AnyObject? = self.valueForKey(attribute as! String)
dict[attribute as! String] = value
}
}
for attribute in relationships {
let relationship: NSManagedObject = self.valueForKey(attribute as! String) as! NSManagedObject
let value = relationship.valueForKey("key") as! String
dict[attribute as! String] = value
}
return dict
}
}
I hope to have helped you.

Resources