Original: Http://www.raywenderlich.com/64623/make-narrated-book-using-avspeechsynthesizer-ios-7
With the introduction of Pageviewcontroller, Apple makes it easier for developers to make book apps. Unfortunately, reading is also a luxury for people living in the five-hour rhythm of the nine-night rush. Why can't you do other things while reading a novel?
At the start of Siri, Apple used complex dynamic text reading to keep developers out of the door, but when IOS7 was released, Apple finally let it go.
In this tutorial, you will make a story book. Each page of the book reads the text as it is displayed. Sound reading will make your app look different in iTunes and protect your eyesight. Audio books are especially popular with radio listeners because they allow people to "read" while exercising, cooking, or working.
When you make your own audio book, you will learn to:
- How to use Avspeechsynthesizer and avspeechutterance to get your IOS device to read text
- How to make this synthesized speech sound more natural by modifying avspeechutterance properties like pitch and.
- How to modify avspeechutterance properties such as pitch and rate to make synthesized speech more natural
Avspeechsynthesizer is certainly less than real-life voice, but it's relatively easy for the app you're going to develop.
Note: For developing ipad children's books with Sprite Kit, refer to Tammy Coron Tutorial: How to Create a Interactive children ' s book for the ipad
Start: Avspeechsynthesizer
First, please download the initial project . Enter the narratedbookusingavspeechstarter directory and double-click narratedbookusingavspeech.xcodeproj to open the initial project.
Build & Run. You will see in the simulator:
The content of the book is about the squirrel's nursery rhymes. It's not the hottest book Amazon buys, but it's enough for this tutorial. Swipe left to page back and swipe right to return to the previous page. Oh, it already has the basic "book" function, it's a good start.
Understanding mechanism
Note: at the end of the tutorial, you will be left with several exercises. The next section will include some of the sample projects so that you can complete these exercises independently. If you are not interested in this section, skip to the next section.
The initial project consists of two classes:
1. Models: The content used to store a book, which is a collection of page.
2. Presentation: Display the models to the screen and respond to user actions (such as swipe gestures).
It is necessary to understand the working mechanism of these two classes when you are making your own books. Open RWTBook.h:
@interface Rwtbook : nsobject //1 @property (nonatomic, copy, ReadOnly) Nsarray *pages; //2 + (instancetype)bookwithpages:(nsarray*)pages; //3 + (instancetype)Testbook; @end |
- The Pages property holds an array of page objects, each of which represents each page in the book.
- Bookwithpages: Method is a method that initializes the book, which returns a book object with the specified array of page objects as parameters.
- Testbook creates a book object for testing. Use Testbook to create a simple book before you start adding and reading your own content.
RWTPage.h declares as follows:
//1 extern NSString * Const Rwtpageattributeskeyutterances; extern NSString * Const Rwtpageattributeskeybackgroundimage; @interface Rwtpage : nsobject //2 @property (nonatomic, Strong, ReadOnly) NSString *DisplayText; @property (nonatomic, Strong, ReadOnly) UIImage *backgroundimage; //3 + (instancetype)pagewithattributes:(nsdictionary*)attributes; @end |
- Constants are used to retrieve pages from a dictionary. The Rwtpageattributeskeyutterances constant retrieves the text from the Page object, and Rwtpageattributeskeybackgroundimage is used to retrieve the background picture used by the Page object.
- The DisplayText property is used to store page text, and the BackgroundImage property is used to store the page's background picture.
- Pagewithattributes: Creates a page instance with the specified nsdictionary.
RWTPAGEVIEWCONTROLLER.M declares as follows:
#pragma mark-class Extension //1 @interface Rwtpageviewcontroller () @property (nonatomic, strong) Rwtbook *book; @property (nonatomic, assign) Nsuinteger CurrentPageIndex; @end @implementation Rwtpageviewcontroller #pragma mark-lifecycle //2 - (void)viewdidload { [Super Viewdidload]; [Self setupbook: [rwtbook Testbook]; Uiswipegesturerecognizer*Swipenext= [[Uiswipegesturerecognizer Alloc]Initwithtarget:Self action:@selector(Gotonextpage)]; Swipenext.direction = uiswipegesturerecognizerdirectionleft; [self.view addgesturerecognizer:swipenext]; Uiswipegesturerecognizer*Swipeprevious= [[Uiswipegesturerecognizer Alloc]Initwithtarget:Self action:@selector(Gotopreviouspage)]; Swipeprevious.direction = uiswipegesturerecognizerdirectionright; [self.view addgesturerecognizer:swipeprevious]; } #pragma mark-private //3 - (rwtpage*)currentpage { return [self.book.pages objectatindex:self.currentpageindex]; } //4 - (void)setupbook:(rwtbook*)newbook { Self.book = Newbook; Self.currentpageindex = 0; [self setupforcurrentpage]; } //5 - (void)setupforcurrentpage { Self.pageTextLabel.text = [self currentpage]. DisplayText; Self.pageImageView.image = [self currentpage]. backgroundimage; } //6 - (void)gotonextpage { if ([self.book.pages count] = = 0 | | Self.currentpageindex = = [self.book.pages count] - 1) { return; } Self.currentpageindex + = 1; [self setupforcurrentpage]; } //7 - (void)gotopreviouspage { if (self.currentpageindex = = 0) { return; } Self.currentpageindex- = 1; [self setupforcurrentpage]; } @end |
The above code illustrates the following:
- The book property holds the current Rwtbook object, and the CurrentPageIndex property holds the current page index of the Rwtbook object.
- When the view is loaded, set the page to be displayed and add a swipe gesture recognizer so that the user can flip through the gesture.
- Returns the Rwtpage object for the current page.
- Set the book property and place the current page as the first page.
- Sets the display content of the current page.
- Finds the next page, and if the page exists, sets the next page as the current page. This method is called by the swipenext gesture recognizer.
- Finds the previous page, and if the page exists, sets the previous page as the current page. This method is called by the swipeprevious gesture recognizer.
Play and Stop!
This is a very deadly problem.
Open rwtpageviewcontroller.m, and under #import "RWTPage.h", add:
The IOS voice feature is provided by the Avfoundation framework and you must import this framework.
tip: @import will import and connect the Avfoundation framework. For the new features of the @import and related o-c languages in iOS7, refer to this article what's ' snew in Objective-c and Foundation in IOS 7.
Under the CurrentPageIndex attribute declaration, add:
@property (nonatomic, strong) Avspeechsynthesizer *synthesizer; |
The Synthesizer object will be used to read the text in each page.
You can think of the Avspeechsynthesizer object defined in Viewcontroller as a person who can speak. And avspeechutterance can imagine a small note, pass the note to this person, then he will read out the words on the note.
Note: a avspeechutterance may be a word, such as "Whisky", or a complete statement, such as "Whisky,frisky,hippidityhop".
At the end of the RWTPAGEVIEWCONTROLLER.M, add the following methods:
#pragma mark-speech Management - (void)speaknextutterance { Avspeechutterance *nextutterance = [[avspeechutterance alloc] Initwithstring: [self currentpage]. DisplayText]; [self.synthesizer speakutterance:nextutterance]; } |
Create a utterance object and tell synthesizer to read it out.
Then implement this method:
- ( void ) startspeaking { if (! Self.synthesizer) { self.synthesizer = [[ Avspeechsynthesizer alloc init; [ self speaknextutterance ; |
This method is responsible for initializing the synthesizer property (if it is not initialized). Then call the Speaknextutterance method and start reading aloud.
Add this line at the end of the Viewdidload, Gotonextpage, and Gotopreviouspage methods:
In this way, when the book opens, or the user pages back and forth, the reading will begin.
Build & Run, you will hear the sounds of avspeechsynthesizer.
Note : If you don't hear anything, check the volume settings for your MAC or IOS device (see where you're running the app). You can try flipping the page to see if you can play the voice.
tip: If you are running a program on a simulator, the console may output a bunch of inexplicable error messages. This will only appear on the emulator and will not print when the device is used.
If you hear voice playback, please Build & Run again. This time, try swiping left (page back) before the first page finishes playing. What did you find out?
Synthesizer will only start reading the next page after the first page is finished. This is not what the user wants, they want the first page to stop playing and the second page starts immediately. This little flaw is not a problem for a short nursery rhyme, but imagine what the effect would be if the contents of each page were very long ...