メインコンテンツまでスキップ
バージョン: 4.6.1

区間コントロール統合

コードベース統合を使用してNetFUNNEL iOSエージェントで区間コントロールを実装する完全なガイドです。

統合方法

これは利用可能な2つの統合方法のうちの1つです。統合方法概要を参照して基本コントロールと比較し、ユースケースに最も適した方法を選択してください。


動作方式

ユーザー体験:

  1. ユーザーがボタンをクリックまたはアクションをトリガーします
  2. 待合室が現在の画面に表示されます
  3. 進入が許可されると待合室が閉じ、ユーザーがアクティブ区間に進入します
  4. ユーザーは区間内で複数の画面をナビゲートできます
  5. ユーザーがプロセスを完了するとキーが返却され、次のユーザーが進入できます

最適なユースケース:

  • マルチステッププロセス(チェックアウト、登録、予約)
  • 特定の領域で固定された同時ユーザー数を維持
  • ユーザーセッション管理
  • 制御された容量が必要なリソース集約的なワークフロー

基本コントロールとの主な違い:

  • 基本コントロール: 進入速度を制御します(キーが迅速に返却される)
  • 区間コントロール: 固定された同時ユーザー数を維持します(区間終了までキーが維持される)

事前要件

サンプルアプリケーション例

このガイドはサンプルアプリケーションを使用して区間コントロール統合パターンを示します。実際のアプリケーションコードはここに示された例とは異なります。統合概念を理解することに集中し、パターンを特定のコードベース、関数名、ビジネスロジックに合わせて調整してください。

💡 練習テンプレート: NetFUNNEL SDK統合練習のための**iOSアプリケーション(単一ViewController)**テンプレートが準備されたサンプルプロジェクトを確認してください。


1ステップ: セグメント作成

2つの制御タイプすべてサポート

コードベース統合は基本コントロール区間コントロールの両方をサポートします。このガイドは区間コントロールを使用します。

1.1 新規セグメント作成

  1. NetFUNNELコンソール → プロジェクトセグメントに移動します
  2. **+**ボタンをクリックして新規セグメントを作成します

セグメント作成ボタン

1.2 制御タイプ選択

区間コントロールを選択し、次へをクリックします

区間コントロール選択

1.3 セグメント構成

セグメント名: 説明的な名前を入力します(例: "チェックアウトプロセス"、"登録フロー"、"予約区間")

区間セグメント名入力

進入状態:

  • セグメントの有効化有効化済み
  • 進入状態: 待機(ユーザーを待合室に送る)

区間セグメント進入状態設定

待合室適用:

  • テストのために基本設定を使用
  • ライブメッセージは空欄のままにします

区間セグメント待合室設定

進入許容数:

  • テストのために0に設定します(誰も許可されない、待合室が常に表示される)
  • これは同時ユーザー数を制御します - 区間で同時にアクティブになれるユーザー数

区間セグメント進入許容数設定

1.4 セグメント作成

作成をクリックしてセグメントを完了します

区間セグメント作成済み


2ステップ: キー発行統合ポイント識別(nfStartSection

サンプルアプリケーション

次の例はデモ目的でサンプルアプリケーションを使用します。実際のアプリケーションコードはここに示されたものとは自然に異なります。統合パターンを特定のコード構造、ボタンID、関数名、ビジネスロジックに合わせて調整してください。

💡 練習プロジェクトが必要ですか? NetFUNNEL SDK統合練習のための**iOSアプリケーション(単一ViewController)**テンプレートが準備されたサンプルプロジェクトを確認してください。

サンプルアプリケーション理解:

NetFUNNEL保護を適用する必要がある位置を理解するためにサンプルアプリケーションを見てみましょう:

2.1 レイアウトで対象ボタン識別

// MainView.swift
struct MainView: View {
@StateObject private var navigationManager = NavigationManager.shared

var body: some View {
ScrollView {
VStack(spacing: 0) {
// Hero Section(簡潔性のために省略)
// ... 既存のUI構造 ...

// Cards Section
VStack(spacing: 20) {
// 他のボタン - 対象ではない
Button(action: {
navigationManager.navigateWithDelay(to: .basicControl)
}) {
ModernCard(
icon: "arrow.right.circle.fill",
title: "Basic Control",
subtitle: "Code-based Integration",
description: "Simple linear navigation flow",
accentColor: MaterialColors.lightPrimary
)
}
.buttonStyle(ModernCardButtonStyle())

// 🎯 対象ボタン: 区間コントロール機能カード
// これがNetFUNNELで保護したいボタンです
Button(action: {
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}) {
ModernCard(
icon: "list.bullet.circle.fill",
title: "Section Control",
subtitle: "Code-based Integration",
description: "Multi-step navigation flow",
accentColor: MaterialColors.lightSecondary
)
}
.buttonStyle(ModernCardButtonStyle())
}
.padding(.horizontal, 20)

Spacer(minLength: 40)
}
}
// 追加UI修飾子は簡潔性のために省略
// ... background, frame, navigationBarHiddenなど ...
}
}

このサンプルに関する仮定:

  • "Section Control"ボタンはマルチステッププロセスを表します
  • これは次のいずれかです: チェックアウトフロー、登録プロセス、予約ワークフロー、またはマルチステップフォーム
  • ユーザーは複数のSwiftUI Viewをナビゲートします: Section1 → Section2 → End
  • この全体のフローで同時にアクティブになれるユーザー数を制御する必要があります

2.2 このボタンのクリックリスナー検索

クリックリスナーとは何ですか?

クリックリスナー(アクションハンドラーまたはイベントハンドラーとも呼ばれる)は、ユーザーがUI要素と相互作用するときに実行されるコードです。SwiftUIでは通常Button(action:)クロージャ構文を使用して定義されます。

SwiftUIボタン構造理解:

Button(action: {
// 🎯 これがクリックリスナーです
// ユーザーがボタンをタップするとここでのコードが実行されます
}) {
// これがボタンの視覚的な外観です
// ボタンがどのように見えるかを定義します
}

サンプルアプリケーションで:

// MainView.swift
struct MainView: View {
@StateObject private var navigationManager = NavigationManager.shared

var body: some View {
ScrollView {
VStack(spacing: 0) {
// Hero Section(簡潔性のために省略)
// ... 既存のUI構造 ...

// Cards Section
VStack(spacing: 20) {
// 他のボタン - 対象ではない(NetFUNNEL保護不要)
Button(action: {
// このボタンはNetFUNNEL保護が必要ありません
navigationManager.navigateWithDelay(to: .basicControl)
}) {
ModernCard(
icon: "arrow.right.circle.fill",
title: "Basic Control",
subtitle: "Code-based Integration",
description: "Simple linear navigation flow",
accentColor: MaterialColors.lightPrimary
)
}
.buttonStyle(ModernCardButtonStyle())

// 🎯 対象ボタン: 区間コントロール機能カード
Button(action: {
// 🎯 クリックリスナー: ここでボタンアクションが定義されます
// ユーザーがボタンをクリックすると実行されるコードです
// 現在: navigationManager.navigateWithDelay(to: .sectionControlSection1)
// これをNetFUNNEL保護で包みます
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}) {
// 🎨 ボタン外観: これがボタンがどのように見えるかを定義します
ModernCard(
icon: "list.bullet.circle.fill",
title: "Section Control",
subtitle: "Code-based Integration",
description: "Multi-step navigation flow",
accentColor: MaterialColors.lightSecondary
)
}
.buttonStyle(ModernCardButtonStyle())
}
.padding(.horizontal, 20)

Spacer(minLength: 40)
}
}
// 追加UI修飾子は簡潔性のために省略
// ... background, frame, navigationBarHiddenなど ...
}
}

核心ポイント:

  • クリックリスナー位置: Button(action:)クロージャ内部
  • 現在のアクション: navigationManager.navigateWithDelay(to: .sectionControlSection1)が即座に実行されます
  • 統合対象: ここにNetFUNNEL保護を追加します

2.3 クリックリスナー内部で起こっていること確認

関数が行うこと:

// NavigationManager.swift
func navigateWithDelay(to destination: NavigationDestination, customDelay: TimeInterval? = nil) {
let delay = customDelay ?? appPreferences.getNavigationDelay()

loadingDialogManager.showLoading() // ← ローディング表示器表示

DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
self.loadingDialogManager.hideLoading() // ← ローディング表示器非表示
self.navigate(to destination) // ← 対象画面に移動
}
}

要約: ローディング表示 → 待機 → ローディング非表示 → 移動。これはサーバー処理をシミュレートし、NetFUNNEL保護が必要です。

2.4 統合ポイント識別

  1. 対象ボタン: MainViewの"Section Control"ボタン(マルチステッププロセスボタン)
  2. クリックリスナー: Button(action:)クロージャがクリックハンドラーを設定します
  3. 統合位置: navigationManager.navigateWithDelay()が呼び出される直前
  4. ここで行う理由: これは区間進入が開始される直前の正確な瞬間です
  5. 保護戦略: 区間進入前にNetFUNNEL区間キューを追加します

全体フロー分析:

  1. ビュー作成: MainView bodyがボタンを作成します
  2. ボタン設定: Button(action:)がボタンのクリックハンドラーを設定します
  3. ユーザーアクション: ユーザーが"Section Control"ボタンをクリックします
  4. 現在の動作: navigationManager.navigateWithDelay()が即座に実行されます
  5. 区間ロード: これがマルチステップ区間プロセスへの進入をトリガーします

ロジック:

  • NetFUNNELなし: ボタンクリック → 即座に区間進入 → 潜在的な同時ユーザー数超過
  • NetFUNNEL使用: ボタンクリック → キュー確認 → 制御された区間進入 → 同時ユーザー数維持

3ステップ: キー発行関数実装(nfStartSection

コードに合わせて調整

以下の例はサンプルアプリケーションのボタンハンドラーにNetFUNNELを統合する方法を示します。このパターンを実際のコード構造に合わせて調整してください - 保護が必要な他の関数名、イベントハンドラー、またはビジネスロジックがある場合があります。

3.1 キー取得

まずコンソールでプロジェクトキーとセグメントキーを見つけてください:

  1. NetFUNNELコンソール → プロジェクトセグメントに移動します
  2. セグメントをクリックします
  3. プロジェクトキーセグメントキーをコピーします

区間コントロールプロジェクトおよびセグメントキー

3.2 nfStartSection関数理解

nfStartSection関数は以下のような基本構造を持ちます:

Netfunnel.shared.nfStartSection(
projectKey: "your_project_key", // コンソールから取得
segmentKey: "your_segment_key" // コンソールから取得
)
APIリファレンス

nfStartSectionパラメータ、デリゲート処理、応答形式の詳細についてはAPIリファレンスを参照してください。

3.3 現在のコードから開始

現在の実装:

// MainView.swift
Button(action: {
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}) {
ModernCard(
icon: "list.bullet.circle.fill",
title: "Section Control",
subtitle: "Code-based Integration",
description: "Multi-step navigation flow",
accentColor: MaterialColors.lightSecondary
)
}
.buttonStyle(ModernCardButtonStyle())

核心概念:

  • ビジネスロジック: navigationManager.navigateWithDelay(to: .sectionControlSection1)はマルチステップ区間への進入を表します
  • 統合ポイント: この区間進入をNetFUNNEL保護で包む必要があります
  • 包む戦略: マルチステッププロセスが開始される前にnfStartSection()を使用して同時ユーザー数を制御します

ここで包む理由:

  • これは区間進入が開始される直前の正確な瞬間です
  • ここで包むと全体のマルチステップ区間が同時ユーザー数超過から保護されます
  • ビジネスロジックは変更されません - 同時ユーザー数制御レイヤーのみ追加します

3.4 必要なimport追加

NetFUNNELを実装する前にSwiftUI Viewに必要なimportを追加してください:

// MainView.swift
import Netfunnel_iOS

核心Import:

  • Netfunnel_iOS - メインNetFUNNELフレームワーク

3.5 基本NetFUNNEL保護追加(成功のみ)

NetfunnelHandler既に作成済み

インストールおよび初期化ステップで既にNetfunnelHandler.swiftが必要です。 まだそのステップを完了していない場合は戻ってまず完了してください。

ビジネスロジックを包む:

// MainView.swift
import SwiftUI
import Netfunnel_iOS

struct MainView: View {
@StateObject private var navigationManager = NavigationManager.shared

var body: some View {
ScrollView {
VStack(spacing: 0) {
// Hero Sectionは簡潔性のために省略
// ... 既存のUI構造 ...

// Cards Section
VStack(spacing: 20) {
// Basic Control機能カード
Button(action: {
navigationManager.navigateWithDelay(to: .basicControl)
}) {
ModernCard(
icon: "arrow.right.circle.fill",
title: "Basic Control",
subtitle: "Code-based Integration",
description: "Simple linear navigation flow",
accentColor: MaterialColors.lightPrimary
)
}
.buttonStyle(ModernCardButtonStyle())

// 区間コントロール機能カード - NetFUNNELで保護済み
Button(action: {
startSectionControl() // NetFUNNEL保護関数呼び出し
}) {
ModernCard(
icon: "list.bullet.circle.fill",
title: "Section Control",
subtitle: "Code-based Integration",
description: "Multi-step navigation flow",
accentColor: MaterialColors.lightSecondary
)
}
.buttonStyle(ModernCardButtonStyle())
}
.padding(.horizontal, 20)

Spacer(minLength: 40)
}
}
// 追加UI修飾子は簡潔性のために省略
// ... background, frame, navigationBarHiddenなど ...
.onAppear {
setupCallbacks()
}
}

private func setupCallbacks() {
// NetFUNNEL応答に対するコールバッククロージャ設定
NetfunnelHandler.shared.onSuccess = { projectKey, segmentKey, statusCode, message in
NSLog("onSuccess \(statusCode) \(message)")
// NetFUNNELが進入を許可するとき元のビジネスロジック実行
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}

NetfunnelHandler.shared.onError = { projectKey, segmentKey, statusCode, message in
NSLog("onError \(statusCode) \(message)")
}

NetfunnelHandler.shared.onNetworkError = { projectKey, segmentKey, statusCode, message in
NSLog("onNetworkError \(statusCode) \(message)")
}

NetfunnelHandler.shared.onBlock = { projectKey, segmentKey, statusCode, message in
NSLog("onBlock \(statusCode) \(message)")
}

NetfunnelHandler.shared.onClose = { projectKey, segmentKey, statusCode, message in
NSLog("onClose \(statusCode) \(message)")
}

NetfunnelHandler.shared.onContinue = { projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate in
NSLog("onContinue \(statusCode) \(message)")
}
}

private func startSectionControl() {
// NetFUNNEL区間キュー保護開始
Netfunnel.shared.nfStartSection(
projectKey: "your_project_key",
segmentKey: "your_segment_key"
)
}

// 色計算プロパティは簡潔性のために省略
// private var backgroundColor: Color { ... }
}

変更事項:

  • 包む: navigationManager.navigateWithDelay()が今はonSuccessコールバック内部にあります
  • 条件付き: 特定のボタンのみNetFUNNEL保護を受けます
  • 成功のみ: NetFUNNELが進入を許可するときのみビジネスロジックが実行されます
  • 完全なインターフェース: すべての必須デリゲートメソッドが適切なロギングと共に実装されました
iOSデリゲート要件

iOSではNetfunnelDelegateはすべてのメソッドを実装する必要があります。 onSuccessのみ実装することはできません - すべてのデリゲートメソッドに対する実装を提供する必要があります。この実装はすべての応答タイプに対する適切なロギングと共に完全なデリゲート処理を提供します。

今実装をテストしてすべてが正しく動作することを確認してください。

アプリを実行し、"Section Control (Code-based Integration)"ボタンをクリックしてください。画面に待合室WebViewが表示されるはずです。すべてが正しく動作していることを確認するにはXcodeコンソールでNetFUNNELログを確認してください。

待合室が表示されない場合

待合室が見えない場合はセグメント構成ステップで進入許容数を0に設定したか確認してください。この設定はユーザーが待合室に送られるか、または直接進行できるかを制御します。

より良いデバッグのためにNetFUNNELロギング有効化:

AppDelegate初期化でprintLog = trueを設定してデバッグロギングを有効化し、次にXcodeコンソールを確認してください。詳細な設定手順についてはNetFUNNEL初期化テスト)セクションを参照してください。

確認事項:

進入許容数 = 0でSection Controlボタンをクリックすると以下のようなログが表示されます:

[NF4] [2025-09-19 16:56:42.832] Initialization successful. NetFUNNEL Version: 4.3.2-onprem
[NF4] [2025-09-19 16:56:58.500] Sending initialEntry request: https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5101&sid=service_1&aid=segKey_2548
[NF4] [2025-09-19 16:56:58.651] Received initialEntry response: Response(timestamp: Optional(1758268618669), code: 201, key: Optional("A5E68F1AB764D05967A41DB8161C611D0952823AE901BA73FA347E320385E354A8FC7C43E5D15069EEB8F9252A1DFC79BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B706CFFE9F9934671086EDABAE8FEDFA67722C312C302C302C302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(1), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(0), waitOrderYn: Optional(0), msg: nil, vwrType: Optional("wait"))
[NF4] [2025-09-19 16:56:59.282] Fetching HTML content from following URL. https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html
[NF4] [2025-09-19 16:56:59.512] Sending reentry request: https://nf4-onprem-demo-4525.stclab.com:443/ts.wseq?opcode=5002&key=A5E68F1AB764D05967A41DB8161C611D0952823AE901BA73FA347E320385E354A8FC7C43E5D15069EEB8F9252A1DFC79BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B706CFFE9F9934671086EDABAE8FEDFA67722C312C302C302C302C302C30&sticky=nf1
[NF4] [2025-09-19 16:56:59.563] Received reentry response: Response(timestamp: Optional(1758268619604), code: 201, key: Optional("A5E68F1AB764D05967A41DB8161C611D462C3B2234ABB4D5F3283A4F82C0952F7F82C9A3B775DE797F13B051D1E06451BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B70694D7C8E4BEA05A019FF78476D2CEAF2F2C312C302C302C302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(1), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(0), waitOrderYn: Optional(0), msg: nil, vwrType: Optional("wait"))

すべてが動作中であることを示す核心指標:

ログメッセージ意味状態
[NF4] Initialization successfulNetFUNNELエージェントが正しくロードされた✅ 良好
[NF4] Sending initialEntry requestnfStartSection()が正常に呼び出された、NetFUNNELサーバーにリクエスト送信された✅ 良好
[NF4] Received initialEntry response with code: 201サーバーがWAIT状態で応答した✅ 良好
[NF4] Fetching HTML content待合室WebViewがロード中、待合室HTMLがロードされている✅ 良好
[NF4] Sending reentry request周期的再進入リクエスト(ポーリング)✅ 良好
[NF4] Received reentry response with code: 201サーバーがWAIT状態で応答した✅ 良好

応答確認:

  • ログでts.wseq?opcode=5002リクエストを見つけてください
  • 応答がcode=201(WAIT)を表示するか確認してください
  • 201 = WAIT, 200 = PASS(進入許可)
  • ここでは進入許容数が0(同時ユーザー数 = 0)なので正しい応答は201です

問題が発生する場合:

  • ログが表示されない: 初期化でprintLog = trueが設定されているか確認してください
  • 待合室がない: コンソールで進入許容数が0に設定されているか確認してください
  • アプリクラッシュ: すべての必須デリゲートメソッドが正しく実装されているか確認してください
  • ネットワークエラー: サーバーURLとネットワーク接続を確認してください

待合室とログが見えれば基本実装が動作しています!今より良いエラー管理のためにデリゲート処理を向上させることができます。進入をテストするにはコンソールで進入許容数を1(同時ユーザー数 = 1)に変更してください。

3.6 完全なコールバック処理追加

今より良いエラー管理とユーザー体験のためにコールバック処理を改善します:

前のステップですべてのコールバックメソッドを基本ロギングで実装しました。今本番環境で強力なサービス可用性と最適なユーザー体験を保証するためにエラー処理を向上させます。

完全なコールバック処理が必須である理由:

  • ユーザー体験: 異なる応答タイプに適切なユーザーフィードバックが必要です
  • サービス安定性: エラー状態がユーザーのワークフローを中断してはいけません
  • デバッグ: 包括的なロギングが問題を迅速に識別するのに役立ちます
  • ビジネス継続性: NetFUNNELに問題が発生してもサービスが継続する必要があります

強力なエラー処理でsetupCallbacks向上:

// MainView.swift - 完全な処理が含まれた更新されたsetupCallbacks
private func setupCallbacks() {
NetfunnelHandler.shared.onSuccess = { projectKey, segmentKey, statusCode, message in
// ユーザーが進行できる - 元のロジック実行
NSLog("onSuccess \(statusCode) \(message)")
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}

NetfunnelHandler.shared.onError = { projectKey, segmentKey, statusCode, message in
// システムエラー発生 - 強力なサービス可用性のために元のロジック進行
NSLog("onError \(statusCode) \(message)")
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}

NetfunnelHandler.shared.onNetworkError = { projectKey, segmentKey, statusCode, message in
// ネットワークエラー発生 - デバッグのためにログのみ残し、ビジネスロジックは実行しない
NSLog("onNetworkError \(statusCode) \(message)")
// 注意: ここではビジネスロジックを実行しない - 以下の説明を参照
}

NetfunnelHandler.shared.onBlock = { projectKey, segmentKey, statusCode, message in
// ユーザーがブロックされた - 適切なメッセージ表示
NSLog("onBlock \(statusCode) \(message)")
}

NetfunnelHandler.shared.onClose = { projectKey, segmentKey, statusCode, message in
// ユーザーが待合室を閉じた - 適切に処理
NSLog("onClose \(statusCode) \(message)")
// メイン画面に維持 - ユーザーがキャンセルした
}

NetfunnelHandler.shared.onContinue = { projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate in
NSLog("onContinue \(statusCode) \(message)")
}
}

応答処理戦略:

応答タイプアクションビジネスロジック
Success実行✅ はい
Error実行✅ はい
NetworkErrorログのみ❌ いいえ
Blockログのみ❌ いいえ
Closeログのみ❌ いいえ
Continueログのみ❌ いいえ

onErrorはビジネスロジックを実行するがonNetworkErrorは実行しない理由:

onError(ステータスコード500)- サーバーエラー:

  • シナリオ: NetFUNNELサーバーが内部エラーに遭遇
  • 戦略: サービス可用性を維持するためにビジネスロジック実行
  • 根拠: サーバーエラーは一般的に一時的であり、ユーザーアクセスをブロックすべきではない
  • 結果: NetFUNNELに問題があっても継続動作する強力なサービス

onNetworkError(ステータスコード1001, 1002)- ネットワーク問題:

  • シナリオ: ネットワーク接続問題(オフライン、タイムアウト)
  • 戦略: ログのみ残し、ビジネスロジックは実行しない
  • 根拠: 自動ネットワーク回復のためにuseNetworkRecoveryMode = true使用
  • 結果: ネットワーク問題中はユーザーが待合室に留まり、接続が回復すると自動的に再開される

ネットワーク回復モード構成:

最適なネットワークエラー処理のためにAppDelegateでネットワーク回復を有効化してください:

// AppDelegate.swift
Netfunnel.initialize(
clientId: "{{CLIENT_ID}}",
delegate: NetfunnelHandler.shared, // selfではなくNetfunnelHandler使用
useNetworkRecoveryMode: true // 自動ネットワーク回復有効化
)

変更事項:

  • 強力なエラー処理: onErrorは最大サービス可用性のためにビジネスロジックを進行します
  • スマートネットワーク処理: onNetworkErrorは手動処理ではなくネットワーク回復モードに依存します
  • 向上したユーザー体験: 異なる応答状態のより良い処理
  • 本番準備: 強力なエラー処理がNetFUNNELに問題があってもサービスが継続することを保証します
  • 包括的なロギング: すべての応答タイプおよびデバッグに対する詳細なコンソールメッセージ
完全なAPIリファレンス

すべてのデリゲート応答タイプ、ステータスコード、応答オブジェクト構造、および高度なコールバックパターンの詳細情報についてはAPIリファレンスを参照してください。

3.7 核心実装ポイント

  1. プロジェクト/セグメントキー: NetFUNNELコンソールから正確なキー使用
  2. 必須import: Netfunnel_iOS import追加
  3. デリゲート実装: すべてのコールバックメソッド実装(NetfunnelDelegate要件)
  4. 強力なエラー処理:
    • onSuccessonErrorはサービス可用性のためにビジネスロジックを実行します
    • onNetworkErrorはログのみ残します(自動回復のためにuseNetworkRecoveryMode = true使用)
  5. ビューライフサイクル: 初期化およびUI更新にonAppear使用
  6. 包括的なロギング: デバッグのためにすべてのデリゲート応答ロギング

6ステップ: 待合室テスト(進入許容数 = 0)

アプリケーションでテスト

以下のテストステップはサンプルアプリケーションに基づいています。テストプロセスを実際のアプリケーションに合わせて調整してください - ボタン名、Viewナビゲーション、確認ステップを特定の実装に合わせて置き換えてください。

6.1 アクショントリガー

  1. Xcodeコンソールログクリア(クリーンな状態で観察したい場合)

    • Xcodeでコンソールのゴミ箱アイコンをクリックして以前のログをクリア
    • またはCmd+Kを使用してコンソールクリア
  2. 保護されたボタンクリック(例: "Section Control (Code-based Integration)"ボタン)

予想結果: 待合室WebViewが現在の画面に表示される

クリック前iOSメイン画面 区間コントロールiOS待合室WebView

6.2 待合室表示確認

以下の要素が正しく表示されているか確認してください:

進入許容数が0に設定され、1人のユーザーのみ接続されている場合確認:

  • 私の待機順序: 1
  • 予想待機時間: 表示されない(区間コントロールのみ)
  • 私の後ろの待機者数: 0
区間コントロール vs 基本コントロール待合室

区間コントロールは既に区間にいるユーザーの完了時間が多様で予測が困難なため、予想待機時間を表示しません。進入が迅速で予測可能な基本コントロールとは異なり、区間コントロールユーザーはマルチステッププロセスを完了するのに多様な時間を消費する可能性があります。

区間コントロールiOS待合室WebView

6.3 Xcodeコンソール活動確認

NetFUNNELログ確認:

AppDelegateでprintLog = trueを設定してデバッグロギングを有効化し、次にXcodeコンソールを確認してください。以下のようなログが表示されるはずです:

[NF4] [2025-09-19 16:56:42.832] Initialization successful. NetFUNNEL Version: 4.3.2-onprem
[NF4] [2025-09-19 16:56:58.500] Sending initialEntry request: https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5101&sid=service_1&aid=segKey_2548
[NF4] [2025-09-19 16:56:58.651] Received initialEntry response: Response(timestamp: Optional(1758268618669), code: 201, key: Optional("A5E68F1AB764D05967A41DB8161C611D0952823AE901BA73FA347E320385E354A8FC7C43E5D15069EEB8F9252A1DFC79BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B706CFFE9F9934671086EDABAE8FEDFA67722C312C302C302C302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(1), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(0), waitOrderYn: Optional(0), msg: nil, vwrType: Optional("wait"))
[NF4] [2025-09-19 16:56:59.282] Fetching HTML content from following URL. https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html
[NF4] [2025-09-19 16:56:59.512] Sending reentry request: https://nf4-onprem-demo-4525.stclab.com:443/ts.wseq?opcode=5002&key=A5E68F1AB764D05967A41DB8161C611D0952823AE901BA73FA347E320385E354A8FC7C43E5D15069EEB8F9252A1DFC79BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B706CFFE9F9934671086EDABAE8FEDFA67722C312C302C302C302C302C30&sticky=nf1
[NF4] [2025-09-19 16:56:59.563] Received reentry response: Response(timestamp: Optional(1758268619604), code: 201, key: Optional("A5E68F1AB764D05967A41DB8161C611D462C3B2234ABB4D5F3283A4F82C0952F7F82C9A3B775DE797F13B051D1E06451BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B70694D7C8E4BEA05A019FF78476D2CEAF2F2C312C302C302C302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(1), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(0), waitOrderYn: Optional(0), msg: nil, vwrType: Optional("wait"))
... (code: 201で繰り返しポーリング) ...

すべてが動作中であることを示す核心指標:

ログメッセージ意味状態
[NF4] Initialization successfulNetFUNNELエージェントが正しくロードされた✅ 良好
[NF4] Sending initialEntry requestnfStartSection()が正常に呼び出された、NetFUNNELサーバーに初期進入リクエスト送信された✅ 良好
[NF4] Received initialEntry response with code: 201サーバーがWAIT状態で応答した✅ 良好
[NF4] Received reentry response with code: 201サーバーがWAIT状態で応答した✅ 良好
[NF4] Fetching HTML content待合室WebViewがロード中、待合室HTMLがロードされている✅ 良好
[NF4] Sending reentry request周期的再進入リクエスト(ポーリング)✅ 良好
[NF4] Received reentry response with code: 201サーバーがWAIT状態で応答した✅ 良好

応答確認:

  • ログでts.wseq?opcode=5002リクエストを見つけてください
  • 応答がcode=201(WAIT)を表示するか確認してください
  • 201 = WAIT, 200 = PASS(進入許可)
  • ここでは進入許容数が0(同時ユーザー数 = 0)なので正しい応答は201です

7ステップ: 区間進入テスト(進入許容数 = 1)

7.1 セグメント設定更新

  1. NetFUNNELコンソールに戻る
  2. セグメントの編集ボタンをクリックして編集画面を開く

区間コントロールNetFUNNELコンソール編集セグメントボタン

  1. 進入許容数0から1に変更
  2. 下部の確認をクリック

区間コントロール進入許容数更新 区間コントロール変更確認

即座に効果

確認をクリックするとすぐに待合室が消え、即座にSectionControlSection1Viewに移動します。この瞬間を観察するには待合室が現在表示されている別の画面を開いておいてください。

7.2 区間進入確認

予想結果: 待合室が即座に消え、SectionControlSection1Viewに移動する

iOS区間進入成功 - Section 1

進入確認のためにXcodeコンソール確認:

以下のようなログが表示されるはずです:

[NF4] [2025-09-19 16:57:06.903] Received reentry response: Response(timestamp: Optional(1758268626936), code: 200, key: Optional("A5E68F1AB764D05967A41DB8161C611DD2AA40A9437F4974D770B5C0AA132C311128743E2F216A772B70073896EB3DB127202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A08001715A51C76F286957F8DE56D6092043B1302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(0), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(1), waitOrderYn: Optional(0), msg: nil, vwrType: Optional(""))
[NF4] [2025-09-19 16:57:06.905] Sending key refresh request: https://nf4-onprem-demo-4525.stclab.com:443/ts.wseq?opcode=5003&key=A5E68F1AB764D05967A41DB8161C611DD2AA40A9437F4974D770B5C0AA132C311128743E2F216A772B70073896EB3DB127202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A08001715A51C76F286957F8DE56D6092043B1302C302C30&sticky=nf1
[NF4] [2025-09-19 16:57:06.949] Received refreshKey response. code=201, key=Optional("A5E68F1AB764D05967A41DB8161C611DD2AA40A9437F4974D770B5C0AA132C311128743E2F216A772B70073896EB3DB127202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A08001715A51C76F286957F8DE56D6092043B1312C302C30")

成功した区間進入の核心指標:

ログメッセージ意味状態
[NF4] Received reentry response with code=200進入許可された - 待合室が閉じられるはず✅ 良好
[NF4] Sending key refresh request区間コントロール: キータイムアウト拡張リクエスト送信された(5003)✅ 良好
[NF4] Received refreshKey response with code=201区間コントロール: キータイムアウトが正常に拡張された✅ 良好

7.3 区間ナビゲーションテスト

区間フローをナビゲートしてください:

  1. Section1 → Section2 → End: マルチステップ区間プロセス完了
  2. 各ステップが正しく動作するか確認: View間のスムーズなナビゲーション保証
  3. タイムアウト拡張ログ確認: 区間中周期的な5003リクエスト検索
iOS区間ナビゲーション - Section 2

予想動作:

  • ユーザーが区間内で自由にナビゲートできる(Section1 → Section2 → End)
  • NetFUNNELが区間中にキータイムアウトを自動的に拡張する(5003リクエスト)
  • 明示的完了まで同時ユーザー数が維持される

7.4 キー返却確認

成功したキー返却確認:

iOS区間完了 - End

End Viewに到達したときにXcodeコンソールで次のログを見つけてください:

[NF4] [2025-09-19 16:57:14.199] Sending returnKey request: https://nf4-onprem-demo-4525.stclab.com:443/ts.wseq?opcode=5004&key=A5E68F1AB764D05967A41DB8161C611D7F3D0E71CEF0573FF58477D0DD6D83AA1366D3C88161ABC35A8FE1E1DA92B83B27202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1312C302C30&sticky=nf1
[NF4] [2025-09-19 16:57:14.236] Received returnKey response. code=200, key=Optional("A5E68F1AB764D05967A41DB8161C611D7F3D0E71CEF0573FF58477D0DD6D83AA1366D3C88161ABC35A8FE1E1DA92B83B27202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1312C302C30")

成功したキー返却の核心指標:

ログメッセージ意味状態
[NF4] Sending returnKey requestnfStopSection()が呼び出された(5004)✅ 良好
[NF4] Received returnKey response with code=200キー返却成功✅ 良好

要約

必須事項(必ず実行)

設定:

  • インストールおよび初期化完了およびNetFUNNELエージェントが正しくロードされているか確認
  • コンソールで区間コントロールでセグメント作成
  • コンソールでプロジェクトキーとセグメントキー取得
  • テストのために進入許容数を0に、本番のために1以上に設定

統合:

  • 必須import追加: Netfunnel_iOSおよびNetfunnelDelegate
  • すべてのデリゲートメソッド実装(iOSプロトコル要件)
  • ボタンハンドラーでNetfunnel.shared.nfStartSection()で区間進入を包む
  • onSuccessデリゲートを処理して区間進入ロジック実行
  • 区間完了後Netfunnel.shared.nfStopSection()呼び出し
  • nfStartSection()nfStopSection()の両方で同一のキー使用

エラー処理:

  • onErrorを処理して区間進入進行(サービス可用性維持)
  • onNetworkErrorをロギングのみ処理(useNetworkRecoveryMode = true使用)
  • onBlockを適切なユーザーメッセージ表示で処理
  • onCloseを現在のビューコントローラーに維持で処理(ユーザーがキャンセルした)
  • すべてのデリゲート応答に対する包括的なロギング実装

テスト:

  • 進入許容数 = 0で待合室が表示されるかテスト
  • 進入許容数 = 1で進入が動作するかテスト
  • 区間完了後キー返却が発生するか確認
  • XcodeコンソールでNetFUNNELログ確認

オプション(あれば良い)

エラー処理向上:

  • 基本ロギングではなくユーザーフレンドリーなエラーメッセージ追加
  • 異なる応答タイプに対するカスタムエラー処理戦略実装
  • NetFUNNELイベントに対する分析追跡追加

コード構成:

  • 中央集約式構成定数作成
  • 再利用可能なNetFUNNELラッパー関数構築
  • 複数のビューコントローラーにわたるモジュール式統合パターン実装

ベストプラクティス

必須Import

import Netfunnel_iOS

これらのimportが重要な理由:

  • NetFUNNEL統合に必須
  • NetFUNNELを使用するすべてのViewに追加する必要がある
  • nfStartSection()およびnfStopSection()関数の両方に必要

完全なコールバック実装

private func setupCallbacks() {
NetfunnelHandler.shared.onSuccess = { projectKey, segmentKey, statusCode, message in
NSLog("onSuccess \(statusCode) \(message)")
// NetFUNNELが進入を許可するとき元のビジネスロジック実行
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}

NetfunnelHandler.shared.onError = { projectKey, segmentKey, statusCode, message in
NSLog("onError \(statusCode) \(message)")
// システムエラー発生 - 強力なサービス可用性のために元のロジック進行
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}

NetfunnelHandler.shared.onNetworkError = { projectKey, segmentKey, statusCode, message in
NSLog("onNetworkError \(statusCode) \(message)")
// ネットワークエラー発生 - デバッグのためにログのみ残し、ビジネスロジックは実行しない
}

NetfunnelHandler.shared.onBlock = { projectKey, segmentKey, statusCode, message in
NSLog("onBlock \(statusCode) \(message)")
// ユーザーがブロックされた - 適切なメッセージ表示
}

NetfunnelHandler.shared.onClose = { projectKey, segmentKey, statusCode, message in
NSLog("onClose \(statusCode) \(message)")
// ユーザーが待合室を閉じた - 適切に処理
}

NetfunnelHandler.shared.onContinue = { projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate in
NSLog("onContinue \(statusCode) \(message)")
// 待機進行情報更新
}
}

核心原則: 常にすべてのコールバックメソッドを実装してください - NetfunnelDelegate要件です。

中央集約式構成

// キーを1箇所に保存
struct NetFunnelConfig {
static let projectKey = "your_project_key"
static let segmentKey = "your_segment_key"
}

// すべての場所で同一の構成使用
Netfunnel.shared.nfStartSection(
projectKey: NetFunnelConfig.projectKey,
segmentKey: NetFunnelConfig.segmentKey
)

Netfunnel.shared.nfStopSection(
projectKey: NetFunnelConfig.projectKey,
segmentKey: NetFunnelConfig.segmentKey
)

利点:

  • 全体のアプリでキーを簡単に更新
  • コピー&ペーストエラー減少
  • 構成に対する単一ソース

強力なエラー処理戦略

// onErrorはビジネスロジックを実行するがonNetworkErrorは実行しない理由:

NetfunnelHandler.shared.onError = { projectKey, segmentKey, statusCode, message in
NSLog("onError \(statusCode) \(message)")
// シナリオ: NetFUNNELサーバーが内部エラーに遭遇
// 戦略: サービス可用性を維持するためにビジネスロジック実行
// 根拠: サーバーエラーは一般的に一時的であり、ユーザーアクセスをブロックすべきではない
// 結果: NetFUNNELに問題があっても継続動作する強力なサービス
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}

NetfunnelHandler.shared.onNetworkError = { projectKey, segmentKey, statusCode, message in
NSLog("onNetworkError \(statusCode) \(message)")
// シナリオ: ネットワーク接続問題(オフライン、タイムアウト)
// 戦略: ログのみ残し、ビジネスロジックは実行しない
// 根拠: 自動ネットワーク回復のためにuseNetworkRecoveryMode = true使用
// 結果: ネットワーク問題中はユーザーが待合室に留まり、接続が回復すると自動的に再開される
}

核心原則: サービス可用性を維持するためにシステムエラーでは常にビジネスロジックを進行してください。

ネットワーク回復モード構成

// AppDelegate.swift
Netfunnel.initialize(
clientId: "{{CLIENT_ID}}",
delegate: NetfunnelHandler.shared, // selfではなくNetfunnelHandler使用
useNetworkRecoveryMode: true // 自動ネットワーク回復有効化
)

利点:

  • ネットワーク接続問題自動処理
  • ネットワークが回復するとユーザーが自動的に再開
  • 手動ネットワークエラー処理の複雑性減少

常にキー返却

// 成功した作業後キー返却
struct SectionControlEndView: View {
var body: some View {
VStack {
// UIコンテンツ
}
.onAppear {
// SwiftUIビューが完全にロードされるときキー返却
Netfunnel.shared.nfStopSection(
projectKey: NetFunnelConfig.projectKey,
segmentKey: NetFunnelConfig.segmentKey
)
}
}
}

キーを返却するとき:

  • SwiftUI Viewが完全にロードされた後
  • 区間完了後(Section1 → Section2 → End)
  • ビジネス作業完了後
  • 作業が失敗した場合でも

キー一致

// 開始と終了は同一のキーを使用する必要がある
let projectKey = "your_project_key"
let segmentKey = "your_segment_key"

Netfunnel.shared.nfStartSection(
projectKey: projectKey,
segmentKey: segmentKey
)

Netfunnel.shared.nfStopSection(
projectKey: projectKey, // 正確に一致する必要がある
segmentKey: segmentKey // 正確に一致する必要がある
)

包括的なロギング

// AppDelegateでデバッグロギング有効化
Netfunnel.initialize(
clientId: "{{CLIENT_ID}}",
delegate: NetfunnelHandler.shared, // selfではなくNetfunnelHandler使用
printLog: true // 詳細なロギング有効化
)

// Xcodeコンソールでログ確認

ロギング利点:

  • NetFUNNEL統合問題を簡単にデバッグ
  • リクエスト/応答フロー追跡
  • キー返却作業モニタリング
  • ネットワーク接続問題識別

一般的な問題およびトラブルシューティング

待合室が表示されない

症状: ボタンクリックは正常に動作するが待合室が表示されない

デバッグステップ:

  1. XcodeコンソールでiOSエラー確認: ⌘+Shift+Y → "Error"でフィルタリング
  2. AppDelegateでNetFUNNEL初期化確認
  3. コンソールでセグメントが有効化されているか確認(無効化されていない)
  4. テストのために進入許容数が0に設定されているか確認
  5. プロジェクトキーとセグメントキーがコンソールと正確に一致しているか確認(大文字小文字区別)

デリゲートが実行されない

症状: nfStartSection()が呼び出されたが応答を受け取れない

デバッグステップ:

  1. XcodeコンソールでNetFUNNELログ確認: "NetFUNNEL"でフィルタリング
  2. NetFUNNELサーバーへのネットワーク接続確認
  3. セグメントが有効化されているか確認(無効化されていない)
  4. 待合室を強制するために進入許容数 = 0で試行
  5. すべてのコールバックメソッドが実装されているか確認(NetfunnelDelegate要件)

ユーザーがキューに閉じ込められる

症状: 最初のユーザーは進入するが2番目のユーザーは通過しない

デバッグステップ:

  1. 区間完了後nfStopSection()が呼び出されているか確認
  2. nfStopSection()のキーがnfStartSection()と正確に一致しているか確認
  3. nfStopSection()実行を妨げるiOSエラー検索
  4. Xcodeコンソールで[NF4] Sending returnKey requestログ確認
  5. ログに[NF4] Sending returnKey requestが表示されるか確認

待合室が表示されるが進入を許可しない

症状: 待合室が表示されるがユーザーが通過しない、進入許容数 = 1の場合でも

デバッグステップ:

  1. コンソールでセグメント状態確認 - "Block"モードではないか確認
  2. 進入許容数が1以上に設定されているか確認
  3. Xcodeコンソールで[NF4] Sending reentry request確認(再進入リクエスト)
  4. NetFUNNELログでエラー応答検索
  5. NetFUNNELサーバーへのネットワーク接続確認

NetFUNNEL呼び出し時アプリクラッシュ

症状: nfStartSection()またはnfStopSection()呼び出し時アプリクラッシュ

デバッグステップ:

  1. 必須importが追加されているか確認: Netfunnel_iOS
  2. AppDelegateでNetFUNNELが初期化されているか確認
  3. すべてのコールバックメソッドが実装されているか確認(NetfunnelDelegate要件)
  4. 初期化でデリゲートが正しく設定されているか確認(NetfunnelHandler.shared
  5. NetFUNNELエージェントが正しくインストールされているか確認

キー返却失敗

症状: nfStopSection()が呼び出されたがキーが返却されない

デバッグステップ:

  1. nfStopSection()のキーがnfStartSection()と正確に一致しているか確認(大文字小文字区別)
  2. Xcodeコンソールで[NF4] Sending returnKey requestメッセージ確認
  3. ログで[NF4] Sending returnKey request検索
  4. [NF4] Received returnKey responsecode=200か確認
  5. nfStopSection()が適切なライフサイクルメソッドで呼び出されているか確認

区間タイムアウト問題

症状: 区間完了前にキーが自動的に返却される

デバッグステップ:

  1. NetFUNNELコンソール → セグメント → 高度設定 → タイムアウトでタイムアウト設定確認
  2. 区間持続時間がタイムアウト期間(基本20秒)を超えているか確認
  3. [NF4] Sending key refresh requestログ検索(キータイムアウト拡張)
  4. タイムアウトが期限切れになる前にnfStopSection()が呼び出されているか確認
  5. 区間ナビゲーションフローがタイムアウト期間内に完了するか確認

ネットワーク回復問題

症状: ネットワーク接続問題中ユーザーが閉じ込められる

デバッグステップ:

  1. AppDelegate初期化でuseNetworkRecoveryMode = true確認
  2. NetFUNNELサーバーへのネットワーク接続確認
  3. ネットワーク問題をシミュレートするために機内モードオン/オフでテスト
  4. XcodeコンソールでonNetworkErrorデリゲート呼び出しモニタリング
  5. onNetworkErrorがビジネスロジックを実行しないか確認(回復モードに依存)

QAチェックリスト

実装前確認

  • プロジェクトキー / セグメントキーがコンソールと正確に一致する(コンソールで再確認)
  • AppDelegateでNetFUNNELエージェントが正しく初期化された
  • 必須import追加された: Netfunnel_iOS
  • すべてのコールバックメソッド実装された(NetfunnelDelegate要件)

待合室テスト(進入許容数 = 0)

  • 進入許容数 = 0のとき待合室WebViewが正しく表示される
  • 待合室が正しい詳細を表示する:
    • 私の待機順序: 1
    • 予想待機時間: 表示されない(区間コントロールのみ)
    • 私の後ろの待機者数: 0
  • 待機中**[NF4] Sending reentry request**がXcodeコンソールに周期的に表示される
  • **[NF4] Received reentry responsecode=201 (WAIT)**を表示する

区間進入テスト(進入許容数 = 1)

  • 進入許容数を1に変更するときonSuccessコールバックが実行される
  • onSuccessコールバックが元の区間進入ロジックを実行する
  • 進入時待合室が即座に消える
  • SectionControlSection1Viewへのナビゲーションが正常に発生する

区間ナビゲーションテスト

  • 区間ナビゲーションが正しく動作する(Section1 → Section2 → End)
  • キータイムアウト拡張が自動的に発生する(5003リクエスト)
  • **[NF4] Sending key refresh request**が区間中周期的に表示される
  • **[NF4] Received refreshKey responsecode=201**を表示する
  • 明示的完了まで同時ユーザー数が維持される

キー返却確認

  • 区間完了ポイントでキー返却が正しく動作する
  • **[NF4] Sending returnKey request**がXcodeコンソールに表示される
  • [NF4] Sending returnKey requestHTTP 200で発生する
  • **[NF4] Received returnKey responsecode=200**を表示する
  • キー返却がnfStartSection呼び出しごとに正確に1回発生する
  • キー返却が区間完了に発生する

エラー処理

  • すべての必須状態に対するコールバック分岐実装された:
    • onSuccess - 元のロジック実行
    • onError - システムエラーを適切に処理する(区間進入進行)
    • onNetworkError - ネットワーク問題を適切に処理する(ロギングのみ)
    • onBlock - ブロックされた状態を適切に処理する
    • onClose - ユーザーキャンセルを適切に処理する
    • onContinue - 待機進行を適切に処理する
  • AppDelegate初期化でネットワーク回復モード有効化された
  • キー一致 - nfStartSectionnfStopSectionprojectKey/segmentKeyが同一
  • すべてのデリゲート応答に対する包括的なロギング実装された

Xcodeコンソール確認

  • NetFUNNELログがXcodeコンソールに表示される("NetFUNNEL"でフィルタリング)
  • 初期化成功メッセージが表示される
  • ボタンクリック時初期進入リクエスト送信メッセージが表示される
  • HTMLコンテンツ取得メッセージが表示される
  • キーリフレッシュリクエスト送信メッセージが表示される(区間コントロール専用)
  • キー返却リクエスト送信メッセージが表示される
  • キー返却応答受信code=200で表示される

4ステップ: キー返却統合ポイント識別(nfStopSection

サンプルアプリケーション

次の例はデモ目的でサンプルアプリケーションを使用します。実際のアプリケーションコードはここに示されたものとは自然に異なります。統合パターンを特定のコード構造、ビジネスロジック完了ポイント、キー返却要件に合わせて調整してください。

💡 練習プロジェクトが必要ですか? NetFUNNEL SDK統合練習のための**iOSアプリケーション(単一ViewController)**テンプレートが準備されたサンプルプロジェクトを確認してください。

サンプルアプリケーション理解:

NetFUNNELキーを返却するためにnfStopSectionを呼び出す必要がある位置を理解するためにサンプルアプリケーションを見てみましょう。

4.1 区間完了ポイント識別

nfStartSection成功後の現在のフロー:

// 3ステップで - nfStartSectionが成功するとき
NetfunnelHandler.shared.onSuccess = { projectKey, segmentKey, statusCode, message in
NSLog("onSuccess \(statusCode) \(message)")
// NetFUNNELが進入を許可するとき元のビジネスロジック実行
navigationManager.navigateWithDelay(to: .sectionControlSection1)
}

次に起こること:

  1. ユーザーがSectionControlSection1Viewに移動 - プロセスの最初のステップ
  2. ユーザーがSectionControlSection2Viewに移動 - プロセスの2番目のステップ
  3. ユーザーがSectionControlEndViewに移動 - 最終完了ステップ
  4. ユーザーの区間セッションが完了 - ここでキーを返却する必要がある
  5. キーを返却する必要がある - キューの次のユーザーが区間に進入できるように

nfStopSection実装に関する重要な注意事項: nfStopSectionは最初にnfStartSectionを呼び出す必要なく独立して呼び出すことができます。nfStartSectionが呼び出されなかった場合、NetFUNNELは必要に応じてキー解放を自動的に処理するか、キーがなければ何も行いません。これによりnfStopSectionは条件付き確認なしでどのシナリオでも安全に呼び出すことができ、実装が単純になります。

4.2 キー返却のための統合ポイント識別

統合ポイントオプション:

統合ポイント使用時期利点
区間終了ビューマルチステップ完了フロー明確な完了ポイント、ほとんどの場合に動作
ビジネスロジック完了複雑な作業(API呼び出し、処理)精密な制御、実際の作業後にキー返却
ユーザーアクション完了ユーザー開始完了ユーザーが作業を完了するときにキー返却

4.3 適切な統合ポイント選択

サンプルアプリケーションの場合:

現在のビジネスフロー: マルチステップナビゲーションプロセス

  • 行うこと: ユーザーがSection1 → Section2 → Endを通過
  • 完了時点: SectionControlEndViewが正常に表示されるとき
  • 最適統合ポイント: SwiftUIビューライフサイクルイベント(onAppear, onDisappear)

統合戦略:

  1. 区間完了: SectionControlEndViewが表示されるときキー返却
  2. シンプルで信頼できる: ナビゲーションベースの区間フローに動作
  3. ユーザー体験: ユーザーが全体の区間を完了したときにキーが返却される

4.4 統合ポイントロジック確認

全体フロー分析:

  1. ユーザーがボタンクリックnfStartSection()呼び出された
  2. 待合室表示 → ユーザーがキューで待機
  3. 進入許可onSuccessデリゲート実行
  4. 区間ナビゲーション開始 → ユーザーがSection1 → Section2 → Endを進行
  5. SectionControlEndView表示 → ユーザーが区間を完了した
  6. キー返却必要 → 区間スロットを解放するためにnfStopSection()呼び出し

この統合ポイントが合理的である理由:

  • ユーザー体験: ユーザーが全体の区間を完了したときにキーが返却される
  • 同時ユーザー数管理: 現在のユーザーが区間を完了するとすぐに次のユーザーが進入できる
  • リソース効率: 不要な同時ユーザー数ブロックを防止
  • 実装単純性: 実装および保守が容易

核心洞察: nfStopSection統合ポイントはユーザーの意図した区間作業が実際に完了し、キューで待機していた区間使用を終えた位置である必要があります。

区間コントロール vs 基本コントロールキー管理

進入後迅速にキーを返却する基本コントロールとは異なり、区間コントロールは全体の区間が完了するまでキーを維持します。 この根本的な違いはnfStopSection()をいつ、どこで呼び出すべきかに影響を与えます:

  • 基本コントロール: 進入直後キー返却(例: ビューロード後)
  • 区間コントロール: 全体の区間中キー維持(例: Section1 → Section2 → End)

5ステップ: キー返却関数実装(nfStopSection

アプリケーションに合わせて調整

以下の例は区間が完了するときにキーを返却するさまざまなアプローチを示します。アプリケーションアーキテクチャに最も適したアプローチを選択してください - SwiftUIビューナビゲーション、API呼び出し、またはその他のビジネスロジック完了後にキーを返却する必要があるかどうかに応じて異なります。

5.1 nfStopSection関数理解

nfStopSection関数は以下のような基本構造を持ちます:

Netfunnel.shared.nfStopSection(
projectKey: "your_project_key", // nfStartSectionキーと正確に一致する必要がある
segmentKey: "your_segment_key" // nfStartSectionキーと正確に一致する必要がある
)

核心要件:

  • 正確なキー一致: キーはnfStartSection()で使用されたものと同一である必要があります
  • タイミング: nfStartSection()直後ではなく区間完了後呼び出し

5.2 必要なimport追加

nfStopSectionを実装する前にViewに必要なimportを追加してください:

import SwiftUI
import Netfunnel_iOS

核心Import:

  • Netfunnel_iOS - メインNetFUNNELフレームワーク(nfStartSectionに既にimport済み)

5.3 基本キー返却追加(SwiftUIビューライフサイクル)

SectionControlEndViewがロードされるときキー返却:

// SectionControlEndView.swift
import SwiftUI
import Netfunnel_iOS

struct SectionControlEndView: View {
@StateObject private var navigationManager = NavigationManager.shared

var body: some View {
VStack(spacing: 0) {
// 成功セクション
VStack(spacing: 24) {
// 成功アイコンおよびタイトルは簡潔性のために省略
// ... 成功UI要素 ...

Text("Section Control Complete")
.font(.system(size: 28, weight: .bold, design: .rounded))
.foregroundColor(primaryTextColor)
.multilineTextAlignment(.center)

Text("This is the completion page for Section Control (Code-based Integration).")
.font(.system(size: 16, weight: .regular, design: .rounded))
.multilineTextAlignment(.center)
.foregroundColor(secondaryTextColor)
.padding(.horizontal, 32)
}
.padding(.top, 60)
.padding(.bottom, 40)

Spacer()

// メインに戻るボタン
Button(action: {
navigationManager.navigateBackWithDelay()
}) {
Text("Back to Main")
}
.buttonStyle(ModernButtonStyle())
}
// 追加UI修飾子は簡潔性のために省略
// ... background, frame, navigationBarHiddenなど ...
.onAppear {
// SwiftUIビューが完全にロードされるときNetFUNNELキー返却
Netfunnel.shared.nfStopSection(
projectKey: "your_project_key",
segmentKey: "your_segment_key"
)
}
}

// 色計算プロパティは簡潔性のために省略
// private var backgroundColor: Color { ... }
// private var primaryTextColor: Color { ... }
// private var secondaryTextColor: Color { ... }
}

変更事項:

  • SwiftUIビューライフサイクル: SectionControlEndViewが完全にロードされるときキー返却
  • シンプルなアプローチ: 基本ナビゲーションシナリオに動作
  • 直接呼び出し: NetFUNNELが初期化され使用可能であると仮定

今キー返却実装をテストしてすべてが正しく動作することを確認してください。

アプリを実行し、次のテストシーケンスに従ってください:

  1. "Section Control (Code-based Integration)"ボタンクリック - 待合室が表示されるはず
  2. NetFUNNELコンソールで進入許容数を0から1に変更 - これは進入を許可する
  3. 待合室閉鎖観察 - 消えてSectionControlSection1Viewに移動するはず
  4. Section1 → Section2 → Endナビゲーション - 区間フロー完了
  5. Xcodeコンソールでキータイムアウト拡張ログ確認 - 区間中に5003リクエストログが見えるはず
  6. Xcodeコンソールでキー返却ログ確認 - 区間が完了するときに5004リクエストログが見えるはず

より良いデバッグのためにNetFUNNELロギング有効化:

AppDelegate初期化でprintLog = trueを設定してデバッグロギングを有効化し、次にXcodeコンソールを確認してください。詳細な設定手順についてはNetFUNNEL初期化テスト)セクションを参照してください。

確認事項:

区間フロー(Section1 → Section2 → End)を完了すると以下のようなログが表示されます:

[NF4] [2025-09-19 16:56:42.832] Initialization successful. NetFUNNEL Version: 4.3.2-onprem
[NF4] [2025-09-19 16:56:58.500] Sending initialEntry request: https://nf4-onprem-demo-4525.stclab.com/ts.wseq?opcode=5101&sid=service_1&aid=segKey_2548
[NF4] [2025-09-19 16:56:58.651] Received initialEntry response: Response(timestamp: Optional(1758268618669), code: 201, key: Optional("A5E68F1AB764D05967A41DB8161C611D0952823AE901BA73FA347E320385E354A8FC7C43E5D15069EEB8F9252A1DFC79BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B706CFFE9F9934671086EDABAE8FEDFA67722C312C302C302C302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(1), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(0), waitOrderYn: Optional(0), msg: nil, vwrType: Optional("wait"))
[NF4] [2025-09-19 16:56:59.282] Fetching HTML content from following URL. https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html
[NF4] [2025-09-19 16:56:59.512] Sending reentry request: https://nf4-onprem-demo-4525.stclab.com:443/ts.wseq?opcode=5002&key=A5E68F1AB764D05967A41DB8161C611D0952823AE901BA73FA347E320385E354A8FC7C43E5D15069EEB8F9252A1DFC79BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B706CFFE9F9934671086EDABAE8FEDFA67722C312C302C302C302C302C30&sticky=nf1
[NF4] [2025-09-19 16:56:59.563] Received reentry response: Response(timestamp: Optional(1758268619604), code: 201, key: Optional("A5E68F1AB764D05967A41DB8161C611D462C3B2234ABB4D5F3283A4F82C0952F7F82C9A3B775DE797F13B051D1E06451BCFD08B8F833299D4D743DBF3C84B6D4E168B227EF3E2A74958D7ED95766B70694D7C8E4BEA05A019FF78476D2CEAF2F2C312C302C302C302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(1), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(0), waitOrderYn: Optional(0), msg: nil, vwrType: Optional("wait"))
... (code: 201で繰り返しポーリング) ...
[NF4] [2025-09-19 16:57:06.903] Received reentry response: Response(timestamp: Optional(1758268626936), code: 200, key: Optional("A5E68F1AB764D05967A41DB8161C611DD2AA40A9437F4974D770B5C0AA132C311128743E2F216A772B70073896EB3DB127202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A08001715A51C76F286957F8DE56D6092043B1302C302C30"), nwait: Optional(0), nnext: Optional(0), tps: Optional(0.0), ttl: Optional(0), ip: Optional("nf4-onprem-demo-4525.stclab.com"), port: Optional(443), preBeginTs: nil, preEndTs: nil, postBeginTs: nil, postEndTs: nil, sticky: Optional("nf1"), vwrHtml: Optional("https://nf4-onprem-demo-4525.stclab.com/content/netfunnel-statics/assets/vwr-page/page/1/1/1/index.html"), liveMessage: nil, chkEnterCnt: Optional(1), waitOrderYn: Optional(0), msg: nil, vwrType: Optional(""))
[NF4] [2025-09-19 16:57:06.905] Sending key refresh request: https://nf4-onprem-demo-4525.stclab.com:443/ts.wseq?opcode=5003&key=A5E68F1AB764D05967A41DB8161C611DD2AA40A9437F4974D770B5C0AA132C311128743E2F216A772B70073896EB3DB127202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A08001715A51C76F286957F8DE56D6092043B1302C302C30&sticky=nf1
[NF4] [2025-09-19 16:57:06.949] Received refreshKey response. code=201, key=Optional("A5E68F1AB764D05967A41DB8161C611DD2AA40A9437F4974D770B5C0AA132C311128743E2F216A772B70073896EB3DB127202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A08001715A51C76F286957F8DE56D6092043B1312C302C30")
... (区間中繰り返されるキーリフレッシュサイクル) ...
[NF4] [2025-09-19 16:57:14.199] Sending returnKey request: https://nf4-onprem-demo-4525.stclab.com:443/ts.wseq?opcode=5004&key=A5E68F1AB764D05967A41DB8161C611D7F3D0E71CEF0573FF58477D0DD6D83AA1366D3C88161ABC35A8FE1E1DA92B83B27202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1312C302C30&sticky=nf1
[NF4] [2025-09-19 16:57:14.236] Received returnKey response. code=200, key=Optional("A5E68F1AB764D05967A41DB8161C611D7F3D0E71CEF0573FF58477D0DD6D83AA1366D3C88161ABC35A8FE1E1DA92B83B27202420DE5AD49E70AB545EDE6D88C5DA85D3F8F85FA7FA7B7F120E3C54DAC2902D1EA62CCD2C8E006BBC45D5A080019F32F0077492B7D5F8DB92356655AFF1312C302C30")

すべてが動作中であることを示す核心指標:

ログメッセージ意味状態
[NF4] Sending initialEntry requestnfStartSection()が正常に呼び出された、NetFUNNELサーバーに初期進入リクエスト送信された✅ 良好
[NF4] Received initialEntry response with code: 201サーバーがWAIT状態で応答した✅ 良好
[NF4] Sending reentry request(繰り返し)周期的再進入リクエスト(ポーリング)✅ 良好
[NF4] Received reentry response with code=200進入許可された - 待合室が閉じられるはず✅ 良好
[NF4] Sending key refresh request区間コントロール: キータイムアウト拡張リクエスト(基本20秒)✅ 良好
[NF4] Received refreshKey response with code=201区間コントロール: キータイムアウトが正常に拡張された✅ 良好
[NF4] Sending returnKey requestnfStopSection()が呼び出された✅ 良好
[NF4] Received returnKey response with code=200キー返却成功✅ 良好

テストシーケンス:

  1. 進入許容数 = 0で開始: 待合室が表示される、initialEntryリクエスト送信された
  2. 進入許容数を1に変更: reentry応答がcode=200に変更された、待合室が閉じられた
  3. 区間進入: ユーザーが区間に進入した、キーリフレッシュリクエストが自動的に開始された
  4. キータイムアウト拡張: 区間コントロールが自動的にキータイムアウトを拡張する(5003リクエスト)ことで自動返却を防止
  5. 区間ナビゲーション: ユーザーがSection1 → Section2 → Endを進行
  6. 区間完了: SectionControlEndView onAppear()nfStopSection()呼び出し
  7. キー返却: 5004リクエスト/応答がキー返却を確認
区間コントロールキー管理

区間コントロールは基本コントロールと比較して固有のキー管理動作を持ちます:

  • キータイムアウト拡張(5003): 区間中自動返却を防止するためにキータイムアウトを自動的に拡張する(基本20秒)
  • タイムアウト構成: NetFUNNELコンソール → セグメント → 高度設定 → タイムアウトでタイムアウト構成
  • 同時ユーザー数: 明示的完了まで区間で固定された同時ユーザー数を維持
  • 自動管理: NetFUNNELがタイムアウト拡張を自動的に処理する - 手動介入不要
  • 手動返却: nfStopSection()が明示的に呼び出されるときのみキーが返却される

問題が発生する場合:

  • returnKeyログなし: SectionControlEndViewでnfStopSection()が呼び出されているか確認してください
  • キー返却失敗: nfStopSection()のプロジェクト/セグメントキーがnfStartSection()と正確に一致しているか確認してください
  • 区間が完了しない: 区間ナビゲーションフローが正しく動作しているか確認してください
  • 待合室が閉じない: コンソールで進入許容数が1に設定されているか確認してください
  • キーが自動返却される: NetFUNNELコンソール → セグメント → 高度設定 → タイムアウトでタイムアウトが短すぎるか確認してください
  • 5003ログなし: 区間持続時間がタイムアウト期間(基本20秒)を超えているか確認してください

待合室 → 進入 → 区間ナビゲーション → 区間完了 → キー返却の全体フローが見えれば実装が正しく動作しています!今エラー処理を向上させ、より強力なデリゲート管理を追加できます。

5.4 核心実装ポイント

ベストプラクティス: 即座にキー返却

区間が完了したらNetFUNNELキーを返却してください。NetFUNNELがタイムアウト後(基本20秒)自動的にキーを返却しますが、手動返却はより良いユーザー体験と同時ユーザー数管理効率を提供します。

キー返却ルール:

  • 常に: 区間完了後(成功または失敗)キー返却
  • ⚠️ 自動タイムアウト: 手動で返却しない場合、NetFUNNELが自動的にキーを返却する
  • タイミング: nfStartSection()直後ではなく区間完了後呼び出し

実装チェックリスト:

  1. 正確なキー一致: nfStopSection()のキーはnfStartSection()と正確に一致する必要がある
  2. SwiftUIビューライフサイクル: キー返却タイミングにonAppear使用
  3. 一貫したキー: 区間フロー全体で同一のプロジェクト/セグメントキー使用
完全なAPIリファレンス

nfStopSectionパラメータ、応答処理、および高度なキー返却パターンの詳細情報についてはAPIリファレンスを参照してください。