NCMBのSwift SDKを使ってデモアプリを作ってみます。今回はDeepL APIを使った翻訳アプリです。翻訳結果をNCMBのデータストアに保存し、後で確認できるようにします。データストアにデータを保存したり、逆に取り出すのはよくあるケースなので、様々な場面で応用できるはずです。
前回は画面の説明とSDKの導入までを解説しましたので、今回は翻訳処理とデータ保存について解説します。
コードについて
今回のコードはNCMBMania/Swift_DeepL_App: Swift NCMB SDKとDeepL APIを組み合わせた翻訳アプリのデモですにアップロードしてあります。実装時の参考にしてください。
翻訳処理について
翻訳処理はDeepL APIを用いて行います。まず、DeepL APIのレスポンスに合わせた構造体を定義します。
// DeepL APIのレスポンス用構造体
struct DeepLResult: Codable {
let translations: [Translation]
struct Translation: Codable {
var detected_source_language: String
var text: String
}
}
Alamofireの追加
ネットワークアクセスはAlamofireを利用します。Swift Package Mangerにて https://github.com/Alamofire/Alamofire.git
を指定してインストールします。
インストールしたら、インポートします。
import Alamofire
翻訳画面について
前の記事でも紹介しました、翻訳画面 TranslateView
は次のようになっています。
// 翻訳用ビュー
struct TranslateView: View {
// 日本語のテキスト
@State private var originalText = ""
// 翻訳結果のテキスト
@State private var translatedText = ""
// 保存完了した際のアラート制御用
@State private var uploaded = false
// JSONデコード用
let decoder: JSONDecoder = JSONDecoder()
// 翻訳実行
func translation() {
}
// 翻訳結果をNCMBに保存する処理
func saveResult() {
}
// 画面表示
var body: some View {
NavigationView{
VStack(spacing:0){
ZStack{
VStack(spacing:20){
// 日本語入力欄
TextEditor(text: $originalText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(maxWidth: 280, maxHeight: 100)
// 翻訳結果があれば表示
if translatedText != "" {
Text(translatedText).padding()
}
// 翻訳実行するボタン
Button(action: {
translation()
}, label: {
Text("翻訳する")
})
}
}
}
.navigationBarTitle("翻訳", displayMode: .inline)
// 保存完了時のアラート用
.alert(isPresented: $uploaded, content: {
Alert(
title: Text("保存完了"),
message: Text("翻訳結果を記録しました"),
dismissButton: .default(Text("閉じる"))
)
})
}
}
}
翻訳処理の実装
翻訳処理は translation
関数に実装します。DeepL用のライブラリはないので、Alamofireで直接実行しています。結果が返ってきたら、正常終了しているか判定した上でJSONデータを解析しています。その処理がうまくいったら画面に翻訳結果を反映(translatedTextに文字列を適用)し、 saveResult
関数を実行しています。
// 翻訳実行
func translation() {
// APIKey.plistに保存したDeepLの認証キーを取得
let authKey = KeyManager().getValue(key: "DeepLAuthKey") as! String
// APIリクエストするパラメータを作成
let parameters: [String: String] = [
"text": originalText,
"target_lang": "EN-US",
"auth_key": authKey
]
// ヘッダーを作成
let headers: HTTPHeaders = [
"Content-Type": "application/x-www-form-urlencoded"
]
// DeepL APIを実行
AF.request("https://api-free.deepl.com/v2/translate", method: .post, parameters: parameters, encoder: URLEncodedFormParameterEncoder.default, headers: headers).responseDecodable(of: DeepLResult.self) { response in
// リクエスト成功か判定
if case .success = response.result {
do {
// 結果をデコード
let result = try decoder.decode(DeepLResult.self, from: response.data!)
// 結果のテキストを取得&画面に反映
translatedText = result.translations[0].text
// 結果をNCMBに保存する処理を呼び出し
saveResult()
} catch {
debugPrint("デコード失敗")
}
} else {
debugPrint("APIリクエストエラー")
}
}
}
データをNCMBに保存
NCMBのSwift SDKをインポートします。
import NCMB
翻訳前の日本語と、翻訳結果をNCMBのデータストアに保存します。データストアのクラス名(DBで言うところのテーブル名相当)はTranslateとしています。
保存がうまくいったら、 updated
フラグを有効にし、アラートダイアログを表示します。
// 翻訳結果をNCMBに保存する処理
func saveResult() {
let translate = NCMBObject(className: "Translate")
translate["original"] = originalText
translate["translate"] = translatedText
translate.saveInBackground(callback: { result in
// 処理が成功しているか判定
if case let .success(_) = result {
uploaded = true
}
})
}
ここまででデータの保存が完了です。実際にデータストアを見ると、Translateクラスができあがり、データが追加されています。
まとめ
NCMBを使うとクラウドデータベースへの保存がわずか数行で書けます。今回は使っていませんが、ACL(アクセス権限)も指定できます。ぜひ試してください。