So here is what I am trying to do.
I am working on an app that allows the company I work for to see what account number they should use when making a purchase. There are certain locations where the costs should be split to different accounts based on location, but they are only for a certain few. I would like to issue a warning in the form of a popup, which I already have coded. My thought process is that I can use if/else statements to issue what I need, but I am unsure as to how to word it. It would supply a regular account number if the accounts need not be split, but then a warning statement if it did. The code is below. My problem is under the didSelectRow.
What's not actually shown is the PopUpVC I am using and the full list of array data because it's long.
Much thanks to this website as it has really helped me code my first project!
let account: [Account] = [Account(number: 0, description: "SELECT")]
//there is actually more data here but I am taking it out so it's shorter
let tasks: [Task] = [Task(number: 0, description: "SELECT")]
//there is actually more data here but I am taking it out so it's shorter
let locations: [Location] = [Location(number: 0, description: "SELECT")]
//there is actually more data here but I am taking it out so it's shorter
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == accountsComponent {
return account.count
} else if component == tasksComponent {
return tasks.count
} else if component == locationsComponent {
return locations.count
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == accountsComponent {
return account[row].description
} else if component == tasksComponent {
return tasks[row].description
} else if component == locationsComponent {
return locations[row].description
}
return nil
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
if component == accountsComponent {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(12)
label.textAlignment = .center
label.text = account[row].description
return label
}
if component == tasksComponent {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(12)
label.textAlignment = .center
label.text = tasks[row].description
return label
}
if component == locationsComponent {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(12)
label.textAlignment = .center
label.text = locations[row].description
return label
} else {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(10)
label.textAlignment = .center
label.text = account[row].description
return label
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
pickerView.reloadAllComponents()
let selectedAccount = pickerView.selectedRow(inComponent: 0)
let selectedTask = pickerView.selectedRow(inComponent: 1)
let selectedLocation = pickerView.selectedRow(inComponent: 2)
let ACCOUNTS = account[selectedAccount].description
let TASKS = tasks[selectedTask].description
let LOCATION = locations[selectedLocation].description
let ACCOUNTSNUMBER = account[selectedAccount].number
let TASKSNUMBER = tasks[selectedTask].number
let LOCATIONNUMBER = locations[selectedLocation].number
if pickerView.selectedRow(inComponent: 2) = 10 //this is what I am unsure of how to do {
textViewInput = "WARNING - this should be split"
}
else {
textViewInput = "\(ACCOUNTSNUMBER) \(TASKSNUMBER) \(LOCATIONNUMBER)"
}
I prefer switch statements over a long series of if-else if-else statements. I would personally do something like this:
switch pickerView.selectedRow(inComponent: 2) {
case 10, 11, 12:
present(popUpVc, animated: true)
default:
textViewInput = "\(ACCOUNTSNUMBER) \(TASKSNUMBER) \(LOCATIONNUMBER)"
}
In this case, you would replace what I put as 10, 11, 12 as whatever rows you determine that need to have the accounts split. I'm also assuming here that PopUpVC is a UIAlertController that you are using to display the warning to the user.
Related
Still Learning swift
What Im trying to do is add a "°C" and "°F"
after an integer, I have a created and array of ints and gave them a specific range
that should be in the pickerView, I got the values to display Im just struggling with how I could get that "special char " to display after the integer
I was thinking of maybe creating a for loop and load in the the values like that and append the "°C" and "°F" using the unicode scalar.
I was wondering if anyone has any recommendations of how i could get this done ?
class tempConversionTabViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
var celsius: [Int] = []
var fahrenheitTemps: [Int] = []
override func viewDidLoad() {
super.viewDidLoad()
fahrenheitTemps += -129...134
celsius += -90...57
// for fahrenheitTemps in -129...134{
// tempPicker.append
//}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch
segmentControl.selectedSegmentIndex{
case 0:
return fahrenheitTemps.count
default:
return celsius.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int , forComponent component: Int) -> String?{
switch segmentControl.selectedSegmentIndex {
case 0:
var selected = fahrenheitTemps[tempPicker.selectedRow(inComponent: 0)]
selected = (selected - 32) * 5/9
convertedLabel.text = String("\(selected) \u{2103}")
let myString = fahrenheitTemps.map { String($0)}
return myString[row]
default:
var selected = celsius[tempPicker.selectedRow(inComponent: 0)]
selected = (selected * 9/5) + 32
convertedLabel.text = String("\(selected) \u{2109}")
let myString = celsius.map { String($0)}
return myString[row]
}
}
Image of how I want it to display
Just use string concatenation to add the character:
Change:
return myString[row]
to:
return myString[row] + "\u{2109}"
I have defined Dictionary in an Array object below:
var dataList : [[String:Any]]?
And then I have loaded some data in to it. Here is the output when i run this code below:
print("DATA LIST:\n \(myRecordList)")
Output:
Optional([["itemCode": 0, "itemText": please select city], ["itemCode": 1, "itemText": City A], ["itemCode": 2, "itemText": City B], ["itemCode": 3, "itemText": City C], ["itemCode": 4, "itemText": City D], ["itemCode": 5, "itemText": City E], ["itemCode": 6, "itemText": City F]])
I would like to reach value of a dictionary from first item in an Array:
As you know, here is the first item in an array:
["itemCode": 0, "itemText": please select city]
And here is the value in above dictionary:
"itemText": please select city
After that I would like to set above text ("please select city") as a button title if dataList count is not zero:
if dataList?.count != 0
{
**//need help in here!!!**
{
self.btnSelectMarkaOutlet.setTitle(tempBtnTitle, for: .normal)
}
}
I have tried below scope. But it crushed:
if let newTry = dataList![0]["itemText"] as? [String]
{
print("here is the output:: \(newTry[0])")
}
Here is the error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
let tempBtnTitle = must be "please select city"
I wanted to do this.
Let me share whole view controller file. Because dataList is nil.
import UIKit
class SinyalSeviyesineGoreAramaYapViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var btnSelectMarkaOutlet: UIButton!
#IBOutlet weak var pickerViewOutlet: UIPickerView!
var dataList : [[String:Any]]?
override func viewDidLoad() {
print("viewDidLoad")
super.viewDidLoad()
self.pickerViewOutlet.delegate = self
self.pickerViewOutlet.dataSource = self
self.loadSayacRecordsForTheUIPickerView()
print("Is the data list nil? : \(self.dataList)")
if let newTry = self.dataList![0]["itemText"] as? String
{
print("here is the output:: \(newTry)")
}
//I WANTED TO SET BUTTON TITLE !!
let tempButtonTitle = ""
self.btnSelectMarkaOutlet.setTitle(tempButtonTitle, for: .normal)
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let recordName = self.dataList![row]
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
//return self.cityList![row]
let info = self.dataList![row]
if let name = info["itemCode"] as? String,
let code = info["itemText"] as? String
{
let text = "\(name) - \(code)"
//print("am i here? \(text)")
return text
}
return nil
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.dataList == nil ? 0 : self.dataList!.count
}
func loadSayacRecordsForTheUIPickerView()
{
print("loadSayacRecordsForTheUIPickerView method is called")
ServiceManager.oServiceManager.loadSayacRecords()
{
(result) in
if let sayacRecords = try? JSONSerialization.jsonObject(with: result!, options: .mutableContainers) as? [String:Any]
{
if let resultCodeFromWebApi = sayacRecords?["resultCode"] as? String
{
DispatchQueue.main.async
{
print("loadSayacRecordsForTheUIPickerView resultCode: \(resultCodeFromWebApi)")
if resultCodeFromWebApi == "999"
{
if let myRecordList = sayacRecords?["recordList"] as? [[String:Any]]
{
//DispatchQueue.main.async
//{
self.dataList = myRecordList
print("DATA LIST:\n \(self.dataList)")
self.pickerViewOutlet.reloadAllComponents()
//}
}
} // resultCodeFromWebApi == 999 ENDS
else
{
if let resultMessageFromWebApi = sayacRecords?["resultMessage"] as? String
{
print("resultMessage: \(resultMessageFromWebApi)")
}
}
} // DispatchQueue.main.async ENDS
}
else
{
print("cant parse it")
} // if let resultCodeFromWebApi = loginResult?["resultCode"] as? Int ENDS
}
}
} // loadSayacRecordsForTheUIPickerView ENDS
} // class SinyalSeviyesineGoreAramaYapViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource ENDS
The problem is in the logic you implemented: the dataList is loaded asynchronously, which means that you don't know when it will be available, but you are using it like it's always available.
Example of this error is in the viewDidLoad:
self.loadSayacRecordsForTheUIPickerView()
print("Is the data list nil? : \(self.dataList)")
if let newTry = self.dataList![0]["itemText"] as? String
{
print("here is the output:: \(newTry)")
}
With the first line you start to load the dataList, but in the for loop you are force unwrapping, which means you are saying "Ehi I'm 100% sure it will be available" - which is not true.
A possible solution for your problem is to convert the dataList! to dataList? everywhere, so if it's not loaded then nothing happens and your app won't crash.
A better and quicker solution is to have a default value for dataList, so in case is not loaded you will just react to an empty data model:
var dataList : [[String:Any]] = [[String:Any]]()
A reason would be array is nil and also you are unwrapping with [String] which is String, which may give nil.
Try below to avoid crashes.
if dataList?.isEmpty == false,let firstDic = dataList?.first, let neededString = firstDic["itemText"] as? String {
}
i'm relatively new to Swift. I've encountered an issue when using PFQuery in pickerView.
I'm trying to implement a 2 component pickerView as demonstrated below:
Component 0: Component 1
"A": "Altivo", "Altrez"
"B": "Beverly", "Bijou"
Choosing "A" from Component 0 will show "Altivo", "Altrez" in Component 1
The values from Component 1 are queried from Parse by using the value from Component 0
Here's my code:
var condoNameList: [String] = [String]()
var condoPicker = UIPickerView()
var condoAlphabet: [String] = [String]()
private let prefixComponent = 0
private let condoNameComponent = 1
override func viewDidLoad() {
super.viewDidLoad()
condoAlphabet = ["A", "B"]
}
//Start: For condoName picker
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == prefixComponent{
return condoAlphabet.count
}else {
return self.condoNameList.count
}
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == prefixComponent {
condoNameList.removeAll()
let query = PFQuery(className: "condodirectory")
let selectedalphabet: String = condoAlphabet[row] as String!
query.whereKey("condoName", hasPrefix: selectedalphabet)
query.findObjectsInBackgroundWithBlock{
(objects:[PFObject]?, error:NSError?)->Void in
if error == nil{
for object in objects!{
//print(object)
let condoName:String = object["condoName"] as! String
self.condoNameList.append(condoName)
}
}
//print("condo Name List is \(self.condoNameList)") //Position 1
}
print("condo Name List is \(self.condoNameList)") //Position 2
condoPicker.reloadComponent(condoNameComponent)
condoPicker.selectRow(0, inComponent: condoNameComponent, animated: true)
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == prefixComponent{
return condoAlphabet[row]
}else {
return self.condoNameList[row]
}
}
The issue is at Position 1, the print function is able to print out the condoNameList but at Position 2 it prints an empty array. As a result, the list for Component 1 is not showing up in the PickerView.
Anyone knows why?
Thanks in advance for the help.
I managed to solve the problem from another thread by using the didset{} method.
var condoNameList: [String] = [] {
didSet {
self.condoNameListTemp = condoNameList
condoName.inputView = condoPicker
condoPicker.reloadAllComponents()
}
}
I have an app in Swift. I have a view controller:
//
// ViewController.swift
// SwiftUIPickerFormatted
//
// Created by Codepixl
// Copyright (c) 2014
//
import UIKit
class FirstViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate,UIAlertViewDelegate {
#IBOutlet weak var chapterPicker: UIPickerView!
let chapterData = [1,2,3,4,5,6,7,8,9,10,11,12,13]
let lessonData = [1,2,3,4,5,6,7,8,9,10]
let classData = ["Pre Algebra","Algebra 1"]
var data = ["ade","01","01"]
override func viewDidLoad() {
super.viewDidLoad()
if(UIApplication.sharedApplication().canOpenURL(NSURL(string:"puffin://")!) == true){
println("Can open Puffin links")
}else{
showPuffinAlert()
}
chapterPicker.delegate = self
chapterPicker.dataSource = self
}
//MARK: - Delegates and datasources
//MARK: Data Sources
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if(component == 0){
return classData.count
}else if(component == 1){
return chapterData.count
}else if(component == 2){
return lessonData.count
}
return 1
}
//MARK: Delegates
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
if(component == 0){
return classData[row]
}else if(component == 1){
return "Chapter " + String(chapterData[row])
}else if(component == 2){
return "Lesson " + String(lessonData[row])
}
return "Error!"
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component == 0){
if(row == 0){
data[0] = "ade"
}else if(row == 1){
data[0] = "ate"
}
}else if(component == 1 || component == 2){
if(row+1 < 10){
data[component] = "0"+String(row+1)
}else{
data[component] = String(row+1)
}
}
println("puffin://www.phschool.com/webcodes10/index.cfm?wcprefix=\(data[0])&wcsuffix=\(data[1])\(data[2])&area=view")
}
func showPuffinAlert(){
var createAccountErrorAlert: UIAlertView = UIAlertView()
createAccountErrorAlert.delegate = self
createAccountErrorAlert.title = "Oops!"
createAccountErrorAlert.message = "It seems you do not have the Puffin web browser installed, which is required for this app to work. You can go ahead, but be aware the video and textbook links will not work."
createAccountErrorAlert.addButtonWithTitle("I understand- Proceed.")
createAccountErrorAlert.addButtonWithTitle("I'll download Puffin for free.")
createAccountErrorAlert.show()
}
func alertView(View: UIAlertView!, clickedButtonAtIndex buttonIndex: Int){
switch buttonIndex{
case 0:
NSLog("Proceed");
break
case 1:
NSLog("DL");
UIApplication.sharedApplication().openURL(NSURL(string: "https://itunes.apple.com/us/app/puffin-academy/id716707933?mt=8#")!)
break
default:
NSLog("Default");
break
//Some code here..
}
}
#IBAction func GoVideo(sender: AnyObject) {
UIApplication.sharedApplication().openURL(NSURL(string:"puffin://www.phschool.com/webcodes10/index.cfm?wcprefix=\(data[0])&wcsuffix=\(data[1])\(data[2])&area=view")!)
}
}
And all works fine until I hit the "I understand-Proceed" or "I'll download Puffin for free" or the GoVideo button- it crashes with no error. I am completely stumped here as to what is happening...
EDIT: I have also cleared my build folder and manually deleted everything in it as well as adding a println in my app delegate and view controllers to make sure they have updated, and they have. Also the Simulator has been cleared.
There's probably a corrupted file in your Xcode project. Just make a new project and try the code there.
In my app I allow the user to change the colour theme for the app via a picker view. In doing this, UI elements such as the bars and buttons are changed based on what the user chooses.
I am having an issue with the picker view returning to the first item when the view is closed and reopened. How can I make the picker view return to the colour that the user previously selected?
Here is the code that I currently have for the picker view:
func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int {
return coloursArray.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
return coloursArray[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent: Int) {
colourSelected = row
if colourSelected == 0 {
self.navigationController.navigationBar.barTintColor = UIColor.newBlueColor()
self.tabBarController.tabBar.selectedImageTintColor = UIColor.newBlueColor()
UINavigationBar.appearance().barTintColor = UIColor.newBlueColor()
UISegmentedControl.appearance().tintColor = UIColor.newBlueColor()
changeButton.layer.backgroundColor = (UIColor.newBlueColor()).CGColor
} else if colourSelected == 1 {
self.navigationController.navigationBar.barTintColor = UIColor.newGreenColor()
self.tabBarController.tabBar.selectedImageTintColor = UIColor.newGreenColor()
UINavigationBar.appearance().barTintColor = UIColor.newGreenColor()
UIButton.appearance().setTitleColor(UIColor.newGreenColor(), forState: UIControlState())
UISegmentedControl.appearance().tintColor = UIColor.newGreenColor()
changeButton.layer.backgroundColor = (UIColor.newGreenColor()).CGColor
} else if colourSelected == 2 {
self.navigationController.navigationBar.barTintColor = UIColor.newOrangeColor()
self.tabBarController.tabBar.selectedImageTintColor = UIColor.newOrangeColor()
UINavigationBar.appearance().barTintColor = UIColor.newOrangeColor()
UISegmentedControl.appearance().tintColor = UIColor.newOrangeColor()
changeButton.layer.backgroundColor = (UIColor.newOrangeColor()).CGColor
} else if colourSelected == 3 {
self.navigationController.navigationBar.barTintColor = UIColor.newPurpleColor()
self.tabBarController.tabBar.selectedImageTintColor = UIColor.newPurpleColor()
UINavigationBar.appearance().barTintColor = UIColor.newPurpleColor()
UISegmentedControl.appearance().tintColor = UIColor.newPurpleColor()
changeButton.layer.backgroundColor = (UIColor.newPurpleColor()).CGColor
} else if colourSelected == 4 {
self.navigationController.navigationBar.barTintColor = UIColor.newRedColor()
self.tabBarController.tabBar.selectedImageTintColor = UIColor.newRedColor()
UINavigationBar.appearance().barTintColor = UIColor.newRedColor()
UISegmentedControl.appearance().tintColor = UIColor.newRedColor()
changeButton.layer.backgroundColor = (UIColor.newRedColor()).CGColor
} else if colourSelected == 5 {
self.navigationController.navigationBar.barTintColor = UIColor.newTurquoiseColor()
self.tabBarController.tabBar.selectedImageTintColor = UIColor.newTurquoiseColor()
UINavigationBar.appearance().barTintColor = UIColor.newTurquoiseColor()
UISegmentedControl.appearance().tintColor = UIColor.newTurquoiseColor()
changeButton.layer.backgroundColor = (UIColor.newTurquoiseColor()).CGColor
}
}
Supposing you have one column ("component") in your picker:
override func viewDidLoad() {
super.viewDidLoad()
let idx = NSUserDefaults.standardUserDefaults().integerForKey("SavedIndex")
pickerView.selectRow(idx, inComponent: 0, animated: false)
}
And, of course, save to NSUserDefaults when a row has been selected.
Depending on your setup, you might have to put this into viewWillAppear().