How to Make a Narrated Book Using AVSpeechSynthesizer in iOS 7
Learn how to make Siri read you a bedtime story to you by using one of iOS 7’s newest features: AVSpeechSynthesizer. By .
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How to Make a Narrated Book Using AVSpeechSynthesizer in iOS 7
30 mins
With the introduction of Siri, Apple has taunted developers with the implication of dynamic spoken text, but with the release of iOS 7, Apple has finally opened the door.
Introducing, AVSpeechSynthesizer. Or Siri-Synthesizer for short :]
In this tutorial, you’ll create a narrated book. Each page of the book will display text while simultaneously speaking the text. Audio narration is a splendid way to make your book app stand out from all the others on iTunes, while also accommodating those with visual impairments. Offering an audio book app can also make your work more appealing to a broader audience, since they allow people to “read” while they exercise, cook or get a little work done.
As you create your narrated book, you’ll learn:
- How to make an iOS device speak text using
AVSpeechSynthesizer
andAVSpeechUtterance
. - How to make this synthesized speech sound more natural by modifying
AVSpeechUtterance
properties likepitch
andrate
.
AVSpeechSynthesizer
may not win any awards for voice acting, but you can use it relatively easily to enhance functionality in apps you develop in the future.
Note: If you are interested in developing children’s books on the iPad using Sprite Kit, check out Tammy Coron’s excellent tutorial over here: How to Create an Interactive Children’s Book for the iPad
Note: If you are interested in developing children’s books on the iPad using Sprite Kit, check out Tammy Coron’s excellent tutorial over here: How to Create an Interactive Children’s Book for the iPad
Getting Started with AVSpeechSynthesizer
Start by downloading the Starter Project. Open the project in Xcode by navigating into the NarratedBookUsingAVSpeech Starter directory and double-clicking on the NarratedBookUsingAVSpeech.xcodeproj project file. You should see something similar to the image below:
Build and run the project. You will see the following in the simulator:
Your first book is a nursery rhyme about squirrels. It’s not exactly Amazon Top Selling material, but it will do for the purposes of this tutorial. Use your mouse to swipe from right-to-left in the simulator, and you’ll move to the next page as below.
Use your mouse to swipe from left-to-right in the simulator, and you’ll return to the first page. Wow, you already have a functioning book. Nice work!
Understanding the Plumbing
Note: At the end of this tutorial, there are a few challenges for you. This next section covers the sample project so you can take those challenges, but if you are not interested, feel free to skip to the next section.
Note: At the end of this tutorial, there are a few challenges for you. This next section covers the sample project so you can take those challenges, but if you are not interested, feel free to skip to the next section.
The starter project has two important classes:
1. Models: These store your book as a single Book
object and its collection of Page
objects.
2. Presentation: These present your models on the screen and respond to user interaction (e.g. swipes).
If you choose to build on this project to make your own books, its important you understand how these work. Open RWTBook.h and examine its structure.
@interface RWTBook : NSObject
//1
@property (nonatomic, copy, readonly) NSArray *pages;
//2
+ (instancetype)bookWithPages:(NSArray*)pages;
//3
+ (instancetype)testBook;
@end
- The
pages
property stores an array ofPage
objects, each representing a single page in the book. -
bookWithPages:
is a convenience method to initialize and return a book with the given array ofPage
objects. -
testBook
creates your book for testing purposes. You’ll start writing and reading your own books soon enough, buttestBook
is a simple book that is perfect to get you started.
Open RWTPage.h and examine its structure.
//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
- Accesses the constants for dictionary look-ups for each page. The
RWTPageAttributesKeyUtterances
constant corresponds to the text on each page of the book. TheRWTPageAttributesKeyBackgroundImage
constant returns each background image for the page - The
displayText
property stores the text of the page that your book presents on-screen, and thebackgroundImage
stores the image behind the text. -
pageWithAttributes:
initializes and returns a page with the given dictionary of attributes.
Finally, open RWTPageViewController.m
and examine its structure:
#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
Here’s what this code does:
- The
book
property stores the current book and, thecurrentPageIndex
property stores the index of the current page inbook.pages
. - Sets up the page display once your view loads, then adds gesture recognizers so you can swipe forwards and backwards through the book’s pages.
- Returns the current page within the current book.
- Sets the book property and makes sure you start at the first page.
- Set up the UI for the current page.
- Go to the next page, if applicable, and set it up. It’s invoked by the
swipeNext
gesture recognizer you created inviewDidLoad
. - Go to the previous page, if there is one, and set it up. This is invoked by the
swipePrevious
gesture recognizer you created inviewDidLoad
.