How to save label content - swift

in my TodoList I have a label that when add something in the Todo, show the date the day.
How can I save it? cause when I open my app I have always the date and time of when I open it.
Here is the code of the label with the date:
class TableViewCell: UITableViewCell {
#IBOutlet weak var Data: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
Data.text = String(describing: DateFormatter())
UserDefaults.standard.string(forKey: "Data")
let dataFormatter = DateFormatter()
dataFormatter.dateFormat = "dd/MM/yyyy H:mm a"
Data.text = dataFormatter.string(from: .init())
}
}

You can use UserDefaults.
UserDefaults.standard.set(value: Any?, forKey: String)
So, whenever you want to save you could do
UserDefaults.standard.set(value: YourValue, forKey: "Data")

First create global lazy variable for your DateFormatter since you don't want to create new one every time you need to set text.
lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy H:mm a"
return formatter
}()
then you can set text of label like this (rename outlet for UILabel to start with small capital letter)
data.text = dateFormatter.string(from: yourDate)
Now for manipulating with Date object with UserDefaults
Saving:
UserDefaults.standard.set(yourDate, forKey: "date")
Getting:
if let date = UserDefaults.standard.object(forKey: "date") as? Date {
... // here you can use `date` of type `Date`
}
One advice at the end. Since you're using UITableViewCell, I suppose that you have more then one Date object saved in UserDefaults. I would recommend you to start using some database like Core Data or Realm.

Move code inside setSelected to awakeFromNib
also i expect this UserDefaults.standard.string(forKey: "Data") to return a value , so someWhere you should have UserDefaults.standard.set(value:"----Any value", forKey: "Data")
guard let res = UserDefaults.standard.object(forKey: "Data") as? Date else { return }
let dataFormatter = DateFormatter()
dataFormatter.dateFormat = "dd/MM/yyyy H:mm a"
Data.text = dataFormatter.string(from:res)
For sett
UserDefaults.standard.set(Date(), forKey: "Data")
#IBOutlet weak var Data: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
UserDefaults.standard.set(Date(), forKey: "Data") // this line need to be placed where you need to store the date
guard let storedDate = UserDefaults.standard.object(forKey: "Data") as? Date else { return } // here you read the stored date
let dataFormatter = DateFormatter()
dataFormatter.dateFormat = "dd/MM/yy H:mm a"
Data.text = dataFormatter.string(from:storedDate)
}

Related

how to call function in Extension in swift?

I'm making an app but I'm confused about how to call the function in the extension file.
This is the code that I'm trying to call the function from the extension.
import UIKit
class RecipeTableViewCell: UITableViewCell {
#IBOutlet weak var commnetLabel: UILabel!
#IBOutlet weak var recipeImageView: UIImageView!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var recipeTypeLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func configureView(recipe: RecipeData){
commnetLabel.text = recipe.comment
recipeImageView.setImage(imageUrl: recipe.imageUrl)
// dateLabel.text = recipe.recordedAt => get something like 2020-10-01 11:08:42
dateLabel.text = setTemplate(strDate: recipe.recordedAt)
recipeTypeLabel.text = recipe.recipeType
}
}
In the configureView function, I used to write dateLabel.text = recipe.recordedAtto show the date to the app. I'm now trying to change how it is displayed, so I created an extension.
import Foundation
extension DateFormatter {
func setTemplate (strDate: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "ydMMM", options: 0, locale: Locale(identifier: "ja_JP"))
let result = dateFormatter.string(from: Date())
return result
}
}
I thought writing dateLabel.text = setTemplate(strDate: recipe.recordedAt) in configureView function enables to call setTemplate function and change my dateLabel's text. However, currently I'm getting
Use of unresolved identifier 'setTemplate'
and I'm confused about why and how to access to setTemplate function.
Could anyone tell me why I'm getting the error and what I'm doing wrong?
You probably meant to extend RecipeTableViewCell, not DateFormatter.
extension RecipeTableViewCell {
func setTemplate(strDate: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "ydMMM", options: 0, locale: Locale(identifier: "ja_JP"))
let result = dateFormatter.string(from: Date())
return result
}
}
If you extend DateFormatter, the function setTemplate is added to the class DateFormatter -- you can't access it from RecipeTableViewCell. But if you really wanted to extend DateFormatter, you could do it like this:
extension DateFormatter {
func setTemplate(strDate: String) -> String {
self.dateFormat = DateFormatter.dateFormat(fromTemplate: "ydMMM", options: 0, locale: Locale(identifier: "ja_JP"))
let result = self.string(from: Date())
return result
}
}
/// usage:
let formatter = DateFormatter()
dateLabel.text = formatter.setTemplate(strDate: recipe.recordedAt)
Extending DateFormatter directly lets you access setTemplate from anywhere (not just RecipeTableViewCell), so you might want to do this.
Your function is correct but you just need to make it static. Just tested in PLayground and it worked.
extension DateFormatter {
static func setTemplate (strDate: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "ydMMM", options: 0, locale: Locale(identifier: "ja_JP"))
let result = dateFormatter.string(from: Date())
return result
}
}

Printing a timestamp to a label from a button IB Function in Xcode (Swift)

I want to create a time stamp thats triggered to the current time when a button is pressed in one view controller and have it print to a label in another view controller.
Im using Xcode 11 and the most recent version of swift.
I Guess this is the function i have so far but dont know how to implement it to the button or the label I want it printed to:
func getDateDayAndTime(timestamp: NSNumber) -> String {
let date = Date(timeIntervalSince1970: Double(truncating: timestamp)/1000)
let calendar = Calendar.current
if calendar.isDateInToday(date) {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = NSTimeZone.local
dateFormatter.dateFormat = "hh:mm a"
let time = dateFormatter.string(from: date)
return time
}else if calendar.isDateInYesterday(date) {
return "Yesterday"
}
else if calendar.isDateInWeekend(date) {
let component = calendar.component(Calendar.Component.weekday, from: date)
return self.getDay(value: component)
} else {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = NSTimeZone.local
dateFormatter.dateFormat = "dd/MM/YY"
let time = dateFormatter.string(from: date)
return time
}
}
We can send the timestamp value from ViewController to SecondViewController as shown below,
import UIKit
class ViewController: UIViewController {
#IBAction func getTimeStampButtonAction(_ sender: Any) {
let timestampVal = NSDate().timeIntervalSince1970
let myTimeInterval = TimeInterval(timestampVal)
let timeStamp = NSDate(timeIntervalSince1970: TimeInterval(myTimeInterval))
let timeStampString = stringFromDate(timeStamp as Date)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let homeView = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
homeView.timeStamp = timeStampString
self.navigationController?.pushViewController(homeView, animated: true)
}
func stringFromDate(_ date: Date) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "dd MMM yyyy HH:mm" //yyyy
return formatter.string(from: date)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var TimeStampLabel: UILabel!
var timeStamp: String!
override func viewDidLoad() {
super.viewDidLoad()
TimeStampLabel.text = timeStamp
}
}
Function that returns current time:
func getTodayString() -> String{
let date = Date()
let calender = Calendar.current
let components = calender.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date)
let year = components.year
let month = components.month
let day = components.day
let hour = components.hour
let minute = components.minute
let second = components.second
let today_string = String(year!) + "-" + String(month!) + "-" + String(day!) + " " + String(hour!) + ":" + String(minute!) + ":" + String(second!)
return today_string
}
Button pressed:
#IBAction func buttonPressed(_ sender: Any) {
yourLabel.text = getTodayString()
}

How can I filter by specific date from realm object in swift?

I have a realm object with date property type of Date , and want to get list of items with specific date.
If I click specific date from calendar, for example 2020-03-06 , then it will present list of items which was created in 2020-03-06.
:: EDITED ::
Here is my realm object named "Profile" and there are dates from
2020-03-05 to 2020-03-08 .
Here is my Profile object and ProfileManager Singleton.
class Profile: Object {
#objc dynamic var date: Date!
#objc dynamic var content: String!
convenience init(_ content: String) {
self.init()
self.content = content
self.date = Date()
}
}
class ProfileManager {
static let shared = ProfileManager()
private var realm = try! Realm()
var profileList: Results<Profile>?
private init() {
profileList = realm.objects(Profile.self)
}
func save(_ object: Profile) {
do {
try realm.write {
realm.add(object)
}
} catch {
print(error)
}
}
func addNewProfile(_ content: String) {
let newProfile = Profile(content)
save(newProfile)
}
}
And lastly, here is a viewController which has to buttons. One for
adding new Profile, and one for printing filtered profile list.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addProfilePressed(_ sender: Any) {
ProfileManager.shared.addNewProfile("profile content")
}
#IBAction func filterButtonPressed(_ sender: Any) {
let stringDate = "2020-03-09"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let results = ProfileManager.shared.profileList!.filter("date == %#", searchDate)
print(searchDate)
print(results)
for profile in results {
print(profile.content!)
}
}
}
the result on the console, when filterButtonPressed method called.
2020-03-08 15:00:00 +0000
Results<Profile> <0x7f9b36f160a0> (
)
How can I fix this problem?
And here is another problem.
I set to 'stringDate' a value of "2020-03-09"
but when I print converted date 'searchDate' , it prints "2020-03-08"
why this happens?
Hope now my questions is more clear to understand.
My original answer is below which, after a lot of research was only somewhat correct.
The actual answer has to do with the timestamp portion of the date.
So... if we create a date object using the below code and set it to a known date,
let stringDate = "2020-03-08"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
the actual object will look like this
2020-03-08T05:00:00.000Z
However, how the Profile object is being created is like this
convenience init(_ content: String) {
self.init()
self.content = content
self.date = Date()
}
and that date object looks like this
2020-03-08T16:10:25.123Z
so as you can see, if we filter for a specific date these are not equal
2020-03-08T05:00:00.000Z != 2020-03-08T16:10:25.123Z
which is why this
let stringDate = "2020-03-08"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let searchResults = realm.objects(Profile.self).filter("date == %#", searchDate)
could not find the date because it's filtering for this
2020-03-08T05:00:00.000Z
To fix, change the profile class with a date stamp with a default time stamp
class Profile: Object {
#objc dynamic var date: Date!
#objc dynamic var content: String!
convenience init(_ content: String) {
self.init()
self.content = content
let formatter = DateFormatter()
formatter.timeStyle = .none
formatter.dateFormat = "MM/dd/yy"
let today = Date()
let s = formatter.string(from: today)
let d = formatter.date(from: s)
self.date = d
}
}
or, store your dates as a string yyyymmdd which will remove the ambiguity completely.
-- ORIGINAL ANSWER BELOW ---
Filtering by date is fully supported on date objects. Here's two quick examples. One for filtering for a specific date (for your question) and one for a date range using BETWEEN.
Note, I have a function makeDate that casts a string to a date object. This example uses a Realm DogClass object that has a dog_birthdate Date property.
This filters for objects with a specific date
let searchDate = self.makeDate(fromString: "06/01/2019")
let specificDateResults = realm.objects(DogClass.self)
.filter("dog_birthdate == %#", searchDate)
for dog in specificDateResults {
print(dog.dog_name)
}
This filters for objects within a date range
let startDate = self.makeDate(fromString: "06/01/2019")
let endDate = self.makeDate(fromString: "06/20/2019")
let dateRangeResuls = realm.objects(DogClass.self)
.filter("dog_birthdate BETWEEN {%#,%#}", startDate, endDate)
for dog in dateRangeResuls {
print(dog.dog_name)
}
EDIT: Using the code in the comment from the OP for testing
let stringDate = "2019-06-01"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let result = realm.objects(DogClass.self).filter("dog_birthdate == %#", searchDate)
for dog in result {
print(dog.dog_name)
}
which works perfectly.

Set Time Default in UIDatePicker

I'm trying to populate a pickerView with a default value (String). Currently I'm able to capture it's value as a time after the user interacts with it, however I'm not able to set the time value before it becomes visible to the user.
I've tried
let test = dateFormatter.date(from: "09:00 AM")
timePicker.setDate(test, animated: false)
however that errors "Value of type '(UIDatePicker) -> ()' has no member 'setDate'"
#IBOutlet weak var timePicker: UIDatePicker!
#IBAction func timePicker(_ sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
//my attempt at passing in a string
let test = dateFormatter.date(from: "09:00 AM")
timePicker.setDate(test, animated: false)
tempTime = (dateFormatter.string(from: sender.date))//successfully captures the user's input value
}
Here's the function that launches the xib (containing the timePicker)
func showSomeDialogue() {
let newVC = SomeViewContoller(nibName: "SomeViewController", bundle: nil)
let popup = PopupDialog(viewController: newVC,
buttonAlignment: .horizontal,
transitionStyle: .bounceUp,
tapGestureDismissal: true,
panGestureDismissal: false)
present(popup, animated: true, completion: nil)
newVC.someDelegate = self as SomeDelegate
}
The xib's class
import UIKit
protocol MealDelegate {
func didCreateMeal(mealTime: String)
}
class SomeViewContoller: UIViewController {
var someDelegate: SomeDelegate!
var tempTime = ""
#IBOutlet weak var timePicker: UIDatePicker!
#IBAction func timePicker(_ sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
tempTime = (dateFormatter.string(from: sender.date))
}
#IBAction func someSaveBtn(_ sender: UIButton) {
mealDelegate.didCreateMeal(mealTime: tempTime)
self.dismiss(animated: true, completion: nil)
}
}
Add following to your view controller class:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
let date = dateFormatter.date(from: "09:00 AM")
timePicker.date = date
Add the following to your SomeViewController class:
//MARK: - View Did Load
override func viewDidLoad() {
super.viewDidLoad()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
let date = dateFormatter.date(from: "10:57 PM")
//or whatever date you want to display as default
timePicker.setDate(date, animated: true)
}
Try this,
#IBAction func timePicker(_ sender: UITextField) {
let datePickerView = UIDatePicker()
datePickerView.datePickerMode = .dateAndTime
sender.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(handleTimePicker(sender:)), for: .valueChanged)
}
#objc func handleTimePicker(sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm "
tempTime = dateFormatter.string(from: sender.date)
// view.endEditing(true)
}

UIPickerView selected time to run code

I have added in a UIPickerView and currently have it store the selected time as a string. I want the app to carry out a simple line of code when the time that was selected on the pickerview is the time in the real world. Here is the code that I have added.
For the Clock, used to find the real world time:
let clockString: String = formatADate()
func formatADate() -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.dateFormat = "hh:mm:ss a"
let date = NSDate()
let output = dateFormatter.string(from: date as Date)
print(output)
return output
}
Here is the code for the UIPickerView:
#IBOutlet var dateTimeDisplay: UILabel!
#IBOutlet var datePicker: UIDatePicker!
#IBAction func datePickerchanged(_ sender: Any) {
setDateAndTime()
}
func setDateAndTime() {
let formatter = DateFormatter()
formatter.dateFormat = "hh:mm:ss a"
_ = formatter.string(from: datePicker.date)
str = dateFormatter.string(from: (datePicker?.date)!)
dateTimeDisplay.text = str
}
And here is what I want to happen when the selected time and the real world time match up:
takePhoto = true
When the pick date the start one timer function
call the function in picker
var timercount = Timer()
viewdidload()
{
timercount = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(Check), userInfo: nil, repeats: true)
}
Func Check()
{
let nowdate = NSDate()//two date declare global Var
let date2 = datePicker?.date //chek the Time How Much Time Remain
let elapsed = date2?.timeIntervalSince(nowdate as Date)
if Int(elapsed!) == 0
{
takePhoto = true
}
}