How to populate UITextField with UIPickerView that have 3 components? - ios

I did a date customized UIPickerView in my ViewController that have 3 components.
This picker work as an input to a UITextField. See some parts of my code to check how it was implemented.
var dataDia1: NSMutableArray!
var dataMes1: NSMutableArray!
var dataAno1: NSMutableArray!
#IBOutlet weak var pickerTextFieldInicio: UITextField!
let pickerViewInicio = UIPickerView()
override func viewDidLoad() {
super.viewDidLoad()
// Declaração dos Picker
pickerViewInicio.delegate = self
pickerViewInicio.dataSource = self
pickerViewInicio.showsSelectionIndicator = true
pickerViewInicio.backgroundColor = UIColor(red: 255/255, green: 193/255, blue: 193/255, alpha: 1)
self.dataDia1 = NSMutableArray()
for dia in 1...31
{
dataDia1.addObject("\(dia)")
}
self.dataMes1 = NSMutableArray()
for mes in 1...12
{
dataMes1.addObject("\(mes)")
}
self.dataAno1 = NSMutableArray()
for ano in 1970...2016
{
dataAno1.addObject("\(ano)")
}
pickerTextFieldInicio.inputView = pickerViewInicio
My question is, how can I populate pickerTextFieldInicio with something like 31/10/2015?
I checked some posts realeted to Objective C, but I could not solve my problem as I'm using Swift.
Thanks.

Add a UIDatePicker to the MainStoryBoardand then create an #IBOutlet for the UIDatePicker in the ViewController.swift name it whatever you want for instance we will use diaPicked
Next create an #IBOutlet for an UILabel and name it.
Create a #IBAction for the DatePicker and name it. For intance let's say that we called it pickerAction Inside of the pickerAction add
#IBAction func PickerAction(sender: AnyObject) {
var diaFormato = NSDateFormatter()
diaFormato.dateFormat = "dd-MM-yyyy HH:mm"
var strDate = diaFormato.stringFromDate(diaPicked.date)
self.selectedDate.text = strDate
}
I see that your variables are in spanish so I'll translate it for you since I speak spanish,
Agrega un UIDatePicker al MainStoryBoard y crea un #IBOutlet para el UIDatePicker en el ViewController.swift y lo puedes llamar lo que quieras pero por este ejemplo vamos a user Dias. y despues crea otro IBOutlet y le llamas diaSelecionado
Después crea un #IBAction para Dias y le llamas diasSelecionadoAcion que salga del UIDatePicker llamado Dias
#IBAction func Dias (sender: AnyObject) {
var diaFormato = NSDateFormatter()
diaFormato.dateFormat = "dd-MM-yyyy HH:mm"
var strDate = diaFormato.stringFromDate(diaPicked.date)
self.diaSelecionado.text = strDate
}

Related

Is there a way to Interrupt viewWillDisappear in iOS?

I'm looking for a way to interrupt viewWillDisappear when the back button is pressed (on UINavigationController), AND a certain data condition occurs, but I cannot find any way to logically keep the user on the view until my conditions have been met.
import UIKit
class DetailViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var serialNumberField: UITextField!
#IBOutlet weak var valueField: UITextField!
#IBOutlet weak var dateLabel: UILabel!
// adds item.name to top of detail view
var item: Item! {
didSet {
navigationItem.title = item.name
}
}
// ************************************
// MARK: Number / Date formatters
// ************************************
let numberFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
return formatter
}()
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
return formatter
}()
// ************************************
// MARK: viewWillAppear
// ************************************
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
nameField.text = item.name
serialNumberField.text = item.serialNumber
valueField.text = numberFormatter.string(from: NSNumber(value: item.valueInDollars))
dateLabel.text = dateFormatter.string(from: item.dateCreated)
}
// ************************************
// MARK: viewWillDisappear
// ************************************
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// clear first responder...
// this creates smoother transition if the
// keyboard is visible when the back button is pressed.
view.endEditing(true)
// save changes to item
item.name = nameField.text ?? ""
item.serialNumber = serialNumberField.text
if let valueText = valueField.text, let value = numberFormatter.number(from: valueText) {
// item.valueInDollars = value.intValue
// Rounding value of item before passing it back.
item.valueInDollars = Int(round(Float(truncating: value)))
} else {
item.valueInDollars = 0
}
}
// *************************************
// MARK: Resign keyboard with return key
// *************************************
// resign keyboard when return pressed from within textFields
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
// ************************************
// MARK: backGroundTapped TapGesture
// ************************************
#IBAction func backgroundTapped(_ sender: UITapGestureRecognizer) {
view.endEditing(true)
}
}

(Swift) Assign UIDatePicker selected date to UITextField

First let me state all the other code you see works as desired except for the UIDatePicker. Right now when I click on the dateTextField the UIDatePicker shows up and I can select a date but when I click the Done button the Date selected is not in the UITextField assigned to it.
One area that may be a place to focus is the doneClicked function. When I initially created it I did not have the (#objc) in front of it and it gave me an error.
/Argument of '#selector' refers to instance method doneClicked() that is not exposed to Objective-C/
So I added (#objc) and the error went away but as stated above the date selected from the UIDatePicker is not being saved in the UITextField.
If you would please explain and show where my code is wrong and how to fix it.
Any help is greatly appreciated in this matter thank you very much.
import Foundation
import UIKit
import Firebase
import FirebaseUI
class TrainViewController: UIViewController{
#IBOutlet weak var trainField: UITextField!
#IBOutlet weak var locationField: UITextField!
#IBOutlet weak var engineField: UITextField!
#IBOutlet weak var dateTextField: UITextField!
let datePicker = UIDatePicker()
#IBAction func saveButton(_ sender: UIButton) {
self.saveText()
trainField.text?.removeAll()
locationField.text?.removeAll()
engineField.text?.removeAll()
dateTextField.text?.removeAll()
self.view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
createDatePicker()
}
func saveText() {
let trainText = self.trainField.text!
let locationText = self.locationField.text!
let engineText = self.engineField.text!
let dateStart = self.dateTextField.text!
let db = Firestore.firestore()
let dict = ["train_text": trainText,
"location_text": locationText,
"engine_text": engineText,
"dateStart_text": dateStart]
db.collection("users").addDocument(data: dict)
}
func createDatePicker(){
//format the display of our datepicker
datePicker.datePickerMode = .date
//assign date picker to our textfield
dateTextField.inputView = datePicker
//create a toolbar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//add a done button on this toolbar
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneClicked))
toolbar.setItems([doneButton], animated: true)
dateTextField.inputAccessoryView = toolbar
}
#objc func doneClicked(){
//format the date display in textfield
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
}
}
extension TrainViewController : UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
you are not assigning the date in textFiled.
Like : dateTextField.text = dateString
in doneClicked click, get the date form datePicker and assign to dateTextField.
Code:
#objc func doneClicked(){
//format the date display in textfield
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
let dateString = dateFormatter.stringFromDate(datePicker.date)
print(dateString)
dateTextField.text = dateString
}

datepicker update value in two differents UIButton

I'm trying to update two buttons with datepicker. Button startDate et endDate. I don't how can I update these butttons with differents datepicker.
Maybe with handler ?
user story : the user click on startDat datepicker is displaying, user choose any date or time, then click on endDate and same action.
EDIT:
class ViewController: UIViewController {
#IBOutlet weak var dateTextField: UITextField!
#IBOutlet weak var dateTextLabel: UILabel!
var whoTriggeredPickerView: UIButton?
#IBOutlet weak var startDateTextButton : UIButton!
#IBOutlet weak var endDateTextButton : UIButton!
#IBOutlet weak var datePick : UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func donePressed(_ sender: UIBarButtonItem) {
dateTextField.resignFirstResponder()
dateTextLabel.resignFirstResponder()
startDateTextButton.resignFirstResponder()
endDateTextButton.resignFirstResponder()
}
func donePressedButton(_ sender :UIButton){
startDateTextButton.resignFirstResponder()
endDateTextButton.resignFirstResponder()
}
func tappedToolBarBtn(_ sender: UIBarButtonItem) {
let dateformatter = DateFormatter()
startDateTextButton.setTitle(dateformatter.string(from: Date()), for: .normal)
endDateTextButton.setTitle(dateformatter.string(from: Date()), for: .normal)
startDateTextButton.resignFirstResponder()
endDateTextButton.resignFirstResponder()
}
func closeDatePicker(){
self.view.endEditing(true)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
closeDatePicker()
}
#IBAction func BtnClicked(sender: UIButton) {
let datePickerView: UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.date
//sender.inputView = datePickerView
self.view.addSubview(datePickerView)
datePickerView.addTarget(self, action: #selector(ViewController.datePickerValueChanged), for: UIControlEvents.valueChanged)
self.whoTriggeredPickerView = sender
}
func datePickerValueChanged(_ sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = DateFormatter.Style.medium
dateFormatter.timeStyle = DateFormatter.Style.none
//dateTextField.text = dateFormatter.string(from: sender.date)
if self.whoTriggeredPickerView == startDateTextButton {
// set startDateBtn title
startDateTextButton.setTitle(dateFormatter.string(from: Date()), for: .normal)
}else if self.whoTriggeredPickerView == endDateTextButton {
// set endDateBtn title
endDateTextButton.setTitle(dateFormatter.string(from: Date()), for: .normal)
}
}
}
For your question:
You can create a tmp variable to record picker is triggered by which button. Then you can decide which button's title you want to set.
//In your view controller:
var whoTriggeredPickerView: UIButton?
//In your BtnClicked function:
self.whoTriggeredPickerView = sender
//Then in datePickerValueChanged function:
if self.whoTriggeredPickerView == StartDateButton {
// set startDateBtn title
}else if self.whoTriggerPickerView == endDateButton {
// set endDateBtn title
}
Some suggestions:
always lowercase the instance name, you are using DatePick as the instance name of UIDatePicker, instead, you should name it as datePicker; for function names as well.
for your case you can use two textfields instead of buttons.
let datePicker = UIDatePicker()
datePicker.addTarget(self, action: #selector(dateChanged), for: .valueChanged)
startDateTextField.inputView = datePicler
endDateTextField.inputView = datePicker

Passing Data Through Segue & some errors

Hey guys I need some one to help me finish my app, I need to finish it before Dec 15. I'm making a Tip Calculator Project in Swift2 and It must have a settings view where I select the default tip rate. I have some issues with passing data, when I select a default tip percentage it doesn't change in the View Controller, also I want to make the app remember the default rate when I close the app and reopened. I will really appreciate that some one corrects my code and test it. Im new in this, below is the code of the two ViewControllers and a screenshot of the Main.Storyboard (Image 1) (ViewController Screenshot)
My apologies for my bad English, is not my native language
ViewController
import UIKit
class ViewController: UIViewController {
//Inputs
#IBOutlet weak var amountTextField: UITextField!
//Labels
#IBOutlet weak var TipPercentageLabel: UILabel!
#IBOutlet weak var numberOfPersonLabel: UILabel!
#IBOutlet weak var tipAmountLabel: UILabel!
#IBOutlet weak var totalBillLabel: UILabel!
#IBOutlet weak var billPerPersonLabel: UILabel!
//Slider & Stepper
#IBOutlet weak var tipSlider: UISlider!
#IBOutlet weak var personsStepper: UIStepper!
//Variables
var tipPercentage = 0.20
var numberOfPerson:Int = 1
let numberFormatter:NSNumberFormatter = NSNumberFormatter()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tipAmountLabel.text = "$0.00"
totalBillLabel.text = "Bill Total"
billPerPersonLabel.text = "$0.00"
TipPercentageLabel.text = "20.0%"
numberOfPersonLabel.text = "1"
self.amountTextField.becomeFirstResponder()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupContainer() {
tipSlider.minimumValue = 0
tipSlider.maximumValue = 100
tipSlider.value = 20
tipSlider.addTarget(self, action: "sliderTipChanged:", forControlEvents: .ValueChanged)
personsStepper.minimumValue = 1
personsStepper.maximumValue = 30
personsStepper.value = 1
personsStepper.addTarget(self, action: "sliderPersonChanged:", forControlEvents: .ValueChanged)
amountTextField.text = ""
refreshCalculation()
}
#IBAction func OnEditingFieldBill(sender: AnyObject) {
refreshCalculation()
}
func refreshCalculation() {
numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
if let amount = numberFormatter.numberFromString(amountTextField.text!) as? Double {
let tipAmount = amount * tipPercentage
let totalBill = amount + tipAmount
let billPerPerson = totalBill / Double(numberOfPerson)
numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
tipAmountLabel.text = numberFormatter.stringFromNumber(tipAmount)
totalBillLabel.text = numberFormatter.stringFromNumber(totalBill)
billPerPersonLabel.text = numberFormatter.stringFromNumber(billPerPerson)
} else {
tipAmountLabel.text = "-"
totalBillLabel.text = "-"
billPerPersonLabel.text = "-"
}
numberFormatter.numberStyle = NSNumberFormatterStyle.PercentStyle
numberFormatter.minimumFractionDigits = 1
numberFormatter.maximumFractionDigits = 1
TipPercentageLabel.text = self.numberFormatter.stringFromNumber(tipPercentage)
numberOfPersonLabel.text = "\(numberOfPerson)"
}
#IBAction func sliderTipChanged(sender: AnyObject) {
tipPercentage = Double(round(tipSlider.value)) / 100
refreshCalculation()
}
#IBAction func StepperPersonChanged(sender: AnyObject) {
numberOfPerson = Int(round(personsStepper.value))
refreshCalculation()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let id = segue.identifier {
if id == "show settings" {
if let SettingsViewController = segue.destinationViewController as? SettingsViewController {
}
}
}
}
}
Settings View Controller
import UIKit
class SettingsViewController: UIViewController {
#IBOutlet weak var tipControl: UISegmentedControl!
var tipRates:Double?
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 DefaultRate(sender: AnyObject) {
var tipRate = [5, 10, 15, 20, 25, 30]
var tipRates = Double(tipRate[tipControl.selectedSegmentIndex])
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let id = segue.identifier {
if id == "goBackToViewController" {
if let ViewController = segue.destinationViewController as? ViewController {
if let tip = tipRates {
ViewController.tipPercentage = tip/100
}
}
}
}
---- Edit from comments ----
I think the reason it is not updating as you would like is due to a minor error with this line.
var tipRates = Double(tipRate[tipControl.selectedSegmentIndex])
Inside of your DefaultRate action function for the UISegmentedControl
Using var is a redeclaration of the same variable name, thus what you are trying to pass in the prepareForSegue is an empty variable.
This function should be changed to:
#IBAction func DefaultRate(sender: AnyObject) {
var tipRate = [5, 10, 15, 20, 25, 30]
tipRates = Double(tipRate[tipControl.selectedSegmentIndex])}
Hopefully this will now solve the error.
---- End Edit ----
From what I can see in the viewDidLoad function of your viewController, you are setting the tip label, and not updating the value based on the variable var tipPercentage.
TipPercentageLabel.text = "20.0%"
is setting the value display to always be 20.0%, you could use this here.
var tipDisplay = tipPercentage * 100
TipPercentageLabel.text = "\(tipDisplay)%"
This should update the displayed value in the label, however you never call on your other functions to recalculate the amount etc.
Thus you should also be calling on
func setupContainer()
or
func refreshCalculation()
within your ViewDidLoad().
In terms of remembering the default value when the app is closed you should look into using NSUserDefaults.
Some information regarding NSUserDefaults can be found here, which explains implementing small amounts of saved data and can be implemented in your case quite simply.

How to add to UIStepper value with other buttons?

I have a UIStepper that increments/decrements by 1 to a UILabel, I want to have a additional +3 button, when the +3 is pressed it does add 3 to the Label, but then if you press the UIStepper it goes back to 1.
My code is below:
import Foundation
import UIKit
import AVFoundation
class ViewTwo : UIViewController, AVAudioPlayerDelegate {
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
/// Actions de sonido -------
#IBAction func stepperSoundRed(sender: UIStepper) {
audioPlayer.play()
}
#IBAction func stepperSoundBlue(sender: UIStepper) {
audioPlayer.play()
}
/////////////////////////
// el nombre del equipo Blue
#IBOutlet weak var teamBlueTextLabel: UILabel!
var BlueName = String()
// nombre del equipo rojo
#IBOutlet weak var teamRedTextLabel: UILabel!
var RedName = String()
// score inicial del equipo rojo
#IBOutlet weak var RedScoreLabel: UILabel!
var RedScore = String()
// score initcial equipo azul
#IBOutlet weak var BlueScoreLabel: UILabel!
var BlueScore = String()
// que funcionen los Steppers
#IBOutlet weak var RedStepperUI: UIStepper!
#IBOutlet weak var BlueStepperUI: UIStepper!
// Botón Done
#IBOutlet weak var BotonDone: UIButton!
#IBAction func BlueStepperValueChange(sender: UIStepper) {
BlueScoreLabel.text = Int(sender.value).description
}
#IBAction func RedStepperValueChange(sender: UIStepper) {
RedScoreLabel.text = Int(sender.value).description
}
#IBOutlet weak var periodUILabel: UILabel!
// archivos de sonidos
var sound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("ping2", ofType: "mp3")!)
var audioPlayer = AVAudioPlayer()
required init? (coder aDecoder: NSCoder){
super.init(coder: aDecoder)
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: sound, fileTypeHint: nil)
audioPlayer.prepareToPlay()
audioPlayer.delegate = self
//audioPlayer.play()
} catch {
// Errors here
}
}
#IBAction func BackToViewOne(sender: UIButton) {
self.dismissViewControllerAnimated(true, completion: nil)
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Landscape
}
// Period
#IBOutlet weak var periodUILabel2: UILabel!
#IBAction func periodAdd1(sender: UIButton) {
if(periodUILabel.text == "20") {
}
else {
let period = Int(periodUILabel.text!)!+1
periodUILabel.text = String(period)
}
}
#IBAction func periodMinus1(sender: UIButton) {
if(periodUILabel.text == "0") {
}
else {
let period = Int(periodUILabel.text!)!-1
periodUILabel.text = String(period)
}
}
// VIEW DID LOAD
override func viewDidLoad() {
// No se para que es esto??
super.viewDidLoad()
BotonDone.layer.cornerRadius = 5
// Checamos si están vacios los nombres
if BlueName.isEmpty {
BlueName = "BLUE"
}
if RedName.isEmpty {
RedName = "RED"
}
if RedScore.isEmpty {
RedScore = "0"
}
if BlueScore.isEmpty {
BlueScore = "0"
}
// Proseguimos a asignarlos a las Labels
teamBlueTextLabel.text = BlueName
teamRedTextLabel.text = RedName
RedScoreLabel.text = RedScore
BlueScoreLabel.text = BlueScore
// Aqui vemos el Red +/-
RedStepperUI.wraps = true
RedStepperUI.autorepeat = false
RedStepperUI.value = Double(RedScore)!
RedStepperUI.maximumValue = 999
// aqui vemos el Blue +/-
BlueStepperUI.wraps = true
BlueStepperUI.autorepeat = false
BlueStepperUI.value = Double(BlueScore)!
BlueStepperUI.maximumValue = 999
//
let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
}
// BOTONES MAS +3
#IBAction func RedPlus3UIButton(sender: UIButton) {
let CurrentScoreRed = RedStepperUI.value;
RedScoreLabel.text = String (Int(CurrentScoreRed) + 3)
audioPlayer.play()
}
#IBAction func BluePlus3UIButton(sender: UIButton) {
audioPlayer.play()
}
// BOTONES + Y -
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestViewController : ViewThree = segue.destinationViewController as! ViewThree
DestViewController.FinalScoreBlue = BlueScoreLabel.text!
DestViewController.FinalScoreRed = RedScoreLabel.text!
DestViewController.TeamNameR1Label = teamRedTextLabel.text!
DestViewController.TeamNameB1Label = teamBlueTextLabel.text!
}
}
class MyButtons : UIButton {
required init(coder aDecoder: (NSCoder!)) {
super.init(coder: aDecoder)!
self.layer.cornerRadius = 5
self.layer.borderColor = UIColor.whiteColor().CGColor
self.layer.borderWidth = 1
}
}
This is the +3 button:
#IBAction func RedPlus3UIButton(sender: UIButton) {
let CurrentScoreRed = RedStepperUI.value;
RedScoreLabel.text = String (Int(CurrentScoreRed) + 3)
audioPlayer.play()
}
You need to update the stepper's value property. Example:
#IBAction func RedPlus3UIButton(sender: UIButton) {
RedStepperUI.value += 3
let CurrentScoreRed = RedStepperUI.value
RedScoreLabel.text = String(Int(CurrentScoreRed))
audioPlayer.play()
}

Resources