How to search for a Character in a String with Swift 2

Working with Strings in Swift 2 has changed significantly. There are several big upcoming changes to how you work with String. 

1. String is no longer a collection type, instead the characters contained with it are accessed via a new property named characters (as mentioned on Apple’s blog).

2. Apple introduced Protocol Extensions in Swift 2 that will significantly change many APIs and functions. There’s a ton of movement from global functions (hard to find!) to methods (easier to find).

Swift 1.2 String Character Search

Searching for a Character in Swift 1.2 uses the global function contains() or find(), you won’t find them in Auto Complete – this greatly reduced the discovery of basic actions in Swift 1.2.

Using the lowercaseString property allows you to make the search case-insensitive.

// Swift 1.2
var word = "Apple"
var searchCharacter: Character = "p"

if contains(word.lowercaseString, searchCharacter) {
    print("word contains \(searchCharacter)")
}

if let index = find(word.lowercaseString, searchCharacter) {
    print("Index: \(index)")
}

To make character search work for both upper and lower case, you can use the lowercaseString property on the String.

Swift 2 String Search

In Swift 2 global many functions are gone and replaced with new instance methods. Some of these transformations were one-to-one and others were renamed. Some error messages can suggest how to change your code, otherwise you may have to dig.

The contains() function has been replaced by the contains() method that can be invoked on the characters property of the new Swift 2 String.

The find() function has been replaced with a new method called indexOf() that works on your characters property.

// Swift 2
var word = "Apple"
var searchCharacter: Character = "p"

if word.lowercaseString.characters.contains(searchCharacter) {
    print("word contains \(searchCharacter)")
}

if let index = word.lowercaseString.characters.indexOf(searchCharacter) {
    print("Index: \(index)")
}

Questions: the evolution of Swift

Working with Strings and Characters is fundamental for any programming language – when it’s hard to find the methods or the language uses different conventions it can be hard to figure out what code to write next.

What other functions, methods, or code tasks have you struggled with in Swift?

Reply below or on Twitter: @PaulSolt

 

Xcode 7 moves Playgrounds Console Output and breaks print() and println()

Xcode 7 Playgrounds behave differently than Xcode 6 Playgrounds – the user interface has changed, the Console Output has moved, and print() is different.

Playgrounds have the ability to show in-line code output, but don't be confused as it's not formatted the same way for println() and print() statements. Playgrounds "Quick Looks" provide a formatted view of your data, but if you want to see what it looks like, you need the Console Output. This moved back down to the Debug Area in Xcode 7 (from the Assistant Editor in Xcode 6).

Breaking println() and print behavior in Swift 2

Xcode 7 makes breaking changes to the behavior of the println() and print() methods. In Swift 2 you will be using print() to display text into the Console (Debug Area).

print() will append a newline to your text, which breaks the previous behavior where it didn't append newlines. If you want to prevent newlines you need to use the new optional parameter and pass in false.

// Swift 1.2
// Prints all on same line
for var i = 0; i < 10; i++ {
    print(i) // no newlines
//    println(i) // appends newline
}

// Swift 2
// Prints on separate lines, must use optional parameter for no newlines
for var i = 0; i < 10; i++ {
    print(i)  // appends newline
//    print(i, appendNewline: false)
}

Xcode 6 Playground Console Output

In order to see your Console Output from a print() statement in Xcode 6 you had to open the Assistant Editor (Venn Diagram icon) with the keyboard shortcut "Alt/Option + Command + Enter"

If you were lucky you would see output (assuming no code errors) and then if you accidentally closed the Console Output you would have to type something in the editor for the Playground and press Enter to get it to recompile and redisplay the Console Output.

Xcode 6 Playgrounds:&nbsp;Press Alt/Option + Command + Enter to see the Console Output

Xcode 6 Playgrounds: Press Alt/Option + Command + Enter to see the Console Output

Xcode 7 Playground Console Output

Xcode 7 changes how the Console Output works and makes this process less error prone and more streamlined. The Console Output is no longer displayed on the Assistant Editor, instead its below the standard editor in the normal Debug Area.

Press "Shift + Command + Y" to hide/show the Debug Area with the new Console Output, or you can press the tiny arrow button in the bottom left corner of your Playground in Xcode 7.

Xcode 7 Playgrounds: press Shift + Command + Y to see Console Output

Xcode 7 Playgrounds: press Shift + Command + Y to see Console Output

The good news is that the changes to Xcode 7 make the Playgrounds a more friendly code environment. It's easier to get to the Console Output without the clunky behavior of the Assistant Editor, which makes Playgrounds feel more like first class citizens.

Free Online Swift App Course

Subscribe to the iPhone Newsletter and learn how to make your first iPhone app in Swift with my free online iPhone app course.

OptionSetType Swift 2 Error: Nil is not compatible with expected argument

If you've been using Swift 1.2 or earlier, or you're an experienced Objective-C developer you'll discover using some APIs is different. 

Apple has been revamping all the APIs in Swift + Objective-C to support the latest Swift 2 language.

Apple has added Generics, Error Handling, and the OptionSetType which will change a large portion of the APIs – especially anything that takes option/setting flags.

Code Massaging

Moving forward you're going to have to massage your existing code, or your old programming habits to work with the new APIs.

I highly recommend opening a Documentation window (Shift + Command + 0) with Swift, since the Quick Help fails to work when you have a syntax error – something that didn't happened in Objective-C.

OptionSetType

The animatWithDuration: API that works with the spring physics has changed it's options: parameter to the new OptionSetType.

var myFirstLabel: UILabel!

func tapped(gesture: UITapGestureRecognizer) {
    UIView.animateWithDuration(0.5, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: nil, animations: {
        
        self.myFirstLabel.center = CGPoint(x: 100, y:40 + 200)
        
        }, completion: nil)
}

In Xcode 6 this code works with Swift 1.2 or lower, however if you run it in Xcode 7 + Swift 2 you'll get the following Error.

Swift 2 Errors

You might see either of these errors, depending on the version of Xcode. Error messages are continuing to evolve, some are even more helpful in diagnosing the problem.

ViewController.swift Nil is not compatible with expected argument type 'UIViewAnimationOptions'

ViewController.swift Cannot invoke 'animateWithDuration' with an argument list of type '(Double, delay: Double, usingSpringWithDamping: Double, initialSpringVelocity: Double, options: nil, animations: () -> _, completion: nil)'

Solution

The error is because the type for the options: parameter is wrong – you'll have to pass in an empty OptionSetType in order to compile.

nil should be replaced with []

Apple has changed options for many existing APIs, instead of being a NS_OPTIONS bitmask, in Swift 2.1+ they are treated as a Set in syntax and behavior. To pass no options (i.e. nil) you pass the empty set: [ ]

UIView.animateWithDuration(0.5, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: [], animations: {
    
    self.myFirstLabel.center = CGPoint(x: 100, y:40 + 200)
    
    }, completion: nil)

Follow me

Have you seen any strange error messages?

Send a Tweet to @PaulSolt