這是一篇關於iOS 7 的 AVSpeechSynthesizer 制作有聲書的文章,看看小編為大家整理的吧。
開始:AVSpeechSynthesizer
首先,請下載 初始項目。進入NarratedBookUsingAVSpeechStarter 目錄,雙擊 NarratedBookUsingAVSpeech.xcodeproj 以打開初始項目。
Build & run 。你將在模擬器中看到:
書的內容是關於松鼠的童謠。雖然不是亞馬遜買得最火的讀物,但對於本教程來說足夠了。向左滑動進行向後翻頁,向右滑動則返回前一頁。噢,它已經擁有了基本的“書”的功能,真是不錯的開始。
理解機制
注意:教程的最後,會留給你幾個習題。接下來一節將包括示例項目的一些內容,以便你能獨立完成這些習題。如果你對這部分內容不感興趣,請跳到下一節。
初始項目包括兩個類:
1. Models: 用於存放書籍的內容,它是page 的集合。
2. Presentation: 將 models 展現到屏幕並響應用戶動作(例如滑動手勢)。
在你制作自己的圖書時,理解這兩個類的工作機制是很有必要的。打開RWTBook.h:
@interface RWTBook : NSObject
//1
@property (nonatomic, copy, readonly) NSArray *pages;
//2
+ (instancetype)bookWithPages:(NSArray*)pages;
//3
+ (instancetype)testBook;
@end
pages 屬性存放了 Page 對象的數組,每個 Page對象代表圖書中的每一頁。
bookWithPages: 方法是一個初始化 Book 的方法,它用指定的 page 對象數組為參數,返回一個 book 對象。
testBook 創建 Book 對象,用於測試。在開始加入和讀取你自己的圖書內容之前,就先使用 testBook 創建一個簡單的 Book 吧。
RWTPage.h聲明如下:
//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
常量用於從字典中檢索頁。RWTPageAttributesKeyUtterances常量可以檢索出page 對象中的文本,RWTPageAttributesKeyBackgroundImage則用於檢索 page 對象所用的背景圖片。
displayText 屬性用於存儲 page 的文本,backgroundImage 屬性用於存儲 page 的背景圖片。
pageWithAttributes:用指定的 NSDictionary 創建一個 page 實例。
RWTPageViewController.m聲明如下:
#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
以上代碼說明如下:
book 屬性保存了當前的 RWTBook 對象,currentPageIndex屬性保存了 RWTBook 對象的當前頁索引。
當視圖加載完畢,設置要顯示的 page,並添加滑動手勢的識別器以便用戶能通過手勢進行翻頁。
返回當前頁的 RWTPage 對象。
設置 book 屬性並將當前頁置為第一頁。
設置當前頁的顯示內容。
查找下一頁,如果該頁存在,則將下一頁設置為當前頁。該方法由 swipeNext 手勢識別器調用。
查找上一頁,如果該頁存在,則將上一頁設置為當前頁。該方法由 swipePrevious 手勢識別器調用。
播放和停止!
這是一個很要命的問題。
打開RWTPageViewController.m,在#import "RWTPage.h" 下面加入:
@import AVFoundation;
iOS 語音功能由 AVFoundation 框架提供,你必須導入這個框架。
提示: @import會導入並連接 AVFoundation 框架。關於 iOS7 中 @import 及相關的 O-C 語言新特性,請參考這篇文章What’sNew in Objective-C and Foundation in iOS 7。
在 currentPageIndex 屬性聲明之下加入:
@property (nonatomic, strong) AVSpeechSynthesizer *synthesizer;
synthesizer 對象將用於朗讀每一頁中的文字。
可以將 ViewController 中定義的AVSpeechSynthesizer 對象想象成一個會說話的人。而 AVSpeechUtterance 則可以想象成一張小紙條,把紙條遞給這個人,則他就會念出紙條上的字。
注意:一個 AVSpeechUtterance 可能是一個單詞,比如“Whisky”,或者是一個完整的語句,比如“Whisky,frisky,hippidityhop”。
在 RWTPageViewController.m 的最後加入以下方法:
#pragma mark - Speech Management
- (void)speakNextUtterance {
AVSpeechUtterance *nextUtterance = [[AVSpeechUtterance alloc] initWithString:[self currentPage].displayText];
[self.synthesizer speakUtterance:nextUtterance];
}
創建了一個 utterance 對象,然後告訴 synthesizer 去念出它。
然後實現這個方法:
- (void)startSpeaking {
if (!self.synthesizer) {
self.synthesizer = [[AVSpeechSynthesizer alloc] init];
}
[self speakNextUtterance];
}
這個方法負責初始化 synthesizer 屬性(如果它未初始化的話)。然後調用speakNextUtterance 方法,開始朗讀。
在 viewDidLoad 、gotoNextPage 和 gotoPreviousPage 方法的最後加上這行:
[self startSpeaking];
這樣,當書一打開,或者用戶前後翻頁的時候,朗讀就會開始。