default value not printing in swift - swift

I am trying to print the value of strVal after lblTxt in the label when the text field is empty but it not accepting the value, instead just printing the value of lblTxt. I know it works when the left hand side variable if of optional, but i am taking value from the textfield how should I make that optional? I am very new to this.

The type of textFieldTest.text is an optional String, or String?. There are several ways to use optionals:
var text4:String? = textFieldTest.text // assign it to another optional variable
var text5 = textFieldTest.text // the same, the compiler will infer that text5 is also an optional string
textFieldTest.text?.append(" hello") // will only call `append(_:)` on `text` if it's not nil, otherwise this will be ignored
let text6:String = textFieldTest.text ?? "It was nil!" // use the coalescing operator
let text7:String = textFieldTest.text! // force-unwrap it into a String; if it's nil, your app will crash
if let text8 = textFieldTest.text {
// this code block will ONLY execute if textField.text was not nil
// in that case, text8 will be of type String (non-optional)
// so it shouldn't be treated as an optional
}
Your code unwraps the optional, and runs a code block only in case the optional was not nil. Then, in the same code block, you still want to test for nil, but again, if it were nil, the code block would not execute in the first place. And you even perform the test on a non-optional type which is not meaningful.
As your code does not seem to require textFieldTest.text to contain a value (actually, on the contrary: you want to explicitly also handle the scenario where it doesn't), you must avoid making your code block only execute in case textFieldTest.text unwraps to a String.
So simply do not unwrap it:
#IBaction func stringButtonPressed(_ sender: Any) {
labelTest.text = "\(lblTxt) \(textFieldTest.text ?? strval!)"
labelTest.backgroundColor = UIColor.yellow
...
}
Or you can use the unwrap logic to do the same in a more verbose way:
#IBaction func stringButtonPressed(_ sender: Any) {
if let text3 = textFieldTest.text {
labelTest.text = "\(lblTxt) \(text3)"
} else {
labelTest.text = "\(lblTxt) \(strval!)"
}
labelTest.backgroundColor = UIColor.yellow
...
}
In any case, be aware that the block after if let is conditional.

If you declare a variable with if let you basically saying Execute this code blocks when its not nil so text3 ?? strval! in that line strval will not gonna execute because text3 isn't nil
If text3 is nil , code blocks in brackets won't execute.

Related

Swift short hand for assignment of Optional values

I'm new to Swift and I'm wondering if there's a 'short hand' form of assigning Optional values to non-optional values without doing if nil check.
For example if I've got an Optional closure:
var onTap: (() -> Void)?
I can later on call this via
onTap?()
The ? let's me skip the nil check and force unwrap.
But I'm curious if something exists for values that are not clousre. For example
var oldTransform: CGAffineTransform?
var someTransform: CGAffineTransform //non optional
and later on, I decide to assign oldTransform to someTransform I have to
if (oldTransform != nil) {
someTransform = oldTransform!
}
Is there a pattern that's less verbose to do the above (kinda of like the ?)?
Yes, of course. You could use if let as below:
if let unwrappedOldTransForm = oldTransform {
someTransform = unwrappedOldTransForm
}
When you check with if let, it will unwrap the value for you and check if it can set the value of oldTransform to unwrappedOldTransForm. If the value is nil you will be able to handle the error by adding an else condition as below:
if let unwrappedOldTransForm = oldTransform {
someTransform = unwrappedOldTransForm
} else {
// handle if oldTransform is nil
}
In the case of a function, as you know, "calling" a nil function (like onTap?()) has no effect - but for an assignment to a non-optional type you need to supply a definite non-optional value. For that you can use the nil-coalescing operator ?? like so:
var optionalString: String?
// ... maybe set optionalString ...
var realString: String = optionalString ?? "<some default value>"
In your example, it would be
someTransform = oldTransform ?? CGAffineTransform(...) // some default - say Identity
or even, as commentator #user28434 suggests
someTransform = oldTransform ?? someTransform // assuming someTransform already initialised
which will only change someTranform if oldTransform isn't nil.
In each case, the left hand operand of ?? will be assigned if is non-nil, otherwise the right hand side operand will be assigned.

Converting from Int to String Swift 2.2

Dears
I have this case where chatId is a property of type Int
let StringMessage = String(self.listingChat?.messages.last?.chatId)
When I debug I find that StringMessage is returning Optional(15) Which means it is unwrapped. But at the same time XCode does not allow me to put any bangs (!) to unwrap it. So I am stuck with Unwrapped Variable. I know its noob question but it I really cant get it. Your help is appreciated.
Thank you
It depends on what you want the default value to be.
Assuming you want the default value to be an empty string (""), You could create a function or a method to handle it.
func stringFromChatId(chatId: Int?) -> String {
if let chatId = chatId {
return String(chatId)
} else {
return ""
}
}
let stringMessage = stringFromChatId(self.listingChat?.messages.last?.chatId)
Or you could handle it with a closure.
let stringMessage = { $0 != nil ? String($0!) : "" }(self.listingChat?.messages.last?.chatId)
If you don't mind crashing if self.listingChat?.messages.last?.chatId is nil, then you should be able to directly unwrap it.
let StringMessage = String((self.listingChat?.messages.last?.chatId)!)
or with a closure
let stringMessage = { String($0!) }(self.listingChat?.messages.last?.chatId)
Update
Assuming chatId is an Int and not an Optional<Int> (AKA Int?) I missed the most obvious unwrap answer. Sorry, I was tired last night.
let StringMessage = String(self.listingChat!.messages.last!.chatId)
Force unwrap all the optionals along the way.
Optionals have a very nice method called map (unrelated to map for Arrays) which returns nil if the variable is nil, otherwise it calls a function on the (non-nil) value. Combined with a guard-let, you get very concise code. (I've changed the case of stringMessage because variables should begin with a lower-case letter.)
guard let stringMessage = self.listingChat?.messages.last?.chatId.map { String($0) } else {
// Do failure
}
// Success. stringMessage is of type String, not String?
I think:
let StringMessage = String(self.listingChat?.messages.last?.chatId)!

Swift String Interpolation displaying optional?

When i use the following code and have nameTextField be "Jeffrey" (or any other name)
#IBAction func helloWorldAction(nameTextField: UITextField) {
nameLabel.text = "Hello, \(nameTextField.text)"
}
nameLabel displays... Hello, Optional("Jeffrey")
But, when I change the previous code to include a "!" like this:
#IBAction func helloWorldAction(nameTextField: UITextField) {
nameLabel.text = "Hello, \(nameTextField.text!)"
}
The code works as expected and nameLabel displays.... Hello, Jeffrey
Why is the "!" required, in the video tutorial I used to create this simple program he did not use the "!" and the program worked as expected.
Another alternative is to use the null coalescing operator within the interpolated string for prettier text without the need for if let.
nameLabel.text = "Hello, \(nameTextField.text ?? "")"
It's less readable in this case, but if there were a lot of strings it might be preferable.
Optionals must be unwrapped. You must check for it or force unwrap as you do. Imagine the optional as a box where you put a value. Before you can access it, you need to put it out.
if let name = nameTextField.text {
nameLabel.text = "Hello, \(name)"
}
Here's a handy extension to unwrap Any? to String.
Set a default value for nil values.
extension String {
init(_ any: Any?) {
self = any == nil ? "My Default Value" : "\(any!)"
}
}
// Example
let count: Int? = 3
let index: Int? = nil
String(count)
String(index)
// Output
// 3
// My Default Value
You can also use optional map.
This is where I learned of how to use it.
Basically, map will take an optional and return a value if there's a value and return nil if there's no value.
It think this makes more sense in code, so here's the code I found useful:
func getUserAge() -> Int? {
return 38
}
let age = getUserAge()
let ageString = age.map { "Your age is \($0)" }
print(ageString ?? "We don't know your age.")
I guess this may not be super helpful in the case where you're passing in an optional string, (nil coalescing works just fine in that case), but this is super helpful for when you need to use some value that isn't a string.
It's even more useful when you want to run logic on the given value since map is a closure and you can use $0 multiple times.

Swift 1.2 Concatenate String

I'm getting errors when concatenating string:
let likeKey = "like-" + foodPhotoObjects[indexPath.row].objectId
Error
binary operator '+' cannot be applied to operands of type 'String' and 'String?!'
So, you have an implicitly-wrapped optional of an optional string, something like this:
struct Thing {
let objectId: String?!
}
let foodPhotoObjects: [Thing] = [Thing(objectId: "2")]
With any doubly-wrapped optional, to get to the object inside you’d need to unwrap it twice:
// first unwrap the String?! into a String?
if let outer = foodPhotoObjects[0].objectId,
// then unwrap that String? into a String
inner = outer {
// inner is now a String
println("like-\(inner)")
}
The key here is even though the outer optional is implicit (i.e. ! rather than ?), you can still unwrap implicit optionals using if let, so the implicitness is irrelevant when doing this.
An alternative way of handling this kind of thing, rather than if-let, is to use map:
let concatedString = foodPhotoObjects[indexPath.row].objectId.map {
"like-" + $0
} ?? ""
map on an optional means: if the optional contains a value, change the value using this function and return that as an optional, otherwise return nil. So, unwrap the String? and prepend “like” to it.
?? on an optional means: if the preceding value is nil, replace it with the default on the right-hand side (the empty string), otherwise unwrap it and return that (i.e. the value we just mapped).
Now for the tricky part: because the value we’re calling map on is an implicit optional, it will be implicitly unwrapped – that is, the map is being called on the inner String? rather than on the String?!. This is unlike the case with if let where that was run on the implicit optional first, then the inner optional.
As with all implicit optionals, there’s a risk that they might actually be nil in which case your code would blow up, like so:
let explode = Thing(objectId: nil)
// the next line will generate fatal error: unexpectedly
// found nil while unwrapping an Optional value
explode.objectId.map { "like-" + $0 }
If this is a concern, you could guard against it with some optional chaining:
// note, ? after objectId
let concatedString = foodPhotoObjects[indexPath.row].objectId?.map {
"like-" + $0
} ?? ""
This snippet could win a prize for most optional-handling techniques crammed into a single statement… but it should do what you need.
Swift does not do implicit conversion, even if both are of same type and one of them is of optional type.
Try this.
var concatedString = ""
if let foodphoto = foodPhotoObjects[indexPath.row].objectId as? String {
concatedString = "like-" + foodphoto
}

Printing optional variable

I am trying with these lines of code
class Student {
var name: String
var age: Int?
init(name: String) {
self.name = name
}
func description() -> String {
return age != nil ? "\(name) is \(age) years old." : "\(name) hides his age."
}
}
var me = Student(name: "Daniel")
println(me.description())
me.age = 18
println(me.description())
Above code produces as follow
Daniel hides his age.
Daniel is Optional(18) years old.
My question is why there is Optional (18) there, how can I remove the optional and just printing
Daniel is 18 years old.
You have to understand what an Optional really is. Many Swift beginners think var age: Int? means that age is an Int which may or may not have a value. But it means that age is an Optional which may or may not hold an Int.
Inside your description() function you don't print the Int, but instead you print the Optional. If you want to print the Int you have to unwrap the Optional. You can use "optional binding" to unwrap an Optional:
if let a = age {
// a is an Int
}
If you are sure that the Optional holds an object, you can use "forced unwrapping":
let a = age!
Or in your example, since you already have a test for nil in the description function, you can just change it to:
func description() -> String {
return age != nil ? "\(name) is \(age!) years old." : "\(name) hides his age."
}
To remove it, there are three methods you could employ.
If you are absolutely sure of the type, you can use an exclamation mark to force unwrap it, like this:
// Here is an optional variable:
var age: Int?
// Here is how you would force unwrap it:
var unwrappedAge = age!
If you do force unwrap an optional and it is equal to nil, you may encounter this crash error:
This is not necessarily safe, so here's a method that might prevent crashing in case you are not certain of the type and value:
Methods 2 and three safeguard against this problem.
The Implicitly Unwrapped Optional
if let unwrappedAge = age {
// continue in here
}
Note that the unwrapped type is now Int, rather than Int?.
The guard statement
guard let unwrappedAge = age else {
// continue in here
}
From here, you can go ahead and use the unwrapped variable. Make sure only to force unwrap (with an !), if you are sure of the type of the variable.
Good luck with your project!
For testing/debugging purposes I often want to output optionals as strings without always having to test for nil values, so I created a custom operator.
I improved things even further after reading this answer in another question.
fileprivate protocol _Optional {
func unwrappedString() -> String
}
extension Optional: _Optional {
fileprivate func unwrappedString() -> String {
switch self {
case .some(let wrapped as _Optional): return wrapped.unwrappedString()
case .some(let wrapped): return String(describing: wrapped)
case .none: return String(describing: self)
}
}
}
postfix operator ~? { }
public postfix func ~? <X> (x: X?) -> String {
return x.unwrappedString
}
Obviously the operator (and its attributes) can be tweaked to your liking, or you could make it a function instead. Anyway, this enables you to write simple code like this:
var d: Double? = 12.34
print(d) // Optional(12.34)
print(d~?) // 12.34
d = nil
print(d~?) // nil
Integrating the other guy's protocol idea made it so this even works with nested optionals, which often occur when using optional chaining. For example:
let i: Int??? = 5
print(i) // Optional(Optional(Optional(5)))
print("i: \(i~?)") // i: 5
Update
Simply use me.age ?? "Unknown age!". It works in 3.0.2.
Old Answer
Without force unwrapping (no mach signal/crash if nil) another nice way of doing this would be:
(result["ip"] ?? "unavailable").description.
result["ip"] ?? "unavailable" should have work too, but it doesn't, not in 2.2 at least
Of course, replace "unavailable" with whatever suits you: "nil", "not found" etc
To unwrap optional use age! instead of age. Currently your are printing optional value that could be nil. Thats why it wrapped with Optional.
In swift Optional is something which can be nil in some cases. If you are 100% sure that a variable will have some value always and will not return nil the add ! with the variable to force unwrap it.
In other case if you are not much sure of value then add an if let block or guard to make sure that value exists otherwise it can result in a crash.
For if let block :
if let abc = any_variable {
// do anything you want with 'abc' variable no need to force unwrap now.
}
For guard statement :
guard is a conditional structure to return control if condition is not met.
I prefer to use guard over if let block in many situations as it allows us to return the function if a particular value does not exist.
Like when there is a function where a variable is integral to exist, we can check for it in guard statement and return of it does not exist.
i-e;
guard let abc = any_variable else { return }
We if variable exists the we can use 'abc' in the function outside guard scope.
age is optional type: Optional<Int> so if you compare it to nil it returns false every time if it has a value or if it hasn't. You need to unwrap the optional to get the value.
In your example you don't know is it contains any value so you can use this instead:
if let myAge = age {
// there is a value and it's currently undraped and is stored in a constant
}
else {
// no value
}
I did this to print the value of string (property) from another view controller.
ViewController.swift
var testString:NSString = "I am iOS Developer"
SecondViewController.swift
var obj:ViewController? = ViewController(nibName: "ViewController", bundle: nil)
print("The Value of String is \(obj!.testString)")
Result :
The Value of String is I am iOS Developer
Check out the guard statement:
for student in class {
guard let age = student.age else {
continue
}
// do something with age
}
When having a default value:
print("\(name) is \(age ?? 0) years old")
or when the name is optional:
print("\(name ?? "unknown") is \(age) years old")
I was getting the Optional("String") in my tableview cells.
The first answer is great. And helped me figure it out. Here is what I did, to help the rookies out there like me.
Since I am creating an array in my custom object, I know that it will always have items in the first position, so I can force unwrap it into another variable. Then use that variable to print, or in my case, set to the tableview cell text.
let description = workout.listOfStrings.first!
cell.textLabel?.text = description
Seems so simple now, but took me a while to figure out.
This is not the exact answer to this question, but one reason for this kind of issue.
In my case,
I was not able to remove Optional from a String with "if let" and "guard let".
So use AnyObject instead of Any to remove optional from a string in swift.
Please refer link for the answer.
https://stackoverflow.com/a/51356716/8334818
If you just want to get rid of strings like Optional(xxx) and instead get xxx or nil when you print some values somewhere (like logs), you can add the following extension to your code:
extension Optional {
var orNil: String {
if self == nil {
return "nil"
}
return "\(self!)"
}
}
Then the following code:
var x: Int?
print("x is \(x.orNil)")
x = 10
print("x is \(x.orNil)")
will give you:
x is nil
x is 10
PS. Property naming (orNil) is obviously not the best, but I can't come up with something more clear.
With the following code you can print it or print some default value. That's what XCode generally recommend I think
var someString: String?
print("Some string is \(someString ?? String("Some default"))")
If you are printing some optional which is not directly printable but has a 'to-printable' type method, such as UUID, you can do something like this:
print("value is: \(myOptionalUUID?.uuidString ?? "nil")")
eg
let uuid1 : UUID? = nil
let uuid2 : UUID? = UUID.init()
print("uuid1: \(uuid1?.uuidString ?? "nil")")
print("uuid2: \(uuid2?.uuidString ?? "nil")")
-->
uuid1: nil
uuid2: 0576137D-C6E6-4804-848E-7B4011B40C11