How to get the text out of a WKInterfaceLabel - swift

It seems that labels are a bit different on the Apple Watch!
I have the following label created :
#IBOutlet weak var playerNameLabel: WKInterfaceLabel!
Then writing the label is no problem (with the "setText" method)
let someString = "Hello"
playerNameLabel.setText(someString)
But how do I get the text out of such a Label into a String-constant ???
I tried:
let plaerName_firstTrial: String = playerNameLabel.description // some weird stuff
let plaerName_secondTrial: String = playerNameLabel.text // error
let plaerName_thirdTrial: String = playerNameLabel // error
let plaerName_fourthTrial: String = ?????

WKInterfacLabel has only setter property and no getter property as defined by Apple.
Check this WKInterfaceLabel class declaration :

According to https://developer.apple.com/library/ios/documentation/WatchKit/Reference/WKInterfaceLabel_class/
They only seem to allow setting the text, not getting it (programmatically).

Related

Converting UItextField from referencing outlet collection from String to Float in swift/Xcode

Im stuck on this part of my code, I'm trying to get an average % from the numbers entered into my Textfields. I'm very new at this and would appreciate it if someone can help out and tell me where I'm going wrong and point me in the right direction.
class ingredientViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var abvTextFields: [UITextField]!
#IBOutlet var AbvTotal: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
AbvTotal.layer.cornerRadius = 8.0
}
func abvList(abvTextFields:Int...) -> Float {
let abv1 = Float(abvTextFields.reduce(0,+))
let abv2 = Float(abvTextFields.count)
let abv3 = abv1 / abv2
return abv3
}
Assuming abvTextFields is a valid outlet collection of text fields their content will be strings, therefore trying to sum them using reduce(0,+) won't work. You will need to convert them to Ints first:
let sum = abvTextFields.compactMap({Int($0.text ?? "")}).reduce(0,+)
let validNumbers = abvTextFields.compactMap({Int($0.text ?? "")}).count
let average = sum / validNumbers
The above handles the text fields being empty by nil coalescing an empty string for their content, and then tries to convert the string to an Int. If the string isn't numeric converting to an Int will return nil, so compactMap is used to drop these cases.
It would be possible to do all the conversion within a complex reduce block, but this demonstrates the steps more clearly.
EDIT Note the comment below. Just use Int($0.text!) without the nil coalescing.

Type has no member

I'm new to swift and I'm trying to create a very simple app but for some reason, the variables are not working.
I'm not really sure what the problem is but I've tried changing var to let.
class ImageViewController: ViewController {
var blocks = [Block(size: 100, centerX: 100, centerY: 100, code: "1", color: image.colorDic["1"]!)]
var codes = ["1"]
var colors = [UIColor(named: "Red")]
//create image
var image = Image(blocksArray: blocks, code: codes, color: colors)
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
title = "Title"
for block in image.blocksArray{
view.addSubview(block.block)
}
// Do any additional setup after loading the view.
}
On the line where I create the image, I get an error that says
"Type 'ImageViewController' has no member 'blocks'"
Also, right under the line where I create 'colors' I'm also getting
"Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee74cbf48)"
your property image access the block property before they are both initilized, to fix your problem your variable "image" should be flagged as lazy variable, meaning it will be initilized after the other properties have been initilized hence it is safe to access those other properties.
More about lazy properties
The official Swift documentation says,
"Lazy properties are useful when the initial value for a property is dependent on outside factors whose values are not known until after an instance’s initialization is complete."
You can read more about lazy properties here: - Swift Properties Official documentation
Here is how to do it: -
lazy var image: Image = {
return Image(blocksArray: blocks, code: codes, color: colors)
}()
for the case of colors part, I think it is a good practice to avoid typing strings when initializing especially for simple colors like yours and use the enum versions.
Change it to this : -
var colors = [UIColor.red]
or this: -
var colors: [UIColor] = [.red]

UILabel Value of type 'String' have no member 'text' (Static Custom Cell)

I'm getting user information from json but when I assign the values to my labels, it shows the error (Value of type 'String' have no member 'text').
Is it because the Custom static table cell? How to fix it? My foundation is not good...
And:
Use different variable names. Its good practise to have unique variable names
As the variable names are same as variable values you are getting the error
UILabel has name empNameLabel : UILabel(In viewDidLoad) and value also has same name.
change
let empNameLabel = user!["crew_name"] as? String //conflicting name with UILabel iboutlet
to
let empNameValue = user!["crew_name"] as? String //variable name is unique
Also you should not force unwrap options(user in your case)
it should be
var empNameValue = ""
if let unwrappedUser = user {
if let empNameValue = unwrappedUser["crew_name"] as? String {
empNameLabel.text = empNameValue //assign value to UILabel
}
}
You are trying to get ".text" value from "String" which is not possible.
Either use self:
self.empnameLabel.text = empnameLabel
or give different names to string constant:
self.empnameLabel.text = str
or directly store that value to lable:
self.empnameLabel.text = user[crewname]! as! String
This is what happens when you give the outlet and variable the same name.
The variable empNameLabel has no property called text.
text is the property of empNameLabel outlet.
change the variable name. Eg
let empName = user!["crew_name"] as? String
Change your label variable name
Set your newLabelVariable.text to the empNameLabel

Setting Text View to be Int rather than String? Swift

I have a text view for the user to input an Int.
I am having an issue with saving the result into an Int variable as it default thinks its a string.
What would be the best solution to force the output as an Int? I am using a numerical only keyboard so the user cannot enter strings
code:
#IBOutlet weak var userExerciseWeight: UITextField!
var userExerciseWeightSet = Int()
if let userExerciseWeightSet = Int(self.userExerciseWeight.text!) {
}
You can simply use if let construct for this. textView always will be string. all you need to do is convert textView text to Int.
if let intText = Int(self.textView.text) {
print(intText)
}
I am having an issue with saving the result into an Int variable as it default thinks its a string.
Text view is a view, not a model. What it displays is always a string. When the string happens to represent an Int, your code is responsible for converting Int to String when setting the initial value, and then for converting String back to Int when reading the value back from the view.
if let intVal = Int(textView.text) {
... intVal from text is valid
} else {
... text does not represent an int - e.g. it's empty
}
The same approach applies to displaying and reading values of other types: your program is responsible for formatting and parsing the data into an appropriate type.

Difference between optional values in swift?

What is the difference between:
var title:String? = "Title" //1
var title:String! = "Title" //2
var title:String = "Title" //3
What am I saying if I were to set title in each way and am I forced to unwrap each variable in a different way?
Think about ? and ! like a box that might have a value or not.
I recommend this article.
Optional box that might have value or might not, and that optional box is not unwrapped.
var title:String? = "Title" //second and third picture
You use unwrapped value like that:
if let title = title {
//do sth with title, here is the same like let title: String = "Title"
}
Optional box that might have a value or might not, and that optional box is actually unwrapped. If there is a value and you access that value, that is ok (second image, just replace ? with !), but if there is no value, then app crash (third image, just replace ? with !)
var title:String! = "Title"
That variable have a value for sure, and you cannot assign to this value nil (because it is not optional). Optional means that there is a value or there is no value (nil):
var title:String = "Title" //first picture
`var title:String? = "Title"`
title currently has a value of Title, but in the future it could possibly be nil. I will need to unwrap it using optional binding:
if let unwrappedTitle = title {
println(unwrappedTitle)
}
Or by forcing the unwrap with the ! character
let unwrappedTitle = title!
The above will crash if title is nil
`var title:String! = "Title"`
title currently has a value of "Title". It could possibly be nil, but I know that it never will be when I am using it. You don't need to unwrap this with optional binding or by forcing the unwrap with the ! character.
Your program will crash if this value is ever accessed while nil, but the compiler will let you set this value to nil.
`var title:String = "Title"`
title currently has a value of "Title". This may change, but the variable title will always have some string value. I don't need to check for nil with optional binding or by forcing an unwrap. The compiler will not let you build if you try to set title to nil.
var title:String? = "Title" //1 Nil Possible-Force Unwrap needed-Nil checking when use
var title1:String! = "Title"//2 Nil Possible-Force Unwrap not needed-Nil cheking when Use
var title2:String = "Title" //3 Nil Not possible as its initailize when declared-No force unwrap needed-No Nil Cheking is needed.