Xcode 7 beta 2 and swift not getting along - ios

I have an error when I typed in some code, it gave me an error. It looks perfect, but here is the code:
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var resultLabel: UILabel!
#IBOutlet weak var tempText1: UITextField!
#IBAction func convertTemp1(sender: AnyObject) {
#let fahrenheit = (tempText1.text as NSString).doubleValue
let celsius = (fahrenheit - 32 )/1.8
let resultText = "Celsius \(celsius)"
resultLabel.text = resultText
}
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.
}
}
It give me the following error: 'String?' is not convertable to 'NSString' On the line I put a # on. The # is not in the real code.
Note: I do not understand much computer talk so please try to speak very simply. :)

The text property of UITextField returns an optional string but your code doesn't handle optionals. Casting to NSString isn't allowed there (also not necessary to get to the doubleValue).
You need to handle the optional. For this you could force-unwrap it using !. But that can lead to crashes. It would be better to use the if let or guard let statements:
guard let fahrenheit = tempText1.text?.doubleValue else { return }
For conciseness we use optional chaining (the ?here). We could also keep this in two steps:
guard let fahrenheitString = tempText1.text else { return }
let fahrenheit = fahrenheitString.doubleValue
Both are basically equivalent.

Related

Swift get value data from protocol

i need help with my code for swift 5,
so i make a struct and protocol to store list from uitextfield and now i wanna show that data in a UiTextView in another view controller
struct PatientNote {
var note : String
init(note :String) {
self.note = note
}
}
protocol AddNotesDelegate {
func AddNotes(controller : UIViewController, notes: PatientNote)
}
class AddNotesController: UIViewController {
var delegate : AddNotesDelegate!
#IBOutlet weak var Notes: UITextView!
#IBAction func addNotes(_ sender: Any) {
if let notes = self.Notes.text {
let patientNote = PatientNote(note: notes)
self.delegate.AddNotes(controller: self, notes: patientNote)
print(patientNote.note)
}
}
}
and now i wanna show in my view controller but i get this error of "Cannot convert value of type 'PatientNote' to expected argument type 'String'" in this viewController
class NotePatientController: UIViewController, AddNotesDelegate{
func AddNotes(controller: UIViewController, notes: PatientNote) {
let NotesPatient = PatientNote(note: notes) *this is where i get the error
}
var delegate : AddNotesDelegate!
var pasien : PatientNote!
override func viewDidLoad() {
super.viewDidLoad()
PatientTextView.text = pasien.note
}
#IBOutlet weak var PatientTextView: UITextView!
//in this ibaction i edit the notes that i get from the first Vc which is AddNotesController
#IBAction func Save(_ sender: UIButton) {
if let notes = self.PatientTextView.text {
let pasienNotes = PatientNote(note: notes)
self.delegate.AddNotes(controller: self, notes: pasienNotes)
}
}
}
i try to show the note from the AddNotesController to the NotePatientController, and in the NotePatientController i can edit and save the notes in UiTextView.
so i know i must be using the protocol in a wrong way, can someone help me how should i use it? im still kinda new in swift so could probably use any help i can get, Cheer!
Change let notesPatient = PatientNote(note: notes) to let notesPatient = PatientNote(note: notes.note)
It appears PatientNote takes a String as an argument but you passed an already created PatientNote to it instead. The below syntax, using notes.note would be a cleaner solution without involving initialising a new PatientNote.
func AddNotes(controller: UIViewController, notes: PatientNote) {
print(notes.note) // access the note String like this
}

swift: defer non-optional object initialization

When dialing with CocoaTouch, it often happens that UIView(Controller) subclass properties can't be initialized in init method (ex. we need view already loaded), but logically they are non-optional and even non-var. In such cases the property must be optional to compile without errors, what looks pretty ugly - the code is fulfilled with !.
Is there any way to solve this problem? I would imagine some deferred initialization. Perfectly if such property can compile without initial value and crash at runtime if it's accessed prior to be initialized.
Some code sample to describe the issue:
class MyVC: UIViewController {
#IBOutlet var someLabel: UILabel!
let viewBasedParam: CustomClass // how to keep it non-optional if it can be initialized after view has been loaded?
override func viewDidLoad() {
super.viewDidLoad()
self.viewBasedParam = CustomClass(self.someLabel.text)
}
}
P.S. CustomClass can't have default initializer, because it requires data from view.
In your MyVC you can have a convenience init method where you can initialize the let variables. Try this and let me know if it works for you:
class MyVC: UIViewController {
let viewBasedParam: CustomClass
convenience init() {
self.init(nibName:nil, bundle:nil)
self.viewBasedParam = CustomClass(self.someLabel.text)//else just initialize with empty string here and then assign actual value in viewDidLoad
}
}
As far as I've discovered the workaround solution may be following:
class MyVC: UIViewController {
#IBOutlet var someLabel: UILabel!
private var _viewBasedParam: CustomClass? = nil
var viewBasedParam: CustomClass {
get { return self._viewBasedParam! } // always unwrap private optional
set { self._viewBasedParam = newValue }
}
override func viewDidLoad() {
super.viewDidLoad()
self.viewBasedParam = CustomClass(self.someLabel.text)
}
}

Saving an integer in core data

Overview
I need to save several TextFields into CoreData, but only the first one (Seen as pickerView below) saves and prints correctly. The others do not save correctly, for instance, when I try to save the integer ones, I get an error saying that they cannot take a String, which makes sense. I just cannot find a way to fix the integer-string issue. The other error occurs when I attempted to cast everything as a string ( mainly because I won't need to do any arithmetic on it, so it doesn't matter ), and it just gives me a breaking point in the saveButton function.
What I would like to know
What I ultimately need is the ability to save all of these TextFields into CoreData so that I can later retrieve them. I appreciate the help in advance. Thank you!
NOTE
I am including the entire ( or most of ) the ViewController.swift file so that you can see how I am declaring things and then how they are being called. The code in question is located in the saveButton action at the bottom of the code block.
CODE
#IBOutlet weak var locationOfMachine: UITextField!
#IBOutlet weak var engineHours: UITextField!
#IBOutlet weak var YOM: UITextField!
#IBOutlet weak var serialNo: UITextField!
#IBOutlet weak var modelName: UITextField!
#IBOutlet weak var pickerTextField: UITextField!
var pickOption = ["Wirtgen","Kleeman","Hamm","Vögele"]
override func viewDidLoad() {
super.viewDidLoad()
var pickerView = UIPickerView()
pickerView.delegate = self
pickerTextField.inputView = pickerView
// 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 numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
#IBAction func saveButton(sender: AnyObject)
{
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
var entity1 = NSEntityDescription.insertNewObjectForEntityForName("UsedInfo", inManagedObjectContext:context) as NSManagedObject
entity1.setValue(pickerTextField.text, forKey: "product")
entity1.setValue(modelName.text, forKey:"modelName")
entity1.setValue(serialNo.text, forKey:"serialNo")
entity1.setValue(Int(YOM.text!), forKey:"yom")
entity1.setValue(engineHours.text, forKey:"engineHours")
entity1.setValue(locationOfMachine.text, forKey:"location")
print(entity1.valueForKey("product"))
print(entity1.valueForKey("modelName"))
print(entity1.valueForKey("serialNo"))
print(entity1.valueForKey("yom"))
print(entity1.valueForKey("engineHours"))
do {
try context.save()
}
catch {
print("error")
}
}
EDIT
Upon trying to save everything as just a string, since i only need to retrieve it, I run into this issue:
entity1.setValue(pickerTextField.text, forKey: "product")
entity1.setValue(modelName.text, forKey:"modelName")
entity1.setValue(serialNo.text, forKey:"serialNo") <-Thread1:Breakpoint1.1
entity1.setValue(YOM.text, forKey:"yom")
entity1.setValue(engineHours.text, forKey:"engineHours")
entity1.setValue(locationOfMachine.text, forKey:"location")
print(entity1.valueForKey("product"))
print(entity1.valueForKey("modelName"))
print(entity1.valueForKey("serialNo"))
print(entity1.valueForKey("yom"))
print(entity1.valueForKey("engineHours"))
I also get "(lldb)" in the debugger window.
I'll just show you how to get int from string. Use it accordingly:
var aString = "0000" // var aString = textField.text!
var numFromString = Int(aString)
You can assign the text field to aString and convert it to Int like i showed you.
For things that don't need arithmetic, define them as strings in Core Data. For other numbers, it should work to do as you have with Int(YOM.text!).
However, I suggest that you create a managed object subclass for "UsedInfo" so that you can work directly with its properties instead of using setValue:forKey:. The benefit of a subclass is that it will show you data types explicitly.
Validate all textfields before trying to store,set the appropriate keyboard for each textfield and provide the valid character set for each textfield.
For Example:
YOM text field : Use Keyboard with only integers.
Valid character set are 0 to 9
And validation for min and max if applicable.
If any of the validation criteria fails ,throw an alert to input valid data.
I guess this solves your issue.

I am getting errors such as " braced block of statements is an unused closure" and expected expression

This is my first time doing a simple project in swift and these errors are bugging me for last couple of hours. I have this code below and even though i have curly braces around and statements inside the if/else i still get that errors. Any help would be greatly appreciated guys.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var `switch`: UISwitch!
#IBOutlet var Answer: UILabel!
#IBOutlet var tempInput: UITextField!
//aqnswer value
#IBAction func switchPressed(sender: AnyObject)
{
if switch.on {
self.Answer.text = "cel to fah"
}
else {
self.Answer.text = "fah to cel"
}
}
//textfield value
#IBAction func calculate(sender: AnyObject)
{
//get user input
// value = celcius
var Value:Int = tempInput.text.toInt()!
var toFah :Int = ( 32 + Value * 9 ) / 5
//to celcius
var toCel: Int = (Value-32) * 5 / 9
if switch.on {
self.Answer.text = toFah.description
}
else {
self.Answer.text = toCel.description
}
// println(fah)
// Answer.text = fah.description
}
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.
}
}
The Swift Language Guide says:
If you need to give a constant or variable the same name as a reserved
Swift keyword, surround the keyword with back ticks (`) when using it
as a name. However, avoid using keywords as names unless you have
absolutely no choice.
In your example you have indeed a choice…
But if you really really really want to use switch as a variable name you have to wrap all occurrences of switch in back ticks.

'UInt32' is not convertible to 'MirrorDisposition'

EDIT:
Ok. I just changed my code as: var randomX = Int(arc4random()%6) Wish i could think of it before posting here :|
I took accepted answer of this topic as reference: Swift convert UInt to Int
I've been trying to make a simple ios guessing app with swift. I'm generating a random number and getting another number from user and comparing both. But i'm stuck with this error: 'UInt32' is not convertible to 'MirrorDisposition' while comparing two integers (one of them converted from string to integer by toInt() method)
Below you can see my ui, my code, two stackoverflow topics i read and how i changed my code after reading those topics.
UI: (i couldn't resize the image)
my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var myImageView: UIImageView!
#IBOutlet var inputField: UITextField!
#IBAction func clickedGuessButtonAction(sender: AnyObject) {
println("Guess button clicked")
var randomX = arc4random()%6
println("randomX = \(randomX)")
var guess = inputField.text.toInt()
if((inputField.text) != nil){
if(guess == randomX){
println("correct")
var image = UIImage(named: "images/tick.png");
myImageView.image=image;
self.view.addSubview(myImageView); // what is this?
inputField.resignFirstResponder();// hides keyboard
}
else
{
println("wrong")
var image = UIImage(named: "images/cross.png")
myImageView.image=image;
self.view.addSubview(myImageView);
inputField.resignFirstResponder();//hides keyboard
}
}
else{
println("invalid input. requires integer only")
inputField.resignFirstResponder();// hides keyboard
}
}
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.
}
}
I found these topics on stackoverflow:
float is not convertible to 'MirrorDisposition' Swift What is mirrordisposition?
iOS Swift Error: 'T' is not convertible to 'MirrorDisposition'
First one especially has an extended answer finally suggesting if intValue == Int(floatValue)
Than i changed var guess = inputField.text.toInt()
to var guess = Int(inputField.text);
But this time i'm getting an error message like this: Cannot invoke 'init' with an argument of type '#lvalue String!'
This time, i searched this error message but couldn't find anything helpful. It shouldn't be this difficult to compare 2 integers. I'm definitely missing something easy. Any ideas?
Try changing:
var randomX = arc4random()%6
to
var randomX = Int(arc4random()%6)
this should do it
let sizeX = UInt32(6)
let randomX = CGFloat(arc4random_uniform(sizeX))

Resources