how to call function in Extension in swift? - 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
}
}

Related

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

How to save label content

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

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

How to convert date picker value into String in swift 3.0?

How to convert date picker value into String type in Swift 3.0 ?
Right now I have managed to create date picker but the value that appear in textfield is today's date which is 2/8/17, m/d/yy format.
My goal is to convert m/d/yy into String and the date value will be 2017-02-08, yyyy/mm/dd format
The code as below.
Date.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet var dateTxt: UITextField!
let datepicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
displayDate()
}
func displayDate(){
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePick))
toolbar.setItems([doneBtn], animated: false)
dateTxt.inputAccessoryView = toolbar
dateTxt.inputView = datepicker
}
func donePick(){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
dateTxt.text = dateFormatter.string(from: datepicker.date)
self.view.endEditing(true)
}
}
Can anyone help ?
Thanks.
For that you need to set dateFormat property of DateFormatter not the dateStyle and timeStyle.
func donePick(){
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
dateTxt.text = dateFormatter.string(from: datepicker.date)
self.view.endEditing(true)
}

How can I extract number of years, months, and days since a date in Swift

How can I extract number of years, months, and days since a date in Swift.
So far I have the follow code in a class file named DatePickerController.
class DatePickerController: UIViewController {
#IBOutlet var datePicker:UIDatePicker!
#IBOutlet var dateDisplay: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func datePickerChanged(sender: AnyObject) {
setDate()
}
let dateFormatter = NSDateFormatter()
// MARK: - Date Format
func setDate() {
dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
dateDisplay.text = dateFormatter.stringFromDate(datePicker.date)
}
}
I will create separate UILables for year, month, and day right.
Like you said, you will need UILabel's for each of the date components. You can then extract the components using custom date formatting strings instead of using NSDateFormatterStye.ShortStyle. This gives you the most flexibility. The formatting strings follow a unicode standard.
I can't test the code in the context of your project, but if you add the labels and connect them correctly to Xcode, I believe that this code will do exactly what you want:
class DatePickerController: UIViewController {
#IBOutlet var datePicker:UIDatePicker!
#IBOutlet var dayDisplay: UILabel!
#IBOutlet var monthDisplay: UILabel!
#IBOutlet var yearDisplay: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func datePickerChanged(sender: AnyObject) {
setDate()
}
let dateFormatter = NSDateFormatter()
// MARK: - Date Format
func setDate() {
dateFormatter.dateFormat = "dd"
dayDisplay.text = dateFormatter.stringFromDate(datePicker.date)
dateFormatter.dateFormat = "MM"
monthDisplay.text = dateFormatter.stringFromDate(datePicker.date)
dateFormatter.dateFormat = "yyyy"
yearDisplay.text = dateFormatter.stringFromDate(datePicker.date)
}
}
You can use NSCalendar to get the NSDateComponents between two dates. In Swift 3:
let components = Calendar.current.dateComponents([.day, .month, .year], from: date1, to: date2)
let dayString = "\(components.day!)"
let monthString = "\(components.month!)"
let yearString = "\(components.year!)"
Or in Swift 2:
let components = NSCalendar.currentCalendar().components([.Day, .Month, .Year], fromDate: date1, toDate: date2, options: [])
let dayString = "\(components.day)"
let monthString = "\(components.month)"
let yearString = "\(components.year)"
Perhaps easier, if you'd like to have a single string that represents the elapsed time between these two dates, you'd use NSDateComponentsFormatter, e.g., in Swift 3:
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.day, .month, .year]
formatter.unitsStyle = .full
let string = formatter.string(from: date1, to: date2)
Or in Swift 2:
let formatter = NSDateComponentsFormatter()
formatter.allowedUnits = [.Day, .Month, .Year]
formatter.unitsStyle = .Full
let string = formatter.stringFromDate(date1, toDate: date2)
This string is localized, too.
You can use NSDateComponents to retrieve year, month and day by using method components(fromDate: toDate: options:) of NSCalender
Example
let date = NSDate(timeIntervalSinceNow: -123123123)
extension NSDate {
func intereval(date:NSDate) -> (year: Int, month:Int, day:Int) {
let calender = NSCalendar.currentCalendar()
let components = calender.components([.Year, .Month, .Day], fromDate: date, toDate: self, options:.MatchStrictly)
return (components.year, components.month, components.day)
}
}
let component = NSDate().intereval(date)
print(component.year)
print(component.month)
print(component.day)
import Foundation
let now = NSDate()
now.description.characters.split {
" -".characters.contains($0)
}.enumerate().forEach {
print($0.0,String($0.1))
}
/*
0 2015
1 12
2 26
3 19:34:33
4 +0000
*/