I'm trying to build a key/values pair, for referencing later.
The array will hold a index reference, and it's values inside. One of the values is a video matching the index, and the other value is the corresponding label name (so I can change the color when video is played).
Here is my code:
class ViewController: UIViewController {
var videos = [5: ["urltovideo1", "locationOne"], 7: ["urltovideo2", "locationTwo"]]
var bg: UILabel!
#IBOutlet weak var locationOne: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
bg = videos[5]![1]
bg.backgroundColor = UIColor.green
}
}
I get an error "Cannot assign value of type 'String' to type 'UILabel!'"
I tried "bg = UILabel(videos[5]![1])" and get an error ""Argument labels '(_:)' do not match any available overloads""
Any ideas on how to fix it or better way to implement this?
Here is a solution for you:
#objc var locationOne: UILabel!
#objc var locationTwo: UILabel!
var videos = [5: ["urltovideo1", "locationOne"], 7: ["urltovideo2", "locationTwo"]]
var bg: UILabel! = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
if let bg = self.value(forKey: videos[5]![1]) as? UILabel {
bg.backgroundColor = UIColor.green
}
}
#objc is required to make self.value(forKey:) working properly - you have to add it for every property you want to access via this method.
Related
I have two types of table cells, one that has 6 buttons, and each button has a number value, and then a second cell that has a button to calculate the total sum of the selected numbers, and a label to display this total sum in.
My issue is I cannot get the label to calculate the total. Here is what I have so far
Number Cell:
protocol ToggleNumberCellDelegate: AnyObject {
/// This method detects the selected value of the cell.
func toggleNumberCell(_ toggleNumberCell: ToggleNumberCell, selectedValue: Int)
}
class ToggleNumberCell: UITableViewCell {
static let reuseIdentifier = String(describing: ToggleNumberCell.self)
#IBOutlet private weak var titleLabel: UILabel!
#IBOutlet private weak var zeroButton: UIButton!
#IBOutlet private weak var oneButton: UIButton!
#IBOutlet private weak var twoButton: UIButton!
#IBOutlet private weak var threeButton: UIButton!
#IBOutlet private weak var fourButton: UIButton!
#IBOutlet private weak var fiveButton: UIButton!
#IBOutlet private weak var sixButton: UIButton!
private weak var delegate: ToggleNumberCellDelegate?
private var value: Int?
//...
#IBAction func buttonTapped(_ sender: UIButton) {
switch sender {
case zeroButton:
self.zeroButton.backgroundColor = UIColor.NBABlue
self.zeroButton.tintColor = UIColor.white
self.value = 0
self.delegate?.toggleNumberCell(self, selectedValue: self.value!)
print("The value you tapped is \(value)")
case oneButton:
self.oneButton.backgroundColor = UIColor.NBABlue
self.oneButton.tintColor = UIColor.white
self.value = 1
self.delegate?.toggleNumberCell(self, selectedValue: self.value!)
print("The value you tapped is \(value)")
case twoButton:
self.twoButton.backgroundColor = UIColor.NBABlue
self.twoButton.tintColor = UIColor.white
self.value = 2
self.delegate?.toggleNumberCell(self, selectedValue: self.value!)
print("The value you tapped is \(value)")
The above code just sets up the buttons, and gives each a value by using its delegate.
Label Cell
class CalculateCell: UITableViewCell, ToggleNumberCellDelegate {
var increment = 0
static let reuseIdentifier = String(describing: CalculateCell.self)
#IBOutlet private weak var calculateButton: UIButton!
#IBOutlet private weak var totalLabel: UILabel!
func configure(answer: AnswerModel) {
self.backgroundColor = UIColor.secondarySystemGroupedBackground
self.totalLabel.text = answer.text
self.totalLabel.font = .preferredFont(forTextStyle: .headline)
calculateButton.layer.cornerRadius = 10.0
}
override func prepareForReuse() {
super.prepareForReuse()
self.totalLabel.text = nil
}
#IBAction func calculateTapped(_ sender: UIButton) {
// You need to get the selected value in here somehow.
}
func toggleNumberCell(_ toggleNumberCell: ToggleNumberCell, selectedValue: Int) {
increment = selectedValue
}
}
Here I called the delegate to get the selected value, but I think I did this wrong, can someone tell me how I can calculate to total value?
Here is a screenshot of what I want to achieve.
You have a basic problem with your approach. You should not store data in table view cells. They are views, and should display data, not store data.
You should set up a model object to store the state of your UI. (it could be as simple as an array of integers, one of the value of each ToggleNumberCell in your table view.)
You should have a controller object serve as the delegate for the ToggleNumberCell. When its toggleNumberCell method gets called, it would update the count for that cell's entry in your data model, and then tell the total cell to update itself. Your table view data source would query the model and use the value for each entry in the model to calculate the totals, then install that value in the total cell.
I would recommend you make the UIViewController (than manages the UITableView) the ToggleNumberCellDelegate. Then that view controller can keep track of the total of all of the buttons. The view controller then can provide the total to
the CalculateCell. This separates the logic between the cells. Ideally the controller manages the logic, while the cells are simply views displaying the data.
Also, I would change the toggleNumberCell function to the following:
func toggleNumberCell(_ toggleNumberCell: ToggleNumberCell, selectedValue: Int) {
// Using += will result in adding to the existing value instead of overwriting it
increment += selectedValue
}
I am parsing JSON data to UITableView in which it consists of one image and 5 labels in which one is of type Int and rest are of type String. I have parsed data for type String but when I add Int type to my model class and then write code for displaying cells in cellForItemAt method of UITableViewDelegate, it says cannot assign value of type Int to String.
Here is the screenshot of my app I have tried:
In this, where it says firstappear, there I want to display year like 1970.
Modal Class:
class Hero {
var name:String?
var team:String?
var imageUrl:String?
var realname:String?
var firstappearance:Int?
var publisher:String?
init(name:String?, team:String?, imageUrl:String?, realname:String?, firstappearance:Int?, publisher:String?) {
self.name = name
self.team = team
self.imageUrl = imageUrl
self.realname = realname
self.firstappearance = firstappearance
self.publisher = publisher
}
}
ViewController:
Also when i click the cell in table view i want to display all the contents to another view. I have tried didselectrowat method of table view, but not getting correctly
my source code for didselectroe method as below
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let heroesDetails:HeroesDetailsViewController = self.storyboard?.instantiateViewController(withIdentifier: "HeroesDetailsViewController") as! HeroesDetailsViewController
heroesDetails.heroImage = heroesDetails.detailsImg
heroesDetails.labelName = heroesDetails.detailsName
heroesDetails.labelPublish = heroesDetails.detailsPublisher
heroesDetails.labelAppear = heroesDetails.detailsAppear
heroesDetails.labelTeam = heroesDetails.detailsTeam
heroesDetails.labelRealName = heroesDetails.detailsRealName
self.navigationController?.pushViewController(heroesDetails, animated: true)
}
my another view controller file named as heroesdetailsviewcontroller swift file as below:
import UIKit
class HeroesDetailsViewController: UIViewController {
#IBOutlet weak var detailsImg: UIImageView!
#IBOutlet weak var detailsName: UILabel!
#IBOutlet weak var detailsRealName: UILabel!
#IBOutlet weak var detailsTeam: UILabel!
#IBOutlet weak var detailsAppear: UILabel!
#IBOutlet weak var detailsPublisher: UILabel!
var heroImage: UIImage!
var labelName: String!
var labelTeam: String!
var labelAppear: String!
var labelPublish: String!
var labelRealName: String!
override func viewDidLoad() {
super.viewDidLoad()
detailsImg.image = heroImage
detailsName.text = labelName
detailsRealName.text = labelRealName
detailsTeam.text = labelTeam
detailsAppear.text = labelAppear
detailsPublisher.text = labelPublish
// Do any additional setup after loading the view.
}
}
code screenshot:
I just looked at the API request -> https://simplifiedcoding.net/demos/marvel/
firstappearance is string, update your API model to string instead of int.
class Hero {
var firstappearance:String?
}
It is understandable why you thought it is int, but check the type of the data not the value.
You are assigning Int type to your label which will never accept. So update your following line of code as follow:
cell.labelAppear.text = String(here.firstappearance ?? 0)
Don't type caste again to Int.....
cell.labelAppear.text = String(hero.firstAppearance)
text attribute of UILabel requires string.
I've been trying to address this issue for a few days and it seems I'm only going in circles.
I'm adding data to core data by tapping on tableView cells and then displaying the items on another tableView.
That works great, the problem is this:
When I click on the other table view rows, to be able to see the item with all the other values stored in core data, I get
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value on the showMeTheGoodiesTwo(entry: myCart) line
...Inside viewDidLoad. But I do not know why that's happening, as the entity is not empty.
Here's the code of the view controller where I want to display the item's details.
Hope somebody can give me a hand.
Cheers!
import UIKit
class productQuantityViewController: UIViewController {
var myCart: Cart!
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var productNameLabel: UILabel!
#IBOutlet weak var productDescriptionLabel: UILabel!
#IBOutlet weak var productAmountLabel: UITextField!
#IBOutlet weak var minusButton: UIButton!
#IBOutlet weak var plusButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
productImage.layer.cornerRadius = 10
minusButton.layer.cornerRadius = minusButton.frame.size.width/2
plusButton.layer.cornerRadius = plusButton.frame.size.width/2
showMeTheGoodiesTwo(entry: myCart)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func showMeTheGoodiesTwo(entry: Cart) {
let name = entry.product
let quantity = entry.inventory
let description = entry.productDescription
let image = entry.productImage as Data?
let xNSNumber = quantity as NSNumber
productNameLabel!.text = name
productDescriptionLabel!.text = description
productAmountLabel!.text = xNSNumber.stringValue
productImage!.image = UIImage(data:image!)
print(productNameLabel.text as Any)
}
}
You need to change
var myCart: Cart!
To
var myCart: Cart?
? is use to make it optional.
And in viewDidLoad use
if (myCart != nil){
showMeTheGoodiesTwo(entry: myCart)
} else {
//do something.
}
instead of
showMeTheGoodiesTwo(entry: myCart)
Screenshot of simulator screen
Hello all. I just recently started trying to learn coding in Swift 2. I am trying to make a very simple app where I can add scores, push my "calculate" button and display the total in a label. I was able to do that as seen in the screenshot. The problem I have is if I don't put a score in one of the textfields and still try to calculate it, it crashes. This is my code:
class ViewController: UIViewController {
#IBOutlet weak var score1: UITextField!
#IBOutlet weak var score2: UITextField!
#IBOutlet weak var score3: UITextField!
#IBOutlet weak var total: UILabel!
#IBAction func Calculate(sender: AnyObject) {
let score1 = Int(score1.text!)!
let score2 = Int(score2.text!)!
let score3 = Int(score3.text!)!
let alltogether = (scoreone) + (scoretwo) + (scorethree)
total.text = "Your total score is \(alltogether)!"
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
Could someone point me in the direction I need to look. I am thinking I need to add some sort of exemption if the field is nil. Or something along the lines of making the default int 0??? Thank you all!
let score1 : Int = Int(score1.text ?? "") ?? 0
let score2 : Int = Int(score2.text ?? "") ?? 0
let score3 : Int = Int(score3.text ?? "") ?? 0
This will yield value 0 in case your fields are empty or otherwise non-numerical (or if UITextField property .text contains nil).
Is it possible to have an #IB Action function inside of viewDidLoad() ?
The action is a simple one - a Stepper that increases other label.text values accordingly. However, the values that the stepper needs to work with depend on the return content of a url - which are only known after the viewDidLoad() of course.
So I think I can't have the IBaction way up on top before the viewDidLoad(), and the error I get if I try to do my IB action inside of the viewDidLoad() is:
"Only instance methods can be declared ‘IBAction' ”
EDIT
Let me clarify myself, sorry for the confusion. I know I need an outlet to get the UIStepper values from. I have that:
#IBOutlet weak var stepper: UIStepper!
I then have an action also connected to same UIStepper that will increase/decrease value of a label's text (new_total) accordingly:
#IBOutlet weak var new_total: UILabel!
#IBAction func step_up_pass(sender: AnyObject) {
new_total.text = "\(Int(stepper.value))"
}
However, I want to start out with a value (todays_price) I'm getting back from a json request and use that as a starting point, to multiply it using the stepper and put the multiplied value into the label's text.
I have a struct in a separate file that defines my object so:
struct PassengerFromOtherBus {
var fname: String?
var lname: String?
var todays_price: Int?
init(json: NSDictionary) {
self.fname = json["fname"] as? String
self.lname = json["lname"] as? String
self.todays_price = json["todays_price"] as? Int
}
}
So later on in the view controller, inside of the viewDidLoad(), after connecting to the URL and then parsing it using NSJSONSerialization and a bunch of other code here (that I don't need to confuse you with) I finally have my value todays_price. So my question is, how do I get my action to use that value when it's only known inside of my viewDidLoad()? Xcode will not even let me connect the IBAction to anywhere inside the viewDidLoad function!
This is not done with an Action but with an Outlet. Connect the Stepper from IB as an Outlet to your ViewController. Then just set the values of the Stepper in ViewDidLoad.
I would never go directly from a UIStepper.value to UILabel.text.
Use an intermediary variable to store the value.
Do the same for the return from the JSON. By setting a didSet function on those variables you can update the UI when any of the values is updated.
class FirstViewController: UIViewController {
var todays_price: Int = 0 {
didSet { // didSet to trigger UI update
myLabel.text = "\(stepperValue * todays_price)"
}
}
var stepperValue : Int = 1 {
didSet { // didSet to trigger UI update
myLabel.text = "\(stepperValue * todays_price)"
}
}
#IBOutlet weak var myStepper: UIStepper!
#IBOutlet weak var myLabel: UILabel!
override func viewDidLoad() {
//
let returnValueFromJson = 10
todays_price = returnValueFromJson
}
#IBAction func stepperUpdate(sender: AnyObject) {
stepperValue = Int(myStepper.value)
}
}
Just add a variable to the top of your view controller to hold the value from your json request. Then in viewDidLoad you update that variable, and then you can use it to set your label and inside the IBAction (that doesn't have to be inside viewDidLoad).
So you would do something like this:
class WhateverViewController: UIViewController {
var todays_price: Int!
override func viewDidLoad() {
super.viewDidLoad()
todays_price = // The value you got from json goes here
new_total.text = "\(todays_price)"
}
#IBAction func step_up_pass(sender: AnyObject) {
new_total.text = "\(Int(stepper.value) * todays_price)"
}
}