How to get the current Title of a button in Swift? - swift

What am I doing wrong?
I get this error:
let letterString = sender.title(for: .normal)! // Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
when I tried to get the title of a button in swift like below:
import UIKit
class ViewController: UIViewController {
// My IBOutlets
#IBOutlet var treeImageView: UIImageView!
#IBOutlet var correctWordLabel: UILabel!
#IBOutlet var scoreLabel: UILabel!
// My Outlet Collection
#IBOutlet var letterButtons: [UIButton]!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Begin the round.
newRound()
}
var listOfWords = ["estufa", "nevera", "computadora", "empanada", "chuleta", "camarones", "brincar", "correr", "caminar", "tigre", "jirafa", "mono", "kisseemmee", "Tampa", "Orlando"]
let incorrectMovesAllowed = 7
let totalWins = 0
let totalLosses = 0
// My IBActions
#IBAction func letterButtonPressed(_ sender: UIButton) {
sender.isEnabled = false
let letterString = sender.title(for: .normal)! // Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
let letter = Character(letterString.lowercased())
currentGame.playerGuessed(letter: letter)
updateUI()
}
var currentGame: Game!
func newRound() {
let newWord = listOfWords.removeFirst()
currentGame = Game(word: newWord, incorrectMovesRemaining: incorrectMovesAllowed, guessedLetters: [])
updateUI()
}
func updateUI() {
scoreLabel.text = "Wins: \(totalWins), Losses: \(totalLosses)"
treeImageView.image = UIImage(named: "Tree \(currentGame.incorrectMovesRemaining)")
}
}
// Game.swift file code:
import Foundation
struct Game {
var word: String
var incorrectMovesRemaining: Int
var guessedLetters: [Character]
mutating func playerGuessed(letter: Character) {
guessedLetters.append(letter)
if !word.contains(letter) {
incorrectMovesRemaining -= 1
}
}
}
I'm a newbie. This is my first program. I appreciate if you code the solution.

You can get the title of the UIButton using titleLabel property. Check the below code.
sender.titleLabel?.text
As the above code returns optional, you can use optional chain to safely get the string
if let titleLabel = sender.titleLabel {
let title = titleLabel.text
}
OR
You can also use the currentTitle property as below.
sender.currentTitle

You can use:
sender.titleLabel.text

Related

I am trying to add a UILabel exactly like I already have but keep getting this error

I am trying to add a label to my calculator where it shows the tip amount but I keep getting
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
I just want it to display the tip amount as well. I copied it exact for the other UILabel.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var PriceTxt: UITextField!
#IBOutlet weak var Tip: UITextField!
#IBOutlet weak var totalFinal: UILabel!
#IBOutlet weak var TipAmount: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
totalFinal.text = ""
TipAmount.text = ""
}
#IBAction func Calcualte(_ sender: Any) {
if PriceTxt.text! == "" || Tip.text! == ""
{
totalFinal.text = "Input the Numbers"
TipAmount.text = ""
}
else {
let price = Double(PriceTxt.text!)!
let tipPer = Double(Tip.text!)!
let TipMult = price * (tipPer/100)
let TipFinal = Double((round(100*TipMult)/100) + price)
totalFinal.text = "$\(TipFinal)"
TipAmount.text = "$\(TipMult)"
}
}
}
It will show you the problem in your code.. please always try to avoid force cast
class ViewController: UIViewController {
#IBOutlet weak var PriceTxt: UITextField!
#IBOutlet weak var Tip: UITextField!
#IBOutlet weak var totalFinal: UILabel!
#IBOutlet weak var TipAmount: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
totalFinal.text = ""
TipAmount.text = ""
}
#IBAction func Calcualte(_ sender: Any) {
if let getPrice = PriceTxt.text , let getTip = Tip.text
{
if getPrice.isEmpty || getTip.isEmpty {
totalFinal.text = "Input the Numbers"
TipAmount.text = ""
}
else {
let price = Double(getPrice)!
let tipPer = Double(getTip)!
let TipMult = price * (tipPer/100)
let TipFinal = Double((round(100*TipMult)/100) + price)
totalFinal.text = "$\(TipFinal)"
TipAmount.text = "$\(TipMult)"
}
} else {
print("either PriceTxt or Tip is nil")
}
}
}
Try using ? instead of !
! force unwraps and gives you a fatal error if there is no value (nil). ? only unwraps if a value is present.
Also, why unwrap the text here at all?
Use
PriceTxt.text == "" || Tip.text == "" without the ! or ?.

Not Retriveing Output Predictions from Remote Firebase Automl custom model

I am currently trying to build an app that uses google's autoML feature. I have trained a model and published it on google firebase and have integrated the necessary code into my app following the documentation:
https://firebase.google.com/docs/ml-kit/ios/label-images-with-automl
I am using a remote model instead of making it local. However when I try running the code, then choose an image in the simulator, an empty list of predictions is output in the console.
I have also turned on the debugging feature, but this has not helped me fix my error. This is the code I am running in ViewController:
import UIKit
import CoreML
import Vision
import Firebase
import FirebaseMLCommon
var serverImage: UIImage? = nil
var topResult = ""
class ViewController: UIViewController {
#IBOutlet var skinDiseaseImageView: UIImageView!
#IBOutlet var result1Label: UILabel!
#IBOutlet var result1Confidence: UILabel!
#IBOutlet var result2Label: UILabel!
#IBOutlet var result2Confidence: UILabel!
#IBOutlet var result3Label: UILabel!
#IBOutlet var result3Confidence: UILabel!
override func viewDidLoad() {
let initialConditions = ModelDownloadConditions(allowsCellularAccess: true,
allowsBackgroundDownloading: true)
let updateConditions = ModelDownloadConditions(allowsCellularAccess: false,
allowsBackgroundDownloading: true)
let remoteModel = RemoteModel(
name: "skinDiseaseModel", // The name you assigned in the console.
allowsModelUpdates: true,
initialConditions: initialConditions,
updateConditions: updateConditions
)
ModelManager.modelManager().register(remoteModel)
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension ViewController {
#IBAction func selectImage(_ sender: Any) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = .savedPhotosAlbum
present(pickerController, animated: true)
}
}
extension ViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
dismiss(animated: true)
guard let skinImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("Error Retrieving Image Line 95")
}
var skinImageToDiagnose = VisionImage(image: skinImage)
serverImage = skinImage
skinDiseaseImageView.image = skinImage
let labelerOptions = VisionOnDeviceAutoMLImageLabelerOptions(
remoteModelName: "skinDiseaseModel", // Or nil to not use a remote model
localModelName: nil // Or nil to not use a bundled model
)
labelerOptions.confidenceThreshold = 0 // Evaluate your model in the Firebase console
// to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: labelerOptions)
var topThreeResults = [String]()
var topThreeConfidences = [String]()
labeler.process(skinImageToDiagnose) { labels, error in
guard error == nil, let labels = labels
else {
print(error)
return
}
//task succeeded
print("1")
print(labels)
var counter = 0
for label in labels {
topThreeResults.append(String(describing: label))
topThreeConfidences.append(String(describing: label.confidence))
counter = counter + 1
print("counter")
if counter == 3 {
break
}
}
}
result1Label.text = topThreeResults[0]
result1Confidence.text = (topThreeConfidences[0] + "%")
result2Label.text = topThreeResults[1]
result2Confidence.text = (topThreeConfidences[1] + "%")
result3Label.text = topThreeResults[2]
result3Confidence.text = (topThreeConfidences[2] + "%")
}
}
This is the error I recieved:
Fatal error: Index out of range
2019-08-31 19:50:19.763469-0700 medicalAppFinal[13776:2281569] Fatal error: Index out of range
(lldb)
I reasoned that the index out of range problem is due to the list of labels(output predictions) being empty after having printed it. Thus I understand why it is index out of range, but I do not know why I am recieving an empty list after passing in the image into labeler.process() How do I solve this error? Tell me if you need more information
This seems to be duplicate of the following question (which was answered by the author):
Not Retriveing Output Prediction List from Remote Firebase Automl custom model

Variable error in Swift code

I have an Xcode project which has some error. I had only a problem with a variable. I convert the txt string variable to int and this called txtint. When I want to make an calculation I can't because it has null value what is impossible because I give a value in function "pass" and then when I want to subtract I can't because txtint has null value.
//
// ViewController.swift
// Biophere
//
// Created by Coder on 2017. 10. 22..
// Copyright © 2017. Pliz Help. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textview: UITextField!
#IBOutlet weak var conv: UILabel!
var text: String? = nil
var txt: String? = nil
var convert: String? = nil
var textint: Int? = nil
var txtint: Int? = nil
#IBAction func pass(_ sender: Any) {
var txt: String {
get {
return textview.text ?? ""
}
set {
textview.text = newValue
}
}
//conv.text = txt
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
label.text = text
txt = textview.text
}
#IBAction func saveButton(_ sender: Any) {
let textint = Int(text!)
let txtint = Int(txt!)
convert = String(textint! - txtint!)
conv.text = txt
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
ERROR: Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
var text: String = ""
var txt: String = ""
var convert: String = ""
var textint: Int = 0
var txtint: Int = 0
#IBAction func saveButton(_ sender: Any) {
if let textint = Int(text), let txtint = Int(txt) {
convert = String(textint - txtint)
conv.text = txt
}else{
print("handle it")
}
}
Suggestion: Try to give variable name descriptive it is a basic thing for development.

incrementing points going back to 0 swift

I have added a button, that adds points to a label.
Everything works fine, and the label is then persisted into core data and appears in a tableViewCell.
When I get back to my detailsVC, I get my label with the persisted number, but when I click on the button again to increment the points, the label goes back to zero.
Here's a part of my code:
import UIKit
import CoreData
class GoalDetailsVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
// IBOutlets:
#IBOutlet weak var titleTF: UITextField!
#IBOutlet weak var detailsTextView: UITextView!
#IBOutlet weak var pointsLabel: UILabel!
#IBOutlet weak var dateOfEntry: UILabel!
#IBOutlet weak var thumbImage: UIImageView!
// properties
var currentScore = 0
var goalToEdit: Goal? // goalToEdit is now an optional, and it needs to be unwrapped when used.
var imagePicker: UIImagePickerController!
override func viewDidLoad() {
super.viewDidLoad()
if let topItem = self.navigationController?.navigationBar.topItem {
topItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
}
// now we need to say that if there is a goal to edit ( not equal to nil), then we load the Goal data with the loadGoalData() function.
if goalToEdit != nil {
loadGoalData()
}
imagePicker = UIImagePickerController()
imagePicker.delegate = self
}
// when button is pressed, I need to
// 1 : add a point to the pointsLabel
// 2 : put the current date to the dateLabel
// 3 : persist the new points and date labels.
#IBAction func plusOneBtnPressed(_ sender: UIButton) {
currentScore += 1
pointsLabel.text = "\(currentScore)"
}
#IBAction func minusOneBtnPressed(_ sender: Any) {
}
#IBAction func savePressed(_ sender: Any) {
var goal: Goal!
let picture = Image(context: context) // Image = Entity
picture.image = thumbImage.image // image = attribute
if goalToEdit == nil {
goal = Goal(context: context)
} else {
goal = goalToEdit
}
goal.toImage = picture
// this is unwrapping because the original goalToEdit is an optional.
if let title = titleTF.text {
goal.title = title
}
// we saveed, or persisted the TITLE
if let points = pointsLabel.text {
goal.plusOnes = (points as NSString).intValue
}
// we saveed, or persisted the POINTS
if let details = detailsTextView.text {
goal.details = details
}
// we saved, or persisted the DETAILS
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE MMM d yyyy"
if let date = dateFormatter.date(from: dateFormatter.dateFormat) {
goal.lastEntry = date as NSDate
}
// we saved, or persisted the DATE
ad.saveContext()
_ = navigationController?.popViewController(animated: true)
}
func loadGoalData() {
if let goal = goalToEdit {
titleTF.text = goal.title
pointsLabel.text = "\(goal.plusOnes)"
detailsTextView.text = goal.details
dateOfEntry.text = (String(describing: goal.lastEntry))
thumbImage.image = goal.toImage?.image as? UIImage
}
}
When you get the persisted number you should also set currentScore to that value (if greater than 0). I believe currently you only set it to 0 that's why the incrementation starts over.

Changing the view color when comparing values

I created a view to use as background and I would like to change its color when label text is greater or less than variable number. The script is okay but the color is not changing.
Thanks in advance.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var localName: UITextField!
#IBOutlet weak var localNameLabel: UILabel!
#IBOutlet weak var localTemp: UILabel!
#IBAction func getData(sender: AnyObject) {
getWeatherData("http://api.openweathermap.org/data/2.5/weather?q=" + localName.text! + "")
}
#IBOutlet weak var fundo: UIView!
override func viewDidLoad() {
super.viewDidLoad()
getWeatherData("http://api.openweathermap.org/data/2.5/weather?q=London")
// 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.
}
func getWeatherData(urlString: String){
let url = NSURL (string: urlString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
self.setLabels(data!)
})
}
task.resume()
}
func setLabels(weatherData: NSData) {
do {
let json = try NSJSONSerialization.JSONObjectWithData(weatherData, options:NSJSONReadingOptions.MutableContainers) as! NSDictionary
print(json)
//localNameLabel.text = json[("name")] as? String
if let name = json[("name")] as? String {
localNameLabel.text = name
}
if let main = json[("main")] as? NSDictionary {
if let temp = main[("temp")] as? Double {
//convert kelvin to celsius
let ft = (temp - 273.15)
let myString = ft.description
localTemp.text = myString
self.changeColor()
}
}
} catch let error as NSError {
print(error)
}
var number : Float
func changeColor(){
number = 19.0
if(Float(localTemp.text!) < number){
fundo.backgroundColor = .blueColor()
}else{
fundo.backgroundColor = .orangeColor()
}
}
}
}
Edited to post the entire script
In your view controller you need to add UITextFieldDelegate which will allow you to access methods related to your text field. The top of your view controller should look like this:
class ViewController: UIViewController,UITextFieldDelegate //set delegate to class
You then need to set the delegate of your text field to self in viewDidLoad and add a target for when the text field changes:
override func viewDidLoad() {
super.viewDidLoad()
localTemp.delegate = self //set delegate to this vc
localTemp.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
}
You can then implement this method which will run on every key press and you need to call your changeColor() method as above:
func textFieldDidChange(textField: UITextField) {
self.changeColor()
}