how to change index of segmentController in swift. i want when button is clicked the value of segment index should be changed
func respondToGesture(sender: UIGestureRecognizer)
{
if let swipeGesture = sender as? UISwipeGestureRecognizer
{
if swipeGesture.direction == UISwipeGestureRecognizerDirection.Right
{
// change the segment to previous
}
else
{
// change th esegment to next
}
}
}
Here is the way you can set selected index for segment:
import UIKit
import AVFoundation
class ViewController: UIViewController {
//outlet of your segment
#IBOutlet weak var segment: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func setOne(sender: AnyObject) {
//set selected index to 0
segment.selectedSegmentIndex = 0
}
#IBAction func setTwo(sender: AnyObject) {
//set selected index to 1
segment.selectedSegmentIndex = 1
}
#IBAction func setThree(sender: AnyObject) {
//set selected index to 2
segment.selectedSegmentIndex = 2
}
#IBAction func four(sender: AnyObject) {
//set selected index to 3
segment.selectedSegmentIndex = 3
}
}
And result will be:
Hope it helps.
You can do like this:
#IBOutlet weak var mySegmentControl: UISegmentedControl!
var current = 0 // For current selection
#IBAction func buttonPressed(sender: AnyObject) {
if current == 0 {
mySegmentControl.selectedSegmentIndex = 1
current = 1
} else {
mySegmentControl.selectedSegmentIndex = 0
current = 0
}
Related
It's my first time creating an app with Xcode, and I have come across an error I can't figure out. The fatal error:
Thread 1: Fatal error: Unexpectedly found nil while implicitly
unwrapping an Optional value, occurs on line 29.
I've seen other posts with comments saying "check your outlets", but they're all good. I've included the Connections inspector of one of my textfields in case it helps.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
var mssgArray:[Int] = [0,0,0,0,0,0,0,0]
#IBOutlet weak var ItemQ: UITextView!
#IBOutlet weak var RTC: UITextView!
#IBOutlet weak var ExpoPrompt: UITextView!
#IBOutlet weak var OrderPrompt: UITextView!
#IBOutlet weak var Data: UITextView!
#IBOutlet weak var CusID: UITextField!
#IBOutlet weak var FirstN: UITextField!
#IBOutlet weak var LastN: UITextField!
#IBOutlet weak var PhoneNum: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
CusID.delegate = self
FirstN.delegate = self
LastN.delegate = self
PhoneNum.delegate = self
}
#IBAction func PizzaBut(_ sender: UIButton) {
if(mssgArray[0] == 0)
{
ItemQ.text += "Pizza\n"
mssgArray[0] = 1
}
if(mssgArray[0] == 1)
{
mssgArray[0] = 2
}
}
#IBAction func SubBut(_ sender: UIButton) {
if(mssgArray[1] == 0)
{
ItemQ.text += "Sub\n"
mssgArray[1] = 1
}
if(mssgArray[1] == 1)
{
mssgArray[1] = 2
}
}
#IBAction func QuesoBut(_ sender: UIButton) {
if(mssgArray[2] == 0)
{
ItemQ.text += "Queso\n"
mssgArray[2] = 1
}
if(mssgArray[2] == 1)
{
mssgArray[2] = 2
}
}
#IBAction func BagBut(_ sender: UIButton) {
if(mssgArray[3] == 0)
{
ItemQ.text += "Baguette\n"
mssgArray[3] = 1
}
if(mssgArray[3] == 1)
{
mssgArray[3] = 2
}
}
#IBAction func PretzelBut(_ sender: UIButton) {
if(mssgArray[4] == 0)
{
ItemQ.text += "Pretzels\n"
mssgArray[4] = 1
}
}
#IBAction func MeatballBut(_ sender: UIButton) {
if(mssgArray[5] == 0)
{
ItemQ.text += "Meatball\n"
mssgArray[5] = 1
}
if(mssgArray[5] == 1)
{
mssgArray[5] = 2
}
}
#IBAction func BoardBut(_ sender: UIButton) {
if(mssgArray[6] == 0)
{
ItemQ.text += "Charcuterie Board\n"
mssgArray[0] = 1
}
if(mssgArray[6] == 1)
{
mssgArray[6] = 2
}
}
#IBAction func SaladBut(_ sender: UIButton) {
if(mssgArray[7] == 0)
{
ItemQ.text += "Salad\n"
mssgArray[7] = 1
}
if(mssgArray[7] == 1)
{
mssgArray[7] = 2
}
}
#IBAction func ClearBut(_ sender: UIButton) {
ItemQ.text = ""
mssgArray = [0,0,0,0,0,0,0,0]
}
#IBAction func SendMssg(_ sender: UIButton) {
ItemQ.text = ""
mssgArray = [0,0,0,0,0,0,0,0]
}
#IBAction func AddCus(_ sender: UIButton) {
}
#IBAction func SearchCus(_ sender: UIButton) {
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if(textField == CusID || textField == PhoneNum)
{
textField.keyboardType = UIKeyboardType.phonePad
}
}
}
And here is a screenshot of the two tab views and what I'm seeing, the right tab is showing the tab bar controller's controller inspector.
I'm currently trying to connect two UISegmentedControls where the first Viewcontroller is connected to the second. Tapping the second UISegment will update the value of the first one.
ViewController:
class ViewController: UIViewController {
#IBOutlet weak var tipLabel: UILabel!
#IBOutlet weak var totalLabel: UILabel!
#IBOutlet weak var billField: UITextField!
#IBOutlet weak var tipController: UISegmentedControl!
#IBOutlet weak var splitController: UISegmentedControl!
#IBOutlet weak var splitLabel: UILabel!
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
defaults.synchronize()
billField.becomeFirstResponder()
tipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
print(tipController.selectedSegmentIndex)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// #IBAction func toSettings(_ sender: Any) {
// self.performSegue(withIdentifier: "toSettings", sender: self)
// }
#IBAction func onTap(_ sender: Any) {
view.endEditing(true)
}
#IBAction func calculateTip(_ sender: Any) {
let tipPercentages = [0.18, 0.20, 0.25]
let splitNumbers = [1,2,3,4]
let bill = Double(billField.text!) ?? 0
let tip = bill * tipPercentages[tipController.selectedSegmentIndex]
let total = bill + tip
tipLabel.text = String(format: "$%.2f", tip)
totalLabel.text = String(format: "$%.2f", total)
splitLabel.text = String(format: "$%.2f", total/Double((splitNumbers[splitController.selectedSegmentIndex])))
}
SettingViewController:
class SettingsViewController: UIViewController {
var tipPercentageIndex:Int!
#IBOutlet weak var settingsTipController: UISegmentedControl!
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
settingsTipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
// Do any additional setup after loading the view.
}
#IBAction func Index(_ sender: Any) {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
}
#IBAction func saveButton(_ sender: Any) {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
defaults.set(tipPercentageIndex, forKey: "default_tip_index")
defaults.synchronize()
self.performSegue(withIdentifier: "Tippy", sender: self)
}
#IBAction func Back(_ sender: Any) {
self.performSegue(withIdentifier: "Tippy2", sender: self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
However, my solution does not update the value nor store the value when switching back from the second to the first.
Note: the first segues to the second.
Add an IBAction for Value Changed for the segmented controls, and update values for the affected controls:
func updateSegments(){
if let value = UserDefaults.standard.value(forKey: "key"){
let selectedIndex = value as! Int
yourSegmentedControl.selectedSegmentIndex = selectedIndex
} else {
yourSegmentedControl.selectedSegmentIndex = 0 // set to default
}
if let value = UserDefaults.standard.value(forKey: "anotherkey"){
let selectedIndex = value as! Int
anotherSegmentedControl.selectedSegmentIndex = selectedIndex
} else {
anotherSegmentedControl.selectedSegmentIndex = 0 // set to default
}
//etc...
}
#IBAction func yourSegmentedControlSelected(_ sender: UISegmentedControl) {
UserDefaults.standard.set(sender.selectedSegmentIndex, forKey: "key")
self.updateSegments()
}
#IBAction func anotherSegmentedControlSelected(_ sender: UISegmentedControl) {
UserDefaults.standard.set(sender.selectedSegmentIndex, forKey: "anotherkey")
self.updateSegments()
}
From how you've explained your code, I think your problem is that the code that loads your dependent values, is only called when your viewController is loaded. And I believe, the viewController you are "switching back" to, has already been loaded. So the set up code will not be executed again after updating your defaults.
One quick fix to try is moving your set up code for viewDidLoad to viewWillAppear:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
defaults.synchronize()
billField.becomeFirstResponder()
tipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
print(tipController.selectedSegmentIndex)
}
Update
Just noticed you said the value is not stored, along with my pervious suggestion try this—
Create a method that sets the defaults to the settingsTipController.selectedSegmentIndex. When you load the SettingsViewController, add the method as a target to the settingsTipController that acts on a .valueChanged event.
When save is tapped the last selected value will be saved.
In SettingsViewController.swift:
override func viewDidLoad() {
super.viewDidLoad()
settingsTipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
settingsTipController.addTarget(nil, action: #selector(didToggleSwitch), for: .valueChanged)
}
#objc func didToggleSwitch() {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
defaults.set(tipPercentageIndex, forKey: "default_tip_index")
}
#IBAction func saveButton(_ sender: Any) {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
defaults.set(tipPercentageIndex, forKey: "default_tip_index")
defaults.synchronize()
self.performSegue(withIdentifier: "Tippy", sender: self)
}
So how i transfer my ViewController label: totalPar to ThirdViewController label: totalPar5. And I want to transfer data that I have added there with my minus and plus buttons
Here is simulator pic that show what I want to transfer
My ThirdViewController is almost same as ViewController except prepare segue
Here is my ViewController
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var totalPar: UILabel!
#IBOutlet weak var plusminusPar: UILabel!
#IBOutlet weak var currentPar: UILabel!
var totalPAR = Int()
var plusminusPAR = 0
var currentPAR = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func minusButton(_ sender: Any) {
totalPAR = Int(totalPar.text!)!
self.totalPar.text = String(totalPAR - 1)
plusminusPAR = Int(plusminusPar.text!)!
self.plusminusPar.text = String(plusminusPAR - 1)
currentPAR = Int(currentPar.text!)!
self.currentPar.text = String(currentPAR - 1)
}
#IBAction func plusButton(_ sender: Any) {
totalPAR = Int(totalPar.text!)!
self.totalPar.text = String(totalPAR + 1)
plusminusPAR = Int(plusminusPar.text!)!
self.plusminusPar.text = String(plusminusPAR + 1)
currentPAR = Int(currentPar.text!)!
self.currentPar.text = String(currentPAR + 1)
}
#IBAction func Seuraava(_ sender: Any) {
self.performSegue(withIdentifier: "next1", sender: Any?.self)
}
#IBAction func seiraava2(_ sender: Any) {
self.performSegue(withIdentifier: "seuraava2", sender: Any?.self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let thirdviewcontroller = segue.destination as! ThirdViewController
thirdviewcontroller.totalPAR5 = self.totalPAR
}
}
From the accepted answer and its comments you need to start improving your code and learn some concepts of data source in general.
For your case stop constantly converting string to integers to string. Choose one or the other:
class ViewController: UIViewController {
var totalPAR: Int = 0
var plusminusPAR: Int = 0
var currentPAR: Int = 0
Do natural operations on actions and separate methods:
#IBAction func minusButton(_ sender: Any) {
addToAll(valueToAdd: -1)
refreshLabels()
}
private func addToAll(valueToAdd: Int) {
totalPAR += valueToAdd
plusminusPAR += valueToAdd
currentPAR += valueToAdd
}
private func refreshLabels() {
self.totalPar.text = String(totalPAR)
self.plusminusPar.text = String(plusminusPAR)
self.currentPar.text = String(currentPAR)
}
Then you will have no issues calling
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let thirdviewcontroller = segue.destination as? ThirdViewController {
thirdviewcontroller.totalPAR = self.totalPAR
thirdviewcontroller.plusminusPAR = self.plusminusPAR
thirdviewcontroller.currentPAR = self.currentPAR
}
}
Now if in both view controllers you call refreshLabels on viewDidLoad the values are successfully transferred.
Simply make the variable in ThirdViewController and assign the value in prepare for segua and setup value to the label in viewDidLoad:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let thirdviewcontroller = segue.destination as! ThirdViewController
thirdviewcontroller.totalPAR5 = self.totalPAR
}
class ThirdViewController: UIViewController {
var totalPAR5 = 0
override func viewDidLoad() {
super.viewDidLoad()
self.totalPar.text = "\(totalPAR5+1)" //You can calculate here like +1 or -1
// Do any additional setup after loading the view.
}
}
How do i set up a label so that when a button is pressed then it will change that value displayed on the label and set it up that each time a button is pressed it they will all just add to the previous number that was pressed - and is it possible to set up 2 view scenes on the same view controller?
#IBOutlet weak var creditLabel: UILabel!
var savedNum:Int = "Credits: /0"
var Money : Int!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func oneDollar(_ sender: Any) {
let oneDollar = 1
}
#IBAction func fiveDollars(_ sender: Any) {
let fiveDollars = 5
}
#IBAction func tenDollars(_ sender: Any) {
let tenDollars = 10
}
#IBAction func twentyDollars(_ sender: Any) {
let twentyDollars = 20
}
#IBAction func fiftyDollars(_ sender: Any) {
let fiftyDollars = 50
}
#IBAction func oneHundredDollars(_ sender: Any) {
let oneHundredDollars = 110
}
}
I think what you're trying to do is something like this…
class ViewController: UIViewController {
#IBOutlet weak var creditLabel: UILabel!
var credit = 0 {
didSet {
creditLabel.text = "Credit: $\(credit)"
}
}
override func viewDidLoad() {
super.viewDidLoad()
credit = 0
}
#IBAction func oneDollar(_ sender: Any) {
credit += 1
}
#IBAction func fiveDollars(_ sender: Any) {
credit += 5
}
// etc
}
Is your Label connected to your UIViewController? What about the corresponding actions? Are you connecting the same actions to the same button? Need more information to help solve your error that's being thrown.
Im creating an app where different buttons in a ViewController load different menu's into the tableViewController. The buttons are linked by a prepare for segue and the menu's (arrays) are linked by a contentMode. 1: breakfast menu & 2: lunch menu. I had allot of help from someone setting this up but now the table is not loading any data... The cell has 3 labels which display an item, info and price. It changes value within the code when a contentMode is selected. Does anyone see the problem in my code? thanks a lot!
import UIKit
class foodMenuController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let foodMenuController = segue.destinationViewController as! foodTableViewController
if segue.identifier == "showBreakfast" {
foodMenuController.contentMode = 1
} else if segue.identifier == "showLunch" {
foodMenuController.contentMode = 2
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
import UIKit
class foodTableViewCell: UITableViewCell {
#IBOutlet weak var foodItem: UILabel!
#IBOutlet weak var foodDescription: UILabel!
#IBOutlet weak var foodPrice: 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
}
}
import UIKit
class foodTableViewController: UITableViewController {
//Content Mode Selection in menu
var contentMode = 0
// THIS SHOULD BE LOADED WHEN CONTENT MODE is "1" --> BREAKFAST
let breakfastItems = ["Bread", "Coffee", "Nada"]
let breakfastInfo = ["Good", "Nice", "Nothing"]
let breakfastPrice = ["$1", "$100", "$12,40"]
// THIS SHOULD BE LOADED WHEN CONTENT MODE IS "2" --> LUNCH
let lunchItems = ["Not bread", "Not Coffee", "Something"]
let lunchInfo = ["Not good", "Not nice", "Yes"]
let lunchPrice = ["$1", "$100", "$12,40"]
var foodItems: [String] = []
var foodInfo: [String] = []
var foodPrice: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
switch (contentMode){
case 1: contentMode = 1
foodItems = breakfastItems
foodInfo = breakfastInfo
foodPrice = breakfastPrice
case 2: contentMode = 2
foodItems = lunchItems
foodInfo = lunchInfo
foodPrice = lunchPrice
default:
break
}
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return foodItems.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! foodTableViewCell
cell.foodItem.text = foodItems[indexPath.row]
cell.foodDescription.text = foodInfo[indexPath.row]
cell.foodPrice.text = foodPrice[indexPath.row]
return cell
}
}
There isn't anything apparently wrong with the snippet you shared. You can check what is returned in the tableView:numberOfRowsInSection: method and see if it is returning a value > 0
Also, this is a given but we've all done it at some point of time - check to make sure the tableview delegate and datasource are set to your viewcontroller.
I have made slight modifications in your project.
1. make the UINavigationController the InitialViewController
2. make the FoodMenuController the root of UINavigationController
Now modify your FoodMenuController
#IBOutlet weak var bakeryButton: UIButton!
#IBOutlet weak var breakfastButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBarHidden = true //hide navigationBar in first ViewController
self.bakeryButton.addTarget(self, action: "bakeryButtonAction:", forControlEvents: .TouchUpInside)
self.breakfastButton.addTarget(self, action: "breakfastButtonAction:", forControlEvents: .TouchUpInside)
}
func bakeryButtonAction(sender: UIButton) {
performSegueWithIdentifier("showLunch", sender: self)
}
func breakfastButtonAction(sender: UIButton) {
performSegueWithIdentifier("showBreakfast", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let foodTableViewController: FoodTableViewController = segue.destinationViewController as! FoodTableViewController
if segue.identifier == "showBreakfast" {
foodTableViewController.contentMode = 1
} else if segue.identifier == "showLunch" {
foodTableViewController.contentMode = 2
}
}
Also you can make UINavigationBar visible in FoodTableViewController
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBarHidden = false
}
PS: It is always better not to add segue directly to a UIButton. Alternatively you can add it from the yellow button on top of your FoodMenuController and specify the segue to be fired in UIButtonAction using performSegueWithIdentifier
I can no where see you setting the datasource and delegate of the tableView, please cross check these are both setup.