iOS SDKs

Prev Next

Available in Classic and VPC

It describes how to use the App Safer iOS SDK for the security of iOS apps. You can integrate App Safer by installing the SDK and configuring the environment.

Note

As for the overall sample codes to which App Safer is applied, check the sample code.

Install SDK and configure environment

To use the features provided by App Safer, first install the iOS SDK and configure the environment. The library of App Safer for iOS apps consists of one framework and supports both the Bitcode Enable/Disable environment. The following describes how to configure it.

Note

It is recommended to build in Xcode 8.0 or later environment.

  1. Decompress the downloaded SDK in an arbitrary directory.
  2. Check the project's Bitcode settings.
    • Path: Build Settings > Build Options > Enable Bitcode
  3. Add the App Safer framework to the project.
    • Path: File > Add Files to "Your Project"... > Options > select Copy items if needed > select AppSaferFramework.framework > click Add
  4. When using Swift, create a bridging header for compatibility with Objective-C.
    • Create a header file: File > New File... > select Header File > Set filename "AppSaferFramework-Bridging-Header.h" at the project root
    • Add a header file to build settings: Build Settings > Swift Compiler - General > Objective-C Bridging Header > Enter the following code inAppSaferFramework-Bridging-Header.h
      #ifndef AppSaferFramework_Bridging_Header_h
      #define AppSaferFramework_Bridging_Header_h
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      #endif /* AppSaferFramework_Bridging_Header_h */
      

Apply the debugging prevention function

The anti-debugging feature is automatically applied when the SDK is installed. If debugging is required, use it with the App Safer SDK temporarily disabled.

Apply the capture blocking and detection function

You must call the API to apply the screen protection function during app preview screen protection, screenshot detection, recording and mirroring provided by the App Safer SDK.

  • Older than iOS 13.0: call the App Safer API from AppDelegate according to the life cycle of the app
  • iOS 13.0 or newer: call the APP Safer API from SceneDelegate according to the life cycle of the app

The following is an example of calling the API.
If you register selector, you can receive a callback and perform the desired action when a capture event is detected.

AppDelegate (Swift)
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    @objc func didDetectCapture() -> Void  {
        print("[DETECT] Detected Screenshot in AppDelegate");
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        AppSafer.registerScreenProtectionObserver(window, observer: self, selector: #selector(didDetectCapture))
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        AppSafer.preventScreenshot(window, isInvisible: 0)
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        AppSafer.preventScreenshot(window, isInvisible: 1)
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        AppSafer.preventScreenshot(window, isInvisible: 0)
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        AppSafer.preventScreenshot(window, isInvisible: 1)
    }
}
AppDelegate (Objective-C)
#import "AppDelegate.h"
#import <AppSaferFramework/AppSaferFramework.h>

@interface AppDelegate ()
@end

@implementation AppDelegate

- (void)didDetectCapture {
    NSLog(@"[DETECT] Detected Screenshot in AppDelegate");
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions {
    [AppSafer registerScreenProtectionObserver:_window observer:self selector:@selector(didDetectCapture)];
    
    return YES;
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    [AppSafer preventScreenshot:_window isInvisible:false];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [AppSafer preventScreenshot:_window isInvisible:false];
}

- (void)applicationWillResignActive:(UIApplication *)application {
    [AppSafer preventScreenshot:_window isInvisible:true];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [AppSafer preventScreenshot:_window isInvisible:true];
}
@end
SceneDelegate (Swift)
import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    @objc func didDetectCapture() -> Void  {
        print("[DETECT] Detected Screenshot in AppDelegate");
    }
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        let contentView = ContentView()

        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
            
            AppSafer.registerScreenProtectionObserver(window, observer: self, selector: #selector(didDetectCapture))
        }
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        AppSafer.preventScreenshot(window, isInvisible: 0)
    }

    func sceneWillResignActive(_ scene: UIScene) {
        AppSafer.preventScreenshot(window, isInvisible: 1)
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        AppSafer.preventScreenshot(window, isInvisible: 0)
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        AppSafer.preventScreenshot(window, isInvisible: 1)
    }
}

SceneDelegate (Objective-C)
#import "SceneDelegate.h"
#import <AppSaferFramework/AppSaferFramework.h>

@interface SceneDelegate ()
@end

@implementation SceneDelegate

- (void)didDetectCapture {
    NSLog(@"[DETECT] Detected Screenshot in SceneDelegate");
}

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)) {
    [AppSafer registerScreenProtectionObserver:_window observer:self selector:@selector(didDetectCapture)];
}

- (void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0)) {
    [AppSafer preventScreenshot:_window isInvisible:false];
}

- (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) {
    [AppSafer preventScreenshot:_window isInvisible:false];
}

- (void)sceneWillResignActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) {
    [AppSafer preventScreenshot:_window isInvisible:true];
}

- (void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0))  {
    [AppSafer preventScreenshot:_window isInvisible:true];
}

@end

Provided APIs

The App Safer API is provided in 2 packages, and the APIs that can be called from each package are as follows:

  • AppSafer
Name Description
initAppSafer Initialize to use AppSafer
checkTampering Real-time security detection
  • Jailbreak detection
  • Simulator detection
  • Debugging detection
  • Memory Tampered detection
  • Unauthorized Signature detection
setUserId Set user identifier
  • AppSaferDelegate
    • This is a callback function that operates asynchronously.
    • Result handling is delegated through AppSaferDelegate.
    • To receive scan results, you must implement AppSaferDelegate and register it using the initAppSafer function.
    • When using Swift, you must implement it in class, not struct, and add both AppSaferDelegate and NSObject.
Name Requirement status Description
appSaferDidInitFinish Required Check the result of initializing App Safer
appSaferDidCheckTamperingFinish Required Check the result of executing the checkTampering function
appSaferDetectedJailbreak Optional Call it when the jailbreaking of the device is detected
appSaferDetectedSimulator Optional Call it when it detects that the device is running in a virtual machine
appSaferDetectedDebugging Optional Call it when debugging is detected
appSaferDetectedMemoryTampered Optional Call it when alteration of the app memory is detected

initAppSafer

You can use App Safer only when it is successfully initialized. To initialize App Safer, use the following code.
Information needed to send the log and variables used globally are initialized.

  • You must implement AppSaferDelegate to receive notification of successful initialization.
func initAppSafer(_ delegate: AppSaferDelegate!, serviceCode: String!, key appsaferKey: String!) -> Int32
- (int) initAppSafer:(id<AppSaferDelegate>)delegate serviceCode:(NSString *)serviceCode key:(NSString *)appsaferKey
  • Parameters

    Parameters Description
    delegate An instance in which AppSaferDelegate is implemented
    serviceCode The code for using App Safer
    NAVER Cloud Platform users must pass "ncloud"
    appsaferKey The App Safer Key value created when an app is registered on the console
  • Return value

    Return value Description
    SUCCESS(0) Success
    FAIL(-1) Failure
  • Example

    struct ContentView: View {
        func initAppSaferExample() {
           // APP_SAFER_KEY generated when registering an app to the Console
           let result = AppSafer().initAppSafer(AppSaferDelegator.delegator, serviceCode: "ncloud", key: "<APP_SAFER_KEY>")
    
           NSLog("initAppSafer() result: %d", result);
    
           if(result == SUCCESS) {
                 // init success
           } else if(result == FAIL) {
                 // init fail
           }
        }
    
        var body: some View {
           Button("initAppSafer") {
                 initAppSaferExample()
           }
        }
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (IBAction)initAppSaferExample:(id)sender {
        AppSafer *appSafer = [[AppSafer alloc] init];
    
        int res = FAIL;
        if(appSafer != nil) {
           // APP_SAFER_KEY generated when registering an app to the Console
           res = [appSafer initAppSafer:self serviceCode:@"ncloud" key:@"<APP_SAFER_KEY>"];
    
           NSLog(@"initAppSafer() result: %d", res);
    
           if(res == SUCCESS) {
                 // init success
           }
        }
    }
    

checkTampering

To execute the real-time security detection function, use the following code.

func checkTampering()
- (int)checkTampering
  • Return value

    Return value Description
    SUCCESS(0) Scan start succeeded
    FAIL(-1) Scan start failed
    BLOCK(2) Blocked for violating the security policy
    BEFOREINIT(3) App Safer is not initialized.
  • Example

    struct ContentView: View {
        func checkTamperingExample() {
            let result = AppSafer().checkTampering()
    
            switch(result) {
            case FAIL:
                print("Failed to check tampering")
                break
            case SUCCESS:
                print("Check Tampering Success")
                break
            case BLOCK:
                print("Device is blocked")
                break
            case BEFOREINIT:
                print("AppSafer is not initialized")
                break
            default:
                break
            }
        }
    
        var body: some View {
            Button("checkTampering") {
                checkTamperingExample()
            }
        }
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (IBAction)checkAppSafer:(id)sender {
        AppSafer *appSafer = [[AppSafer alloc] init];
    
        if(appSafer != nil) {
            int res = [appSafer checkTampering];
    
            switch(res) {
                case FAIL:
                    NSLog(@"Failed to check tampering");
                    break;
                case SUCCESS:
                    NSLog(@"Check Tampering Success");
                    break;
                case BLOCK:
                    NSLog(@"Device is blocked");
                    break;
                case BEFOREINIT:
                    NSLog(@"AppSafer is not initialized");
                    break;
            }
        } else {
            NSLog(@"AppSafer is nil");
        }
    }
    
    @end
    

setUserId

Use the code below to include the user identifier in the log sent to the App Safer server when initialization and detection events occur.

func setUserId(_ userId: String!) -> Int32
- (int)setUserId:(NSString *)userId
  • Parameters

    Parameters Description
    userId User identifier
  • Return value

    Return value Description
    SUCCESS(0) Setting succeeded
    FAIL(-1) Setting failed
  • Example

    struct ContentView: View {
        func setUserIdExample(_ userId: String) {
           print("setUserId(\(userId))")
    
           let result = AppSafer().setUserId(userId)
    
           switch(result) {
           case FAIL:
                 print("Failed to set userId: \(userId)")
                 break
           case SUCCESS:
                 print("setUserId() Success: \(userId)")
                 break
           default:
                 break
           }
        }
    
        var body: some View {
           Button("setUserId") {
                 setUserIdExample("ExampleUserId")
           }
        }
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (IBAction)setUserId:(id)sender {
        AppSafer *appSafer = [[AppSafer alloc] init];
    
        if(appSafer != nil) {
           NSLog(@"setUserId(%@)", [self.useridText text]);
    
           int res = [appSafer setUserId:[self.useridText text]];
    
           switch(res) {
                 case FAIL:
                    NSLog(@"Failed to set userId");
                    break;
                 case SUCCESS:
                    NSLog(@"setUserId Success");
                    break;
           }
        } else {
           NSLog(@"AppSafer is nil");
        }
    }
    

appSaferDidInitFinish

After calling the initAppSafer function, the function below is called to pass the initialization result.

func appSaferDidInitFinish(_ result: Int32)
- (void)appSaferDidInitFinish:(int)result
  • Parameters

    Parameters Description
    SUCCESS(0) Successfully initialized
    FAIL(-1) Initialization failed
    BLOCK(2) Blocked for violating the security policy
  • Example

    func appSaferDidInitFinish(_ result: Int32) {
        print("appSaferDidInitFinish result: \(result)");
        if(result == BLOCK) {
           print("Device is blocked!");
           // add to exit application logic
        }
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (void)appSaferDidInitFinish:(NSUInteger)result msg:(NSString *)message {
        NSLog(@"appSaferDidInitFinish result: %d", result);
        if(result == BLOCK) {
           NSLog(@"Device is blocked!");
           // add to exit application logic
        }
    }
    

appSaferDidCheckTamperingFinish

The function below is called to pass the result of executing the checkTampering function.

func appSaferDidCheckTamperingFinish(_ result: Int32)
- (void)appSaferDidCheckTamperingFinish:(int)result
  • Parameters

    Parameters Description
    FAIL(-1) Scan failed
    SAFE(0) The event is not detected.
    DETECT(1) The event is detected.
    BLOCK(2) Blocked
  • Example

    func appSaferDidCheckTamperingFinish(_ result: Int32) {
        print("appSaferDidCheckTamperingFinish result: " + (
                 result == FAIL   ? "FAIL" :
                 result == SAFE   ? "SAFE" :
                 result == DETECT ? "DETECT" :
                 result == BLOCK  ? "BLOCK": "UNKNOWN"))
    
        if(result == BLOCK) {
           print("Device is blocked!")
           // add to exit application logic
        }
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (void)appSaferDidCheckTamperingFinish:(int)result {
        NSLog(@"appSaferDidCheckTamperingFinish result: %@",
              result == FAIL   ? @"FAIL" :
              result == SAFE   ? @"SAFE" :
              result == DETECT ? @"DETECT" :
              result == BLOCK  ? @"BLOCK": @"UNKNOWN");
    
        if(result == BLOCK) {
           NSLog(@"Device is blocked!");
           // add to exit application logic
        }
    }
    

appSaferDetectedJailbreak

When the jailbreaking of the device is detected, the following function is called. You can use it when you want to receive the result even if the operation of the checkTampering function is not completed.

func appSaferDetectedJailbreak()
- (void)appSaferDetectedJailbreak
  • Example

    func appSaferDetectedJailbreak() {
        print("[DETECT] appSaferDetectedJailbreak");
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (void)appSaferDetectedJailbreak {
        NSLog(@"[DETECT] appSaferDetectedJailbreak");
    }
    

appSaferDetectedSimulator

The function below is called when it is detected that the app is running in a virtual machine. You can use it when you want to receive the result even if the operation of the checkTampering function is not completed.

func appSaferDetectedSimulator()
- (void)appSaferDetectedSimulator
  • Example

    func appSaferDetectedSimulator() {
        print("[DETECT] appSaferDetectedSimulator");
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (void)appSaferDetectedSimulator {
        NSLog(@"[DETECT] appSaferDetectedSimulator");
    }
    

appSaferDetectedDebugging

When debugging is detected in the device, the following function is called. You can use it when you want to receive the result even if the operation of the checkTampering function is not completed.

func appSaferDetectedDebugging()
- (void)appSaferDetectedDebugging
  • Example

    func appSaferDetectedDebugging() {
        print("[DETECT] appSaferDetectedDebugging");
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (void)appSaferDetectedDebugging {
        NSLog(@"[DETECT] appSaferDetectedDebugging");
    }
    

appSaferDetectedMemoryTampered

When memory alteration is detected, the following function is called. You can use it when you want to receive the result even if the operation of the checkTampering function is not completed.

func appSaferDetectedMemoryTampered()
- (void)appSaferDetectedMemoryTampered
  • Example

    func appSaferDetectedMemoryTampered() {
        print("[DETECT] appSaferDetectedMemoryTampered");
    }
    
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @implementation ViewController
    
    - (void)appSaferDetectedMemoryTampered {
        NSLog(@"[DETECT] appSaferDetectedMemoryTampered");
    }