I'm new in swift and programming. I have a UIPickerView and UIbutton(by default button is invisible ) in my storyBoard and i want to show myButton when I change row in a UIPickerView (PickerView.selectedRowInComponent(0) == 1) and when press MyButton do something. Here is my code: MyButton and PickerView.
How can i show myButton?
#IBAction func myButton(sender: UIButton) {
println("Button was clicked", sender)
//here i will do something
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if PIckerView.selectedRowInComponent(0) == 1 {
//how to set UIButton property visible, here ???
}
Try this:
myButton.hidden = false
To get access to your button in code you need to create an IBOutlet: In InterfaceBuilder ctrl-drag from the button to your class file and in the popup menu choose outlet. Give that outlet a descriptive name i.e. myButton. Also give your #IBAction a descriptive name, not myButton
So your class will look similar like this:
#IBOutlet weak var myButton: UIButton!
#IBAction func myButtonClick(sender: UIButton) {
println("Button was clicked", sender)
// here i will do something
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if PIckerView.selectedRowInComponent(0) == 1 {
myButton.hidden = false
}
}
And don't forget to assign your custom class in InterfaceBuilder accordingly.
Related
I have a picker view that needs to be presented when UIButton is pressed. The text of the UIButton will change to the text of selected row. But how do I initiate the picker view for a button?
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
picker.dataSource = self
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return CountryData.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
CountryButton.setTitle(CountryData[row], for: .normal)
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return CountryData[row]
}
#IBAction func Country(_ sender: AnyObject) {
CountryButton.inputView == picker
}
This won't work
Note: when you set the action method, be sure to set the sender to the type of control that's invoking the action, the UIButton or the UIPickerView or whatever. Don't leave it as AnyObject.
It's not completely clear to me what you're trying to do. You say that the picker view needs to change when you press a button, then you say that the text of the button needs to change to the row selected in the picker view.
Are you trying to get the text of the button to change when you select something in the picker view? Or are you trying to instantiate a new picker view when you press the button?
If you're trying to change the text of the button when you select a row in the picker view, then you want to add an onChanged() action method for the picker view and change the button's text in that method.
#IBAction func pickerChanged(_ sender: UIPickerView) {
button.setTitle("New text", for: UIControlState)
}
An easy way to present a new picker view when a button is pressed is to put the picker view in a stack view and set its hide property. Then the button's onPress() method can unhide the picker view in the stack view.
#IBAction func onPress(_ sender: UIButton) {
if weWannaShowthePicker {
pickerStack.arrangedSubviews[pickerPosition].isHidden = false
} else { // hide it
pickerStack.arrangedSubviews[pickerPosition].isHidden = true
}
}
I'm making a GPA calculator using swift and I've run into some problems. I created a picker view with all the letter grades (A to F). I've put 7 text fields (one for each course). I want the user to tap on a textfield and the pickerview should appear, and the grade selected would appear in the textfield. I've managed to do that for the first textfield but I dont know how to write the code that allows me to pick the grade for each textfield. I've tried different methods but I always end up changing the first textfield only.
Any help is appreciated :-)
Here is my code (gradeOne is a textfield for course 1, gradeTwo for course 2, etc.):
import UIKit
class GPA: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet var gradeOne: UITextField!
#IBOutlet var gradeTwo: UITextField!
//Grades array
var grades = ["A+/A (85-100)", "A- (80-84)", "B+ (77-79)", "B (73-76)", "B- (70-72)", "C+ (67-69)", "C (63-66)", "C- (60-62)", "D+ (57-59)", "D (53-56)", "D- (50-52)", "F (0-49)"]
//Grade 1 Picker
func numberOfComponentsInPickerView(gradePickerView: UIPickerView) -> Int {
return 1
}
func pickerView(gradePickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return grades.count
}
func pickerView(gradePickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return grades[row]
}
func pickerView(gradePickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
gradeOne.text = grades[row]
}
//Make keyboard disappear
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let gradePickerView = UIPickerView()
gradePickerView.delegate = self
gradeOne.inputView = gradePickerView
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
}
You should set gradePickerView as the inputView for all your textfields
gradeTwo.inputView = gradePickerView
gradeThree.inputView = gradePickerView
// set for rest of textfields
and then in your pickerView:didSelectRow: method you need to set the text to the active text field at the time. I suggest setting the active textfield using UITextFieldDelegate
var activeField: UITextField?
override func viewDidLoad() {
// Set VC as textfield's delegate
gradeTwo.delegate = self
gradeThree.delegate = self
// Set for rest of textfields
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
activeField = textField
}
func pickerView(gradePickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
activeField.text = grades[row]
}
Use the delegate for UITextField to set all inputviews to pickerView. Make sure you set delegate for all textfields
let gradePickerView = UIPickerView()
override func viewDidLoad() {
super.viewDidLoad()
// set delegates for all textfields
gradePickerView.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
textField.inputView = gradePickerView
}
I think you want to tap on 7 textfiel. Each time the pickerView will show. You picker a cell in pickerView and the textfiel(that you just tap) will show your select? If it's true. You should do fowllow this step:
1: Add tag to each textFiel: yourtextFiel.view.tag = 0 (or 1,2,3,4,...)
2: When show pickerView: Add pickerView.tag = yourtextFiel.view.tag
3: in fucion pickerView didSelectRow : get your textFiel's tag will show your selected: let mytag = pickerView.tag.
Find your textFiel with "mytag" and change your text
Googluck
I have been looking all over for an answer for this...I do not know how to pass data through an unwind segue. I know I am supposed to use prepareForSegue but I am not sure what I am supposed to put in. I am trying to pass a variable (myLabel) from a UIPickerView in one class:
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
myLabel.text = pickerData[row]
}
to another class. I have the unwind segue code already but do not know where to put the prepareForSegue and what to put in it.
Let me know if my question needs more clarification.
If I understand your question correctly, you should do something like this:
class MyPickerController : UIViewController {
#IBOutlet weak var myLabel: UILabel!
var pickerData:[String]
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
myLabel.text = pickerData[row]
performSegueWithIdentifier( "mySegueName", sender: self )
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let myController = segue.destinationController as? MyDestinationViewController {
myController.text = myLabel.text
}
}
That will pass the label text to the MyDestinationViewController instance.
Note that I don't pass the UILabel object, but the text.
You can not place that UILabel object in the destination controller interface, but you can use the text an set another label with it, for example.
prepareForSegue is called in the class of the view controller that you will be unwinding from (the view controller that was previously pushed or presented, and is now being popped or dismissed). The destination view controller of the segue is the view controller that will appear as a result.
I hope the title makes some sense but what I am trying to do is to set a field value to the item selected variable from my dataPicker. I have been able to make this work when there is only one field to set but my project will have multiple fields on each view that will call data from the dataPicker based on what field it is. I hope that is clear. Maybe as you look at the code it will.
I have set up a test project to limit things to this issue only. So my variable to tell the view what array to populate in the dataPicker is either season or sport. the field that will receive the data from the season/sport array is enterSeason and enterSport. When the picker has returned a value from season, I want to combine it with enter to create the var enterSeason to set that == itemSelected. This language is very new to me so I am trying the only way I have used before to combine text and variables in one value. It is obviously not working. Help is appreciated.
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UIGestureRecognizerDelegate {
#IBOutlet var enterSeason: UITextField!
#IBOutlet var enterSport: UITextField!
var dataPickerView = UIPickerView()
var season = ["2013", "2014", "2015"] //multi-season
//var season = ["2015"] //single-season
var sport = ["Baeball", "Football", "Basketball", "Hokey"]
var activeField = []
override func viewDidLoad() {
super.viewDidLoad()
enterSeason.inputView = dataPickerView
dataPickerView.delegate = self
dataPickerView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return activeField.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return activeField[row] as! String
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
var itemSelected = activeField[row] as! String
self.enter"\activeField".text = itemSelected
}
}
EDIT : How do you show and hide the picker? Your code anly shows variable declarations and the delegate methods... answers could vary accordingly..
Since you show the picker as text field's input view, set UITextFieldDelegate for each of these text fields .. and in the textFieldDidBeginEditing check which field becomes active with simple if else
func textFieldDidBeginEditing(textField: UITextField) {
if textField === enterSeason {
activeField = season
}
else if textField === enterSport {
activeField = sport
}
}
And in the picker selector, set value of the relevant text field as per current activeField object
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if activeField === season {
enterSeason.text = season[row] as! String
}
else if activeField === sport {
enterSeason.text = sport[row] as! String
}
}
Setting the delegate for your text fields in storboard/xib :
P.S.
- Rename activeField to activeDataArray or somethiong more appropriate
EDIT 2 : As you mentioned, second approach i have mentioned below is not suitable for you because there are too many of these fields i am still keeping it as part of the answer as it may help someone else
But what you are trying to achieve is very simple and approach is too convoluted / weird. So heres another way you can implement the whole thing..
The easiest (but still probably not the best) way is to have two instances of the UIPickerView for each field. you can directly check pickerView == seasonPickerView OR pickerView == sportPickerViewin an if else block and do the conditional programming and you wont need the activeField variable..
I am currently working on a small project and i have a viewController that has 4 textFields which 3 work ok. They take String objects. However, the 4th textField is supposed to bring up a UIPickerView with 4 selectable items.
So far this is what i have in my controller that implements this:
#IBOutlet var pickerTextfield: UITextField!
#IBOutlet var itemPicker: UIPickerView! = UIPickerView()
The pickerTextfield is the UITextField object that is the 4th field.
The itemPicker is an unlinked UIPickerView that i want to create programatically.
Right below these properties, i have an array of items for the UIPickerView object:
var seasonalItems = ["Spring", "Summer", "Fall", "Winter"]
In my viewDidLoad method i have this as follow:
itemPicker.hidden = true;
pickerTextfield.text = seasonalItems[0]
pickerTextfield.delegate = self
And the rest of the implementation:
// Below these lines is the implementation of the Picker
func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int{
return 1
}
// returns the # of rows in each component..
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int{
return seasonalItems.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
return seasonalItems[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
{
pickerTextfield.text = seasonalItems[row]
itemPicker.hidden = true;
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
itemPicker.hidden = false
return false
}
So the end result from this is when i tap the pickerTextfield object in the app, it shows the first item of the array (Spring) but in text within the UITextField object but it does not show the UIPickerView object with the other selectable items where i could select one and then hide it when selected.
My question is, where or what am i doing wrong here? i been trying to figure this out on my own but i do not seem to get good clear examples with Swift and storyboards. I much rather not drag a UIPickerView in the storyboard but rather the way i attempted to implement. Thanks
You can give UIPickerView as inputView for your TextField in which you want to show picker view.
You also do not need to initially hide picker view in this case.
pickerTextfield.inputView = itemPicker
When you use UIPickerView as inputView of any UITextField then when you tap on the TextField instead of default keypad PickerView will show.