# iOS SDK

{% hint style="success" %} <mark style="color:$success;">**iOS SDK v1.0.0-rc02 (호환성 정보)**</mark>

**iOS** 15.0+
{% endhint %}

{% hint style="info" %}

## <mark style="color:$tint;">Notice</mark>

현재 CocoaPods을 통한 설치는 지원하지 않습니다. 추후 Swift Package Manager 지원이 제공될 예정입니다
{% endhint %}

## iOS SDK 설치하기

핑거푸시 링크 iOS SDK는 아래 방법으로 설치할 수 있습니다.

{% tabs %}
{% tab title="직접 설치" %}
1\. 핑거푸시 링크 iOS SDK를 다운로드합니다.

{% file src="/files/UiBbBGfFbYaFsN6VygET" %}

2\. fplink.xcframework를 프로젝트에 추가합니다. \
\[Xcode] > \[프로젝트 파일] > \[General] > \[Frameworks, Libraries, and Embedded Content]에서 ‘+’를 클릭합니다.

3\. \[Add Other...]에서 ‘Add Files...’를 클릭하고 fplink.xcframework를 선택합니다.

4\. fplink.xcframework의 Embed를 **Do Not Embed**로 설정합니다.

5\. \[Targets 프로젝트] > \[Build Settings] > **'User Script Sandboxing'** 값을 **No**로 변경합니다.

6\. RunScript 를 추가합니다.\
\[Targets 프로젝트] > \[Build Phases] > '+' 클릭 > **'New RunScript Phase'** 클릭 후 아래의 스크립트를 추가합니다.

{% code title="fplink script" overflow="wrap" expandable="true" %}

```sh
set -euo pipefail

: "${CODE_SIGN_ENTITLEMENTS:=}"
[ -n "$CODE_SIGN_ENTITLEMENTS" ] || exit 0

ENTITLEMENTS_PATH="${SRCROOT}/${CODE_SIGN_ENTITLEMENTS}"
[ -f "$ENTITLEMENTS_PATH" ] || exit 0

RESOURCES_DIR="${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
OUTPUT_PLIST="$RESOURCES_DIR/AssociatedDomains.plist"

[ -f "$ENTITLEMENTS_PATH" ] || exit 0

mkdir -p "$RESOURCES_DIR"
rm -f "$OUTPUT_PLIST"

/usr/libexec/PlistBuddy -c "Add :applinks array" "$OUTPUT_PLIST"

i=0
added=0
while true; do
  raw=$(/usr/libexec/PlistBuddy -c "Print :com.apple.developer.associated-domains:${i}" "$ENTITLEMENTS_PATH" 2>/dev/null) || break

  if [[ "$raw" == applinks:* ]]; then
    domain="${raw#applinks:}"
    /usr/libexec/PlistBuddy -c "Add :applinks:$added string $domain" "$OUTPUT_PLIST"
    added=$((added+1))
  fi

  i=$((i+1))
done
```

{% endcode %}
{% endtab %}
{% endtabs %}

### SDK 초기화하기

시스템 방식에 따라 SDK 초기화 방법이 다릅니다. SceneDelegate Lifecycle 또는 AppDelegate Lifecycle은 AppDelegate를 참고해 주세요. SwiftUI Lifecycle는 SwiftUI를 참고해 주세요.

YOUR\_APP\_ID와 YOUR\_MOBILE\_APP\_API\_KEY은 핑거푸시 링크 대시보드의 \[모바일 앱] > \[앱 관리] > \[API 키] 에서 확인할 수 있습니다.

{% tabs %}
{% tab title="AppDelegate (Swift)" %}

```swift
import UIKit
import fplink

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        Fplink.initialize(appID:"YOUR_APP_ID", apiKey:"YOUR_MOBILE_APP_API_KEY")
        return true
    }
}
```

{% endtab %}

{% tab title="AppDelegate (Objective-C)" %}

```objective-c
#import "AppDelegate.h"
#import <fplink/fplink-Swift.h>

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [Fplink initializeWithAppID:@"YOUR_APP_ID" apiKey:@"YOUR_MOBILE_APP_API_KEY"];
    return YES;
}

@end
```

{% endtab %}

{% tab title="SwiftUI" %}

```swift
import SwiftUI
import fplink

@main
struct ExampleApp: App {
    init() {
        Fplink.initialize(appID: "YOUR_APP_ID", apiKey: "YOUR_MOBILE_APP_API_KEY")
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %} <mark style="color:$danger;">**주의하세요**</mark>

<mark style="color:$danger;">`Fplink.initialize`</mark> 함수를 <mark style="color:$danger;">`AppDelegate`</mark> 의 <mark style="color:$danger;">`application(_:didFinishLaunchingWithOptions:)`</mark> 시점에 호출해야 올바르게 동작합니다.
{% endhint %}

## **딥링크**

<sup>이 문서에서 FINGERPUSH.LINK 딥링크는 이하 '</sup><sup>**FP 딥링크**</sup><sup>'로 표기합니다.</sup>

링크 생성 시 모바일 딥링크를 설정하면, 사용자가 해당 링크를 클릭했을 때 앱이 실행되며 지정한 화면으로 이동하도록 할 수 있습니다.

### **딥링크 설정하기**

FP 딥링크를 사용하기 위해 먼저  핑거푸시 링크 대시보드에서 앱을 추가하고, 딥링크 설정을 진행합니다.

<details>

<summary>1. 앱 추가하기</summary>

[핑거푸시 링크 대시보드](https://console.fingerpush.link/console)에서 아래 경로로 이동하여 앱을 추가합니다.

\[모바일 앱] > \[앱 관리] > \[새 앱 추가] > iOS 플랫폼 선택

**필수 정보 입력**

Team ID : [애플 개발자 대시보드](https://developer.apple.com/account/resources)의 멤버십 세부 사항에서 <mark style="color:blue;">`팀 ID`</mark> 값을 가져와서 입력하거나, [애플 개발자 프로그램 리소스](https://developer.apple.com/account/resources)의 앱의 \[Identifier]에서 <mark style="color:blue;">`App ID Prefix(팀 ID)`</mark>  값을 가져와서 입력해주세요.

Bundle ID : [애플 개발자 프로그램 리소스](https://developer.apple.com/account/resources)의 앱의 \[Identifier]에서 <mark style="color:blue;">`Bundle ID`</mark> 값을 가져와서 입력해주세요.

앱 스킴(App Scheme) : 앱에서 사용하는 URL 스킴을 입력합니다.

앱 스토어 URL : 앱이 설치되지 않은 경우 이동할 App Store 주소를 입력합니다.

</details>

FP 딥링크로 앱이 실행될 수 있도록, 앱에서 딥링크 설정을 진행합니다.

<details>

<summary>2  딥링크 설정하기</summary>

#### **스킴 딥링크 앱 설정**

1\. Xcode에서 \[YOUR\_PROJECT] > \[Info] > \[URL Types]로 이동합니다.

2\. '+'를 클릭한 후에 URL Schemes에 핑거푸시 링크 대시보드에서 입력한 iOS URL 스킴을 입력합니다.

{% hint style="danger" %} <mark style="color:$danger;">**주의하세요**</mark>

<mark style="color:$danger;">`://`</mark>를 제외한 iOS URL 스킴을 입력해야 합니다.
{% endhint %}

#### **유니버셜 링크 앱 설정**

1\. Xcode에서 \[YOUR\_PROJECT]>\[Signing & Capabilities]로 이동합니다.

2\. '+ Capability'를 클릭하면 Associated Domains를 추가할 수 있습니다.

3\. Associated Domains에 핑거푸시 링크 대시보드의 \[도메인 & 인프라] > \[커스텀 도메인] 에서 사용하고자 하는 모든 도메인을 applinks:\[도메인 이름] 형태로 추가합니다.

</details>

***

### **딥링크 처리하기**

딥링크로 앱이 실행될 때,  <mark style="color:blue;">`handleDeeplink`</mark> 를 호출해 딥링크를 SDK로 전달하고 FP 딥링크 여부를 확인해주세요. <mark style="color:blue;">`handleDeeplink`</mark> 를 통해 SDK는 딥링크 오픈 이벤트를 수집하며, FP 딥링크인 경우 해당 딥링크를 처리합니다. &#x20;

FP 딥링크인 경우, SDK는 설정된 링크 정보를 조회하여 url과 schemeUrl을 가져옵니다. \
가져온 값은 <mark style="color:blue;">`setDeeplinkCallback`</mark> 으로 설정한 콜백으로 전달됩니다.\
콜백으로 전달된 url 또는 schemeUrl을 이용해 유저를 원하는 화면으로 이동시켜주세요.

#### 딥링크 처리 흐름

<mark style="color:blue;">`handleDeeplink`</mark> 의 반환값 isFingerpushDeeplink 값이 true이면 FP 딥링크이며, 처리 성공/실패 여부는 onSuccess/onFailure 콜백으로 전달됩니다.\
반환값이 false이면 FP 딥링크가 아니며, 이 경우 <mark style="color:blue;">`setDeeplinkCallback`</mark> 및 성공/실패 콜백은 호출되지 않습니다.

이를 활용하면 FP 딥링크와 그 외 딥링크를 분리하여 처리할 수 있습니다 &#x20;

#### 콜백 설정

<mark style="color:blue;">`setDeeplinkCallback`</mark> 은 앱 시작 시점에 설정해야 합니다.

* SceneDelegate와 AppDelegate가 모두 있는 경우: AppDelegate에서 설정 &#x20;
* AppDelegate만 있는 경우: AppDelegate에서 설정 &#x20;
* SwiftUI를 사용하는 경우: App 클래스에서 설정&#x20;

{% tabs %}
{% tab title="AppDelegate (Swift)" %}

```swift
import UIKit
import fplink

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // SDK 초기화 이후 작성
        Fplink.instance().setDeeplinkCallback { url, schemeUrl in
            if let url {
                //  url을 활용해 유저를 설정한 목적지로 이동하는 로직 작성
            }
        }
        return true
    }
    ...
}
```

{% endtab %}

{% tab title="AppDelegate (Objective-C)" %}

```objective-c
#import "AppDelegate.h"
#import <fplink/fplink-Swift.h>

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // SDK 초기화 이후 작성
    [[Fplink instance] setDeeplinkCallback:^(NSURL * _Nullable url, NSURL * _Nullable schemeUrl) {
        //  url을 활용해 유저를 설정한 목적지로 이동하는 로직 작성
    }];
    return YES;
}
...
@end
```

{% endtab %}

{% tab title="SwiftUI" %}

```swift
import SwiftUI
import fplink

@main
struct ExampleApp: App {
    init() {
        // SDK 초기화 이후 작성
        Fplink.instance().setDeeplinkCallback { url, schemeUrl in
            if let url {
                //  url을 활용해 유저를 설정한 목적지로 이동하는 로직 작성
            }
        }
    }
    ...
}
```

{% endtab %}
{% endtabs %}

#### handleDeeplink 호출

<mark style="color:blue;">`handleDeeplink`</mark> 는 딥링크로 앱이 실행될 때 호출해야 합니다.

* SceneDelegate와 AppDelegate가 모두 있는 경우: SceneDelegate에서 호출 &#x20;
* AppDelegate만 있는 경우: AppDelegate에서 호출 &#x20;
* SwiftUI를 사용하는 경우: App 클래스(onOpenURL)에서 호출

{% tabs fullWidth="false" %}
{% tab title="AppDelegate (swift)" %}
**URL Scheme**으로 오픈되는 경우   <mark style="color:blue;">`application:open:options:`</mark> &#x20;

**유니버셜 링크**로 오픈되는 경우   <mark style="color:blue;">`application:continue:restorationHandler:`</mark> &#x20;

해당 콜백에서 <mark style="color:blue;">`handleDeeplink`</mark> 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 <mark style="color:blue;">`setDeeplinkCallback`</mark> 함수를 통해서 유저를 이동시키세요.

{% code expandable="true" %}

```swift
import UIKit
import fplink

class AppDelegate: UIResponder, UIApplicationDelegate {
    ...
    func application(
        _ app: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey : Any] = [:]
    ) -> Bool {
        // 핑거푸시 딥링크를 사용여부 확인
        var isFingerpushDeeplink = Fplink.instance().handleDeeplink(open: url)
        if isFingerpushDeeplink { return true }
        
        // 다른 딥링크로 앱 실행 시 기존 로직 사용
        
        return true
    }
    
    func application(
        _ application: UIApplication,
        continue userActivity: NSUserActivity,
        restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
    ) -> Bool {
        // 핑거푸시 딥링크를 사용여부 확인
        var isFingerpushDeeplink = Fplink.instance().handleDeeplink(continue: userActivity)
        if isFingerpushDeeplink { return true }
        
        // 다른 딥링크로 앱 실행 시 기존 로직 사용
        
        return true
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="SceneDelegate (swift)" %}
앱이 꺼지거나 백그라운드에 있는 상태에서 \
**URL Scheme** 또는 **유니버셜 링크**로 오픈되는 경우   <mark style="color:blue;">`scene:willConnectTo:options:`</mark> &#x20;

앱이 백그라운드에 있는 상태에서\
**URL 스킴**으로 오픈되는 경우   <mark style="color:blue;">`scene:openURLContexts:`</mark>  \
**유니버셜링크**로 오픈되는 경우   <mark style="color:blue;">`scene:continue:`</mark> &#x20;

해당 콜백에서 <mark style="color:blue;">`handleDeeplink`</mark> 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 <mark style="color:blue;">`setDeeplinkCallback`</mark> 함수를 통해서 유저를 이동시키세요.

{% code expandable="true" %}

```swift
import UIKit
import fplink

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        ...
        
        // 핑거푸시 딥링크를 사용여부 확인
        var isFingerpushDeeplink = Fplink.instance().handleDeeplink(options: connectionOptions) 
        if isFingerpushDeeplink { return }
        
        // 다른 딥링크로 앱 실행 시 기존 로직 사용
    }
    
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        // 핑거푸시 딥링크를 사용여부 확인
        var isFingerpushDeeplink = Fplink.instance().handleDeeplink(openURLContexts: URLContexts)
        if isFingerpushDeeplink { return }
        
        // 다른 딥링크로 앱 실행 시 기존 로직 사용
    }
    
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        // 핑거푸시 딥링크를 사용여부 확인
        var isFingerpushDeeplink = Fplink.instance().handleDeeplink(continue: userActivity)
        if isFingerpushDeeplink { return }
        
        // 다른 딥링크로 앱 실행 시 기존 로직 사용
    }
    ...
}
```

{% endcode %}
{% endtab %}

{% tab title="AppDelegate (Objective-C)" %}
**URL Scheme**으로 오픈되는 경우   <mark style="color:blue;">`application:openURL:options:`</mark> &#x20;

**유니버셜 링크**로 오픈되는 경우   <mark style="color:blue;">`application:continueUserActivity:restorationHandler:`</mark> &#x20;

해당 콜백에서  <mark style="color:blue;">`handleDeeplink`</mark> 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 <mark style="color:blue;">`setDeeplinkCallback`</mark> 함수를 통해서 유저를 이동시키세요.

{% code expandable="true" %}

```swift
#import "AppDelegate.h"
#import <fplink/fplink-Swift.h>

@interface AppDelegate ()

@end

@implementation AppDelegate
...
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
   // 핑거푸시 딥링크를 사용여부 확인
    BOOL isFingerpushDeeplink = [[Fplink instance] handleDeeplinkWithOpen:url onSuccess:nil onFailure:nil];
    if (isFingerpushDeeplink) { return YES; }
    
    // 다른 딥링크로 앱 실행 시 기존 로직 사용
    
    return isFingerpushDeeplink;
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
   // 핑거푸시 딥링크를 사용여부 확인
    BOOL isFingerpushDeeplink = [[Fplink instance] handleDeeplinkWithContinue:userActivity onSuccess:nil onFailure:nil];
    if (isFingerpushDeeplink) { return YES; }
    
    // 다른 딥링크로 앱 실행 시 기존 로직 사용
    
    return isFingerpushDeeplink;
}
@end
```

{% endcode %}
{% endtab %}

{% tab title="SceneDelegate (Objective-C)" %}
앱이 꺼지거나 백그라운드에 있는 상태에서 \
**URL Scheme** 또는 **유니버셜 링크**로 오픈되는 경우   <mark style="color:blue;">`scene:willConnectToSession:options:`</mark> &#x20;

앱이 백그라운드에 있는 상태에서\
**URL 스킴**으로 오픈되는 경우   <mark style="color:blue;">`scene:openURLContexts:`</mark>  \
**유니버셜링크**로 오픈되는 경우   <mark style="color:blue;">`scene:continueUserActivity:`</mark> &#x20;

해당 콜백에서 <mark style="color:blue;">`handleDeeplink`</mark> 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 <mark style="color:blue;">`setDeeplinkCallback`</mark> 함수를 통해서 유저를 이동시키세요.

{% code expandable="true" %}

```swift
#import "SceneDelegate.h"
#import <fplink/fplink-Swift.h>

@interface SceneDelegate ()

@end

@implementation SceneDelegate
...
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    // 핑거푸시 딥링크를 사용여부 확인
    BOOL isFingerpushDeeplink = [[Fplink instance] handleDeeplinkWithOptions:connectionOptions onSuccess:nil onFailure:nil];
    if (isFingerpushDeeplink) { return; }
    
    // 다른 딥링크로 앱 실행 시 기존 로직 사용
}

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
    // 핑거푸시 딥링크를 사용여부 확인
    BOOL isFingerpushDeeplink = [[Fplink instance] handleDeeplinkWithOpenURLContexts:URLContexts onSuccess:nil onFailure:nil];
    if (isFingerpushDeeplink) { return; }
    
    // 다른 딥링크로 앱 실행 시 기존 로직 사용
}

- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
    // 핑거푸시 딥링크를 사용여부 확인
    BOOL isFingerpushDeeplink = [[Fplink instance] handleDeeplinkWithContinue:userActivity onSuccess:nil onFailure:nil];
    if (isFingerpushDeeplink) { return; }
    
    // 다른 딥링크로 앱 실행 시 기존 로직 사용
}
...
@end
```

{% endcode %}
{% endtab %}

{% tab title="SwiftUI" %}
앱이 꺼지거나 백그라운드에 있는 상태에서\
**URL Scheme** 또는 **유니버셜 링크** 로 오픈되는 경우   <mark style="color:blue;">`onOpenURL`</mark>&#x20;

해당 콜백에서 <mark style="color:blue;">`handleDeeplink`</mark> 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 <mark style="color:blue;">`setDeeplinkCallback`</mark> 함수를 통해서 유저를 이동시킬 수 있습니다.

```swift
import SwiftUI
import fplink

@main
struct ExampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    let isFingerpushDeeplink = Fplink.instance().handleDeeplink(url: url)
                    if isFingerpushDeeplink { return }
                }
        }
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %} <mark style="color:$tint;">**Notice**</mark>

<mark style="color:blue;">`handleDeeplink`</mark> 는 FP 딥링크인 경우 true를 반환하고, 변환된 링크 정보를 <mark style="color:blue;">`setDeeplinkCallback`</mark> 함수로 전달합니다.&#x20;

FP 딥링크가 아닌 경우 false를 반환하며, SDK 처리는 수행되지 않습니다.

<mark style="color:blue;">`setDeeplinkCallback`</mark>  고객 화면 이동을 자동으로 수행하지 않습니다.

콜백으로 전달된 링크 정보를 기반으로 앱에서 직접 화면 이동을 구현해야 합니다.
{% endhint %}

***

### 디퍼드 딥링크 설정하기

앱이 설치되지 않은 상태에서 디퍼드 딥링크가 설정된 FP 딥링크를 클릭하면, 해당 딥링크 정보가 서버에 저장됩니다.  이후 앱이 설치되고 처음 실행될 때, SDK를 통해 저장된 딥링크 정보를 전달받을 수 있습니다.

<mark style="color:blue;">`handleDeferredDeeplink`</mark> 를 호출하면, 저장된 딥링크 정보를 확인하고 콜백으로 전달합니다. 콜백으로 전달된 링크 정보를 이용해 유저를 원하는 화면으로 이동시켜주세요.

{% tabs %}
{% tab title="AppDelegate (Swift)" %}

```swift
import UIKit
import fplink

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        ...
        // SDK 초기화 이후 작성
        let isFirstCalled = Fplink.instance().handleDeferredDeeplink { url, schemeUrl in
            // 앱 설치 후 handleDeferredDeeplink가 호출 될 때
            if let url {
                //  url을 활용해 유저를 설정한 목적지로 이동하는 로직 작성
            }
        }
        return true
    }
}
```

{% endtab %}

{% tab title="AppDelegate (Objective-C)" %}

```objective-c
#import "AppDelegate.h"
#import <fplink/fplink-Swift.h>

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // SDK 초기화 이후 작성
    BOOL isFirstCalled = [[Fplink instance] handleDeferredDeeplinkOnSuccess:^(NSURL * _Nullable url, NSURL * _Nullable schemeUrl) {
            // 앱 설치 후 handleDeferredDeeplink가 호출 될 때
            if let url {
                //  url을 활용해 유저를 설정한 목적지로 이동하는 로직 작성
            }
        } onFailure:nil];
        
    return YES;
}

@end
```

{% endtab %}

{% tab title="SwiftUI" %}

```swift
import SwiftUI
import fplink

@main
struct ExampleApp: App {
    init() {
        // SDK 초기화 이후 작성
        let isFirstCalled = Fplink.instance().handleDeferredDeeplink { url, schemeUrl in
            // 앱 설치 후 handleDeferredDeeplink가 호출 될 때
            if let url {
                //  url을 활용해 유저를 설정한 목적지로 이동하는 로직 작성
            }
        }
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
```

{% endtab %}
{% endtabs %}

<mark style="color:blue;">`handleDeferredDeeplink`</mark> 함수는 앱이 설치되고 처음으로 호출되었으면 true를 반환하고, SDK가 초기화되지 않았거나 <mark style="color:blue;">`handleDeferredDeeplink`</mark> 함수를 처음으로 호출하는 것이 아닌 경우 false를 전달합니다.

{% hint style="danger" %} <mark style="color:$danger;">**Warning**</mark>

디퍼드 딥링크로 앱을 설치하고, 실행없이 딥링크로 앱을 열면 FP 딥링크는 디퍼드 딥링크 유무에 관계없이 null을 onSuccess에 전달해서 딥링크만 처리되도록 합니다.
{% endhint %}

## 추가 설정하기

#### 앱 내에서 FP 딥링크 활용하기 &#x20;

웹뷰 또는 푸시 메시지 URL 로드와 같이 링크를 여는 방식에 따라, FP 딥링크가 정상적으로 동작하지 않을 수 있습니다. (중간 페이지 이동, 앱스토어 연결, 클릭 추적 등) &#x20;

이 경우 <mark style="color:blue;">`click`</mark> 함수를 사용하여 앱 내에서 FP 딥링크를 정상적으로 처리할 수 있습니다 .

### click 함수 사용 방법&#x20;

<mark style="color:blue;">`click`</mark> 함수는 전달된 URL이 FP 딥링크인지 확인하고, FP 딥링크인 경우 SDK를 통해 처리합니다.

<mark style="color:blue;">`click`</mark> 함수는 두 가지 방식으로 결과를 제공합니다.

1. <mark style="color:blue;">`onSuccess`</mark> 콜백으로 결과를 받는 방식&#x20;
   * 입력된 URL이 FP 딥링크인 경우 true 반환
   * 처리 완료 시 <mark style="color:blue;">`onSuccess`</mark> 콜백으로 최종 URL 전달
   * 처리 실패 시 <mark style="color:blue;">`onFailure`</mark> 콜백 호출
2. <mark style="color:blue;">`setDeeplinkCallback`</mark> 을 통해 결과를 받는 방식 &#x20;
   * 입력된 URL이 FP 딥링크인 경우 true 반환&#x20;
   * 처리 완료 시 <mark style="color:blue;">`setDeeplinkCallback`</mark> 으로 설정한 콜백을 통해 url과 schemeUrl 전달
   * 처리 실패 시 <mark style="color:blue;">`onFailure`</mark> 콜백 호출

입력된 URL이 FP 딥링크가 아닌 경우 false를 반환하며, SDK에서 처리를 수행하지 않습니다.

{% tabs %}
{% tab title="Swift" %}
{% code title="결과를 onSuccess 콜백으로 직접 받는 방식" overflow="wrap" expandable="true" %}

```swift
import UIKit
import fplink

...
let isHandled = Fplink.instance().click(url: url) { url, schemeUrl in
    // url이 FP 링크일 때, 처리에 성공한 경우 url / schemeUrl 처리
} onFailure: {
    // url이 FP링크 일때, 처리에 실패한 경우
} 
if isHandled {
    // url이 FP 링크일 때
}
...
```

{% endcode %}

{% code title="setDeeplinkCallback을 통해 결과를 받는 방식" overflow="wrap" expandable="true" %}

```swift
import UIKit
import fplink

...
let isHandled = Fplink.instance().click(url: url) {
    // url이 FP링크 일때, 처리에 성공한 경우
} onFailure: {
    // url이 FP링크 일때, 처리에 실패한 경우
}
if isHandled {     
 // url이 FP 링크일 때
}
...
```

{% endcode %}
{% endtab %}

{% tab title="Objective-C" %}
{% code title="결과를 onSuccess 콜백으로 직접 받는 방식" overflow="wrap" expandable="true" %}

```objective-c
#import <fplink/fplink-Swift.h>

...
BOOL isHandled = [[Fplink instance] clickWithUrl:url onSuccessWithResult:^(NSURL * _Nullable url, NSURL * _Nullable schemeUrl) {
    // url이 FP 링크일 때, 처리에 성공한 경우 url / schemeUrl 처리
} onFailure:^{
    // url이 FP 링크일 때, 처리에 실패한 경우
}];

if (isHandled) { 
    // url이 FP 링크일 때
}
```

{% endcode %}

{% code title="setDeeplinkCallback을 통해 결과를 받는 방식" overflow="wrap" expandable="true" %}

```objective-c
#import <fplink/fplink-Swift.h>

...
BOOL isHandled = [[Fplink instance] clickWithUrl:url onSuccess:^{
    // url이 FP 링크일 때, 처리에 성공한 경우
} onFailure:^{
    // url이 FP 링크일 때, 처리에 실패한 경우
}];
if (isHandled) {  
    // url이 FP 링크일 때
}  
...
```

{% endcode %}
{% endtab %}
{% endtabs %}

***

### 웹뷰에서 딥링크 처리하기

웹뷰는 기본적으로 딥링크 실행을 지원하지 않기 때문에, 웹뷰 내에서 FP 딥링크를 클릭하는 경우 의도와 다르게 동작할 수 있습니다.

이 경우 <mark style="color:blue;">`click`</mark>  함수를 호출하여 SDK가 딥링크 처리를 대신 수행하도록 설정해야 합니다.

{% tabs %}
{% tab title="Swift" %} <mark style="color:blue;">`WKWebView`</mark>에서 <mark style="color:blue;">`webView(_:decidePolicyFor:decisionHandler:)`</mark> 를 구현하면, 특정 URL이 로드되는 시점에 해당 URL을 확인하고 로딩 여부를 제어할 수 있습니다.

이 메서드에서 <mark style="color:blue;">`click`</mark> 함수를 호출해 FP 딥링크 여부를 확인하고, FP 딥링크인 경우 웹뷰 로딩을 중단하고 앱 내 이동을 처리합니다.

{% code title="결과를 onSuccess 콜백으로 직접 받는 방식" overflow="wrap" expandable="true" %}

```swift
import UIKit
import fplink

...
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping @MainActor (WKNavigationActionPolicy) -> Void) {
    let request: URLRequest = navigationAction.request
    if let url = navigationAction.request.url {
        let isHandled = Fplink.instance().click(url: url) { url, schemeUrl in
            // url이 FP링크 일때, 처리에 성공한 경우 url 처리
        } onFailure: {
            // url이 FP링크 일때, 처리에 실패한 경우
        } 
        if isHandled {
            decisionHandler(.cancel)
            return
        }
    }
    // url이 FP링크가 아닌 경우 처리
    decisionHandler(.allow)
}
...
```

{% endcode %}

{% code title="setDeeplinkCallback을 통해 결과를 받는 방식" overflow="wrap" expandable="true" %}

```swift
import UIKit
import fplink

...
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping @MainActor (WKNavigationActionPolicy) -> Void) {
    let request: URLRequest = navigationAction.request
    if let url = navigationAction.request.url {
        let isHandled = Fplink.instance().click(url: url) {
            // url이 FP링크 일때, 처리에 성공한 경우
        } onFailure: {
            // url이 FP링크 일때, 처리에 실패한 경우
        }
        if isHandled {
            decisionHandler(.cancel)
            return
        }
    }
    // url이 FP링크가 아닌 경우 처리
    decisionHandler(.allow)
}
...
```

{% endcode %}
{% endtab %}

{% tab title="Objective-C" %} <mark style="color:blue;">`WWKWebView`</mark>에서 <mark style="color:blue;">`webView(_:decidePolicyFor:decisionHandler:)`</mark> 를 구현하면, 특정 URL이 로드되는 시점에 해당 URL을 확인하고 로딩 여부를 제어할 수 있습니다.

이 메서드에서 <mark style="color:blue;">`click`</mark> 함수를 호출해 FP 딥링크 여부를 확인하고, FP 딥링크인 경우 웹뷰 로딩을 중단하고 앱 내 이동을 처리합니다.

{% code title="결과를 onSuccess 콜백으로 직접 받는 방식" overflow="wrap" expandable="true" %}

```objective-c
@import WebKit;
#import <fplink/fplink-Swift.h>

...
- (void)webView:(WKWebView *)webView 
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURL *url = navigationAction.request.URL;
    if (url) {
        BOOL isHandled = [[Fplink instance] clickWithUrl:url onSuccessWithResult:^(NSURL * _Nullable url, NSURL * _Nullable schemeUrl) {
            // url이 FP 링크일 때, 처리에 성공한 경우 url / schemeUrl 처리
        } onFailure:^{
            // url이 FP 링크일 때, 처리에 실패한 경우
        }];
        
        if (isHandled) {
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    // url이 FP 링크가 아닌 경우 처리
    decisionHandler(WKNavigationActionPolicyAllow);
}
...
```

{% endcode %}

{% code title="setDeeplinkCallback을 통해 결과를 받는 방식" overflow="wrap" expandable="true" %}

```objective-c
@import WebKit;
#import <fplink/fplink-Swift.h>

...
- (void)webView:(WKWebView *)webView 
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURL *url = navigationAction.request.URL;
    if (url) {
        BOOL isHandled = [[Fplink instance] clickWithUrl:url onSuccess:^{
            // url이 FP 링크일 때, 처리에 성공한 경우
        } onFailure:^{
            // url이 FP 링크일 때, 처리에 실패한 경우
        }];
        if (isHandled) {
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    // url이 FP 링크가 아닌 경우 처리
    decisionHandler(WKNavigationActionPolicyAllow);
}
...
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.fingerpush.com/link/ios-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
