---
title: "iOSのSDKでフローにデータを渡す"
description: "iOSアプリからフローに値を渡し、テキスト要素に表示します。"
---

> **AI agents**: to search Adapty docs faster and with fewer tokens, install the Adapty skill. Claude Code (self-updating via plugin): `claude plugin marketplace add adaptyteam/adapty-skills && claude plugin install adapty-skills@adapty` — other tools: `npx skills add adaptyteam/adapty-skills --all`

[カスタムタグ](flow-custom-tags)とは、アプリからの値を持つカスタム変数です。変数の設定で **Value comes from outside the app** を選択すると、Adapty SDKを通じてアプリからその値を設定できます。たとえば、テキスト要素に「コイン:」とカスタムタグが含まれている場合、アプリがタグに「120」を渡すと、ユーザーには「コイン: 120」と表示されます。

## 始める前に \{#before-you-start\}

Adapty SDK v4 以降が必要です。v4 より前のバージョンではフローが表示されません。

## フローにカスタムタグを追加する \{#add-custom-tags-to-the-flow\}

アプリの値をフローで表示するには、ビルダーでカスタムタグを設定します。

1. アプリが渡す各値に対して[カスタムタグを作成](flow-custom-tags#create-a-custom-tag)します。

   <ZoomImage id="flow-custom-tag-create.webp" width="500px" alt="名前、説明、String値タイプ、および初期値を含む変数作成フォーム" />

2. [各タグをテキスト要素に挿入](flow-custom-tags#add-a-custom-tag-to-a-text-element)します。
3. グループ名を含む各タグのフルネームを確認してください。アプリのコードはこの名前で各値を渡します。たとえば、`user` グループに `streak` タグが含まれている場合、タグのフルネームは `user.streak` となります。

   <ZoomImage id="flow-custom-tag-full-name.webp" width="500px" alt="streakタグがuserグループ内にある、変数追加ドロップダウンのカスタムタブ" />

## カスタムタグの値を渡す \{#pass-custom-tag-values\}

アプリの値を`getFlowConfiguration`の`tagResolver`パラメータに、`[String: String]`ディクショナリとして渡します：

- 各キーは`user.streak`など、カスタムタグのフル名です。
- 各値は、タグの代わりにユーザーに表示される文字列です。
- 各値は「1250.0」ではなく「1,250」のように、人間が読める形式である必要があります。Adaptyはフォーマットや翻訳を行いません。

```swift showLineNumbers title="Swift"
let customTags = [
    "username": "DragonSlayer42",
    "coins": "1,250",
]

do {
    let flowConfiguration = try await AdaptyUI.getFlowConfiguration(
        forFlow: flow,
        tagResolver: customTags
    )
    // present the flow
} catch {
    // handle the error
}
```

SwiftUI の [`.flow` モディファイアと `AdaptyFlowView`](ios-present-paywalls#present-flows-and-paywalls-in-swiftui)、および UIKit の[フローコントローラー](ios-present-paywalls#present-flows-and-paywalls-in-uikit)には、カスタムタグ値を指定するパラメーターはありません。渡したフロー設定に含まれる値がそのまま表示されます。

カスタムタグをテストするには、タグの値を設定するコードを追加した後、アプリでフローを開いてください。ビルダーのキャンバスおよび[デバイスでのプレビュー](paywall-device-compatibility-preview#preview-on-devices)には初期値のみが表示されます。Adapty モバイルアプリはカスタムタグの値を設定しません。

旧ペイウォールビルダーのペイウォールでカスタムタグ値をすでに設定している場合は、[フローにおけるカスタムタグの違い](migrate-to-flows#custom-tags-from-the-old-paywall-builder)をご確認ください。

## 値が設定されていない場合にユーザーに表示されるもの \{#what-users-see-without-a-value\}

以下の場合、ユーザーにはカスタムタグの**初期値**がフォールバックとして表示されます。

- アプリがそのタグに値を渡していない場合。
- ユーザーがアプリを値を渡すバージョンにアップデートしていない場合。
- アプリのコード内の名前が、大文字・小文字を含めタグのフルネームと一致していない場合。
- 同じテキスト要素内の別のカスタムタグに値がない場合。その場合、そのテキスト要素内のすべてのカスタムタグが初期値を表示します。

タグの位置に何も表示しないようにするには、空の文字列を渡してください。Adapty は空の文字列を値として扱うため、フォールバックは表示されません。

## 例：オンボーディングの回答からBMIを表示する \{#example-show-a-bmi-from-onboarding-answers\}

フローはユーザーから回答を収集でき、カスタムタグはアプリの値を表示できます。この2つを組み合わせることで、スコア、おすすめプラン、健康指標など、回答からアプリが計算した結果をユーザーに表示できます：

1. フローが回答を収集し、アプリに送信します。
2. アプリが結果を計算します。
3. アプリが次のフローにカスタムタグの値として結果を渡します。

この例では、オンボーディングフローがユーザーの体重と身長を収集します。ユーザーがオンボーディングフローの最後の画面を閉じると、アプリがBMI（ボディマス指数）を計算します。そして、BMIを表示するペイウォールフローを開きます。

### フローの設定 \{#set-up-the-flows\}

1. [2つのフローを作成します](paywall-builder-templates): ユーザーの体重と身長を収集するオンボーディングフローと、BMIを表示するペイウォールフローです。
2. オンボーディングフローに2つの[**Number**入力](builder-inputs-and-forms)を追加します:
   - 体重（キログラム）用。**Element ID**を`weight`に設定します。
   - 身長（センチメートル）用。**Element ID**を`height`に設定します。

   両方の入力で、**Format**を**Integer**に設定します。入力はユーザーが入力した通りのテキストとして値を送信するため、[サンプルコード](#pass-the-bmi-to-the-paywall)は"70.5"と"70,5"を同じように読み取りません。整数には小数点区切り文字がないため、すべてのロケールで同じように読み取られます。
3. アプリが両方の値を確実に受け取れるよう、オンボーディングフローを入力のない画面で終了させます。その画面に、[**Close flow**](onboarding-actions#close-flow)アクションを持つボタンを追加します。入力はフォーカスを失ったとき、またはユーザーが別の画面に移動したときに値を送信します。Close flowアクションは値を送信しません。サンプルコードは、ユーザーが最後の画面に到達した場合にのみペイウォールを開きます。
4. ペイウォールフローで、`bmi`という名前の[カスタムタグを作成します](flow-custom-tags#create-a-custom-tag)。**Initial value**フィールドにダッシュ（`—`）を入力します。アプリがBMIを渡さない場合、ユーザーにはダッシュが表示されます。
5. ペイウォールフローに「Your BMI:」という文字列を含むテキスト要素を追加します。この文字列の後に、[`bmi`カスタムタグを挿入します](flow-custom-tags#add-a-custom-tag-to-a-text-element)。
6. オンボーディングフローを`onboarding`などの[プレースメント](placements)に追加します。ペイウォールフローをID `bmi_paywall`のプレースメントに追加します。[BMIをペイウォールに渡す](#pass-the-bmi-to-the-paywall)のコードは、このIDでペイウォールを取得します。

### BMI をペイウォールに渡す \{#pass-the-bmi-to-the-paywall\}

[フローからデータを処理する](ios-flow-input)で説明したように、オンボーディングフローの `flow_user_input` イベントから体重と身長を収集してください。ユーザーが最後の画面に到達したことを知るには、[フロー画面のビューを追跡する](ios-flow-screen-views)で説明したように、`is_last_screen` が `true` に設定された `flow_screen_showed` イベントを監視してください。ユーザーがその画面の後にオンボーディングフローを閉じたら、BMI を計算します。次に、ペイウォールのフロー設定を取得し、`bmi` カスタムタグに BMI を渡してください。

The following code is for UIKit. It implements the `AdaptyFlowControllerDelegate` methods on one view controller, which is the delegate of both the onboarding flow's controller and the paywall's controller. The view controller must also implement the delegate's purchase and restore methods, which this example leaves out. To see them, go to [UIKit でフローとペイウォールを表示する](ios-present-paywalls#present-flows-and-paywalls-in-uikit).

```swift showLineNumbers title="Swift"
private var bodyAnswers: [String: String] = [:]
private var reachedLastScreen = false

func flowController(
    _ controller: AdaptyFlowController,
    didReceiveAnalyticEvent name: String,
    params: [String: any Sendable]
) {
    if name == "flow_screen_showed", params["is_last_screen"] as? Bool == true {
        reachedLastScreen = true
        return
    }
    guard name == "flow_user_input",
          let elementId = params["element_id"] as? String,
          let value = params["value"] as? String
    else { return }

    bodyAnswers[elementId] = value
}

func flowControllerDidDisappear(_ controller: AdaptyFlowController) {
    // This delegate receives events from both flows. Reset `bodyAnswers` and
    // `reachedLastScreen` whenever a flow disappears, so that the paywall
    // doesn't open again when the user closes it.
    let answers = bodyAnswers
    let finished = reachedLastScreen
    bodyAnswers.removeAll()
    reachedLastScreen = false

    // Number inputs send their values as strings.
    guard finished,
          let weight = answers["weight"].flatMap({ Double($0) }),
          let height = answers["height"].flatMap({ Double($0) }),
          height > 0
    else { return }

    let heightInMeters = height / 100
    let bmi = weight / (heightInMeters * heightInMeters)

    Task {
        await showBMIPaywall(bmi: bmi.formatted(.number.precision(.fractionLength(1))))
    }
}

func showBMIPaywall(bmi: String) async {
    do {
        let flow = try await Adapty.getFlow(placementId: "bmi_paywall")
        let flowConfiguration = try await AdaptyUI.getFlowConfiguration(
            forFlow: flow,
            tagResolver: ["bmi": bmi]
        )
        let flowController = try AdaptyUI.flowController(
            with: flowConfiguration,
            delegate: self
        )
        present(flowController, animated: true)
    } catch {
        // handle the error
    }
}
```

`formatted` はユーザーのロケールの小数点区切り文字を使用します：英語では "22.7"、ドイツ語では "22,7"。

SwiftUI では、デリゲートメソッドの代わりにオンボーディングフローの `.flow` モディファイアのクロージャを使用してください：

- `didReceiveAnalyticEvent`：体重と身長を収集し、最後の画面の `flow_screen_showed` イベントを監視します。
- `didDisappear`：ユーザーが最後の画面に到達した場合、BMI を計算します。次に、ペイウォールのフロー設定を取得し、`bmi` カスタムタグに BMI を渡します。その設定を2番目の `.flow` モディファイアで表示します。

### BMIをユーザーのプロファイルに保存する \{#save-the-bmi-to-the-users-profile\}

BMIに基づいて異なるフローをユーザーに表示するには、BMIをプロファイルの[カスタム属性](setting-user-attributes#custom-user-attributes)として保存します。Adapty ダッシュボードで、キー `bmi` を持つ[**Number** カスタム属性を作成](segments#custom-attributes)します。その後、その属性から作成した[オーディエンス](audience)に各フローを表示します。

`flowControllerDidDisappear` 内の `bmi` を計算する行のすぐ後に `updateProfile` メソッドを呼び出します。セグメントがBMIをしきい値と比較できるよう、フォーマットされた文字列ではなく `Double` 型の値を渡してください。

```swift showLineNumbers title="Swift"
do {
    let params = try AdaptyProfileParameters.Builder()
        .with(customAttribute: bmi, forKey: "bmi")
        .build()
    try await Adapty.updateProfile(params: params)
} catch {
    // handle the error
}
```