iOS エージェント
概要
NetFUNNEL エージェントは、NetFUNNEL サーバーと通信するための NetFUNNEL 専用クライアントです。 適用したいクライアントアプリケーションのコードに、エージェントが提供する各種関数を適用・実装することで、仮想待機室を適用できます。
最小要件
- iOS 15.6 以上
- Storyboard(Objective-C、Swift)、SwiftUI
エージェントの動作フロー
待機前
- 待機前に、設定情報を初期化します。 この過程では、NetFUNNEL サーバーから設定情報を取得し、その情報に基づいてオブジェクトを初期化します。
- 「初期化関数」を使用して NetFUNNEL の設定情報を初期化してください。
待機中
- 仮想待機室を表示し、トラフィック待機を適用したい画面(View)で待機させる過程です。
- 「待機開始関数」を使用して仮想待機室を適用してください。
待機後
- 待機終了後の状況に対する処理過程です。エンドユーザーの待機が終了する状況は次のとおりです。
- 待機完了後の進入成功
- 待機中にサーバーエラーまたはネットワークエラーにより進入失敗
- 待機中のエンドユーザーによる待機キャンセル
- 「コールバック関数」と「待機終了関数」を使用して、待機終了後のロジックを実装してください。
エージェントのインストール
エージェントのダウンロード
NetFUNNEL コンソールのエージェントタブから NetFUNNEL iOS エージェントをダウンロードします。
プロジェクトのフォーマットに合わせたエージェントのインストールには、.xcframework の利用を推奨します。
エージェントの適用
Frameworks フォルダの作成
プロジェクトのルートに Frameworks フォルダを作成します。
Framework ファイルの配置
NetFUNNEL iOS エージェントをプロジェクト内の Frameworks フォルダに追加します。
Framework の登録
NetFUNNEL iOS エージェントをプロジェクトに Framework として含めます。
-
[プロジェクト > General > Frameworks, Libraries, and Embedded Content > +] をクリックし、前の手順で配置したパスにあるエージェントを追加します。
-
[Add Files…] をクリックします。
-
Frameworksに配置したエージェントを選択し、[Open] をクリックします。 -
Framework が表示されれば、プロジェクトに正常に含まれています。
Xcode でフレームワークファイルに疑問符(?)が表示される場合は、そのフレームワークのローカルファイルパスとの接続が切れているか、Git で管理されている外部ファイルがまだプロジェクトに追加されていないときに発生します。
この場合は、次の方法で手動登録により解決できます。
[フレームワークを右クリック > Source Control > Add netfunnel_ios.xcframework]
正常に登録されると疑問符アイコンが消え、ビルド時にフレームワークが正しく認識されます。
エージェントの初期化
NetFUNNEL iOS エージェントは、アプリ起動と同時に初期化する必要があります。
AppDelegate の application(_:didFinishLaunchingWithOptions:) で、アプリ起動時に1回だけ実行されるよう初期化を行います。
Swift
let agent = Netfunnel.shared
agent.initialize(
clientId: "{{CLIENT_ID}}",
serverUrl: "{{SERVER_URL}}",
errorUrl: "{{ERROR_URL}}",
delegate: self, // Set the delegate to a specified delegate object or 'self'.
networkTimeout: 3000,
retryCount: 0,
printLog: false,
useNetfunnelTemplate: true,
errorBypass: false,
userId: "{{USER_ID}}",
useNetworkRecoveryMode: false
)
Objective-c
Netfunnel *agent = [Netfunnel shared];
[agent initializeWithClientId:@"{{CLIENT_ID}}"
serverUrl:@"{{SERVER_URL}}"
errorUrl:@"{{ERROR_URL}}"
delegate:self // Set the delegate to a specified delegate object or 'self'.
networkTimeout:3000
retryCount:0
printLog:NO
useNetfunnelTemplate:YES
errorBypass:NO
userId:@"{{USER_ID}}"
useNetworkRecoveryMode:NO];
| パラメータ | 型 | 説明 | 必須 | 条件 |
|---|---|---|---|---|
| clientId | String | ユーザー固有ID | O | |
| delegate | NetfunnelDelegate | NetfunnelDelegate を継承した View Controller(またはクラス) | O | プロトコルを実装したオブジェクト |
| serverUrl | String | NetFUNNEL サーバーアドレス | X | 空文字不可 |
| errorUrl | String | NetFUNNEL エラーページアドレス | X | 空文字不可 |
| networkTimeout | NSNumber (Long) | NetFUNNEL のネットワークタイムアウト | X | 既定(ms): 3,000<br/>最大(ms): 10,000<br/>最小(ms): 100 |
| retryCount | NSNumber (Int) | NetFUNNEL のリトライ回数 | X | 既定(回): 0<br/>最大(回): 10<br/>最小(回): 0 |
| printLog | NSNumber (Bool) | NetFUNNEL デバッグ用ログ出力の有無 | X | 既定: false |
| errorBypass | NSNumber (Bool) | エラー時のバイパス有無 | X | 既定: false |
| useNetfunnelTemplate | NSNumber (Bool) | コンソールで設定した待機室テンプレートの使用有無 | X | 既定: true |
| userId | String | NetFUNNEL White/Black List 判別用データ | X | N/A |
| useNetworkRecoveryMode | NSNumber (Bool) | 待機中にネットワーク障害が発生しても、ネットワーク回復まで待機室を終了せず維持 | X | 既定: false |
エージェントの適用
NetFUNNEL iOS エージェントが提供する関数により、特定の画面に待機室を適用できます。
開始関数・終了関数で使用するプロジェクトキーとセグメントキーは、コンソールのプロジェクトタブで確認できます。
デリゲート
NetFUNNEL iOS エージェントを使用するには、開始関数と終了関数にデリゲートを必ず注入する必要があります。
待機室は様々な状況(待機成功、キャンセル、ブロック、エラー、ネットワークエラーなど)で終了し得るため、各状況の処理はデリゲートで実装します。
| デリゲート | 必須実装 |
|---|---|
| nfSuccess | 必須 |
| nfError | 必須 |
| nfNetworkError | 必須 |
| nfBlock | 任意 |
| nfClose | 任意 |
| nfContinue | 任意 |
| nfComplete | 任意 |
開始デリゲート
| デリゲート | ステータスコード | シナリオ |
|---|---|---|
| nfSuccess | 200 | 正常に待機列を通過し、サービスへのアクセスが許可された場合 |
| nfSuccess | 300 | サブスクリプションまたはライセンスの期限切れ<br/>コンソールのプロジェクト/セグメントが無効化された場合<br/>エージェントの errorBypass=true でエラーが発生した場合 |
| nfSuccess | 303 | コンソールのホワイトリストに登録された IP または ID によるリクエスト(管理者バイパス) |
| nfError | 500 | エージェント未初期化の状態で開始関数を呼び出した場合<br/>開始関数に存在しないプロジェクト/セグメントキーを指定した場合<br/>コンソールでセグメントが削除された場合<br/>サーバーエラーによりレスポンスが一部欠落した場合 |
| nfNetworkError | 1001 | ネットワーク接続が遮断された場合(Wi-Fi・携帯データの遮断) |
| nfNetworkError | 1002 | ネットワークタイムアウト<br/>サーバーエラーにより不正な HTML URL を受信した場合<br/>サーバーダウン(502 等)によりレスポンスがない場合 |
| nfBlock | 301 | コンソールのセグメントブロック(任意進入ブロック) |
| nfBlock | 302 | コンソールのブラックリストに登録された IP または ID によるリクエスト(管理者ブロック)<br/>コンソールの BotManager Basic 有効時(悪意ある進入ブロック) |
| nfClose | 495 | 待機室終了後の閉じるボタン押下 |
| nfClose | 496 | 待機室表示前の閉じるボタン押下 |
| nfClose | 497 | マクロブロック室の閉じるボタン押下 |
| nfClose | 498 | ブロック室の閉じるボタン押下 |
| nfClose | 499 | 待機室のキャンセルボタン押下 |
| nfContinue | 201 | エージェント useNetfunnelTemplate=false 時のデフォルト待機 |
終了デリゲート
| コールバック | ステータスコード | シナリオ |
|---|---|---|
| nfComplete | 200 | 待機後に進入キーをサーバーへ正常に返却した場合 |
| nfComplete | 500 | 待機後の進入キー返却がサーバーで失敗した場合 |
Swift
import Foundation
import Netfunnel_iOS
class NetfunnelHandler: NSObject, NetfunnelDelegate {
static let shared = NetfunnelHandler()
// MARK: - Required callback closures
var onSuccess: ((String, String, Int, String) -> Void)?
var onError: ((String, String, Int, String) -> Void)?
var onNetworkError: ((String, String, Int, String) -> Void)?
// MARK: - Optional callback closures
var onContinue: ((String, String, Int, String, Int, Int, String, Int) -> Void)?
var onBlock: ((String, String, Int, String) -> Void)?
var onClose: ((String, String, Int, String) -> Void)?
var onComplete: ((String, String, Int, String) -> Void)?
private override init() {}
// MARK: - NetfunnelDelegate Methods
func nfSuccess(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfSuccess \(statusCode) \(message)")
/**
* Logic to run when queue is passed
* ex - service screen entry
*/
onSuccess?(projectKey, segmentKey, statusCode, message)
}
func nfError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfError \(statusCode) \(message)")
/**
* Logic to run on error
* ex - show error message to user or bypass
*/
onError?(projectKey, segmentKey, statusCode, message)
}
func nfNetworkError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfNetworkError \(statusCode) \(message)")
/**
* Logic to run on network error
* ex - guide to reconnect or navigate to retry screen
*/
onNetworkError?(projectKey, segmentKey, statusCode, message)
}
func nfContinue(projectKey: String, segmentKey: String, statusCode: Int, message: String,
aheadWait: Int, behindWait: Int, waitTime: String, progressRate: Int) {
NSLog("nfContinue \(statusCode) \(message)")
/**
* UI update logic while waiting (only when not using NetFUNNEL waiting room)
* ex - update custom waiting screen with real-time wait info
*/
onContinue?(projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate)
}
func nfBlock(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfBlock \(statusCode) \(message)")
/**
* Logic when user entry is blocked
* ex - show access denied message
*/
onBlock?(projectKey, segmentKey, statusCode, message)
}
func nfClose(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfClose \(statusCode) \(message)")
/**
* Logic when user cancels wait
* ex - show exit Toast (WebView returns automatically)
*/
onClose?(projectKey, segmentKey, statusCode, message)
}
func nfComplete(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
NSLog("nfComplete \(statusCode) \(message)")
/**
* Logic when finally complete
* ex - post-wait follow-up
*/
onComplete?(projectKey, segmentKey, statusCode, message)
}
}
Objective-c
#import <Foundation/Foundation.h>
#import <Netfunnel_iOS/NetfunnelDelegate.h>
NS_ASSUME_NONNULL_BEGIN
@interface NetfunnelHandler : NSObject <NetfunnelDelegate>
+ (instancetype)sharedInstance;
// Required callbacks
@property (nonatomic, copy, nullable) void (^onSuccess)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
@property (nonatomic, copy, nullable) void (^onError)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
@property (nonatomic, copy, nullable) void (^onNetworkError)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
// Optional callbacks
@property (nonatomic, copy, nullable) void (^onContinue)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message, NSInteger aheadWait, NSInteger behindWait, NSString *waitTime, NSInteger progressRate);
@property (nonatomic, copy, nullable) void (^onBlock)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
@property (nonatomic, copy, nullable) void (^onClose)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
@property (nonatomic, copy, nullable) void (^onComplete)(NSString *projectKey, NSString *segmentKey, NSInteger statusCode, NSString *message);
@end
NS_ASSUME_NONNULL_END
#import "NetfunnelHandler.h"
@implementation NetfunnelHandler
+ (instancetype)sharedInstance {
static NetfunnelHandler *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[NetfunnelHandler alloc] init];
});
return sharedInstance;
}
#pragma mark - NetfunnelDelegate Methods
- (void)nfSuccessWithProjectKey:(NSString *)projectKey
segmentKey:(NSString *)segmentKey
statusCode:(NSInteger)statusCode
message:(NSString *)message {
NSLog(@"nfSuccess %ld %@", (long)statusCode, message);
/**
* Logic to run when queue is passed
* ex - service screen entry
*/
if (self.onSuccess) {
self.onSuccess(projectKey, segmentKey, statusCode, message);
}
}
- (void)nfErrorWithProjectKey:(NSString *)projectKey
segmentKey:(NSString *)segmentKey
statusCode:(NSInteger)statusCode
message:(NSString *)message {
NSLog(@"nfError %ld %@", (long)statusCode, message);
/**
* Logic to run on error
* ex - show error message to user or bypass
*/
if (self.onError) {
self.onError(projectKey, segmentKey, statusCode, message);
}
}
- (void)nfNetworkErrorWithProjectKey:(NSString *)projectKey
segmentKey:(NSString *)segmentKey
statusCode:(NSInteger)statusCode
message:(NSString *)message {
NSLog(@"nfNetworkError %ld %@", (long)statusCode, message);
/**
* Logic to run on network error
* ex - guide to reconnect or navigate to retry screen
*/
if (self.onNetworkError) {
self.onNetworkError(projectKey, segmentKey, statusCode, message);
}
}
- (void)nfContinueWithProjectKey:(NSString *)projectKey
segmentKey:(NSString *)segmentKey
statusCode:(NSInteger)statusCode
message:(NSString *)message
aheadWait:(NSInteger)aheadWait
behindWait:(NSInteger)behindWait
waitTime:(NSString *)waitTime
progressRate:(NSInteger)progressRate {
NSLog(@"nfContinue %ld %@", (long)statusCode, message);
/**
* UI update logic while waiting (only when not using NetFUNNEL waiting room)
* ex - update custom waiting screen with real-time wait info
*/
if (self.onContinue) {
self.onContinue(projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate);
}
}
- (void)nfBlockWithProjectKey:(NSString *)projectKey
segmentKey:(NSString *)segmentKey
statusCode:(NSInteger)statusCode
message:(NSString *)message {
NSLog(@"nfBlock %ld %@", (long)statusCode, message);
/**
* Logic when user entry is blocked
* ex - show access denied message
*/
if (self.onBlock) {
self.onBlock(projectKey, segmentKey, statusCode, message);
}
}
- (void)nfCloseWithProjectKey:(NSString *)projectKey
segmentKey:(NSString *)segmentKey
statusCode:(NSInteger)statusCode
message:(NSString *)message {
NSLog(@"nfClose %ld %@", (long)statusCode, message);
/**
* Logic when user cancels wait
* ex - show exit Toast (WebView returns automatically)
*/
if (self.onClose) {
self.onClose(projectKey, segmentKey, statusCode, message);
}
}
- (void)nfCompleteWithProjectKey:(NSString *)projectKey
segmentKey:(NSString *)segmentKey
statusCode:(NSInteger)statusCode
message:(NSString *)message {
NSLog(@"nfComplete %ld %@", (long)statusCode, message);
/**
* Logic when finally complete
* ex - post-wait follow-up
*/
if (self.onComplete) {
self.onComplete(projectKey, segmentKey, statusCode, message);
}
}
@end
基本制御
開始関数
特定の画面(View)に待機室を適用するには、エージェントが提供する待機開始関数を使用して仮想待機室を表示します。基本制御は、サーバー負荷とエンドユーザー体験を管理するため、エンドユーザーが特定の画面に進入したときに待機を適用する場合に有用です。
Swift
var agent = Netfunnel.shared
agent.nfStart(projectKey: "{{PROJECT_KEY}}", segmentKey: "{{SEGMENT_KEY}}")
Objective-c
Netfunnel *agent = [Netfunnel shared];
[agent nfStartWithProjectKey: @"{{PROJECT_KEY}}" segmentKey:@"{{SEGMENT_KEY}}"];
| パラメータ | 型 | 説明 | 必須 |
|---|---|---|---|
| projectKey | String | コンソール基本制御のプロジェクトキー | O |
| segmentKey | String | コンソール基本制御のセグメントキー | O |
終了関数
基本制御の待機が正常に完了した場合、次を実装する必要があります。
- 待機後のサービス進入コード(対象ページへの進入コード)
- サービス進入キーを NetFUNNEL サーバーに返却するため、ビジネスロジック後に「待機終了関数」を呼び出すコード
Swift
var agent = Netfunnel.shared
agent.nfStop(projectKey: "{{PROJECT_KEY}}", segmentKey: "{{SEGMENT_KEY}}")
Objective-c
Netfunnel *agent = [Netfunnel shared];
[agent nfStopWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
| パラメータ | 型 | 説明 | 必須 |
|---|---|---|---|
| projectKey | String | コンソール基本制御のプロジェクトキー | O |
| segmentKey | String | コンソール基本制御のセグメントキー | O |
セクション制御
開始関数
セクション制御は、特定ページの進入から退出までの間、待機状態を維持します。セクション制御により、ページの特定セクション内でスムーズなフローを維持できます。
- イベントページ進入後、商品購入から支払い完了ボタン押下まで
- エンドユーザーのログインからログアウトまで
セクション制御を開始するには、「セクション開始関数」で制御セクションの開始を定義します。これにより、そのセクションのフロー中は待機状態が維持されます。
Swift
var agent = Netfunnel.shared
agent.nfStartSection(projectKey: "{{projectKey}}", segmentKey: "{{segmentKey}}")
Objective-c
Netfunnel *agent = [Netfunnel shared];
[agent nfStartSectionWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
| パラメータ | 型 | 説明 | 必須 |
|---|---|---|---|
| projectKey | String | コンソールセクション制御のプロジェクトキー | O |
| segmentKey | String | コンソールセクション制御のセグメントキー | O |
終了関数
セクション制御の待機が正常に完了した場合、次を実装できます。
- 待機後のサービス進入コード(対象ページへの進入コード)
セクション制御を終了するには、「セクション終了関数」でセクションの終了を定義します。これにより、該当エンドユーザーのセクション制御が終了し、次のエンドユーザーの進入が可能になります。
Swift
var agent = Netfunnel.shared
agent.nfStopSection(projectKey: "{{projectKey}}", segmentKey: "{{segmentKey}}")
Objective-c
Netfunnel *agent = [Netfunnel shared];
[agent nfStopSectionWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
| パラメータ | 型 | 説明 | 必須 |
|---|---|---|---|
| projectKey | String | コンソールセクション制御のプロジェクトキー | O |
| segmentKey | String | コンソールセクション制御のセグメントキー | O |