Skip to main content
Version: 4.6.1-saas

iOS Agent

Overview

The NetFUNNEL agent is a dedicated client for communicating with the NetFUNNEL server. Users can apply a virtual waiting room by applying and implementing the various functions provided by the agent in their client application code.

Minimum Requirements

  • iOS 15.6 or later
  • Storyboard (Objective-C, Swift), SwiftUI

Agent Operation Flow

Before Waiting

  • Before waiting, configuration is initialized. This process involves fetching configuration from the NetFUNNEL server and initializing objects based on that information.
  • Use the "initialization function" to initialize NetFUNNEL configuration.

While Waiting

  • This is the process of displaying the virtual waiting room and applying traffic waiting on the screen (View) where you want it.
  • Use the "wait start function" to apply the virtual waiting room.

After Waiting

  • This is the process of handling situations after waiting ends. Situations where an end-user's wait ends are:
    • Entry success after waiting
    • Entry failure due to server or network error during waiting
    • End-user cancels waiting during wait
  • Use the "callback function" and "wait stop function" to implement logic after waiting ends.

Agent Installation

Agent Download

Download the NetFUNNEL iOS agent from the agent tab in the NetFUNNEL Console. Using .xcframework is recommended for installation that matches your project format.

Agent Application

Create Frameworks Folder

Create a Frameworks folder at the project root.

Move Framework File

Add the NetFUNNEL iOS agent to the Frameworks folder in your project.

Register Framework

Include the NetFUNNEL iOS agent in the project as a Framework.

  1. Click [Project > General > Frameworks, Libraries, and Embedded Content > +] to add the agent from the path where you placed it in the previous step.

  2. Click [Add Files…].

  3. Click the agent in Frameworks and then click [Open].

  4. When the framework appears, it has been included in the project successfully.

danger

If a question mark (?) appears on the framework file in Xcode, the framework's connection to the local file path is broken, or an external file managed by Git has not yet been added to the project.

In that case, you can resolve it by manual registration:

[Right-click framework > Source Control > Add netfunnel_ios.xcframework]

Once registered correctly, the question mark icon will disappear and the framework will be recognized at build time.

Agent Initialization

The NetFUNNEL iOS agent must be initialized when the app starts.

info

Perform initialization in the AppDelegate's application(_:didFinishLaunchingWithOptions:) so that it runs only once at app startup.

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];
ParameterTypeDescriptionRequiredCondition
clientIdStringUser unique identifierO
delegateNetfunnelDelegateView Controller (or class) that conforms to NetfunnelDelegateOObject implementing the protocol
serverUrlStringNetFUNNEL server addressXCannot be empty string
errorUrlStringNetFUNNEL error page addressXCannot be empty string
networkTimeoutNSNumber (Long)Network timeout for NetFUNNELXDefault (ms): 3,000<br/>Max (ms): 10,000<br/>Min (ms): 100
retryCountNSNumber (Int)NetFUNNEL retry countXDefault (times): 0<br/>Max (times): 10<br/>Min (times): 0
printLogNSNumber (Bool)Whether to print debug logsXDefault: false
errorBypassNSNumber (Bool)Whether to bypass on errorXDefault: false
useNetfunnelTemplateNSNumber (Bool)Whether to use waiting room template set in ConsoleXDefault: true
userIdStringData for NetFUNNEL White/Black List distinctionXN/A
useNetworkRecoveryModeNSNumber (Bool)Keep waiting room open until network recovers during waitXDefault: false

Agent Application

You can apply the waiting room to specific screens using the functions provided by the NetFUNNEL iOS agent.

info

Project Key and Segment Key used in the start and stop functions can be found in the Console's project tab.

Delegate

To use the NetFUNNEL iOS agent, you must inject a delegate into the start and stop functions.

The waiting room can end in various situations (wait success, cancel, block, error, network error, etc.), and handling for each situation can be implemented through the delegate.

DelegateRequired
nfSuccessRequired
nfErrorRequired
nfNetworkErrorRequired
nfBlockOptional
nfCloseOptional
nfContinueOptional
nfCompleteOptional

Start Delegate

DelegateStatus CodeScenario
nfSuccess200Passed queue normally; service access allowed
nfSuccess300Subscription or license expired<br/>Console project/segment deactivated<br/>Agent errorBypass=true and error occurred
nfSuccess303Request with IP or ID on Console whitelist (admin bypass)
nfError500Start function called without agent initialization<br/>Non-existent project/segment key in start function<br/>Segment deleted in Console<br/>Response partially missing due to server error
nfNetworkError1001Network connection blocked (Wi-Fi, cellular data blocked)
nfNetworkError1002Network timeout<br/>Invalid HTML URL received due to server error<br/>No response due to server down (502, etc.)
nfBlock301Console segment block (voluntary entry block)
nfBlock302Request with IP or ID on Console blacklist (admin block)<br/>Console BotManager Basic enabled (malicious entry block)
nfClose495Post-waiting room close button pressed
nfClose496Pre-waiting room close button pressed
nfClose497Macro block room close button pressed
nfClose498Block room close button pressed
nfClose499Waiting room cancel button pressed
nfContinue201Agent useNetfunnelTemplate=false and default wait

Stop Delegate

CallbackStatus CodeScenario
nfComplete200Entry key successfully returned to server after wait
nfComplete500Entry key return to server failed after wait

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

Basic Control

Start Function

To apply the waiting room on a specific screen (View), use the wait start function provided by the agent to show the virtual waiting room. Basic Control is useful for applying wait when an end-user enters a specific screen to manage server load and end-user experience.

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}}"];
ParameterTypeDescriptionRequired
projectKeyStringConsole Basic Control project keyO
segmentKeyStringConsole Basic Control segment keyO

Stop Function

When Basic Control wait completes successfully, you must implement the following:

  • Code to enter the service after wait (code to enter the target page)
  • Code that calls the "wait stop function" after business logic to return the service entry key to the NetFUNNEL server

Swift

var agent = Netfunnel.shared
agent.nfStop(projectKey: "{{PROJECT_KEY}}", segmentKey: "{{SEGMENT_KEY}}")

Objective-c

Netfunnel *agent = [Netfunnel shared];
[agent nfStopWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
ParameterTypeDescriptionRequired
projectKeyStringConsole Basic Control project keyO
segmentKeyStringConsole Basic Control segment keyO

Section Control

Start Function

Section Control applies a waiting state between entry and exit of a specific page. With Section Control, users can maintain a smooth flow in a specific section of the page.

  • After entering an event page, purchasing a product, and clicking the payment complete button
  • From end-user login until logout

To start Section Control, use the "section start function" to define the start of the control section. This keeps the waiting state in that section's flow.

Swift

var agent = Netfunnel.shared
agent.nfStartSection(projectKey: "{{projectKey}}", segmentKey: "{{segmentKey}}")

Objective-c

Netfunnel *agent = [Netfunnel shared];
[agent nfStartSectionWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
ParameterTypeDescriptionRequired
projectKeyStringConsole Section Control project keyO
segmentKeyStringConsole Section Control segment keyO

Stop Function

When Section Control wait completes successfully, you can implement:

  • Code to enter the service after wait (code to enter the target page)

To end Section Control, use the "section stop function" to define the end of the section. This ends the end-user's section control and allows the next end-user to enter.

Swift

var agent = Netfunnel.shared
agent.nfStopSection(projectKey: "{{projectKey}}", segmentKey: "{{segmentKey}}")

Objective-c

Netfunnel *agent = [Netfunnel shared];
[agent nfStopSectionWithProjectKey: @"{{projectKey}}" segmentKey:@"{{segmentKey}}"];
ParameterTypeDescriptionRequired
projectKeyStringConsole Section Control project keyO
segmentKeyStringConsole Section Control segment keyO