7

Since Swift 3.0 I have some troubles with Strings, especially with concatenation. 1st example would be what I used since I started using Swift to define my url strings.

internal let host: String! = "https://host.io/"
let urlString = "\(host)oauth/access_token"

where host is defined as at the beginning of the class. This worked perfectly until Swift 3.0, now that prints out like this:

Optional("https://host.io/")oauth/access_token

which is very strange. Now I have to write this

let urlString = host + "oauth/access_token"

To get the expected output.

https://host.io/oauth/access_token

Another - I guess similar problem I'm having with Strings is this. I'm again concatenating strings but this time I'm using + ilke with urlString - but this time that doesn't work. Line of code looks like this:

self.labelName.text = currentUser.name + " " + String(describing: ageComponents.year)

which unfortunately produces string like this: "My Name Optional(26)". In this case I don't have a solution String(describing: ageComponents.year) is not an optional and it doesn't allow me to do things like String(describing: ageComponents.year) ?? "whatever"

Anyone seen something similar?

jovanjovanovic
  • 4,158
  • 3
  • 22
  • 32
  • 4
    See [Swift 3 incorrect string interpolation with implicitly unwrapped strings](http://stackoverflow.com/questions/39537177/swift-3-incorrect-string-interpolation-with-implicitly-unwrapped-strings) – if Swift can type check an implicitly unwrapped optional as a strong optional, it will favour doing so over force unwrapping it. In your second example, is `ageComponents.year` an (implicitly unwrapped) optional? – Hamish Sep 19 '16 at 16:21
  • I'm really trying to see the good in all these Swift 3.0 changes but it's going very slow and hard. In 2nd example .year wasn't unwrapped. That solves 2nd example. Maybe you should write it as an answer. – jovanjovanovic Sep 19 '16 at 16:26
  • 1
    I can't really wrap my head around this SE-0054 proposal. Example says that if we do something like: let x: Int! = 5 let y = x let z = x + 0; 'y' will be 'Int?' - optional. Fine, 'z' won't be because it can't be created as an optional because of '+' sign. What I can't get is, why is this 'y becoming Int?' good? Why would something created from implicitly unwrapped 'Int!' become 'Int?'? I understand '!' as - I already told you that it's not an optional, so use it that way. – jovanjovanovic Sep 20 '16 at 10:06
  • 1
    One good reason for it becoming a strong optional is that it limits the places where the compiler is implicitly force unwrapping – which can be a source of crashes. As with quite a few of the Swift 3 evolution proposals, it's not considered to be the 'perfect model', rather it's a stepping stone towards reaching that model. In this case, the Swift team are looking to completely remove implicitly unwrapped optionals from the language down the line, once there are other language features to replace them (you can read the rationale for this in the 'Motivation' section of the proposal). – Hamish Sep 20 '16 at 13:31
  • Excerpt from the motivation: "*we would like to limit their usage moving forward, and introduce more specific language features to take their place. Except for a few specific scenarios, optionals are always the safer bet, and we’d like to encourage people to use them instead of IUOs. This proposal seeks to limit the adoption of IUOs to places where they are actually required, and put the Swift language on the path to removing implicitly unwrapped optionals from the system entirely when other technologies render them unnecessary.*" – Hamish Sep 20 '16 at 13:31
  • @Hamish, thanks for your explanation. Still, this change seems to me like it's messing with programmers, trying to fix and protect them from themselves - which is maybe something good languages are supposed to do. Anyway, I wouldn't support this change just because it tires to "think instead of me". Thanks again for your comments. – jovanjovanovic Sep 20 '16 at 17:26

1 Answers1

2

In Swift 3 all properties of the native struct DateComponents are optionals unlike the Foundation NSDateComponents counterparts.

var year: Int? { get set }

You need to unwrap it. If you specified the unit year in ageComponents you can do that safely.

vadian
  • 274,689
  • 30
  • 353
  • 361