I have a button that adds 1 to an a attempt score label and then a button that adds a 1 or 0 to the correct score label depending which button is pressed. This data is then passed to various viewControllers. On the last viewController i want to convert the string from the label into a int and then do a simply calculation in order to get a percentage. The code i have tried is below. The percentage is not being displayed so I do not think i am converting it correctly?
On previous VC the aScore and cScore are set as variable that = 0. For example..
var aScore = 0
var cScore = 0
I am passing the data between VC and then on the final viewController the following code exits.
import UIKit
class gViewController: UIViewController {
#IBOutlet weak var correctScore: UILabel!
#IBOutlet weak var attemptScore: UILabel!
#IBOutlet weak var percentage: UILabel!
var aScore: Int!
var cScore: Int!
var percentage1: Int!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
correctScore.text = NSString(format: "%i", cScore) as String
attemptScore.text = NSString(format: "%i", aScore) as String
let c:Int? = Int(correctScore.text!)
let a:Int? = Int(attemptScore.text!)
percentage1 = c!/a!
percentage.text = NSString(format: "%i", percentage1) as String
}
Try this
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.correctScore.text = String(format: "%.1f", cScore)
self.attemptScore.text = String(format: "%.1f", aScore)
var percentage1 = Float(cScore)/Float(aScore)
self.percentage.text = String(format: "%.1f", percentage1)
}
Related
import UIKit
class ViewController: UIViewController {
#IBOutlet var Text1: UITextField!
#IBOutlet var Text2: UITextField!
#IBOutlet var Text3: UITextField!
#IBOutlet var Label: UILabel!
let array = ["Frodo", "sam", "wise", "gamgee"]
let randomIndex = Int(arc4random_uniform(UInt32(array.count))) //Problem is here
#IBAction func button(_ sender: Any) {
Label.text = array[randomIndex]
}
}
You didn't ask any question so I assume you have problem with accessing count of array.
In general you can't access any of instance members until init is completed.
There are (at least) three solutions for your problem.
First is to override all init required by UIViewController and set randomIndex there.
Second is to use lazy for randomIndex:
lazy var randomIndex = {
Int(arc4random_uniform(UInt32(array.count)))
}()
Third is to use some model (class/struct) for those data and inject it to ViewController
You cannot run the line to get the random index on the top level of the class.
It must be located within a function / method:
#IBAction func button(_ sender: Any) {
let randomIndex = Int(arc4random_uniform(UInt32(array.count)))
Label.text = array[randomIndex]
}
And please conform to the naming convention that variable names start with a lowercase letter (text1, label).
Im trying to implement Kingfisher image cache, with images hosted in firebase for my UITableView. However I'm having issues with converting the value types of imageView.kf.setImage..
The error I get is "Cannot convert value of type 'RetrieveImageTask' to type 'UIImageView' in coercion" this is related to the " let profileImage = imageView.kf.setImage(with: imageURL) as UIImageView" line of code below.
I don't seem to understand what imageView.kf.setImage is... I expected it to be an image within in an image view... but seems like it is something else..
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "feedCell") as? feedCell else
{print("dequeueResuableCell return an else"); return UITableViewCell() }
// data fro userdataArray
let imageURL = URL(string: userdataArray[indexPath.row].profileImage)
let imageView = UIImageView()
let profileImageView = imageView.kf.setImage(with: imageURL) as UIImageView
let profileName = userdataArray[indexPath.row].name
// data from activityArray
let activityDate = "8 October"
let distance = "8 km"
let activityName = "test"
let sightings = "20"
let kills = "10"
// Border styling
// cell.addBottomBorderWithColor(color: UIColor.lightGray, width: 0.5)
cell.clipsToBounds = true
// Shadow styling
cell.layer.shadowColor = UIColor.darkGray.cgColor
cell.layer.shadowOpacity = 0.25
cell.layer.shadowRadius = 1
cell.layer.shadowOffset = CGSize(width: 0, height: 1) // shadow on the bottom right
cell.layer.masksToBounds = false // important to show the shadow
cell.configureCell(profileImageView: profileImageView, profileName: profileName, activityDate: activityDate, ActivityName: activityName , distance: distance, sightings: sightings, kills: kills)
return cell
}
configureCell is in a separate view file
import UIKit
class feedCell: UITableViewCell {
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var profileName: UILabel!
#IBOutlet weak var activityDate: UILabel!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var distance: UILabel!
#IBOutlet weak var sightings: UILabel!
#IBOutlet weak var kills: UILabel!
func configureCell(profileImageView: UIImageView, profileName: String, activityDate: String, ActivityName: String, distance: String, sightings: String, kills: String) {
self.profileImage = profileImageView
self.profileName.text = profileName
self.activityDate.text = activityDate
self.name.text = ActivityName
self.distance.text = distance
self.sightings.text = sightings
self.kills.text = kills
}
}
You can't declare profileImageView with "imageView.kf.setImage(with: imageURL) as UIImageView" because It doesn't return anything.
You need to do like this;
let profileImageView = UIImageView()
profileImageView.kf.setImage(with: imageURL)
Swift 2. I'm trying to use the answer of a label.text! to multiply again. The label is an optional but it has to be multiplied with a Double.
#IBOutlet weak var testLabel: UILabel!
#IBOutlet weak var first: UITextField!
#IBOutlet weak var second: UITextField!
func calculation1() {
let dfirst = Double(first.text!)
let dsecond = Double(second.text!)
if dfirst != nil && dsecond != nil {
let answerCal = ceil(dfirst! * dsecond!)
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .DecimalStyle
testLabel.text = numberFormatter.stringFromNumber(answerCal)
}
}
Any help will be appreciated.
First of all, apologies as I've put this together on a tablet meaning I cannot access the code editor. However, here's my take on your problem:
#IBOutlet weak var testLabel: UILabel!
#IBOutlet weak var first: UITextField!
#IBOutlet weak var second: UITextField!
func calculation1() -> Void {
// Check our two text fields contain text
guard let _ = first.text,
let _ = second.text else { return }
c // Check that the text can be parsed as Doubles
c guard let dfirst : Double = Double(first.text!),
let dsecond : Double = Double(second.text!) else { return }
// Now that we know we have two valid numbers, do the calculation
let answerCal : Double = ceil(dfirst! * dsecond!)
// Fetch a number formatter
let numberFormatter : NSNumberFormatter = {
let nF : NSNumberFormatter = NSNumberFormatter()
nF.numberStyle = .DecimalStyle
return nF
}()
// And update the text field with the answer if it produces a valid result
if let answerText : String = numberFormatter.stringFromNumber(answerCal) {
testLabel.text = answerText
}
}
You've got to be careful with UI elements where the user can theoretically type in anything and crash your app if you don't check it first. Hence the guard statements that will safely exit the method call if there is no text in the text fields or if those fields contain unusable text.
The reason you're getting an Optional back from your number formatter is because there is no guarantee that the formatter will be able to give you a valid string. Therefore you'll see that I've explicitly checked that the numbe formatter does generate a non-nil result before trying to update the text field.
(Note - I appreciate the closure for the number formatter is technically surplus to requirements but I find it clearer sometimes when configuring an object.)
UPDATE:
Vidal - did you try the code I sent you? I've quickly knocked up the following which is based on what I put together last night. It is obviously crude but shows that the methodology I suggested works fine, unless I'm missing something. The only issue I can think of is that you've done something in interface builder which I'm unaware of. Hope that helps!
import UIKit
class ViewController: UIViewController {
var calculatorView : UIView!
var textFieldOne : UITextField!
var textFieldTwo : UITextField!
var calButton : UIButton!
var answer : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.calculatorView = {
let cV : UIView = UIView(frame: CGRect(origin: CGPointZero, size: CGSizeMake(400, 400)))
cV.backgroundColor = UIColor.redColor()
func buildTextField() -> UITextField {
let tF : UITextField = UITextField()
tF.backgroundColor = UIColor.whiteColor()
tF.textColor = UIColor.blackColor()
tF.placeholder = "Please enter number"
return tF
}
self.textFieldOne = buildTextField()
self.textFieldTwo = buildTextField()
self.textFieldOne.frame = CGRect(origin: CGPointMake(20, 20), size: CGSizeMake(160, 50))
self.textFieldTwo.frame = CGRect(origin: CGPointMake(220, 20), size: CGSizeMake(160, 50))
self.calButton = {
let cB : UIButton = UIButton()
cB.setTitle("Calculate", forState: .Normal)
cB.frame = CGRect(origin: CGPointMake(20, 80), size: CGSizeMake(360, 50))
cB.addTarget(self, action: #selector(self.getAnswer), forControlEvents: UIControlEvents.TouchUpInside)
return cB
}()
self.answer = {
let a : UILabel = UILabel()
a.backgroundColor = UIColor.blueColor()
a.textColor = UIColor.whiteColor()
a.frame = CGRect(origin: CGPointMake(20, 140), size: CGSizeMake(360, 50))
return a
}()
cV.addSubview(textFieldOne)
cV.addSubview(textFieldTwo)
cV.addSubview(calButton)
cV.addSubview(answer)
return cV
}()
self.view.addSubview(calculatorView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getAnswer() -> Void {
// Check our two text fields contain text
guard let _ = self.textFieldOne.text,
let _ = self.textFieldTwo.text else { return }
// Check that the text can be parsed as Doubles
guard let dfirst : Double = Double(self.textFieldOne.text!),
let dsecond : Double = Double(self.textFieldTwo.text!) else { return }
// Now that we know we have two valid numbers, do the calculation
let answerCal : Double = ceil(dfirst * dsecond)
// Fetch a number formatter
let numberFormatter : NSNumberFormatter = {
let nF : NSNumberFormatter = NSNumberFormatter()
nF.numberStyle = .DecimalStyle
return nF
}()
// And update the text field with the answer if it produces a valid result
if let answerText : String = numberFormatter.stringFromNumber(answerCal) {
self.answer.text = answerText
}
}
}
For one of my static labels on my main story board, it prints out "Optional("United States"). However, I would like it to print out "United States". So my question is, how do I get rid of the "Optional" part? I've already tried doing:
if let p = placemarks!.first{
self.addressLabel.text = "\(p.country)"
}
I think the exclamation mark is supposed to "unwrap" some value right? However, even if I do p = placemarks!.first, it prints out "Optional("United States").
Below is the rest of my code just in case you would like some context:
//
// ViewController.swift
// Map Demo Rob 2
//
// Created by Jae Hyun Kim on 8/17/15.
// Copyright © 2015 Jae Hyun Kim. All rights reserved.
//
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var latitudeLabel: UILabel!
#IBOutlet weak var longitudeLabel: UILabel!
#IBOutlet weak var courseLabel: UILabel!
#IBOutlet weak var speedLabel: UILabel!
#IBOutlet weak var altitudeLabel: UILabel!
#IBOutlet weak var addressLabel: UILabel!
var manager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
manager = CLLocationManager()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
// 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 locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
let userLocation: CLLocation = locations[0]
self.latitudeLabel.text = "\(userLocation.coordinate.latitude)"
self.longitudeLabel.text = "\(userLocation.coordinate.longitude)"
self.courseLabel.text = "\(userLocation.course)"
self.speedLabel.text = "\(userLocation.speed)"
self.altitudeLabel.text = "\(userLocation.altitude)"
CLGeocoder().reverseGeocodeLocation(userLocation, completionHandler: {(placemarks, error) -> Void in
print(userLocation)
if error != nil {
print(error)
return
}
else {
if let p = placemarks?.first{
self.addressLabel.text = "\(p.country)"
}
}
})
}
}
In
if let p = placemarks!.first{
self.addressLabel.text = "\(p.country)"
}
p.country is an Optional<String>. You need to unwrap that aswell in order to output only it's content (if it exists).
if let country = placemarks?.first?.country {
self.addressLabel.text = country
}
I have a profile view, where there are 4 TextField, in one of which must be inserted the date using a DatePicker, I realized, though, that this DatePicker is always visible, on the other hand I would like to appear when you click on the TextField that contains the date. How can I fix?
The code that I inserted is this:
import UIKit
class ProfileViewController: UIViewController {
#IBOutlet weak var bornDate: UITextField!
#IBOutlet weak var dateSec: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
dateSec.addTarget(self, action: Selector("datePickerChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func datePickerChanged(datePicker:UIDatePicker) {
var dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
var strDate = dateFormatter.stringFromDate(dateSec.date)
bornDate.text = strDate
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Ok, I solved the problem with the date format by inserting this piece of code:
var dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd"
let d = NSDate()
let s = dateFormatter.stringFromDate(d)
println(s)