Having trouble using lazy with a var in swift - ios

I am following the standford ios class for Fall 2017. As the professor goes through the demo, I follow by inputting and running like he does. He shows how using lazy with a var allows one to use the UIButton count for variable initialization. When I add the lazy keyword, the error doesn't go away. Thinking it was maybe an xcode update related problem, I downloaded someone else's version of the project and that project doesn't have the issue. The code is below, any thoughts? :/
class ViewController: UIViewController {
lazy var game = ConcentrationModel(numberOfPairsOfCards: (cardButtons.count + 1) / 2)
//Could have had var flipCount: Int = 0
//But it is inferred
var flipCount = 0 {
didSet {
flipCountLabel.text = "Flips: \(flipCount)"
}
}
var emojiChoices = ["🎃","👻","👿","🎃","👻","👿"]
#IBOutlet var cardButtons: [UIButton]!
#IBOutlet weak var flipCountLabel: UILabel!
#IBAction func touchCard(_ sender: UIButton) {
flipCount += 1
if let cardNumber = cardButtons.index(of: sender) {
flipCard(withEmoji: emojiChoices[cardNumber], on: sender)
print("cardNumber = \(cardNumber)")
} else {
print("chosen card was not in cardButtons")
}
print("agh!!! a ghost")
}
func flipCard(withEmoji emoji: String, on button: UIButton) {
if button.currentTitle == emoji {
button.setTitle("", for: UIControlState.normal)
button.backgroundColor = #colorLiteral(red: 1, green: 0.5763723254, blue: 0, alpha: 1)
} else {
button.setTitle(emoji, for: UIControlState.normal)
button.backgroundColor = #colorLiteral(red: 0.9999960065, green: 1, blue: 1, alpha: 1)
}
}
}

To initialize a lazy property which depends on the value of another property you have to use the closure syntax
lazy var game : ConcentrationModel = {
return ConcentrationModel(numberOfPairsOfCards: (self.cardButtons.count + 1) / 2)
}()

Related

How to enable IBAction once numbers are entered into a UIText Field

I am quite new to a programming and I need a help.
I am trying to build a simple calculator. In nutshell: There are two UITextField where the numbers are inserted. There is IBAction (buttonCalculate) that performs the calculation + there is another IBAction (buttonClear) that clears the data inserted into text fields. Upon starting the application both IBAction buttons are disabled. The goal is to enable the IBAction (buttonCalculate) once numbers are inserted. In case the user inserts any other character then numbers a warning message(warrningSign2) needs to appear telling the user that ony numbers are accepted.
Can somebody give a tip / hint how I should proceed?
Thanks!
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var Value: UITextField!
#IBOutlet weak var field1: UITextField!
#IBOutlet weak var field2: UITextField!
#IBOutlet weak var buttonClear: UIButton!
#IBOutlet weak var buttonCalculate: UIButton!
#IBOutlet weak var warrningSign: UITextField!
#IBOutlet weak var warrningSign2: UITextField!
func appLoad () {
buttonClear.isEnabled = false
buttonClear.backgroundColor = .gray
if field1.text == "" || field1.text == "" {
warrningSign.textColor = .red
butonCalculate.isEnabled = false
butonCalculate.backgroundColor = .gray}
}
override func viewDidLoad() {
super.viewDidLoad()
appLoad()
}
#IBAction func calculate(_ sender: Any) {
buttonClear.isEnabled = true
buttonClear.backgroundColor = UIColor(red: 74/255, green: 105/255, blue:187/255, alpha: 1)
Value.text = String(Float(field1.text!)! + Float(field2.text!)!)
}
#IBAction func Clear(_ sender: Any) {
Value.text = "Value"
self.field1.text = nil
self.field2.text = nil
}
}
Make UITextField(field1 and field2) Keyboard type to Number Pad or only acceptable number type.
You can catch the characters sent to a UITextField control by adding the below line:
textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
In textFieldDidChange delegate method you can get the text and validate as per your needs.
I would recommend to update the code like below,
#IBAction func calculate(_ sender: Any) {
calculateAction()
}
private func calculateAction() {
buttonClear.isEnabled = true
buttonClear.backgroundColor = UIColor(red: 74/255, green: 105/255, blue:187/255, alpha: 1)
Value.text = String(Float(field1.text!)! + Float(field2.text!)!)
}
And then call the calculateAction() in textFieldDidChange().

How can I implement Presets savings in Tableview

I need help I have these ColorSlider App that change the color of Square with 3 sliders RGB .I like to create a Tableview where i can store presets of color and retrieve from preset name e.g. Ocean Blue,
Emerald Green, Red Ferrary etc. I create The Tableview with the push of the button but I am stuck with the rest of implementation. Please I need help.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var redSlider: UISlider!
#IBOutlet weak var greenSlider: UISlider!
#IBOutlet weak var blueSlider: UISlider!
#IBOutlet weak var displaylbl: UILabel!
#IBOutlet weak var displayView: UIView!
var color:Color!
override func viewDidLoad() {
super.viewDidLoad()
color = Color(red: redSlider.value, green: greenSlider.value, blue: blueSlider.value)
displaylbl.text = color.getString()
displayView.backgroundColor = color.getColor()
}
#IBAction func sliderChanged(_ sender: UISlider) {
if (sender.tag == 1){
color.setRed(red: sender.value)
displaylbl.text = color.getString()
displayView.backgroundColor = color.getColor()
}
else if (sender.tag == 2) {
color.setGreen(green: sender.value)
displaylbl.text = color.getString()
displayView.backgroundColor = color.getColor()
}
else if (sender.tag == 3) {
color.setBlue(blue: sender.value)
displaylbl.text = color.getString()
displayView.backgroundColor = color.getColor()
}
}
}
import UIKit
class Color {
private var red:CGFloat
private var green:CGFloat
private var blue:CGFloat
init(red:Float, green:Float, blue:Float) {
self.red = CGFloat(red)
self.green = CGFloat(green)
self.blue = CGFloat(blue)
}
func setRed(red:Float) {
self.red = CGFloat(red)
}
func setGreen(green:Float) {
self.green = CGFloat(green)
}
func setBlue(blue:Float) {
self.blue = CGFloat(blue)
}
func getColor() -> UIColor {
let color = UIColor(red: red/255, green: green/255, blue: blue/255, alpha: 1.0)
return color
}
func getString() -> String {
let string = "Red: \(Int(round(red)))\nGreen: \(Int(round(green)))\nBlue: \(Int(round(blue)))"
return string
}
}
First you need to get the RGB color from slider and show in box, if you have done this part then now you need to do is whenever you are showing color in box you just make a dictionary with keys like :
let dict = [ colorName : "whatever you want",
colorCode : "Which you get from slider"
]
Add it in array too like:
arrayColor.append(dic)
Populate your tableview from arrayColor array, and in didselectatindexpath you need to get colorCode atIndexPath.row and set in box.
Hope this will help you. For any other query comment below.

Cannot use variables inside class [duplicate]

This question already has answers here:
How to initialize properties that depend on each other
(4 answers)
Closed 3 years ago.
I'm trying to follow along CS 193P course and I'm currently on a Lecture 2. The lector made var game = Concentration(numberOfPairsOfCards: cardButtons.count / 2) and it worked fine for him, however, it doesn't work at all for me. Am I missing something? I can't pass anything there.
Here's my ViewController class:
class ViewController: UIViewController {
#IBOutlet weak var flipCountLabel: UILabel!
#IBOutlet var cardButtons: [UIButton]!
var game = Concentration(numberOfPairsOfCards: cardButtons.count / 2)
var emojiChoices = ["🎃", "👻", "🎃", "👻"]
var flipCount = 0 {
didSet {
flipCountLabel.text = "Flips: \(flipCount)"
}
}
//MARK: - IBActions
#IBAction func touchCard(_ sender: UIButton) {
flipCount += 1
if let cardNumber = cardButtons.index(of: sender) {
flipCard(withEmoji: emojiChoices[cardNumber], on: sender)
}
}
//MARK: - Methods
func flipCard(withEmoji emoji: String, on button: UIButton) {
if button.currentTitle == emoji {
button.setTitle("", for: .normal)
button.backgroundColor = #colorLiteral(red: 0.9372549057, green: 0.3490196168, blue: 0.1921568662, alpha: 1)
} else {
button.setTitle(emoji, for: .normal)
button.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
}
}
}
And Concentration:
class Concentration {
var cards = [Card]()
func chooseCard(at index: Int) {
}
init(numberOfPairsOfCards: Int) {
for _ in 1...numberOfPairsOfCards {
let card = Card()
cards += [card, card]
}
//TODO: - Shuffle the cards
}
}
The error is
Cannot use instance member 'cardButtons' within property initializer;
property initializers run before 'self' is available
and auto completion doesn't work either
You need to make it a var
var game:Concentration!
then inside viewDidLoad
game = Concentration(numberOfPairsOfCards: cardButtons.count / 2)
OR make it a lazy var
lazy var game:Concentration = {
return Concentration(numberOfPairsOfCards:self.cardButtons.count / 2)
}()

Dynamically / Programmatically assign IBAction to a button

For my project, I have created an ordering menu that programmatically creates buttons that scroll horizontally. However I am looking for ways to assign IBAction - specially action to write to Firebase database - to those buttons dynamically...
Would tagging the buttons and using conditionals work?
My codes are
Food.swift - properties sets of each menu item
class Food
{
var title = ""
var featuredImage: UIImage
var color: UIColor
init(title: String, featuredImage: UIImage, color: UIColor)
{
self.title = title
self.featuredImage = featuredImage
self.color = color
}
static func fetchFoods() -> [Food]
{
return [
Food(title: " Biscuits", featuredImage: UIImage(named: "f1")!, color: UIColor(red: 63/255.0, green: 71/255.0, blue: 80/255.0, alpha: 0.6)),
Food(title: " Sandwich", featuredImage: UIImage(named: "f2")!, color: UIColor(red: 63/255.0, green: 71/255.0, blue: 80/255.0, alpha: 0.6)),
Food(title: " Veg Sandwich", featuredImage: UIImage(named: "f3")!, color: UIColor(red: 63/255.0, green: 71/255.0, blue: 80/255.0, alpha: 0.6)),
]
}
}
UICollectionCell swift
import UIKit
class FoodCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var featuredImageView: UIImageView!
#IBOutlet weak var backgroundColorView: UIView!
#IBOutlet weak var foodButton: UIButton!
var food: Food? {
didSet {
self.updateUI()
}
}
private func updateUI()
{
if let food = food {
featuredImageView.image = food.featuredImage
backgroundColorView.backgroundColor = food.color
foodButton.setTitle("\(food.title)", for: .normal)
} else {
featuredImageView.image = nil
backgroundColorView.backgroundColor = nil
foodButton.setTitle("", for: .normal)
}
}
}
Can I add to Food.swift,
var buttonTag = ""
then assign tag to individual button.
At UICollectionCell.swift, append tag. Using If...else... conditionals to match tag to individual IBAction {ref?.child...")
Thanks everyone!!!
ps.There is another swift file for arranging the menu items horizontally..
Tags are one way to do it, but the easiest way is probably to call addTarget(_:action:for:) on each one to set up its action, e.g.
button.addTarget(button,
action: #selector(buttonFunctionThatDoesSomething:),
for: .touchUpInside) // or .primaryActionTriggered
The first argument is the object whose selector (the second argument) is to be called. The #selector() syntax is really picky; you may want to read this SO answer to figure out the right way to call it.
from the apple document https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/ImplementingACustomControl.html. :
button.addTarget(self, action: #selector(funcName), for: .touchUpInside)
and then:
#objc func funcName() {
//do what u want in here
}

Swift How To Take Int from two textfield and generate a random number [duplicate]

This question already has answers here:
How to generate a random number in Swift?
(26 answers)
Closed 6 years ago.
I have to text fields on a differnet scene.One text field has a smaller number and another one has a bigger number.I need to take those numbers and generate a random number using the smallest number and the biggest number.Then I needed to make a multiplication problem out of it.Example:User enters in 4 and 8.I need to make two random numbers that is more than 4 and less than 8.Here is my code:
//
// CustomModeWithTimer.swift
// BetaVersion0.1
//
// Created by James Ikeler on 5/26/16.
// Copyright © 2016 James Ikeler. All rights reserved.
//
import UIKit
import Foundation
var CustomNumber1 = UInt32(CustomInputForGame)
var CustomNumber2 = UInt32(CustomInput2ForGame)
var Random = arc4random_uniform(CustomNumber2) + CustomNumber1
var Random2 = arc4random_uniform(CustomNumber2) + CustomNumber1
var UnConvertInt = 0
var scorecustom = 0
var TimerCustom = NSTimer()
var CountDownCustom = 10
var GameOverCustom = UIAlertView()
var AnswerCustom = Int(CustomNumber1 * CustomNumber2)
class CustomModeWithTimer: UIViewController {
#IBOutlet weak var CustomInputForGame3: UITextField!
#IBOutlet weak var QuestionForCustomGame: UILabel!
#IBOutlet weak var ScoreLabelForCustom: UILabel!
#IBOutlet weak var TimerCustomLabel: UILabel!
#IBOutlet weak var RightOrWrongCustom: UILabel!
#IBOutlet weak var CustomImgForGame: UIImageView!
func IfAnswerWrong() {
print("TEST\(AnswerCustom)")
CustomInputForGame3.text = ""
CustomImgForGame.image = UIImage(named: "Label")
CustomImgForGame.hidden = false
RightOrWrongCustom.hidden = false
RightOrWrongCustom.text = "Wrong!"
RightOrWrongCustom.textColor = UIColor(red: 225, green: 0, blue: 0, alpha: 1)
}
func IfAnswerRight() {
CountDownCustom = 10
scorecustom += 1
ScoreLabelForCustom.text = "Score: \(scorecustom)"
Random = arc4random_uniform(CustomNumber2) + CustomNumber1
Random2 = arc4random_uniform(CustomNumber2) + CustomNumber1
QuestionForCustomGame.text = "\(Random) x \(Random2)"
AnswerCustom = Int(Random * Random2)
CustomImgForGame.image = UIImage(named: "Label")
RightOrWrongCustom.hidden = false
CustomImgForGame.hidden = false
RightOrWrongCustom.text = "Right!"
RightOrWrongCustom.textColor = UIColor(red: 0, green: 225, blue: 0, alpha: 1)
CustomInputForGame3.text = ""
}
#IBAction func ConfirmAnswerCustom(sender: AnyObject) {
TimerCustom.invalidate()
TimerCustom = NSTimer.scheduledTimerWithTimeInterval(0.8, target: self,selector: Selector("UpdateClockCustom"), userInfo: nil, repeats: true)
let InputAnswerCustom = Int(CustomInputForGame3.text!)
if InputAnswerCustom == AnswerCustom {
IfAnswerRight();
} else {
IfAnswerWrong();
}
}
func UpdateClockCustom() {
TimerCustomLabel.text = ("Time: \(CountDownCustom--)")
if CountDownCustom == -2 {
TimerCustom.invalidate()
GameOverCustom.title = "Game Over!"
GameOverCustom.message = "Nice job you got a score of \(scorecustom).The answer to the question you missed was \(AnswerCustom)!"
GameOverCustom.addButtonWithTitle("Play Again!")
GameOverCustom.show()
}
}
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.
}
Define a randBetween function:
func randBetween(lower: Int, _ upper: Int) -> Int {
return Int(arc4random_uniform(UInt32(upper - lower - 1))) + lower + 1
}
This returns a random number x where lower < x < upper. It doesn't check that lower + 1 < upper which you can decide how to handle yourself.

Resources