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
}
}
}
Related
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)
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)
}
I am newbie to programming. With CoreData, I am trying to create the function to edit the data in input text field to edit the data to be saved to core data. I am having fatal error:
unexpectedly found nil while unwrapping an Optional value
#IBAction func update(sender: AnyObject) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let manageContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Coursework")
do {
let results = try manageContext.executeFetchRequest(fetchRequest)
let attribute = results[0] as! NSManagedObject
detailItem?.value = modulename.text
attribute.setValue(courseworkname.text, forkey: "courseworkname")
attribute.setValue(dueDateLabel.text, forkey: "duedate")
attribute.setValue(level.text, forkey: "level")
attribute.setValue(mark.text, forkey: "mark")
attribute.setValue(modulename.text, forkey: "modulename")
attribute.setValue(notes.text, forkey: "notes")
attribute.setValue(progressbar.text, forkey: "progressbar")
attribute.setValue(reminder.text, forkey: "reminder")
attribute.setValue(value.text, forkey: "value")
try manageContext.save()
}catch let error as NSError {
}
}
Full code:
#IBOutlet weak var detailDescriptionLabel: UILabel!
#IBOutlet weak var dueDateLabel: UITextField!
#IBOutlet weak var value: UITextField!
#IBOutlet weak var courseworkname: UITextField!
#IBOutlet weak var modulename: UITextField!
#IBOutlet weak var level: UITextField!
#IBOutlet weak var mark: UITextField!
#IBOutlet weak var reminder: UITextField!
#IBOutlet weak var notes: UITextField!
#IBAction func edit(sender: AnyObject) {
modulename.userInteractionEnabled = true
modulename.enabled = true
dueDateLabel.userInteractionEnabled = true
value.userInteractionEnabled = true
modulename.userInteractionEnabled = true
level.userInteractionEnabled = true
mark.userInteractionEnabled = true
reminder.userInteractionEnabled = true
notes.userInteractionEnabled = true
//Interaction
value.enabled = true
dueDateLabel.enabled = true
courseworkname.enabled = true
modulename.enabled = true
level.enabled = true
mark.enabled = true
reminder.enabled = true
notes.enabled = true
}
#IBAction func update(sender: AnyObject) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let manageContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Coursework")
do {
let results = try manageContext.executeFetchRequest(fetchRequest)
let attribute = results[0] as! NSManagedObject
detailItem?.value = modulename.text
attribute.setValue(courseworkname.text, forKey: "courseworkname")
attribute.setValue(dueDateLabel.text, forKey: "duedate")
attribute.setValue(level.text, forKey: "level")
attribute.setValue(mark.text, forKey: "mark")
attribute.setValue(modulename.text, forKey: "modulename")
attribute.setValue(notes.text, forKey: "notes")
attribute.setValue(progressbar.text, forKey: "progressbar")
attribute.setValue(reminder.text, forKey: "reminder")
attribute.setValue(value.text, forKey: "value")
try manageContext.save()
}catch let error as NSError{
}
}
var detailItem: Coursework?
var detailItem2: Task?
{
didSet {
// Update the view.
self.configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
if let detail = self.detailItem {
if let label = self.detailDescriptionLabel {
label.text = detail.courseworkname
}
if let label = self.dueDateLabel {
label.text = detail.duedate
}
if let label = self.value {
label.text = detail.value
}
if let label = self.courseworkname {
label.text = detail.courseworkname
}
if let label = self.modulename {
label.text = detail.modulename
}
if let label = self.level {
label.text = detail.level
}
if let label = self.mark {
label.text = detail.mark
}
if let label = self.reminder{
label.text = detail.reminder
}
if let label = self.notes{
label.text = detail.notes
}
}
Is it a new attribute? You have to uninstall and reinstall the app when you're changing your CoreData models.
Also just saw that you don't have an IBOutlet defined for progressbar, if you link it it should work.
I have a TextView with some text, which font is Bold. And i´ve a button. When this button is tapped, the Bold Font should change to "UnBold"
There´s a ViewController & a class called "FontManager" to manage the Fonts of the TextKit/UITextView.
My code for the FontManager:
import UIKit
class FontManager {
var textView: UITextView! = nil
init(textView: UITextView) {
self.textView = textView
self.setFont()
}
// set a Range of the TextView to Bold at start:
func setFont() {
// set font to "HelveticaNeue"
let newFont = UIFont(name:"HelveticaNeue", size: textView.font!.pointSize)
self.textView.font = newFont
let range = NSMakeRange(11, 24)
self.makeBold(range)
}
// set attributes
func getDict(key : String, value: UIFont ) -> [String: AnyObject] {
return [key : value]
}
This code to set the Font to Bold in selectedRange works without problem
func makeBold(selectedRange: NSRange) {
self.addOrRemoveFontTraitWithName("Bold", andValue: UIFontDescriptorSymbolicTraits.TraitBold.rawValue, andRange:selectedRange)
}
func addOrRemoveFontTraitWithName(traitName: String, andValue traitValue: UInt32, andRange selectedRange: NSRange) {
let currentAttributesDict : NSDictionary! = self.textView.textStorage.attributesAtIndex(selectedRange.location, effectiveRange: nil)
let currentFont : UIFont = currentAttributesDict .objectForKey(NSFontAttributeName) as! UIFont
let fontDescriptor : UIFontDescriptor! = currentFont.fontDescriptor()
let fontNameAttribute : NSString = fontDescriptor.objectForKey(UIFontDescriptorNameAttribute) as! NSString
var existingTraitsWithNewTrait : UInt32! = nil
var changedFontDescriptor : UIFontDescriptor! = nil
Here is a check, if there is already bold text. If not (== NSNotFound) the text in selectedRange becomes the Bold "trait"
if fontNameAttribute.rangeOfString(traitName).location == NSNotFound {
existingTraitsWithNewTrait = fontDescriptor.symbolicTraits.rawValue | traitValue
changedFontDescriptor = fontDescriptor.fontDescriptorWithSymbolicTraits(UIFontDescriptorSymbolicTraits.TraitBold)
(1) if the Font in selectedRange is bold (else: != NSNotFound) the Font should be set to normal (UnBold)
} else {
existingTraitsWithNewTrait = fontDescriptor.symbolicTraits.rawValue & ~traitValue
changedFontDescriptor = fontDescriptor.fontDescriptorWithSymbolicTraits(UIFontDescriptorSymbolicTraits(rawValue: existingTraitsWithNewTrait))
}
let updatedFont = UIFont(descriptor:changedFontDescriptor, size: 0.0)
let dict = self.getDict(NSFontAttributeName, value: updatedFont)
self.textView.textStorage.beginEditing()
textView.textStorage.setAttributes(dict, range: selectedRange)
self.textView.textStorage.endEditing()
}
And now the Code of the ViewController:
class ViewController: UIViewController {
#IBOutlet weak var textView: UITextView!
var fontManger: FontManager! = nil
// the #IBAction to change the Font
#IBAction func SwitchFont(sender: AnyObject) {
let range = NSMakeRange(11, 24)
fontManger.makeBold(range)
}
#IBOutlet weak var textView: UITextView!
var fontManger: FontManager! = nil
override func viewDidLoad() {
super.viewDidLoad()
// init the FontManager
fontManger = FontManager(textView: self.textView)
}
At the first Tap of the button there should be a skip to (1), the else...
But this doesn´t happen. Can see that in debug mode???
Any idea is welcome!
download project
Found it! The Bold-Font is "HelveticaNeue-Bold". The "UnBold"-Font is "HelveticaNeue-Medium" but not "HelveticaNeue" and this difference is almost unvisible!
See no other way as adding
var updatedFont = UIFont(descriptor:changedFontDescriptor, size: 0.0)
if updatedFont.fontName == "HelveticaNeue-Medium" {
updatedFont = UIFont(name:"HelveticaNeue", size: textView.font!.pointSize)!
}
Or do u see a better solution?
class RecordSoundsViewController: UIViewController, AVAudioRecorderDelegate{
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var recodinginProgress: UILabel!
#IBOutlet weak var stopButton: UIButton!
var audioPlayer: AVAudioPlayer!
var recordAudio: RecordedAudio!
var audioRecorder:AVAudioRecorder
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.
}
override func viewWillAppear(animated: Bool) {
//hide the stop button
stopButton.hidden = true
recordButton.enabled = true
}
#IBAction func recordAudio(sender: UIButton) {
recordButton.enabled = false
stopButton.hidden = false
recodinginProgress.hidden = false
//TODO: Record the user"s voice
let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
.UserDomainMask, true)[0] as String
let currentDateTime = NSDate()
let formatter = NSDateFormatter()
formatter.dateFormat = "ddMMyyyy-HHmmss"
let recordingName = formatter.stringFromDate(currentDateTime)+".wav"
let pathArray = [dirPath, recordingName]
let filePath = NSURL.fileURLWithPathComponents(pathArray)
println(filePath)
var session = AVAudioSession.sharedInstance()
session.setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil)
audioRecorder = AVAudioRecorder(URL: filePath, settings: nil, error: nil)
audioRecorder.delegate = self
audioRecorder.meteringEnabled = true
audioRecorder.prepareToRecord()
audioRecorder.record()
}
I don't know what I am doing wrong. My error is coming on my class.
It says
class RecordSoundsViewController has no initializers on RecordSoundsViewController: UIViewController, AVAudioRecorderDelegate{
The error message is a bit bad from the compiler. The reason you see the error is because you have a property which does not have a default value.
In Swift all values needs to have a default value unless it's an optional.
In your case it's this property: var audioRecorder:AVAudioRecorder
In your case I would make this property an optional: var audioRecorder:AVAudioRecorder? and make sure to check for nil when using. Or to make it an implicitly unwrapped optional (if you know there's always gonna be a value): var audioRecorder:AVAudioRecorder!