Listing 26.5 Activating the speech synthesizer


#1

Here’s my code snippet below, pretty straightforward and out of the book (with the exception of a comment and a bit of humor)

Build fails on the “if let contents = textView.string {” line with the message:
Initializer for conditional binding must have Optional type, not ‘String’

Using Xcode 9.0 compiling for Swift 4.0. Tried compiling for swift 3.2 but that resulted in even more errors in the Document.swift file.

Any guidance would be greatly appreciated
Dave


import Cocoa

class ViewController: NSViewController {

let speechSynthesizer = NSSpeechSynthesizer()

@IBOutlet var textView: NSTextView!

@IBAction func speakButtonClicked(_ sender: NSButton) {
    //print("I should speak \(textView.string)")
    if let contents = textView.string {
        speechSynthesizer.startSpeaking(contents)
    } else {
        speechSynthesizer.startSpeaking("The document is empty, you muppet.")
    }

}

@IBAction func stopButtonClicked(_ sender: NSButton) {
    print("The stop button was clicked")
}

}


#2

The documentation for textView.string says this:

var string: String { get set }

That is, the string property always has a value. (An empty string means no value.)

Therefore, the value in string property can’t accessed with a conditional binding (because string is not optional.)

Try this:

let contents = textView.string

if !contents.isEmpty {
    speechSynthesizer.startSpeaking (contents)
} else {
     speechSynthesizer.startSpeaking ("The document is empty, you muppet.")
}

#3

Excellent, thanks so much.

Does make me wonder though why the authors wrote the code to use a conditional binding. Perhaps something changed since the book went to print?


#4

Swift and associated frameworks will be in a state of flux until some degree of maturity is reached. The books can’t catch up with the pace of change. So it is always a good idea to check the documentation.


#5

Just use NStextView’s methods to let the system speak its content if you aren’t yet going to do the challenges:

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var textView: NSTextView!

    var contents: String {
        get {
        
            return textView.string
        }
        set {
            textView.string = newValue
        }
    }

    @IBAction func speakButtonClicked(_ sender: NSButton) {
        textView.startSpeaking(sender)
    }
    @IBAction func stopButtonClicked(_ sender: NSButton) {
    textView.stopSpeaking(sender)
    }
}