Saving `Date` to `CoreData` does not work - ios

I am trying to save a Date into a textfield and have that save into CoreData. I have the textfield set up and am able to use the date picker just fine with the NSDateFormatter but I am having trouble with getting it to save into the textfield into CoreData.

extension NSDate{
var stringValue: String{
return self.toString()
}
func toString() -> String {
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let str = formatter.stringFromDate(self)
return str
}
}
extension String{
var dateValue: NSDate?{
return self.toDate()
}
func toDate() -> NSDate? {
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
if let date = formatter.dateFromString(self) {
return date
}else{
// if format failed, Put some code here
return nil // an example
}
}
}
add this befor your class or another swift file,
then change textFieldDDate.NSDate = ddate to:
textFieldDDate.text = ddate.stringValue
you can only use text(String!) with UITextField,also only NSDate in your newItem.ddate.
change newItem.ddate = textFieldDDate.text to
newItem.ddate = textFieldDDate.text.dateValue

I see var ddate = data.valueForKey("ddate"), I guess it is type of NSDate? maybe you need change it to String, it can't be just use as!(?) String,if I am right, you need use my code of extension NSDate{} to change it too.

I checked your codes, just find some lines maybe it is save data to coreData:
if segue.identifier == "update" {
var selectedItem: NSManagedObject = myDivelog[self.tableView.indexPathForSelectedRow()!.row] as! NSManagedObject
let ADLVC: AddDiveLogViewController = segue.destinationViewController as! AddDiveLogViewController
ADLVC.divenumber = selectedItem.valueForKey("divenumber") as! String
ADLVC.ddate = selectedItem.valueForKey("ddate") as! NSDate
ADLVC.divelocation = selectedItem.valueForKey("divelocation") as! String
ADLVC.existingItem = selectedItem
}
am I right? I get this link of an answer of how to save a Data to CoreData for you. because maybe something wrong in there.
here it is https://stackoverflow.com/a/26025022/5113355

Related

To receive by Swift DateFormatter utc?

I would like to receive the date value in the api value as utc. I looked up the stackoverflow.
There was a similar case, but we couldn't solve it because it was different from me.
The server (POSTMAN(db) stores the value "b_date": 1602813891.
link >> Dateformatter issue in swift
mycode
var ViewItem: BoardView?
func DetailViewList() {
DispatchQueue.main.async {
self.txtUserName.text = String(ViewItem.userId ?? "")
self.txtCount.text = String(ViewItem.b_count ?? 0)
}
}
func utcToLocal(utcDate: String, dateFormat: String) -> String {
let dfFormat = DateFormatter()
dfFormat.dateFormat = dateFormat
dfFormat.timeZone = TimeZone(abbreviation: "UTC")
let dtUtcDate = dfFormat.date(from: utcDate)
dfFormat.timeZone = TimeZone.current
dfFormat.dateFormat = dateFormat
txtDate.text = Int(ViewItem?.b_date) // ERROR [Cannot invoke initializer for type 'Int' with an argument list of type '(Int?)'] , Overloads for 'Int' exist with these partially matching parameter lists: (CGFloat), (Double), (Float), (Float80), (Int64), (Word), (__shared NSNumber)
return dfFormat.string(from: dtUtcDate!)
}
jsonData
struct BoardView: Codable {
var b_date: Int?
var b_count: Int?
var userId: String?
}

Save array of Days in Swift 5

So i have created a class for a Day and for a Drink. and I'm trying to track how much you drink in a day, but I'm struggling with saving multiple days. I'm currently managing to save the current day(with the amount drunk that day) but i don't know how to save more than one day.
I want to save an array of type Day with all the days. how can i do this?
This is my Day class:
public class Day: NSObject {
var date: Date
var goalAmount: Drink
var consumedAmount: Drink
func saveDay() {
let formatting = DateFormatter()
formatting.dateFormat = "EEEE - dd/mm/yy"
UserDefaults.standard.set(formatting.string(from: date), forKey: "date")
UserDefaults.standard.set(goalAmount.amountOfDrink, forKey: "goal")
UserDefaults.standard.set(consumedAmount.amountOfDrink, forKey: "consumed")
}
func loadDay() {
let rawDate = UserDefaults.standard.value(forKey: "date") as? String ?? ""
let formatter = DateFormatter()
formatter.dateFormat = "EEEE - dd/mm/yy"
date = formatter.date(from: rawDate)!
goalAmount.amountOfDrink = UserDefaults.standard.float(forKey: "goal")
consumedAmount.amountOfDrink = UserDefaults.standard.float(forKey: "consumed")
}
}
This is my Drink class:
class Drink: NSObject {
var typeOfDrink: String
var amountOfDrink: Float
}
i am calling saveDay() when there are any changes made to the day, and then loadDay() when the app opens.
A better approach would be is to store the object of the class in userDefaults instead of storing particular properties of that class. And use [Date] instead of Date to save multiple days
For this first, you have Serialize the object to store in userDefaults and Deserialize to fetch the data from userDefaults.
import Foundation
class Day: Codable {
var date = Date()
var goalAmount: Drink
var consumedAmount: Drink
init(date: Date, goalAmount: Drink,consumedAmount: Drink ) {
self.date = date
self.goalAmount = goalAmount
self.consumedAmount = consumedAmount
}
static func saveDay(_ day : [Day]) {
do {
let object = try JSONEncoder().encode(day)
UserDefaults.standard.set(object, forKey: "days")
} catch {
print(error)
}
}
static func loadDay() {
let decoder = JSONDecoder()
if let object = UserDefaults.standard.value(forKey: "days") as? Data {
do {
let days = try decoder.decode([Day].self, from: object)
for day in days {
print("Date - ", day.date)
print("Goal Amount - ", day.goalAmount)
print("Consumed Amount - ",day.consumedAmount)
print("----------------------------------------------")
}
} catch {
print(error)
}
} else {
print("unable to fetch the data from day key in user defaults")
}
}
}
class Drink: Codable {
var typeOfDrink: String
var amountOfDrink: Float
init(typeOfDrink: String,amountOfDrink: Float ) {
self.typeOfDrink = typeOfDrink
self.amountOfDrink = amountOfDrink
}
}
Use saveAndGet() method to store and fetch details from userDefaults
func saveAndGet() {
// use any formats to format the dates
let date = Date()
let goalAmount = Drink(typeOfDrink: "Water", amountOfDrink: 5.0)
let consumedAmount = Drink(typeOfDrink: "Water", amountOfDrink: 3.0)
let day1 = Day(date: date, goalAmount: goalAmount, consumedAmount: consumedAmount)
let day2 = Day(date: date, goalAmount: goalAmount, consumedAmount: consumedAmount)
let day3 = Day(date: date, goalAmount: goalAmount, consumedAmount: consumedAmount)
let day4 = Day(date: date, goalAmount: goalAmount, consumedAmount: consumedAmount)
let days = [day1, day2, day3, day4]
Day.saveDay(days)
Day.loadDay()
}
1) You need to create array of object for this :
goalAmount = [Drink]()
var date = [Date]()
and append with each new element.
you can also add date variable inside your drink class.
2) you can also create array of dictionary:
var userData = [String : Any]()
key will be you date and Any contain related to drink data in Any you can store Anything.

Current Location TimeZone abbrevation

I want to show timezone as "IST", "EST", etc.
That seems to be simple but there is an issue.When I use following code:
let timeZone = TimeZone.current.abbreviation()
For India I get "GMT+5:30" but for Toronto, I get "EDT".
Please help, or let me know some other way to show such abbreviations.
EDIT 1
I came up with a workaround but still, sometimes I get some weird timezones:
func getTimeZoneAbbrevation() -> String {
var returnTimeZone = ""
let timezone = TimeZone.current.identifier
let dict = TimeZone.abbreviationDictionary
for (key,value) in dict {
if value == timezone {
returnTimeZone = key
break
}
}
if returnTimeZone == "" {
if let timezone = NSTimeZone.default.abbreviation() {
returnTimeZone = timezone
}
}
return returnTimeZone
}
EDIT 2:
Try this
let timeZoneDict = TimeZone.abbreviationDictionary.filter {
$0.value == TimeZone.current.identifier
}
if !timeZoneDict.isEmpty {
let timeZone = timeZoneDict.first?.key
print(timeZone)
}
This should work.
let someTime = TimeZone(identifier: "America/Toronto")
let timezone = someTime?.abbreviation()
Now timezone contains value "EDT" so you can directly use this.
Just FYI if you want to check for these identifier so you can get it from
var timeZoneIdentifiers: [String] { return TimeZone.knownTimeZoneIdentifiers }
I hope this will help now.

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

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

How to get the latest date from array in Swift

I have an array of dates. I need to find the latest one. Can someone show me an example?
You can make NSDate conform to Comparable, as shown here
Given this, you can then use maxElement to find the maximum (i.e. the latest).
import Foundation
extension NSDate: Comparable { }
public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.isEqualToDate(rhs)
}
public func <(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.compare(rhs) == .OrderedAscending
}
let dates = [NSDate(), NSDate()]
let maxDate = maxElement(dates)
Note, maxElements goes bang for empty arrays so you may want to guard it with isEmpty:
let maxDate = dates.isEmpty ? nil : Optional(maxElement(dates))
Or, if you don’t want to go the extension route:
if let fst = dates.first {
let maxDate = dropFirst(dates).reduce(fst) {
$0.laterDate($1)
}
}
or, to return an optional:
let maxDate = dates.reduce(nil) {
(lhs: NSDate?, rhs: NSDate?)->NSDate? in
lhs.flatMap({rhs?.laterDate($0)}) ?? rhs
}
You can make use of reduce:
guard let dates = dates, !dates.isEmpty else { return nil }
dates.reduce(Date.distantPast) { $0 > $1 ? $0 : $1 }
Edit: Handle empty or nil array
Swift has Array methods for getting both the min and max values for dates.
You can use the following:
let maxDate = myArrayOfDates.max()
let minDate = myArrayOfDates.min()
So if you have an array of dates like so:
And here is the code if you want to copy it:
let now = Date()
let dates = [
now,
now.addingTimeInterval(120),
now.addingTimeInterval(60)
]
let sut = dates.max()
print(sut!)
Hope this helps someone!
Run this in your playground
var dates = [NSDate]()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
let date1 = dateFormatter.dateFromString("02-06-1987")
let date2 = dateFormatter.dateFromString("02-06-2001")
let date3 = dateFormatter.dateFromString("02-06-2010")
//var date1 = NSDate()
dates.append(date3!)
dates.append(date1!)
dates.append(date2!)
var maxDate = dates[0]
for i in 0...dates.count-1
{
if(maxDate.compare(dates[i]).rawValue == -1){
maxDate = dates[i]
println(maxDate)
}
println(maxDate)
}
println(maxDate.description)
have a good day :)

Resources