Count point in a specific moment when button taped in a new column Parse for example :
#IBAction func nbTapped(sender: AnyObject) {
let PFUser.currentUser()!.objectForKey("buttonpressed") as? Int (buttonpressed)! + 1
}
Should be written as follows:
#IBAction func nbTapped(sender: AnyObject) {
var count = PFUser.currentUser()!.objectForKey("buttonpressed")
PFUser.currentUser()!["buttonpressed"] = count + 1
}
I'm not exactly Swift literate (Obj-C user), but that should work with minimal changes.
Related
I am trying to get buttons (they are numbers) when pressed to show two digits in the label, currentChannelLabel, I created. I have been messing around with this and I can either get one number to show, or I get two of the same number to show. How do I fix my code so I get one number to show, then a second number? After this, if another button is selected, it will show the first number again and then the second. For example:
(button 1 is pressed)
currentChannelLabel: 1
(button 2 is pressed)
currentChannelLabel: 12
(button 3 is pressed)
currentChannelLabel: 3
(button 4 is pressed)
currentChannelLabel: 34
here is my code:
#IBAction func channelNumbers(_ sender: UIButton) {
var number = ""
if let pressed = sender.currentTitle {
number = "\(pressed)"
currentChannelLabel.text = number
if let pressed2 = sender.currentTitle{
number += "\(pressed2)"
currentChannelLabel.text = number
}
}
}
The problem with your code is that pressed2 will always be equal to pressed, because it's not going to change within the body of the function — instead, when the second button is pressed, the function is called again.
Here's some code that should do what you want:
#IBAction func channelNumbers(_ sender: UIButton) {
guard let number = currentChannelLabel.text else {
currentChannelLabel.text = sender.currentTitle
return
}
currentChannelLabel = (number.count == 1 ? number : "") + (sender.currentTitle ?? "")
}
Your code doesn't make much sense. You have two nested if let statements. Either the first will fail, or both will succeed.
You need something like this:
#IBAction func channelNumbers(_ sender: UIButton) {
if let pressed = sender.currentTitle {
let oldLabelText = currentChannelLabel.text ?? ""
currentChannelLabel.text = oldLabelText + pressed
}
}
The string you get in pressed will be the title of the button that was pressed. Then you append that to previous text from the label, and put the result back into currentChannelLabel.text.
(Note that storing your string in currentChannelLabel.text is not ideal. You should really keep a string var in your view controller, append to that, and copy that string into currentChannelLabel.text. (View objects should not hold state. They should display info to the user and collect input from the user.)
I am using a segue to go from View Controller 1 to View Controller 2. View Controller 1 has a button that sets the persistent data when it is clicked on:
I declare a global var for user default:
let userDefault = UserDefaults()
Here is my button to set the user default to a string with text values from labels:
#IBAction func saving(_ sender: UIButton) {
let savedText = "Gallon \(gallonTextFieldOutlet.text) is equal to Litre \(litreTextFieldOutlet.text) is equal to Pint \(pintTextFieldOutlet.text)"
userDefault.setValue(savedText, forKey: "SavedConversion")
}
I then get a reference to View Controller 2 and pass this user default when the user goes from View Controller 1 to View Controller 2 via a segue:
// in view controller 2: reference to get persistent data
var volumeDataOne:String?
// in view controller 2: instantiation of my queue class to use methods
var queue = Queue<String>()
// segue action in view controller 1
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "savedVolumeData"
{
let historyVC:VolumeHistoryViewController = segue.destination as! VolumeHistoryViewController
if let value = userDefault.value(forKey: "SavedConversion") as? String {
historyVC.volumeDataOne = value
}
}
I get this in the View Controller 2 and I am trying to set this to three labels that I have in this View Controller:
func DisplayVolumeHistory() {
let labelArray = [volumeDataLabelOutlet, volumeDataLabelTwoOutlet, volumeDataLabelThreeOutlet]
if let bindingOptional = volumeDataOne
{
for index in 0..<labelArray.count
{
queue.enqueue(val: bindingOptional)
labelArray[index]?.text = queue.arr[index]
}
}
}
In my specification, I have been told that the data needs to be persistent and that only the last five data can be stored at one time. So I have a class that I have called Queue which is referenced in this function. This function gets called on the viewDidLoad of the View Controller 2.
override func viewDidLoad() {
super.viewDidLoad()
//Debug ...
volumeDataLabelOutlet.text = "na"
volumeDataLabelTwoOutlet.text = "na 2"
volumeDataLabelThreeOutlet.text = "na 3"
//...
DisplayVolumeHistory()
// Do any additional setup after loading the view.
}
I have tested my Queue class in a Playground and it works as expected. The Queue class can be seen here:
class Queue {
var arr = [T]()
func enqueue(val: T){
if(arr.count < 3) {
arr.append(val)
} else {
for i in 0..<arr.count-1 {
arr[i] = arr[i + 1]
}
arr[arr.count - 1] = val
}
}
func dequeue() -> (T?){
if (arr.isEmpty){
return nil
} else {
return arr.remove(at: 0)
}
}
}
Here is my issue that I cannot seem to figure out. In View Controller 2, all of the three labels will have persistent data, but they will all be of the same data,
For example, if I have data as follows:
DATA 1: 555
DATA 2: 700
DATA 3: 62
I would want:
LABEL 1 --> 555
LABEL 2 --> 700
LABEL 3 --> 62
However, currently it will be:
LABEL 1 --> 62
LABEL 2 --> 62
LABEL 3 --> 62
I am unsure as to why debugging. I believe it is because my persistent data in my View Controller 1 is only taking a string, which the Dictionary is overriding as I use the same key.
However, I looked at the documentation and trying to use a user default array did not solve my issue and I am unsure as to what is causing this problem.
I appreciate any guidance and help to try to solve this issue.
Thanks
You are right on your comment,
which the Dictionary is overriding as I use the same key
Each time you tap that button, you are overriding the value with the new one. So you should be seeing always on your v2, the last one.
So probably you should store an array instead of a String.
//on v1
var values = [String]()
#IBAction func saving(_ sender: UIButton) {
let savedText = "Gallon \(gallonTextFieldOutlet.text) is equal to Litre \(litreTextFieldOutlet.text) is equal to Pint \(pintTextFieldOutlet.text)"
values.append(savedText)
UserDefaults.standard.setValue(values, forKey: "SavedConversion")
}
You will pass it to v2 as you are doing now
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "savedVolumeData"
{
let historyVC:VolumeHistoryViewController = segue.destination as! VolumeHistoryViewController
if let values = userDefault.value(forKey: "SavedConversion") as? [String] {
historyVC.volumeDataOne = values //volumeDataOne now needs to be an [String]
}
}
Then on V2, go through your array and labels.
Each time I press a button I am trying to append that new number to the end of my array. I have tried a ton of different things, but I can't quite get it.
I have tried the append, insert, creating an empty array and so much more.
import UIKit
import Foundation
var num1 = 0
class ViewController: UIViewController {
#IBAction func button(_ sender: UIButton) {
var digitCounts = Array(repeating: 0, count: 10)
var number_list = [1,2,3]
if num1 >= 0 {
digitCounts.insert(3, at: num1)
print(digitCounts)
number_list.append(num1)
num1 += 1
print(num1)
print(number_list)
}
}
the result would look like
starting array [1,2,3] after button pressed first time [1,2,3,4] after
button pressed second time [1,2,3,4,5] after button pressed third time
[1,2,3,4,5,6]
Ok now that you've shown the full code I can see the problem. You are creating new arrays every-time you click the button, but are storing num1 outside of this function.
Try this:
import UIKit
import Foundation
class ViewController: UIViewController {
var num1 = 0
var digitCounts = Array(repeating: 0, count: 10)
var number_list = [1,2,3]
#IBAction func button(_ sender: UIButton) {
if num1 >= 0 {
digitCounts.insert(3, at: num1)
print(digitCounts)
number_list.append(num1)
num1 += 1
print(num1)
print(number_list)
}
}
By storing the arrays as properties of the class, instead of inside the function, they will persist through multiple clicks
you have to make you array global and make changes as follow
import UIKit
import Foundation
var num1 = 0
class ViewController: UIViewController {
var number_list = [1,2,3]
#IBAction func button(_ sender: UIButton) {
var number = number_list.last ?? 0
number += 1
number_list.append(number)
print(number_list)
}
}
If you're not multithreading, a simple solution is to remember the last number instead of having to check the last element in the array:
class ViewController: UIViewController {
var number_list = [1, 2, 3]
var num1 = 3
#IBAction func button(_ sender: UIButton) {
number += 1
number_list.append(number)
print(number_list)
}
}
First of all you should declare var number_list as a ViewController's property:
class ViewController: UIViewController {
var number_list = [1,2,3]
}
Otherwise var number_list with it's default value will be created each time when button(_ sender:) is calling.
And use the following handler for your button:
#IBAction func button(_ sender: UIButton) {
number_list += number_list.last.flatMap { [$0+1] } ?? []
print(number_list)
}
All code in this post was tested in Xcode 10.2.1. I used Swift 5.
I am wondering how to make just 1 view terminate in iOS. I am making an app such that in the viewDidLoad() it generates 52 random strings and appends them to an array. I have it so that when you shake the device, it will perform a segue.
The problem with this is that it keeps the items in the array that I mentioned earlier. This means that when it does the user goes into that view again, it will still have the 52 random strings, plus when it goes through the viewDidLoad function, it will append 52 more strings, so if the user doesn't terminate the whole entire app, but just segues out of the view and goes back in, there will be 104 strings and not 52.
I don't want the above to happen in my app, so I am wondering how you could just terminate this one view while also performing a segue so that this problem won't happen.
Here is some code from my app:
These are the arrays I had:
var theCardsTopPlayerHas = [""]
var theCardsBottomPlayerHas = [""]
var theCardsThatWork = ["2_of_clubs", "2_of_diamonds", "2_of_hearts", "2_of_spades", "3_of_clubs", "3_of_diamonds", "3_of_hearts", "3_of_spades", "4_of_clubs", "4_of_diamonds", "4_of_hearts", "4_of_spades", "5_of_clubs", "5_of_diamonds", "5_of_hearts", "5_of_spades", "6_of_clubs", "6_of_diamonds", "6_of_hearts", "6_of_spades", "7_of_clubs", "7_of_diamonds", "7_of_hearts", "7_of_spades", "8_of_clubs", "8_of_diamonds", "8_of_hearts", "8_of_spades", "9_of_clubs", "9_of_diamonds", "9_of_hearts", "9_of_spades", "10_of_clubs", "10_of_diamonds", "10_of_hearts", "10_of_spades", "jack_of_clubs2", "jack_of_diamonds2", "jack_of_hearts2", "jack_of_spades2", "queen_of_clubs2", "queen_of_diamonds2", "queen_of_hearts2", "queen_of_spades2", "king_of_clubs2", "king_of_diamonds2", "king_of_hearts2", "king_of_spades2","ace_of_clubs", "ace_of_diamonds", "ace_of_hearts", "ace_of_spades"]
Here is what the viewDidLoad method has:
struct shuffledVar {
static var shuffled = [String]();
}
override func viewDidLoad() {
super.viewDidLoad()
upperLabelNumber.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
//MARK: - Shuffling Cards
for _ in 1...52 {
let shuffledCardList = Int(arc4random_uniform(UInt32(theCardsThatWork.count)))
let the_card = theCardsThatWork[shuffledCardList]
print("\(the_card)")
shuffledVar.shuffled.append(the_card)
theCardsThatWork.remove(at: shuffledCardList)
print("Finished Card")
}
theCardsTopPlayerHas = Array(shuffledVar.shuffled[0...25])
theCardsBottomPlayerHas = Array(shuffledVar.shuffled[26...51])
print("")
print(shuffledVar.shuffled)
print("")
print(theCardsTopPlayerHas)
print("")
print(theCardsBottomPlayerHas)
}
This is the code that segues the view:
override func motionBegan(_ motion: UIEventSubtype, with event: UIEvent?) {
performSegue(withIdentifier: "friendToDashboard", sender: self)
}
Thank you!
The problem is that you are using a static var to store your array of strings.
To solve this problem there are several solutions depending on what you need. Here there are a couple of solutions:
Solution 1
If you really need to keep the shuffled array as a Singleto, then you can empty the shuffled array in the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
shuffledVar.shuffled = []
upperLabelNumber.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
...
}
Solution 2
If you do not need to keep the shuffled array as a Singleton, then you can modify it as follows:
struct shuffledVar {
var shuffled = [String]();
}
var shuffled = shuffledVar()
override func viewDidLoad() {
super.viewDidLoad()
upperLabelNumber.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
//MARK: - Shuffling Cards
for _ in 1...52 {
let shuffledCardList = Int(arc4random_uniform(UInt32(theCardsThatWork.count)))
let the_card = theCardsThatWork[shuffledCardList]
print("\(the_card)")
shuffled.shuffled.append(the_card)
theCardsThatWork.remove(at: shuffledCardList)
print("Finished Card")
}
theCardsTopPlayerHas = Array(shuffled.shuffled[0...25])
theCardsBottomPlayerHas = Array(shuffled.shuffled[26...51])
print("")
print(shuffled.shuffled)
print("")
print(theCardsTopPlayerHas)
print("")
print(theCardsBottomPlayerHas)
}
You are using static var shuffled so you are using static variable. Do you really need a static variable? If not instead of:
struct shuffledVar {
static var shuffled = [String]();
}
use:
var shuffled:[String] = []
and then in code use:
shuffled.append(the_card)
But if you need this variable to be static (for example you are using it in some other view controller) just remove all elements before adding a new one:
//MARK: - Shuffling Cards
shuffledVar.shuffled.removeAll()
You can read more about static vars https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html and more about arrays: https://developer.apple.com/documentation/swift/array
I'm trying to make some view controllers that save a variable of a label every time and sum it to a total var. At the last view controller, show the result.
My code is:
FirstViewController
#IBAction func playSystemSoundV1(sender: UIButton) {
// Other code...
puntsLocal = 3
}
#IBAction func playSystemSoundRet(sender: UIButton) {
// Other code...
puntsLocal = 5
}
This code is similar for 5 controller. At the end of the controller I have a button to pass from one viewController to another. When I click I do the code above:
#IBAction func puntuacioAction(sender: UIButton) {
let puntuacion = Sum()
puntuacion.sumPoints(puntsLocal)
}
Sum Class
import Foundation
class Sum {
var points = 0
// Method to sum points from every question.
func sumPoints(num: Int) {
self.points += num
}
func getPoints() -> Int {
return points
}
}
The problem is that returns only the last number without do any kind of sum. What can I do? In other languages it's very easy to resolve but in Swift I cannot reach the answer. Help please!
Thanks.
You need to declare your variable outside the function:
let puntuacion = Sum()
#IBAction func puntuacioAction(sender: UIButton) {
puntuacion.sumPoints(puntsLocal)
}
Your original code created a new Sum everytime the function was called, explaining the behavior you are seeing. In Swift, variable declarations are bound to the scope they appear (e.g., inside a function, inside a class, etc).
If, besides that, you want to share this Sum object across many view controllers, this might help:
class Sum {
static let shared = Sum()
...
}
and use it like this:
#IBAction func puntuacioAction(sender: UIButton) {
Sum.shared.sumPoints(puntsLocal)
}
Of course, you should then delete the let puntuacion = Sum() line.