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.
Related
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
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
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]
(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
It was a logic error. This part of the code:
result1Label.text = topThreeResults[0]
result1Confidence.text = (topThreeConfidences[0] + "%")
result2Label.text = topThreeResults[1]
result2Confidence.text = (topThreeConfidences[1] + "%")
result3Label.text = topThreeResults[2]
result3Confidence.text = (topThreeConfidences[2] + "%")
should have been inside the labeler.process() function. Otherwise it was running the above code without having even retrieved a list of predictions, thus causing the fatal error. By placing it inside, I ensure it has retrieved the list of predictions and only then runs the above code to find specific values in the list.
An oldish retired DEC PDP 8 assembly programmer needs another set of eyes. I created a Hello World program that displays images of the family. The animation works fine, but I would like the user to be able to stop the animation so I added a button to “Pause” the image so that the user can view it at their leisure. However, the .stopAnimation function clears the view. How can this be prevented. Please be kind.
import UIKit
class FamilyUnitController: UIViewController {
#IBOutlet weak var familyMember: UILabel!
#IBOutlet weak var familyPhotos: UIImageView!
var familyName: String = ""
var familyUnitArray = [String]()
#IBOutlet weak var pauseButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
enter code here
configureImageView()
}
#IBAction func pauseImage(_ sender: UIButton) {
if familyPhotos.isAnimating {
familyPhotos.stopAnimating()
pauseButton.setTitle("Paused", for: [])
} else {
familyPhotos.startAnimating()
pauseButton.setTitle("Pause", for: [])
}
}
func configureImageView() {
familyMember.text = familyUnitArray[0]
familyMember.sizeToFit()
let imagePrefix = familyUnitArray[1]
print ("configureImageView called...")
let maxImageCnt = 10
if let imageView = familyPhotos {
print ("Processing images...")
let fileManager = FileManager.default
let path = Bundle.main.resourcePath!
print (#function,">Path> ",path)
let enumerator:FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: path)!
var imageArr = [UIImage]()
var imageCnt: Int = 0
while let element = enumerator.nextObject() as? String {
print (#function,"> element.description",element.debugDescription)
let tmpStr = element.lowercased()
let tmpImagePrefix = imagePrefix.lowercased()
if (element.hasSuffix("png") || element.hasSuffix("jpg") || element.hasSuffix("jpeg"))
&& tmpStr.hasPrefix(tmpImagePrefix)
&& imageCnt < maxImageCnt {
let elementWithPath = path+"/"+element
imageArr.append(UIImage(contentsOfFile: elementWithPath)!)
imageCnt += 1
}
}
imageView.isUserInteractionEnabled = true
imageView.animationImages = imageArr
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = UIColor.white
imageView.animationDuration = 15
imageView.startAnimating()
}
}
}
You may refer here to for pausing the animation / not stopping it.
Is there a way to pause a CABasicAnimation?
In your case ,the code should be like the following, you may need to change a little to make it perfect.
#IBAction func pauseImage(_ sender: UIButton) {
if familyPhotos.layer.speed != 0 {
let time = familyPhotos.layer.convertTime(CACurrentMediaTime(), to: nil)
familyPhotos.layer.speed = 0
familyPhotos.layer.timeOffset = time
pauseButton.setTitle("Paused", for: [])
} else {
familyPhotos.layer.beginTime = familyPhotos.layer.timeOffset - CACurrentMediaTime()
familyPhotos.layer.timeOffset = 0
familyPhotos.layer.speed = 1
pauseButton.setTitle("Pause", for: [])
}
}
I am new here and would like to ask a question that has been working for me for days. I'm just learning Swift 4 and I've come quite a long way. I really do not know what to do any more, and my books on swift do not help me either.
I have created a small testapp, in which should simply be charged.
There are 5 view controllers. The first one has 4 buttons to get to one of the other 4 and to enter a number there in a text box. This number is then output in the first viewcontroller in a label. The numbers are displayed and even the last entered number is displayed again after a restart of the app.
But now I want to charge off the numbers in the first viewcontroller. How can I fix the code?
My Viewports:
my viewports
code from main viewport:
import UIKit
class ViewController: UIViewController, sendValue1, sendValue2, sendValue3, sendValue4 {
#IBOutlet weak var value1: UILabel!
#IBOutlet weak var value2: UILabel!
#IBOutlet weak var value3: UILabel!
#IBOutlet weak var value4: UILabel!
#IBOutlet weak var calculatedValue1: UILabel! // here i want to see the calculated value like from the label 1-4...value1 + value2 + value3 + value4 = ???
#IBOutlet weak var calculatedValue2: UILabel! // here the same like in claculatedValue1 value but with "-" or "*" or something else...
func value1Data(data: String) {
value1.text = data
UserDefaults.standard.set(value1.text, forKey: "value1")
}
func value2Data(data: String) {
value2.text = data
UserDefaults.standard.set(value2.text, forKey: "value2")
}
func value3Data(data: String) {
value3.text = data
UserDefaults.standard.set(value3.text, forKey: "value3")
}
func value4Data(data: String) {
value4.text = data
UserDefaults.standard.set(value4.text, forKey: "value4")
}
override func viewDidAppear(_ animated: Bool) {
if let lastValue1Data = UserDefaults.standard.object(forKey: "value1") as? String {
value1.text = lastValue1Data
}
if let lastValue2Data = UserDefaults.standard.object(forKey: "value2") as? String {
value2.text = lastValue2Data
}
if let lastValue3Data = UserDefaults.standard.object(forKey: "value3") as? String {
value3.text = lastValue3Data
}
if let LastValue4Data = UserDefaults.standard.object(forKey: "value4") as? String {
value4.text = LastValue4Data
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "VC1" {
let SendingVC1: Value1ViewController = segue.destination as! Value1ViewController
SendingVC1.delegate = self
}
if segue.identifier == "VC2" {
let SendingVC2: Value2ViewController = segue.destination as! Value2ViewController
SendingVC2.delegate = self
}
if segue.identifier == "VC3" {
let SendingVC3: Value3ViewController = segue.destination as! Value3ViewController
SendingVC3.delegate = self
}
if segue.identifier == "VC4" {
let SendingVC4: Value4ViewController = segue.destination as! Value4ViewController
SendingVC4.delegate = self
}
}
#IBAction func unwindToView1(_ segue: UIStoryboardSegue) {
}
and the code from one of the other four:
import UIKit
protocol sendValue1 {
func value1Data(data: String)
}
class Value1ViewController: UIViewController {
var delegate: sendValue1? = nil
#IBOutlet weak var textValue1: UITextField!
#IBAction func done(_ sender: Any) {
if delegate != nil {
if textValue1.text != nil {
let data = textValue1.text
delegate?.value1Data(data: data!)
dismiss(animated: true, completion: nil)
}
}
}
why is the result always nil here?
let a = Float(value3.text!) ?? 0
let b = Float(value4.text!) ?? 0
let SUM = a + b
calculatedValue1.text = "\(SUM)" + "m"
No matter what I do, the numbers are not processed ...