フローとペイウォールを取得する - iOS

getFlow で取得される内容
フロー BETA Flow Builder で作成——デバイス上でネイティブにレンダリングされ、WebView は不要
Paywall Builder のペイウォール 既存のすべての Paywall Builder コンテンツ

フローまたはペイウォールビルダーのペイウォールを設計したら、それをモバイルアプリに表示できます。最初のステップは、以下の説明に従って、プレースメントに関連付けられたフローまたはペイウォールとそのビュー設定を取得することです。

Adapty SDK をモバイルアプリに統合した実例を見たいですか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを示すサンプルアプリをご確認ください。

始める前に
  1. Adapty ダッシュボードでプロダクトを作成します。
  2. Adapty ダッシュボードでフロー/ペイウォールを作成し、プロダクトを組み込みます。
  3. Adapty ダッシュボードでプレースメントを作成し、フロー/ペイウォールを組み込みます。
  4. モバイルアプリに Adapty SDK をインストールします。

フローまたはペイウォールの取得

フロービルダーまたはペイウォールビルダーを使ってフローやペイウォールをデザインした場合、それをモバイルアプリのコードでレンダリングしてユーザーに表示することを心配する必要はありません。このようなフローやペイウォールには、表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてIDを取得し、ビュー設定を準備した上で、モバイルアプリに表示する必要があります。 フローまたはペイウォールとそのビュー設定は、できるだけ早い段階で取得してください。表示する直前ではなく、理想的にはずっと前に取得しましょう。ビュー設定を取得した時点で、SDKはバックグラウンドで画像のダウンロードとキャッシュを開始します。早く取得するほど、ダウンロードが完了するまでの時間が長く確保できます。フローまたはペイウォールを表示する頃には、設定と画像がすでにキャッシュ済みで表示できる状態になっています。

フローまたはペイウォールを取得するには、getFlow メソッドを使用します:

パラメーター:

パラメータ必須/任意説明
placementId必須取得したいプレースメントの識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。
fetchPolicyデフォルト: .reloadRevalidatingCacheData

デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。この方法を推奨するのは、ユーザーが常に最新のデータを受け取れるためです。

ただし、ユーザーが不安定なインターネット環境を利用していると想定される場合は、.returnCacheDataElseLoad を使用することを検討してください。これにより、キャッシュが存在する場合はキャッシュデータを返します。この場合、最新のデータが取得できないことがありますが、通信環境に左右されずに読み込み時間を短縮できます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けたい場面での使用も安全です。

キャッシュはアプリを再起動しても保持され、アプリの再インストールや手動でのクリアを行った場合にのみ削除されます。

Adapty SDK はペイウォールをローカルに2つの層で保存しています。1つは上記の定期更新キャッシュ、もう1つはフォールバックペイウォールです。また、CDN を使用してペイウォールをより高速に取得し、CDN に接続できない場合のスタンドアロンフォールバックサーバーも用意しています。このシステムは、常にペイウォールの最新バージョンを取得しつつ、インターネット接続が不安定な場合でも信頼性を確保するよう設計されています。

loadTimeoutデフォルト: 5秒

このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。

まれに、内部で複数のリクエストが発生する場合があるため、loadTimeout に指定した時間よりわずかに遅くタイムアウトすることがあります。

レスポンスパラメーター:
パラメーター説明
Flowプレースメント、識別子(idvariationId)、名前、リモートコンフィグ、およびフローにビュー設定が含まれるかどうかを示す hasViewConfiguration フラグを含む AdaptyFlow オブジェクトです。プリロード、カスタム UI、またはプログラムによるチェック用に実際のプロダクトを取得するには、getPaywallProducts(flow:) を呼び出してください。

ビュー設定の取得

フローまたはペイウォールを取得したら、flow.hasViewConfiguration を使ってビュー設定が含まれているかどうかを確認します。このフラグは、Adapty ダッシュボードでプレースメントがどのように設計されたかを示します。

  • true — プレースメントが Flow Builder(フロー)または Paywall Builder(ペイウォール)で設計されています。Adapty が UI をレンダリングします。以降の手順に従い、ビュー設定を取得してフローまたはペイウォールを表示してください。
  • false — プレースメントはビルダー UI を持たないカスタムペイウォールです。 getFlowConfiguration メソッドを使用してビュー設定を読み込みます。

guard flow.hasViewConfiguration else {
    // handle as remote config paywall
    return
}

let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow)

パラメーター:

パラメーター必須/任意説明
forFlow必須Adapty.getFlow で取得した AdaptyFlow オブジェクト。
locale

任意

デフォルト: nil

ペイウォールのローカライズの識別子。- で区切られた1つまたは2つのサブタグを持つ言語コードで指定します(例: enpt-br)。詳細はローカライズとロケールコードを参照してください。
loadTimeoutデフォルト: 5秒このメソッドのタイムアウトを制限する値です。タイムアウトに達した場合、キャッシュされたデータまたはローカルのフォールバックが返されます。内部で複数のリクエストが発生する場合があるため、loadTimeout で指定した時間よりわずかに遅れてタイムアウトすることがあります。
products任意画面上のプロダクト表示タイミングを最適化するために、AdaptyPaywallProduct オブジェクトの配列を指定します。nil を渡すと、AdaptyUI が必要なプロダクトを自動的に取得します。
systemRequestsHandler任意フローのアクションによってトリガーされるシステムの権限リクエストやレビューリクエストを処理する、AdaptySystemRequestsHandler に準拠したオブジェクト。フローにそのようなアクションが含まれる場合にのみ必要です。
assetsResolver任意フロー/ペイウォール内の画像や動画を上書きする [String: AdaptyCustomAsset] 辞書。詳細はアセットのカスタマイズを参照してください。
timerResolver任意開発者が定義したタイマーの終了日時を提供する、AdaptyTimerResolver に準拠したオブジェクト。詳細は開発者定義タイマーの設定を参照してください。
読み込みが完了したら、フロー/ペイウォールを表示します。

デフォルトオーディエンスのフローまたはペイウォールを取得して高速化する

通常、フローやペイウォールはほぼ瞬時に取得されるため、このプロセスの高速化を特に気にする必要はありません。ただし、オーディエンスやプレースメントが多数あり、ユーザーのインターネット接続が不安定な場合は、フローやペイウォールの取得に想定以上の時間がかかることがあります。そのような状況では、何も表示しないよりもスムーズなユーザー体験を提供するために、デフォルトのフローまたはペイウォールを表示したいと思うかもしれません。 これに対処するために、getFlowForDefaultAudience メソッドを使用できます。このメソッドは、指定されたプレースメントの All Users オーディエンス向けのフローまたはペイウォールを取得します。ただし、推奨されるアプローチは getFlow メソッドでフローまたはペイウォールを取得することであり、詳細は上記のペイウォール情報の取得セクションをご覧ください。

getFlow を推奨する理由

getFlowForDefaultAudience メソッドにはいくつかの重大な欠点があります:

  • 後方互換性の問題: 異なるアプリバージョン(現在と将来)で別々のペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンに対応したペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールで問題が発生することを許容するかのどちらかを選択することになります。
  • ターゲティングの喪失: すべてのユーザーに All Users オーディエンス向けに設計された同じペイウォールが表示されるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらのデメリットを許容してでもフローやペイウォールの取得を高速化したい場合は、以下のように getFlowForDefaultAudience メソッドを使用してください。それ以外の場合は、上記で説明した getFlow を使用してください。
Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in
    switch result {
        case let .success(flow):
            // the requested flow
        case let .failure(error):
            // handle the error
    }
}
パラメーター必須/任意説明
placementId必須プレースメントの識別子。Adapty ダッシュボードでプレースメントを作成した際に指定した値です。
fetchPolicyデフォルト: .reloadRevalidatingCacheData

デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。この方式はユーザーが常に最新のデータを受け取れるため、こちらをお勧めします。

ただし、ユーザーのインターネット接続が不安定だと思われる場合は、.returnCacheDataElseLoad を使用すると、キャッシュが存在する場合にそれを返すことができます。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込みが速くなります。キャッシュはセッション中でも定期的に更新されるため、ネットワークリクエストを避ける目的でのキャッシュ使用は安全です。

なお、キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。

アセットのカスタマイズ

ペイウォール/フローの画像や動画をカスタマイズするには、カスタムアセットを実装します。

ヒーロー画像と動画には事前定義済みのID(hero_imagehero_video)が割り当てられています。カスタムアセットバンドルでは、これらのIDを使って各要素を指定し、動作をカスタマイズします。

その他の画像や動画については、Adapty ダッシュボードでカスタムIDを設定する必要があります。

たとえば、次のようなことができます。

  • 一部のユーザーに別の画像や動画を表示する。
  • リモートのメイン画像の読み込み中に、ローカルのプレビュー画像を表示する。
  • 動画を再生する前にプレビュー画像を表示する。
  • 動画が読み込まれる前にプレイヤーがレイアウトスペースを確保できるよう、動画のピクセル解像度を指定する(アスペクト比 = width / height)。スキップするには nil を渡す。

カスタムアセットをシンプルな辞書で提供する方法の例を以下に示します:

let customAssets: [String: AdaptyCustomAsset] = [
    // Show a local image using a custom ID
    "custom_image": .image(
        .uiImage(value: UIImage(named: "image_name")!)
    ),

    // Show a local preview image while a remote main image is loading
    "hero_image": .image(
        .remote(
            url: URL(string: "https://example.com/image.jpg")!,
            preview: UIImage(named: "preview_image")
        )
    ),

    // Show a local video with a preview image and a known resolution
    "hero_video": .video(
        .file(
            url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!,
            preview: .uiImage(value: UIImage(named: "video_preview")!),
            resolution: CGSize(width: 1080, height: 1920)
        )
    ),
]

let flowConfig = try await AdaptyUI.getFlowConfiguration(
    forFlow: flow,
    assetsResolver: customAssets
)

アセットが見つからない場合、ペイウォール/フローはデフォルトの外観にフォールバックします。

開発者定義タイマーの設定

モバイルアプリでカスタムタイマーを使用するには、AdaptyTimerResolver プロトコルに準拠したオブジェクトを作成します。このオブジェクトは、各カスタムタイマーのレンダリング方法を定義します。必要であれば、このプロトコルにすでに準拠している [String: Date] ディクショナリを直接使用することもできます。以下に例を示します:

@MainActor
struct AdaptyTimerResolverImpl: AdaptyTimerResolver {
    func timerEndAtDate(for timerId: String) -> Date {
        switch timerId {
        case "CUSTOM_TIMER_6H":
            Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours
        case "CUSTOM_TIMER_NY":
            Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0)
        default:
            Date(timeIntervalSinceNow: 3600.0) // 1 hour
        }
    }
}

この例では、CUSTOM_TIMER_NYCUSTOM_TIMER_6H は、Adapty ダッシュボードで設定した開発者定義タイマーの Timer ID です。timerResolver により、アプリは各タイマーを正しい値で動的に更新できます。例えば:

  • CUSTOM_TIMER_NY: 元日など、タイマーの終了までの残り時間。
  • CUSTOM_TIMER_6H: ユーザーがペイウォールを開いてから始まった6時間のうち、残りの時間。

Adapty ダッシュボードのペイウォールビルダーでペイウォールのビジュアルデザインを作成したら、それをモバイルアプリに表示できます。最初のステップは、以下の説明に従ってプレースメントに関連付けられたペイウォールとそのビュー設定を取得することです。

このトピックはペイウォールビルダーでカスタマイズされたペイウォールに関するものです。ペイウォールを手動で実装する場合は、リモートコンフィグペイウォール用のペイウォールとプロダクトの取得を参照してください。

Adapty SDK をモバイルアプリに統合した実際の例を見たい方は、サンプルアプリをご覧ください。ペイウォールの表示、購入処理、その他の基本的な機能を含む完全なセットアップを確認できます。

モバイルアプリでペイウォールを表示する前に
  1. Adapty ダッシュボードでプロダクトを作成する
  2. Adapty ダッシュボードでペイウォールを作成し、プロダクトを追加する
  3. Adapty ダッシュボードでプレースメントを作成し、ペイウォールを追加する
  4. モバイルアプリに Adapty SDK をインストールする。

ペイウォールビルダーで作成したペイウォールを取得する

ペイウォールビルダーを使ってペイウォールをデザインした場合、ユーザーに表示するためのレンダリングコードをアプリに書く必要はありません。このようなペイウォールには、表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてペイウォールのIDを取得し、ビュー設定を取得してから、アプリ内に表示する必要があります。 最適なパフォーマンスを確保するために、ペイウォールとそのビュー設定をできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードに十分な時間を確保することが重要です。

ペイウォールを取得するには、getPaywall メソッドを使用します:

パラメーター:

パラメータ必須/任意説明
placementId必須取得したいプレースメントの識別子です。Adapty ダッシュボードでプレースメントを作成する際に指定した値を使用します。
locale

任意

デフォルト: en

ペイウォールのローカライズの識別子です。このパラメータは、マイナス(-)で区切られた1つまたは2つのサブタグで構成された言語コードを指定します。最初のサブタグは言語、2番目のサブタグは地域を表します。

例: en は英語、pt-br はブラジルポルトガル語を表します。

ロケールコードの詳細と推奨される使い方については、ローカライズとロケールコードを参照してください。

fetchPolicyデフォルト: .reloadRevalidatingCacheData

デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを受け取れるようになるため、この設定を推奨します。

ただし、ユーザーの通信環境が不安定な場合は、.returnCacheDataElseLoad を使用してキャッシュが存在する場合はキャッシュデータを返すことを検討してください。この設定では最新データが取得できないことがありますが、通信が不安定な環境でも読み込みが速くなります。キャッシュはセッション中に定期的に更新されるため、ネットワークリクエストを減らす目的でキャッシュを利用しても問題ありません。

キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリアによってのみ削除されます。

Adapty SDK はペイウォールをローカルに2層で保存します。1つは上記の定期更新キャッシュ、もう1つはフォールバックペイウォールです。また、ペイウォールをより速く取得するために CDN を使用し、CDN に接続できない場合に備えてスタンドアロンのフォールバックサーバーも用意しています。このシステムは、通信環境が悪い場合でも常にペイウォールの最新バージョンを確実に取得できるよう設計されています。

loadTimeoutデフォルト: 5秒

このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルのフォールバックが返されます。

内部的に複数のリクエストが発生する場合があるため、まれに loadTimeout で指定した時間よりもわずかに遅くタイムアウトすることがあります。

レスポンスパラメーター:
パラメーター説明
PaywallプロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む AdaptyPaywall オブジェクト。

ペイウォールビルダーで作成したペイウォールのビュー設定を取得する

ペイウォールビルダーで Show on device トグルを有効にしてください。このオプションがオンになっていない場合、ビュー設定を取得できません。

ペイウォールを取得したら、ビュー設定が含まれているかどうかを確認してください。ビュー設定が存在する場合は、そのペイウォールがペイウォールビルダーで作成されたことを意味します。これにより、ペイウォールの表示方法が決まります。ビュー設定がある場合はペイウォールビルダーのペイウォールとして扱い、ない場合はリモートコンフィグのペイウォールとして処理してくださいgetPaywallConfiguration メソッドを使って、ビュー設定を読み込みます。


guard paywall.hasViewConfiguration else {
    //  use your custom logic
    return
}

do {
    let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(
            forPaywall: paywall,
            products: products
    )
    // use loaded configuration
} catch {
    // handle the error
}

パラメーター:

パラメータ必須/任意説明
paywall必須対象のペイウォールのコントローラーを取得するための AdaptyPaywall オブジェクト。
loadTimeoutデフォルト: 5秒このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュされたデータまたはローカルのフォールバックが返されます。内部で複数のリクエストが発生する場合があるため、まれに loadTimeout で指定した時間よりもわずかに遅れてタイムアウトすることがあります。
products任意画面上でのプロダクト表示タイミングを最適化するために、AdaptyPaywallProduct オブジェクトの配列を指定します。nil を渡した場合、AdaptyUI が自動的に必要なプロダクトを取得します。

複数の言語を使用している場合は、ペイウォールビルダーのローカライゼーションを追加する方法と、ロケールコードを正しく使用する方法をこちらでご確認ください。

読み込みが完了したら、ペイウォールを表示してください。

デフォルトオーディエンス向けペイウォールを取得してより速く表示する

通常、ペイウォールはほぼ瞬時に取得されるため、速度を気にする必要はありません。ただし、オーディエンスやペイウォールの数が多く、ユーザーのインターネット接続が不安定な場合は、ペイウォールの取得に想定以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を提供することを検討するとよいでしょう。 この問題に対処するために、getPaywallForDefaultAudience メソッドを使用できます。このメソッドは、指定されたプレースメントの All Users オーディエンス向けペイウォールを取得します。ただし、推奨されるアプローチは getPaywall メソッドでペイウォールを取得することであり、詳細は上記の ペイウォール情報の取得 セクションをご覧ください。

getPaywall を推奨する理由

getPaywallForDefaultAudience メソッドにはいくつかの重大な欠点があります:

  • 後方互換性の問題: 異なるアプリバージョン(現行バージョンと将来のバージョン)に対して異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現行(レガシー)バージョンに対応したペイウォールを設計するか、現行(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇するリスクを許容するかのどちらかを選択しなければなりません。
  • ターゲティングの喪失: すべてのユーザーが All Users オーディエンス向けに設計された同じペイウォールを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらのデメリットを受け入れてでもペイウォールの取得を高速化したい場合は、以下のように getPaywallForDefaultAudience メソッドを使用してください。そうでない場合は、上記で説明した getPaywall を使用してください。
Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
    switch result {
        case let .success(paywall):
            // the requested paywall
        case let .failure(error):
            // handle the error
    }
}

getPaywallForDefaultAudience メソッドは iOS SDK バージョン 2.11.2 以降で利用可能です。

パラメーター必須/任意説明
placementId必須プレースメントの識別子です。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。
locale

任意

デフォルト: en

ペイウォールのローカライズの識別子です。このパラメーターは、マイナス(-)文字で区切られた1つ以上のサブタグで構成される言語コードである必要があります。最初のサブタグは言語、2番目は地域を表します。

例: en は英語、pt-br はブラジルポルトガル語を表します。

ロケールコードおよび推奨される使用方法については、ローカライズとロケールコードを参照してください。

fetchPolicyデフォルト: .reloadRevalidatingCacheData

デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを受け取れるため、この設定を推奨します。

ただし、ユーザーが不安定なインターネット環境にある場合は、.returnCacheDataElseLoad の使用を検討してください。キャッシュが存在する場合はキャッシュデータを返すため、最新データが得られない場合もありますが、接続状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを減らす目的で安全に利用できます。

キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。

アセットのカスタマイズ

ペイウォールの画像や動画をカスタマイズするには、カスタムアセットを実装します。

ヒーロー画像と動画には、hero_imagehero_video という定義済みIDがあります。カスタムアセットバンドルでは、これらのIDを使って各要素を指定し、動作をカスタマイズできます。

その他の画像や動画については、Adapty ダッシュボードでカスタムIDを設定する必要があります。

たとえば、次のようなことができます。

  • 一部のユーザーに別の画像や動画を表示する。
  • リモートのメイン画像の読み込み中に、ローカルのプレビュー画像を表示する。
  • 動画を再生する前にプレビュー画像を表示する。

この機能を使用するには、Adapty iOS SDK をバージョン 3.7.0 以上にアップデートしてください。

カスタムアセットをシンプルな辞書形式で提供する方法の例を示します:

let customAssets: [String: AdaptyCustomAsset] = [
    // Show a local image using a custom ID
    "custom_image": .image(
        .uiImage(value: UIImage(named: "image_name")!)
    ),

    // Show a local preview image while a remote main image is loading
    "hero_image": .image(
        .remote(
            url: URL(string: "https://example.com/image.jpg")!,
            preview: UIImage(named: "preview_image")
        )
    ),

    // Show a local video with a preview image
    "hero_video": .video(
        .file(
            url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!,
            preview: .uiImage(value: UIImage(named: "video_preview")!)
        )
    ),
]

let paywallConfig = try await AdaptyUI.getPaywallConfiguration(
    forPaywall: paywall,
    assetsResolver: customAssets
)

アセットが見つからない場合、ペイウォールはデフォルトの外観にフォールバックします。

デベロッパー定義タイマーの設定

モバイルアプリでカスタムタイマーを使用するには、AdaptyTimerResolver プロトコルに準拠したオブジェクトを作成します。このオブジェクトは、各カスタムタイマーのレンダリング方法を定義します。[String: Date] ディクショナリはすでにこのプロトコルに準拠しているため、直接使用することもできます。以下に例を示します。

@MainActor
struct AdaptyTimerResolverImpl: AdaptyTimerResolver {
    func timerEndAtDate(for timerId: String) -> Date {
        switch timerId {
        case "CUSTOM_TIMER_6H":
            Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours
        case "CUSTOM_TIMER_NY":
            Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0)
        default:
            Date(timeIntervalSinceNow: 3600.0) // 1 hour
        }
    }
}

この例では、CUSTOM_TIMER_NYCUSTOM_TIMER_6H は、Adapty ダッシュボードで設定した開発者定義タイマーの Timer ID です。timerResolver により、アプリは各タイマーを正しい値で動的に更新できます。例えば:

  • CUSTOM_TIMER_NY: 元日など、タイマー終了までの残り時間。
  • CUSTOM_TIMER_6H: ユーザーがペイウォールを開いてから始まった6時間のうち、残り時間。