0

This is very basic but I'm kinda confused why my code isn't working. I have a user that has an optional username and I am trying to check whether the email or username contains my search query

struct ChatUser: Codable, Identifiable {
let email: String    
var username: String?
}

@State var user: ChatUser

if user.email.lowercased().contains(search.lowercased()) || 
user.username.lowercased().contains(search.lowercased()) {...}

It works if I unwrap user.username! but then my App crashes due to unwrapping nil values. How do I check for user.username != nil and then force unwrap in the if check?

AdamLeet
  • 127
  • 8
  • 2
    Using ``if let`` or ``guard let`` to cover your optional value. https://stackoverflow.com/questions/32256834/swift-guard-let-vs-if-let – Thang Phi Sep 29 '22 at 08:58
  • May be it's `user.username!.lowercased().contains(search.lowercased())`? – Cy-4AH Sep 29 '22 at 09:22

3 Answers3

3

Calling lowercased() again and again is unnecessarily expensive.

But with your given syntax this is the swifty way

if user.email.lowercased().contains(search.lowercased()) || 
   user.username?.lowercased().contains(search.lowercased()) == true {...}

The Optional Chaining expression returns nil immediately if username is nil.

However range(of:options: can handle the optional and the case

if user.email.range(of: search, options: .caseInsensitive) != nil ||
    user.username?.range(of: search, options: .caseInsensitive) != nil {

}
vadian
  • 274,689
  • 30
  • 353
  • 361
1

You can use nil-coalescing(??) to unwrap your optional value.

if user.email.lowercased().contains(search.lowercased()) || 
user.username?.lowercased().contains(search.lowercased()) ?? false {

}
Nirav D
  • 71,513
  • 12
  • 161
  • 183
  • Somehow I didn't think of this, instead I tried this `user.username! != nil ? user.username!.lowercased().contains(search.lowercased()) : user.email.lowercased().contains(search.lowercased())` – AdamLeet Sep 29 '22 at 09:05
  • 1
    That is also correct but you need to add one more check, Also it is `user.username != nil` you need to remove `!`, otherwise it is still forced wrapping, so it will crash if username is nil – Nirav D Sep 29 '22 at 09:07
  • This answer is better, but it isn’t the answer that was accepted by the OP in the first place and it is getting close to another answer. I usually only add to accepted answers in this case instead of changing them. *Another was to do it is to use optional chaining like vadian suggested and then use nil-coalescing to unwrap the optional Bool* – vacawama Sep 29 '22 at 10:00
0
if user.email.lowercased().contains(search.lowercased()) || 
(user.username.map { $0.lowercased().contains(search.lowercased()) } ?? false) {

}
Cy-4AH
  • 4,370
  • 2
  • 15
  • 22