Was the String contains(_:) method changed in Swift 4?

I am looking at the latest version of the “App Development with Swift” iBook on page 122. There’s a code example I’ll paste below.

“Maybe you want to check if one string is somewhere within another string. You can use the contains(_:) method to return a Boolean value that indicates whether or not the substring was found.

let greeting = "Hi Rick, my name is Amy."
if greeting.contains("my name is") {
  print("Making an introduction")
}”

Excerpt From: Apple Education. “App Development with Swift.” Apple Inc. - Education, 2017. iBooks. https://itunes.apple.com/us/book/app-development-with-swift/id1219117996?mt=11 <https://itunes.apple.com/us/book/app-development-with-swift/id1219117996?mt=11&gt;

When I try to run this code, I get the following error:

error: cannot convert value of type 'String' to expected argument type 'String.Element' (aka 'Character')
if greeting.contains("my name is") {
                                ^~~~~~~~~~~~

From what I can tell, the Swift 4 Strings are once again collections, so the contains method will only work with characters.

What can I use to find a substring inside a String in Swift 4?

Thank you!

String has also a

   func contains<T>(_ other: T) -> Bool where T : StringProtocol

method, but apparently only if Foundation is imported.

···

Am 08.11.2017 um 04:03 schrieb David Keck via swift-users <swift-users@swift.org>:

I am looking at the latest version of the “App Development with Swift” iBook on page 122. There’s a code example I’ll paste below.

“Maybe you want to check if one string is somewhere within another string. You can use the contains(_:) method to return a Boolean value that indicates whether or not the substring was found.

let greeting = "Hi Rick, my name is Amy."
if greeting.contains("my name is") {
  print("Making an introduction")
}”

Excerpt From: Apple Education. “App Development with Swift.” Apple Inc. - Education, 2017. iBooks. https://itunes.apple.com/us/book/app-development-with-swift/id1219117996?mt=11

When I try to run this code, I get the following error:

error: cannot convert value of type 'String' to expected argument type 'String.Element' (aka 'Character')
if greeting.contains("my name is") {
                                ^~~~~~~~~~~~

From what I can tell, the Swift 4 Strings are once again collections, so the contains method will only work with characters.

What can I use to find a substring inside a String in Swift 4?

Thank you!
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Which isn’t a huge surprise when you consider how tricky string containment is.

import Foundation

// U+00DF LATIN SMALL LETTER SHARP S

let s = "Friedrichstra\u{df}e"
let ss = "strasse"
if s.contains(s) {
    print("It's a street!")
}

Share and Enjoy

···

On 8 Nov 2017, at 08:47, Martin R via swift-users <swift-users@swift.org> wrote:

but apparently only if Foundation is imported.

--
Quinn "The Eskimo!" <http://www.apple.com/developer/&gt;
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

> but apparently only if Foundation is imported.

Which isn’t a huge surprise when you consider how tricky string
containment is.

As someone who has used Swift professionally since it first came out, this
subtle API change after import actually is a surprise to me.

Would you be able to clarify where the line is between “tricky” and “not
tricky” and if possible the reasoning behind making this distinction?
Because as an outsider this seems to me like an unfortunate remnant of ObjC
rather than an obvious and forward-thinking API decision.

import Foundation

// U+00DF LATIN SMALL LETTER SHARP S

let s = "Friedrichstra\u{df}e"
let ss = "strasse"
if s.contains(s) {
    print("It's a street!")
}

In Swiss German “Straße” and “Strasse” are equivalent (or rather, the first
one doesn’t officially exist). In High/“Standard” German they’re not /
would be pronounced differently etc. Some Germans call the “sharp s” an
“sz” instead. So the difficulty of this distinction is not restricted to
Unicode :)

Cheers,
Geordie

···

Quinn "The Eskimo!" via swift-users <swift-users@swift.org> schrieb am Mi. 8. Nov. 2017 um 09:56:

On 8 Nov 2017, at 08:47, Martin R via swift-users <swift-users@swift.org> > wrote:

Share and Enjoy
--
Quinn "The Eskimo!" <http://www.apple.com/developer/&gt;
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Unicode correct string comparison _is_ tricky, but `s.contains(s)` will always be true :)

And `s.contains(ss)` with your example strings return false.

Regards, Martin

···

Am 08.11.2017 um 09:56 schrieb Quinn The Eskimo! via swift-users <swift-users@swift.org>:

On 8 Nov 2017, at 08:47, Martin R via swift-users <swift-users@swift.org> wrote:

but apparently only if Foundation is imported.

Which isn’t a huge surprise when you consider how tricky string containment is.

import Foundation

// U+00DF LATIN SMALL LETTER SHARP S

let s = "Friedrichstra\u{df}e"
let ss = "strasse"
if s.contains(s) {
   print("It's a street!")
}

Share and Enjoy
--
Quinn "The Eskimo!" <http://www.apple.com/developer/&gt;
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

The “only available after importing Foundation” thing has been around since 1.0 — it’s an artifact of the bridging of String and NSString*. After importing Foundation, the methods of NSString are implicitly available as an extension of String. I would think that by now the Swift standard library would have added those methods, but I guess not all of them…

—Jens

* And IIRC it also manifests with Array, Dictionary, and other bridged classes.

···

On Nov 8, 2017, at 2:24 AM, Geordie Jay via swift-users <swift-users@swift.org> wrote:

Would you be able to clarify where the line is between “tricky” and “not tricky” and if possible the reasoning behind making this distinction? Because as an outsider this seems to me like an unfortunate remnant of ObjC rather than an obvious and forward-thinking API decision.

Indeed, apparently so tricky I can’t type my tests in properly )-:

Share and Enjoy

···

On 8 Nov 2017, at 09:28, Martin R <martinr448@gmail.com> wrote:

Unicode correct string comparison _is_ tricky …

--
Quinn "The Eskimo!" <http://www.apple.com/developer/&gt;
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

Would you be able to clarify where the line is between “tricky” and “not
tricky” and if possible the reasoning behind making this distinction?
Because as an outsider this seems to me like an unfortunate remnant of ObjC
rather than an obvious and forward-thinking API decision.

The “only available after importing Foundation” thing has been around
since 1.0 — it’s an artifact of the bridging of String and NSString*. After
importing Foundation, the methods of NSString are implicitly available as
an extension of String. I would think that by now the Swift standard
library would have added those methods, but I guess not all of them…

Hi, and thanks for your response.

I’m aware of the legacy. What I meant was I’m surprised that
String.contains(anotherString) returns two different things depending
whether or not Foundation is imported.

And I was looking for some clarification re: “tricky” vs not. I gather
NSString didn’t even exist in ObjC outside of Foundation. What I was
getting at was whether it makes sense to stick with the status quo on this
point.

Geordie

···

Jens Alfke <jens@mooseyard.com> schrieb am Mi. 8. Nov. 2017 um 16:54: > > > On Nov 8, 2017, at 2:24 AM, Geordie Jay via swift-users < > swift-users@swift.org> wrote:

—Jens

* And IIRC it also manifests with Array, Dictionary, and other bridged
classes.