Skip to main content

iOS 넷퍼넬 대기실 미사용

이 문서는 NetFUNNEL iOS 에이전트에서 넷퍼넬 대기실을 사용하지 않고, 자체 커스텀 대기실을 적용하기 위한 최소한의 예제를 제공합니다.


1. nfContinue

nfContinue

nfContinue는 넷퍼넬 대기실이 아닌 자체 커스텀 대기실로 구현할 경우 사용하는 함수입니다.

parametertype설명예시
statusCodeInt대기 상태에 대한 응답 코드201
messageString대기 상태에 대한 메시지Continue
aheadWaitInt내 앞 대기자 수{N}
behindWaitInt내 뒤 대기자 수{N}
waitTimeString예상 대기 시간{HH:mm:ss}
progressRateInt진행률 (%){0~100}
danger

자체 커스텀 대기실 사용 시, 기본 대기 외 기능 사용에 제한이 있습니다.

따라서 넷퍼넬 대기실을 사용하는 useNetfunnelTemplate=true 설정을 권장합니다.


2. 자체 커스텀 대기실 적용

2.1 초기화 함수 설정

기본 WebView 대기실 대신 자체 구현한 대기실 UI를 사용하려면, useNetfunnelTemplate: false로 설정합니다.

이 설정 시 nfContinue 콜백을 통해 실시간 대기 정보를 직접 받아 커스텀 다이얼로그에 반영해야 합니다.

SampleApp.swift
import SwiftUI
import Netfunnel_iOS

@main
struct SampleApp: App {
init() {
AppConfig.shared.useNetfunnelTemplate = false

Netfunnel.shared.initialize(
clientId: "{CLIENT_ID}",
delegate: NetfunnelHandler.shared,
networkTimeout: 3000,
retryCount: 0,
printLog: true,
errorBypass: false,
useNetfunnelTemplate: false
)
}

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

2.2 자체 커스텀 대기실 생성

자체 커스텀 대기실은 예상 대기 시간, 진행률, 앞/뒤 대기자 수, 닫기 버튼 등의 요소를 포함해 SwiftUI로 구성할 수 있습니다.

해당 UI는 커스텀 대기실로 구현하고, nfContinue 델리게이트를 통해 상태를 갱신합니다.

CustomWaitingView.swift
import SwiftUI

struct CustomWaitingView: View {
let aheadWait: Int
let behindWait: Int
let waitTime: String
let progressRate: Int
let onCancel: () -> Void

var body: some View {
VStack(spacing: 24) {
Text("Waiting in progress")
.font(.title2)
.fontWeight(.semibold)

VStack(spacing: 12) {
InfoRow(title: "People ahead of me", value: "\(aheadWait)")
InfoRow(title: "People behind me", value: "\(behindWait)")
InfoRow(title: "Estimated wait time", value: waitTime)
}

VStack(spacing: 8) {
ProgressView(value: Float(progressRate), total: 100)
.progressViewStyle(LinearProgressViewStyle(tint: .blue))
.frame(height: 10)
.clipShape(Capsule())

Text("Progress: \(progressRate)%")
.font(.subheadline)
.foregroundColor(.gray)
}

Button(action: onCancel) {
Text("Cancel Waiting")
.font(.headline)
.foregroundColor(.white)
.padding()
.frame(maxWidth: .infinity)
.background(Color.red)
.cornerRadius(12)
}
}
.padding()
.background(Color.white)
.cornerRadius(20)
.shadow(radius: 10)
.padding(.horizontal, 24)
}
}

private struct InfoRow: View {
let title: String
let value: String

var body: some View {
HStack {
Text(title)
.font(.subheadline)
.foregroundColor(.gray)
Spacer()
Text(value)
.font(.body)
.fontWeight(.medium)
}
}
}

2.3 NetFUNNEL 델리게이트 핸들러

nfContinue 콜백을 처리하는 델리게이트 클래스를 구성합니다.

NetfunnelHandler.swift
import Foundation
import Netfunnel_iOS

class NetfunnelHandler: NSObject, NetfunnelDelegate {
static let shared = NetfunnelHandler()

var onContinue: ((String, String, Int, String, Int, Int, String, Int) -> Void)?
var onSuccess: ((String, String, Int, String) -> Void)?
var onError: ((String, String, Int, String) -> Void)?
var onNetworkError: ((String, String, Int, String) -> Void)?

private override init() {
super.init()
}

func nfContinue(projectKey: String, segmentKey: String, statusCode: Int, message: String, aheadWait: Int, behindWait: Int, waitTime: String, progressRate: Int) {
onContinue?(projectKey, segmentKey, statusCode, message, aheadWait, behindWait, waitTime, progressRate)
}

func nfSuccess(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
onSuccess?(projectKey, segmentKey, statusCode, message)
}

func nfError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
onError?(projectKey, segmentKey, statusCode, message)
}

func nfNetworkError(projectKey: String, segmentKey: String, statusCode: Int, message: String) {
onNetworkError?(projectKey, segmentKey, statusCode, message)
}
}

2.4 nfContinue 사용

nfContinue 콜백에서 대기실을 띄우고 실시간 대기 정보를 업데이트합니다.

warning
중요: 대기 취소 시 반드시 해당 함수 호출

대기를 취소할 때는 반드시 다음 함수 중 하나를 호출해야 합니다:

  • 기본 제어: nfStop()

  • 구간 제어: nfStopSection()

이 함수들을 호출하지 않으면:

  • 서버에서 사용자의 대기 상태가 정리되지 않음

  • 정확한 대기열 관리에 영향을 줄 수 있음

ContentView.swift
import SwiftUI
import Netfunnel_iOS

struct ContentView: View {
@State private var showWaitingRoom = false
@State private var ahead = 0
@State private var behind = 0
@State private var progress = 0
@State private var waitTime = ""
@State private var showCompleted = false

let projectKey = "{PROJECT_KEY}"
let segmentKey = "{SEGMENT_KEY}"

var body: some View {
if showCompleted {
Text("Entry Complete Screen")
.font(.title)
.padding()
} else if showWaitingRoom {
CustomWaitingView(
aheadWait: ahead,
behindWait: behind,
waitTime: waitTime,
progressRate: progress
) {
// Basic Control - Cancel Waiting
Netfunnel.shared.nfStop(projectKey: projectKey, segmentKey: segmentKey)
showWaitingRoom = false
}
} else {
SplashView(
projectKey: projectKey,
segmentKey: segmentKey,
showWaitingRoom: $showWaitingRoom,
ahead: $ahead,
behind: $behind,
waitTime: $waitTime,
progress: $progress,
showTabs: $showCompleted
)
}
}
}

struct SplashView: View {
let projectKey: String
let segmentKey: String

@Binding var showWaitingRoom: Bool
@Binding var ahead: Int
@Binding var behind: Int
@Binding var waitTime: String
@Binding var progress: Int
@Binding var showTabs: Bool

var body: some View {
VStack {
Spacer()
Text("Splash").font(.title3)
Spacer()
}
.onAppear {
bindNetfunnelCallbacks()
Netfunnel.shared.nfStart(projectKey: projectKey, segmentKey: segmentKey)
}
}

private func bindNetfunnelCallbacks() {
NetfunnelHandler.shared.onContinue = { _, _, _, _, aheadWait, behindWait, time, prog in
DispatchQueue.main.async {
if !AppConfig.shared.useNetfunnelTemplate {
ahead = aheadWait
behind = behindWait
waitTime = time
progress = prog
showWaitingRoom = true
}
}
}

NetfunnelHandler.shared.onSuccess = { _, _, _, _ in
DispatchQueue.main.async {
showWaitingRoom = false
showTabs = true
}
}

NetfunnelHandler.shared.onError = { _, _, _, _ in
DispatchQueue.main.async {
showWaitingRoom = false
showTabs = true
}
}

NetfunnelHandler.shared.onNetworkError = { _, _, _, _ in
DispatchQueue.main.async {
showWaitingRoom = false
showTabs = true
}
}
}
}