Twilio Voice Swift Quickstart for iOS(日本語訳)

[原本](https://github.com/twilio/voice-quickstart-swift)

# Twilio Voice Swift Quickstart for iOS

## iOSでVoiceを始めよう:
* [Quickstart](#quickstart) - クイックスタートアプリを実行する
* [Access Tokens](#-access-tokens) - アクセストークンを使用
* [Managing Audio Interruptions](#managing-audio-interruptions) - 音声の中断の管理
* [Managing Push Credentials](#managing-push-credentials) - プッシュ認証情報の管理
* [More Documentation](#more-documentation) - Voice iOS SDKに関連するその他のドキュメント
* [Issues and Support](#issues-and-support) - ファイリングの問題と一般的なサポート

## Quickstart
クイックスタートアプリケーションを使い始めるには、次の手順に従います。 
手順1〜6により、アプリケーションは電話をかけることができます。 
残りの手順7〜10では、アプリケーションはAppleのVoIPサービスを使用してプッシュ通知の形式で着信通話を受信できるようになります。

1. [TwilioVoice frameworkをインストールする](#1-twiliovoice-frameworkをインストールする)
2. [Voice API keyを作成する](#2-voice-api-keyを作成する)
3. [アプリで使用するアクセストークンを生成するようにサーバーを構成する](#3-アプリで使用するアクセストークンを生成するようにサーバーを構成する)
4. [TwiML applicationを作成する](#4-twiml-applicationを作成する)
5. [アプリケーションサーバーを設定する](#5-アプリケーションサーバーを設定する)
6. [アプリを実行する](#6-アプリを実行する)
7. [VoIP Service Certificateを作成する](#7-voip-service-certificateを作成する)
8. [VoIP Service Certificateを使ってPush Credentialを作成する](#8-voip-service-certificateを使ってpush-credentialを作成する)
9. [XcodeのプロジェクトにVoIPpush通知の設定をする](#9-xcodeプロジェクト設定にプッシュ通知の設定をする)
10. [着信を受ける](#10-電話を受ける)
11. [clientからclientに電話をかける](#11-client-から-client-に発信する)
12. [clientからPSTNに電話をかける](#12-client-から-pstn-に発信する)

### 1. TwilioVoice frameworkをインストールする

**Carthage**

Cartfileに次の行を追加します。

```
github "twilio/twilio-voice-ios"
```

`carthage bootstrap`を実行します (SDKをアップデートしている場合は `carthage update` を実行します)

対象のapplication targetの `Build Phases` タブにて,  `+` アイコンをクリックして、 `New Run Script Phase`を選びます。 Run Scriptにshell(ex: `/bin/sh`)を指定し , 以下の内容のscriptを追加します:

```
/usr/local/bin/carthage copy-frameworks
```

“Input Files”の下に、使用したいframeworkのパスを追加します:

```
$(SRCROOT)/Carthage/Build/iOS/TwilioVoice.framework
```

**Cocoapods**

quickstartのフォルダ内で`pod install`を実行すると、Cocoapodsがworkspaceを作成します。 
また、必ず **Cocoapods v1.0 以降を使用してください**。
Cocoapodsのインストールが完了し,`SwiftVoiceQuickstart.xcworkspace`を開くとSwiftを用いた基本的なquickstartプロジェクトとCallKit quickstartプロジェクトが見つかります。

Note: TwilioVoice の最新版を取得するには、`pod repo update master`を実行し [CocoaPods Master Spec Repo](https://github.com/CocoaPods/Specs) から最新版を取得する必要があるかもしれません。

### <a name="bullet2"></a>2. Voice API keyを作成する
[Voice API Keys](https://jp.twilio.com/console/voice/settings/api-keys) ページに移動して新しいAPI keyを作成してください:

<kbd><img src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/create-api-key.png"/></kbd>

**作成した`API_KEY` と `API_KEY_SECRET` をメモをとってください**。 次のステップで必要となります。

### <a name="bullet3"></a>3. アプリで使用するアクセストークンを生成するようにサーバーを構成する

サーバー用のスタータープロジェクトの1つをダウンロードします。

* [voice-quickstart-server-java](https://github.com/twilio/voice-quickstart-server-java)
* [voice-quickstart-server-node](https://github.com/twilio/voice-quickstart-server-node)
* [voice-quickstart-server-php](https://github.com/twilio/voice-quickstart-server-php)
* [voice-quickstart-server-python](https://github.com/twilio/voice-quickstart-server-python)

サーバーのREADMEに記載されている手順に従って、アプリケーションサーバーをローカルで起動し、パブリックインターネット経由でアクセスできるようにします。[console](https://jp.twilio.com/console)から取得できる **Twilio Account SID** と先ほどメモをとった `API_KEY` と `API_SECRET` を置き換えてください。
    
    ACCOUNT_SID = 'AC***'
    API_KEY = 'SK***'
    API_KEY_SECRET = '***'

### <a name="bullet4"></a>4. TwiML applicationを作成する
次にTwiMLアプリケーションを作成する必要があります。TwiML applicationは [TwiML呼び出し先](https://jp.twilio.com/docs/api/twiml)に設定されているパブリックURLを参照します。 
iOSアプリがTwilioを呼び出すと、TwilioはこのURLにWebhookを用いてリクエストを送信し、アプリケーションサーバーはTwiMLを生成してResponseを返し、返ってきたResponseに沿ってTwilioは応答します。
TwiMLアプリケーションを作成するには [TwiML app page](https://jp.twilio.com/console/voice/dev-tools/twiml-apps)にアクセスしてください。 
新しいTwiML applicationを作成し, アプリケーションサーバーの`/makeCall`エンドポイントをVoice Request URLに設定します。(あなたのアプリケーションサーバーがPHPで書かれている場合、最後に` .php`拡張子が必要です)。

<kbd><img src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/create-twiml-app.png"/></kbd>

ご覧の通りRequest URLには[ngrok](https://ngrok.com/)のパブリックアドレスを使用しています。
TwiML Applicationの設定を保存し, **TwiML Application SID**(`AP`から始まる長い識別子)を取得します。

### <a name="bullet5"></a>5. アプリケーションサーバーを設定する
残りの `APP_SID` 設定情報をサーバーのコードに入れましょう。 

    ACCOUNT_SID = 'AC***'
    API_KEY = 'SK***'
    API_KEY_SECRET = '***'
    APP_SID = 'AP***'

それが終わったら、サーバーを再起動して新しい設定情報を使用します。今度はテストする時が来ました。

ブラウザを開き、アプリケーションサーバーのAccess Tokenを取得するためのURLをご覧ください。
 **Access Token endpoint**: `https://{YOUR_SERVER_URL}/accessToken` (あなたのアプリケーションサーバーが、PHPで書かれている場合は、最後に.php拡張子をつける必要があります)
すべてが正しく設定されていれば、長い文字列と数字が表示されるはずです。これがTwilioアクセストークンです。iOSアプリはTwilioに接続するためにこのようなトークンを使用します。

### <a name="bullet6"></a>6. アプリを実行する
それでは`SwiftVoiceQuickstart.xcworkspace`に戻りましょう。`baseURLString` をngrokのパブリックURLで更新します。

```swift
import UIKit
import AVFoundation
import PushKit
import TwilioVoice

let baseURLString = "https://3b57e324.ngrok.io"
let accessTokenEndpoint = "/accessToken"
let identity = "alice"
let twimlParamTo = "to"

class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationDelegate, TVOCallDelegate, AVAudioPlayerDelegate, UITextFieldDelegate {
```

アプリをビルドして実行します

<kbd><img width="500px" src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/build-and-run.png"/></kbd>

テキストフィールドを空のままにして、callボタンを押して通話を開始します。お祝いメッセージが聞こえます。別のclientまたは番号への発信は、手順11および12で説明されています。切断するには、"Hang Up"をタップします。

<kbd><img width="500px" src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/hang-up.png"/></kbd>

### <a name="bullet7"></a>7. VoIP Service Certificateを作成する
Programmable Voice SDKはAppleのVoIPサービスを使用して、着信呼び出しを受信したことをアプリケーションに通知します。ユーザーに着信を受けさせる場合は、アプリケーションでVoIPサービスを有効にしてVoIP Services Certificateを生成する必要があります。

[Apple Developer portal](https://developer.apple.com/)へアクセスして、以下を行う必要があります:

- 証明書を作成できるようにApple Developer Programの会員になる。
- 対象のApp IDで“Push Notifications”サービスが有効になっていることを確認してください。
- App IDに対応するプロビジョニングプロファイルを作成します。
- Certificates - > Productionに移動し、右上の`+`をクリックして新しい証明書を追加して、このアプリの[Apple VoIP Services Certificate](https://developer.apple.com/library/prerelease/content/documentation/Performance/Conceptual/EnergyGuide-iOS/OptimizeVoIP.html#//apple_ref/doc/uid/TP40015243-CH30-SW1)を作成します。

<kbd><img src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/create-voip-service-certificate.png"/></kbd>

### <a name="bullet8"></a>8. VoIP Service Certificateを使ってPush Credentialを作成する
Keychain Accessを使用してVoIP Service Certificateを生成したら、それをTwilioにアップロードして、Twilioがあなたに代わってアプリにプッシュ通知を送信できるようにする必要があります。

VoIPサービス証明書をKeychain Accessから.p12ファイルとしてエクスポートしてから、opensslコマンドを使用して.p12ファイルから証明書と秘密鍵を抽出します。
.p12が書き出しのオプションではない場合は、Keychain Accessの検索バーに`voip`を入力して、証明書を書き出すときに必ず両方の項目を選択してください。

    $> openssl pkcs12 -in PATH_TO_YOUR_P12 -nocerts -out key.pem
    $> openssl rsa -in key.pem -out key.pem
    $> openssl pkcs12 -in PATH_TO_YOUR_P12 -clcerts -nokeys -out cert.pem

[Push Credentials page](https://jp.twilio.com/console/voice/sdks/credentials)に移動して新しいPush Credentialを作成します。証明書と秘密鍵を貼り付けます。plaintextとしてキーを貼り付ける必要があります:

* `cert.pem`の `-----BEGIN CERTIFICATE-----` から `-----END CERTIFICATE-----`まで貼り付ける必要があります。 
* `key.pem`の `-----BEGIN RSA PRIVATE KEY-----` から `-----END RSA PRIVATE KEY-----`まで貼り付ける必要があります。

**「Sandbox」オプションを必ずチェックしてください**。これは重要。生成したVoIP Service Certificateは、本番環境でもAppleのsandbox infrastructureでも使用できます。このチェックボックスをオンにすると、開発プロビジョニングプロファイルに適したApplesandbox infrastructureにプッシュが送信されます。

アプリのストア送信準備が整ったら、「APS Environment：production」でplistを更新し、同じVoIP Certificateを使用して「Sandbox」オプションをチェックせずに別のPush Credentialを作成します。

<kbd><img src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/add-push-credential.png"/></kbd>

それでは、サーバーのコードに戻り、Push Credential SIDを更新しましょう。Push Credential SIDがアクセストークンに埋め込まれます。

    PUSH_CREDENTIAL_SID = 'CR***'

### <a name="bullet9"></a>9. Xcodeプロジェクト設定にプッシュ通知の設定をする
プロジェクトの Capabilities タブで,“**Push Notifications**”を有効化します。
Xcode 8以前では、バックグラウンドモードで “**Voice over IP**” と “**Audio, AirPlay Picture in Picture**” の両方の機能を有効にします。

<kbd><img src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/xcode-project-capabilities.png"/></kbd>

Xcode 9以降では、“**Audio, AirPlay and Picture in Picture**”機能が有効になっていることと、"**audio**"と"**voip**"を含む"**UIBackgroundModes**"がアプリのplistにあることを確認してください。

```
<key>UIBackgroundModes</key>
<array>
  <string>audio</string>
  <string>voip</string>
</array>
```

### <a name="bullet10"></a>10. 電話を受ける
これで着信を受ける準備が整いました。アプリをRebuildして、アプリケーションサーバーのエンドポイント **/placeCall** にアクセスします。 `https://{YOUR_SERVER_URL}/placeCall` (あなたのアプリケーションサーバーがPHPで書かれている場合、最後に` .php`拡張子が必要です)
これによりTwilio REST APIリクエストがトリガーされ、モバイルアプリへのインバウンドコールが行われます。アプリが通話を受け付けると、お祝いのメッセージが聞こえます。

<kbd><img width="500px" src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/incoming-call.png"/></kbd>

### <a name="bullet11"></a>11. client から client に発信する
clientからclientへの発信を行うには、2つのデバイスでアプリケーションを実行する必要があります。 追加のデバイスでアプリケーションを実行するには、新しいデバイスを登録するときに必ずアクセストークンに別のIDを使用してください。例えば,  `identity` を `bob` に変更してアプリを実行します。

```swift
let accessTokenEndpoint = "/accessToken"
let identity = "bob"
let twimlParamTo = "to"
```

テキストフィールドを使用して通話受信者のIDを指定してから、“Call”ボタンをタップして発信します。 `TwilioVoice.call()`メソッドで使用されるTwiMLパラメーターはサーバーで使用されている名前と一致する必要があります。

<kbd><img width="500px" src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/client-to-client.png"/></kbd>

### <a name="bullet12"></a>12. client から PSTN に発信する
検証済電話番号を一つ用意します。検証済電話番号はTwilioから外線発信できるあなたの電話番号が使えます。この番号はTwilioに移植されていないので、この電話番号のためにTwilioに支払う必要はありません。

clientから発信するためには, まずhttps://jp.twilio.com/console/phone-numbers/verified から検証済電話番号を取得します。 サーバーコードの `CALLER_NUMBER` を検証済電話番号に置き換えます。サーバーを再起動させて、新しい設定値を使用します。TwiML applicationのVoice Request URLはパブリックなアプリケーションサーバーのエンドポイント`/makeCall`を指定する必要があります。

<kbd><img width="500px" src="https://github.com/twilio/voice-quickstart-swift/raw/master/Images/client-to-pstn.png"/></kbd>

## <a name="access-tokens"></a> Access Tokens

access tokenはサーバーコンポーネントの[jwt](https://jwt.io)により作成されます。
作成されたaccess tokenにはProgrammable Voiceの`grant`、あなたが指定した `identity`、有効期限を設定する`time-to-live`が含まれます。`time-to-live`の初期値は1時間でTwilio helper ライブラリを使用して最大24時間まで設定することができます。

### 用途

iOS SDKでは、access tokenは次の目的で使用されます:

1. `TwilioVoice.call(...)`経由で外線発信する 
2. `TwilioVoice.registerWithAccessToken(...)`と`TwilioVoice.unregisterWithAccessToken(...)`経由で着信時のVoIP Push Notificationsの登録、解除。登録されると着信時に`TVOCallInvite`経由で承認するか拒否するか選ぶことができます。着信を受けるときはaccess tokenは必要ありません。`TVOCallInvite`は内部的にaccess tokenを保持しており、それは私たちのインフラストラクチャにアクセスすることができます。

### 有効期限切れ

前述のように、アクセストークンは最終的に期限切れになります。アクセストークンが期限切れになった場合、私たちのインフラストラクチャは登録時に `TVOCallDelegate`を介して` TVOErrorAccessTokenExpired` / `20104`エラーまたはcompletionエラーを返します。

アクセストークンの有効期限を適切に管理するテクニックは数多くあります:

- 発信呼び出しを行う前に、必ずアクセストークンサーバーから新しいアクセストークンを取得してください。
-  `TVOErrorAccessTokenExpired` /` 20104`エラーが発生するまでアクセストークンを保持し、エラーが発生した後に新しいトークンを取得してください。
- アクセストークンを要求されたときのタイムスタンプと一緒に保存しておくと、サーバーで使用されている「有効期限」に基づいて、トークンがすでに期限切れになっているかどうかを事前に確認できます。
- 発信呼び出しに関連付けられた `UIApplication`または` UIViewController`が作成されるたびにアクセストークンをフェッチします。

## Managing Audio Interruptions

iOSのバージョンが異なると **AVAudioSession** 割り込みの処理方法が若干異なります。このセクションでは、Programmable Voice iOS SDKが音声の中断を管理し、中断が終了した後に通話の音声を再開する方法について説明します。 iOSでは、中断が終了したことを示すために必要な通知が提供されないため、SDKが通話音声を自動的に再開できない場合があります。

### Programmable Voice iOS SDKがオーディオの中断をどのように処理するか
- SDKは自身を `TwilioVoice.initialize（）` の中で `AVAudioSessionInterruptionNotification`のオブザーバーとして登録します。
- 通知が発生し、中断の種類が `AVAudioSessionInterruptionTypeBegan` の場合、SDKは自動的にオーディオデバイスを無効にし、アクティブな通話を保留にします。
- SDKが `AVAudioSessionInterruptionTypeEnded`で通知を受け取ると、SDKはオーディオデバイスを再度有効にしてアクティブな通話のオーディオを再開します。
- iOS 8と9では、 `AVAudioSessionInterruptionTypeEnded`による割り込み通知が常に発生するわけではないため、SDKは通話音声を自動的に再開できません。これは既知の問題であり、別の方法は `UIApplicationDidBecomeActiveNotification`を使用して中断後にアプリが再びアクティブになったときに音声を再開することです。


### 異なるiOSバージョンでの通知
以下は、音声の中断を引き起こし、Voice SDKの通話中に再開するためのさまざまな手順で受信したシステム通知の一覧です。 （アプリがアクティブなVoice SDK通話中であると仮定します）

|シナリオ|中断通知の開始|中断終了の通知|通話の再開?|Note|
|---|---|---|---|---|
|PSTN割り込み|
|A.<br>PSTN割り込み<br>PSTN着信通話を受け入れる<br>電話相手が電話を切る|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11| |
|B.<br>PSTN割り込み<br>PSTN着信通話を受け入れる<br>自分が電話を切る|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11| |
|C.<br>PSTN割り込み<br>PSTNを拒否|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11| |
|D.<br>PSTN割り込み<br>PSTNを無視|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11| |
|E.<br>PSTN割り込み<br>自分が応答する前に相手が電話を切る|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11| |
|そのほかのAudio Interruption<br>(例えばYouTubeアプリ)|
|F.<br>YouTubeアプリに切り替えてビデオを再生する<br>ビデオを停止<br>Voiceアプリに戻る|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:x: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:x: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|中断終了通知はiOS 9では発生しません。<br>iOS 10/11でVoiceアプリに切り替えた後、数秒まで割り込み終了通知は発生しません。<br>`AVAudioSessionInterruptionOptionShouldResume`フラグは` false`です。|
|G.<br>YouTubeアプリに切り替えてビデオを再生する<br>ビデオを停止せずにVoiceアプリに戻る|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:x: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:x: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|中断終了通知はiOS 9では発生しません。<br>iOS 10/11でVoiceアプリに切り替えた後、数秒まで割り込み終了通知は発生しません。<br>`AVAudioSessionInterruptionOptionShouldResume`フラグは` false`です。|
|H.<br>YouTubeアプリに切り替えてビデオを再生する<br>ホームボタンを2回押してYouTubeアプリを終了する<br>Voiceアプリに戻る|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|:white_check_mark: iOS 9<br>:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|Voiceアプリがアクティブ状態に戻るまで、中断終了通知は発生しません。<br>`AVAudioSessionInterruptionOptionShouldResume`フラグは` false`です。|

### CallKit
iOS 10以降では、CallKit（統合されている場合）は、一連のデリゲートメソッドを提供することで中断を処理し、アプリケーションが適切なオーディオデバイスの処理と状態の遷移で応答できるようにします。

#### Notifications & 割り込み中のコールバック
CallKitフレームワークへの呼び出しを報告するときに `CXCallUpdate`オブジェクトの` supportsHolding`フラグを有効にすることで、別のPSTNまたはCallKit対応の呼び出しがあるときに**"Hold＆Accept"** オプションが表示されます。 **“Hold＆Accept”** オプションを押すと、一連のシナリオとコールバックが起こります:

1. `provider：performSetHeldCallAction：`delegateメソッドは `CXSetHeldCallAction.isOnHold = YES`で呼び出されます。ここで音声通話を保留にして、操作を実行します。
2. `AVAudioSessionInterruptionNotification`はAVAudioSessionの中断が始まったことを示すために起動されます。
3. CallKitはあなたのアプリのAVAudioSessionを無効にし、 `provider：didDeactivateAudioSession：`コールバックを起動します。あなたは `TwilioVoice.audioEnabled = NO`を呼び出してSDKオーディオデバイスを無効にする必要があります。
4. 割り込んだ電話が終了した時、`AVAudioSessionInterruptionNotification`を通知します。システムがそれを通知した時、`provider:performSetHeldCallAction:`メソッドを再度呼ぶことで、あなたは中断された通話を再開することができます。**Note** 割り込みコールがリモートパーティによって切断された場合、このコールバックは実行されません。
5. AVAudioSessionが再度有効化されます。あなたは`provider:didActivateAudioSession:`メソッド内にて、`TwilioVoice.audioEnabled = YES`を行い、再度SDKのaudio deviceを有効化する必要があります。

|シナリオ|中断後に音声を再開しますか？|Note|
|---|---|---|
|A.<br>保留 & 承認<br>自分が電話を切る|:white_check_mark: iOS 10<br>:white_check_mark: iOS 11| |
|B.<br>保留 & 承認<br>相手が電話を切る|:x: iOS 10<br>:x: iOS 11|割り込みが終了しても`provider:performSetHeldCallAction:`は呼ばれません。|
|C.<br>保留 & 承認<br>システムUIで音声通話に戻る|:white_check_mark: iOS 10<br>:white_check_mark: iOS 11| |
|D.<br>拒否する|:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|
割り込まれた通話に応答しないため、通話の中断は発生しません。|
|E.<br>無視する|:white_check_mark: iOS 10<br>:white_check_mark: iOS 11|割り込まれた通話に応答しないため、通話の中断は発生しません。|


ケース2の場合、CallKitは `provider：performSetHeldCallAction：`メソッドを呼び出して通話音声を自動的に再開しませんが、システムUIは音声通話がまだ保留中であることを示します。あなたは**"Hold"**ボタンを使って呼び出しを再開することができます、あるいは `CXSetHeldCallAction`を使ってプログラムで保留状態を解除することができます。アプリはまた、ユーザーの混乱を避けるために通話の「保留」状態を示すためにUI状態を更新する責任があります。

```.objc
// Resume call audio programmatically after interruption
CXSetHeldCallAction *setHeldCallAction = [[CXSetHeldCallAction alloc] initWithCallUUID:self.call.uuid onHold:holdSwitch.on];
CXTransaction *transaction = [[CXTransaction alloc] initWithAction:setHeldCallAction];
[self.callKitCallController requestTransaction:transaction completion:^(NSError *error) {
    if (error) {
        NSLog(@"Failed to submit set-call-held transaction request");
    } else {
        NSLog(@"Set-call-held transaction successfully done");
    }
}];
```

## Managing Push Credentials

push認証情報はプッシュ通知チャネルのレコードです。iOSの場合、このpush認証情報はAPNS VoIPのプッシュ通知チャネルレコードです。push認証情報は[Mobile Push Credentials](https://jp.twilio.com/console/voice/sdks/credentials)で管理されます。

iOS SDKの `TwilioVoice.registerWithAccessToken：deviceToken：completion`を介して登録が実行されるたびに、JWTベースのアクセストークンより` identity`と`Push Credential SID`が提供されます。電話をかけるたびに`identity`、 `Push Credential SID`と`device token`をユニークなアドレスとしてAPNS VoIP push通知を送信します。`TwilioVoice.unregisterWithAccessToken：deviceToken：completion`を使うと、その` identity`に対する関連付けが削除されます。


### Push Credentialの更新

Appleから提供された認証情報を変更または更新する必要がある場合は、[console](https://jp.twilio.com/console/voice/sdks/credentials)でPush Credentialを選択し、次に示すPush Credentialページのテキストボックスに新しい`certificate`と`private key`を追加します。

<kbd><img height="667px" src="https://raw.githubusercontent.com/twilio/voice-quickstart-swift/master/Images/update_push_credential.png"/></kbd>

### Push Credentialの削除

作成したアプリケーションが使用されていない場合を除き、**プッシュ資格情報を削除することはお勧めしません。**

**APNS VoIP証明書がもうすぐ期限切れになるか期限切れになった場合は、Push Credentialを削除しないでください。** 代わりに、「Push Credentialの更新」セクションに従ってPush Credentialを更新する必要があります。

Push Credentialが削除されると**このPush Credentialで行われた関連登録はすべて削除されます**。将来的にこの削除されたPush CredentialのPush Credential SIDを使用して登録された`identity`を参照しようとすると**失敗するでしょう**。


確実にPush Credentialを削除したい場合は、選択した[Push Credential](https://jp.twilio.com/console/voice/sdks/credentials)ページで`Delete this Credential`をクリックしてください。

Push Credentialを削除した後、新しいアクセストークンを生成するときには必ずPush Credential SIDを削除または置き換えてください。

## More Documentation
あなたは以下のgetting startedとAppleの最新ドキュメントより、たくさんのドキュメントを見つけることができます。

* [Getting Started](https://jp.twilio.com/docs/api/voice-sdk/ios/getting-started)
* [AppleDoc](https://media.twiliocdn.com/sdk/ios/voice/latest/docs)

## Twilio Helper Libraries

TwiMLとProgrammable Voice Calls APIの使用方法の詳細については、TwiMLクイックスタートをご覧ください。:

* [TwiML Quickstart for Python](https://jp.twilio.com/docs/quickstart/python/twiml)
* [TwiML Quickstart for Ruby](https://jp.twilio.com/docs/quickstart/ruby/twiml)
* [TwiML Quickstart for PHP](https://jp.twilio.com/docs/quickstart/php/twiml)
* [TwiML Quickstart for Java](https://jp.twilio.com/docs/quickstart/java/twiml)
* [TwiML Quickstart for C#](https://jp.twilio.com/docs/quickstart/csharp/twiml)

## Issues and Support
あなたが見つけた問題をGithubで提出してください: [Voice Swift Quickstart](https://github.com/twilio/voice-quickstart-swift).
問題を報告する際に[Personally Identifiable Information(PII)](https://jp.twilio.com/docs/glossary/what-is-personally-identifiable-information-pii)または機密アカウント情報（APIキー、資格情報など）を共有していないことを確認してください。

Voice SDKに関する一般的なお問い合わせは[file a support ticket](https://twilioforkwc.zendesk.com/hc/ja)をご覧ください。

## License
MIT