5

I have a the following code which i am trying to use to initialize a variable and perform some operation on it.

let formattedPointsValue: String?
self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name) ?? .none

However i am getting the warning

Left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used.

When i remove the ?? .none my projects runs fine without a problem however when i run my unit tests i get an error

fatal error: unexpectedly found nil while unwrapping an Optional value

The only way i found to solve this is to use this code.

if let unformattedValue = model.pointUnitsEarned {
    self.formattedPointsValue = unformattedValue.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name)
} else {
    self.formattedPointsValue = nil
}

I would like to understand why something like this works:

let legend: String?
self.legend = model.pointsCategory ?? .none

but this fails:

let formattedPointsValue: String?
self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name) ?? .none
pacification
  • 5,838
  • 4
  • 29
  • 51
Erent
  • 571
  • 6
  • 15
  • 29

4 Answers4

5

I think you are a little confused with the ?? operator.

You thought this works because legend is optional, didn't you?

let legend: String?
self.legend = model.pointsCategory ?? .none

That is not the reason! The actual reason why the above works is because model.pointsCategory is optional. It has nothing to do with what's on the left hand side of the =. It's all about the operand on the left of ??. So the above says something like this:

set self.legend to model.pointsCategory if model.pointsCategory is not nil. If it is nil, set self.legend to .none.

In this case:

self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+
    " "+"model.name".localized(in: .name) ?? .none

Since "model.name".localized(in: .name) is not an optional, it does not compile. I suspect that what you intended to do here might be this:

if self.formattedPointsValue == nil {
    self.formattedPointsValue = .none
} else {
   self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+
        " "+"model.name".localized(in: .name)
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

.name property is not optional thats why error is comming make .name property optional in model

Amey
  • 795
  • 8
  • 31
  • The .name property is a property from an objective c class. In the project i am working with both OC and swift. Thus i cannnot change the property to optional – Erent Apr 24 '18 at 06:32
  • when i try adding brackets i still get this error : Left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used – Erent Apr 24 '18 at 06:48
  • If you have an Objective-C property that is declared as nonnull, but at the same time can return nil, then you are in trouble. – gnasher729 Apr 24 '18 at 06:57
0

?? only has a use if the value on the left can be nil,

Swift is telling you that it can never be nil so the value on the right will never be used. You can remove : String? as well.

The value of model.pointsCategory is optional, so might be nil, which is why it works for that and doesn’t give you any errors or warnings.

The point of the nil coalescing operator is to be able to fall back to a default value if a value doesn’t exist, there’s no point using it if there’s always going to be a value, so that’s why you’re getting a warning.

Kane Cheshire
  • 1,654
  • 17
  • 20
  • So essentially this code will never work ? let formattedPointsValue: String? self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name) ?? .none – Erent Apr 24 '18 at 06:51
0

model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name)==> should return the value of optional string

For Example: Below code will get the same error which you received

let nickName: String = "k"
let fullName: String? = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"

But below code will work without issues.

let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"

So the conclusion is Coalescing operator '??' will replace or use default value from Right side to Left. NOT from Left to Right.

Subathra D
  • 389
  • 3
  • 7