70

Let's say I want to split a string by an empty space. This code snippet works fine in Swift 1.x. It does not work in Swift 2 in Xcode 7 Beta 1.

var str = "Hello Bob"
var foo = split(str) {$0 == " "}

I get the following compiler error:

Cannot invoke 'split' with an argument list of type '(String, (_) -> _)

Anyone know how to call this correctly?

Updated: Added a note that this was for the Xcode 7 beta 1.

ABakerSmith
  • 22,759
  • 9
  • 68
  • 78
Mallioch
  • 1,416
  • 1
  • 10
  • 17

3 Answers3

126

split is a method in an extension of CollectionType which, as of Swift 2, String no longer conforms to. Fortunately there are other ways to split a String:

  1. Use componentsSeparatedByString:

    "ab cd".componentsSeparatedByString(" ") // ["ab", "cd"]
    

    As pointed out by @dawg, this requires you import Foundation.

  2. Instead of calling split on a String, you could use the characters of the String. The characters property returns a String.CharacterView, which conforms to CollectionType:

    " ".characters.split(" ").map(String.init) // ["", ""]
    
  3. Make String conform to CollectionType:

    extension String : CollectionType {}
    
    "w,x,y,z".split(",") // ["w", "x", "y", "z"]
    

    Although, since Apple made a decision to remove String's conformance to CollectionType it seems more sensible to stick with options one or two.


In Swift 3, in options 1 and 2 respectively:

  • componentsSeparatedByString(:) has been renamed to components(separatedBy:).
  • split(:) has been renamed to split(separator:).
ABakerSmith
  • 22,759
  • 9
  • 68
  • 78
  • Thanks. That was helpful. – Mallioch Jun 10 '15 at 14:40
  • 1
    It would seem that option #2 is possibly the intended replacement for the removal of `Sliceable`. – Andrew Jul 30 '15 at 02:35
  • 1
    Option #1 needs `import Foundation`, no? – dawg Dec 14 '15 at 02:16
  • 2
    It's worth noting that option 1 and option 2 are not the same. For example, if the string/character you are separating by appears at the beginning of the string, option 1 will return an array with an additional empty string in index 0, where option 2 will not. – Zig Mar 09 '16 at 23:10
  • The split option generates a memory leak (in xCode8 at least). Once I replaced my split line for the componentsSerparateByString the memory leak was gone. – Loebre Sep 16 '16 at 08:41
  • 1
    About your 2nd solution: You are getting a collection of *characters* and then you split them by where ever you find `" "`. I am not sure I understand the rest. So then you try to use a *String* constructor to convert to a String/human readable value? What's with the `init`? shouldn't it instead be something like `String($0)`? – mfaani Oct 03 '16 at 22:25
18

Swift 4

let str = "Hello Bob"
let strSplitArray = str.split(separator: " ")
strSplitArray.first!    // "Hello"
strSplitArray.last!     // "Bob"

Xcode 7.1.1 with Swift 2.1

let str = "Hello Bob"
let strSplit = str.characters.split(" ")
String(strSplit.first!)
String(strSplit.last!)
Community
  • 1
  • 1
Warif Akhand Rishi
  • 23,920
  • 8
  • 80
  • 107
9

In Swift 3 componentsSeparatedByString and split is used this way.

let splitArray = "Hello World".components(separatedBy: " ") // ["Hello", "World"]

split

let splitArray = "Hello World".characters.split(separator: " ").map(String.init) // ["Hello", "World"]
Nirav D
  • 71,513
  • 12
  • 161
  • 183