> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knotapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS Version 1.0+

## Overview

To simplify your application logic and integration with the Knot iOS SDK, Version 1.0 includes a number of breaking changes that may affect the way your integration works or behaves.

The new version includes a number of significant improvements:

1. Enhanced speed and stability in loading merchant flows.
2. More streamlined initialization of the SDK.
3. Simplified event handling, more informative event messaging, and uniform naming conventions for easier debugging.
4. Improved maintainability and foundations for new feature compatibility.

## Breaking Changes

Configuring and opening the Knot SDK has changed significantly in iOS Version 1.0 and requires some refactoring in order to initialize the SDK with a session. Errors are now encapsulated in a `KnotError` object which provides an enumerated value to debug with.

### Session Initialization

**Changes**

* `Knot.createCardSwitcherSession` and `Knot.createTransactionsLinkSession ` are replaced with a more flexible `KnotConfiguration`.
* The new interface allows configuration of additional properties such as `useCategories`, `useSearch`, and `merchantIds`.
* The `open` action now requires a `KnotConfiguration` and an optional `KnotEventDelegate` which is now `Knot.open(configuration:delegate:)`.

**Before**

<CodeGroup>
  ```swift Swift theme={"system"}
  let session = CardOnFileSwitcherSession(sessionId: "SESSION_ID", clientId: "CLIENT_ID", environment: .sandbox)

  session.entryPoint = "Onboarding" // Optionally, set an entry point.
  session.merchantIds = [44] // Optionally, a specific merchant Id

  Knot.open(session: session)
  ```

  ```objectivec Objective-C theme={"system"}
  #import "CardOnFileSwitcherSession.h"
  #import "Knot.h"

  // ...

  CardOnFileSwitcherSession *session = [[CardOnFileSwitcherSession alloc]
      initWithSessionId:@"SESSION_ID"
                clientId:@"CLIENT_ID"
             environment:CardOnFileSwitcherEnvironmentSandbox];

  session.entryPoint = @"Onboarding"; // Optionally, set an entry point.
  session.merchantIds = @[@44];       // Optionally, a specific merchant ID

  [Knot openWithSession:session];
  ```
</CodeGroup>

**After**

<CodeGroup>
  ```swift Swift theme={"system"}
  let configuration = KnotConfiguration(
      sessionId: "SESSION_ID",
      clientId: "CLIENT_ID",
      environment: .development,
      entryPoint: nil,
      product: .card_switcher,
      useCategories: true,
      useSearch: false,
      merchantIds: nil
  )

  Knot.open(configuration: configuration, delegate: self)
  ```

  ```objectivec Objective-C theme={"system"}
  KnotConfiguration *configuration = [[KnotConfiguration alloc] 
      initWithSessionId:@"SESSION_ID"
                clientId:@"CLIENT_ID"
             environment:KnotEnvironmentDevelopment
              entryPoint:nil
                 product:KnotProductCardSwitcher
           useCategories:YES
               useSearch:NO
             merchantIds:nil];

  [Knot openWithConfiguration:configuration delegate:self];
  ```
</CodeGroup>

### Event Handling

**Changes**

* Event handling is now managed through `KnotEventDelegate` instead of closures.
* Events like `onSuccess`, `onError`, and `onExit` are now **explicit methods** inside a delegate.
* The `onEvent` method introduces the `KnotEvent` object to better handle Knot emitted events.
* The `KnotError` type provides improved error descriptions.
* The `sendCard` parameter is deprecated and its functionality incorporated into the `metaData` dictionary within `KnotEvent` when `KnotEvent.event` equals `AUTHENTICATED`.

**Before**

<CodeGroup>
  ```swift Swift theme={"system"}
  session.onSuccess = { merchant in
      print("Successfully updated card for \(merchant)")
  }

  session.onError = { errorCode, errorMessage in
      print("Error: \(errorCode) - \(errorMessage)")
  }

  session.onExit = {
      print("User exited the SDK")
  }

  session.onEvent = { event, merchant, taskId, sendCard in
      print("event code: \(event), merchant: \(merchant), taskId: \(taskId), sendCard: \(sendCard)")
  }
  ```

  ```
  session.onSuccess = ^(Merchant *merchant) {
      NSLog(@"Successfully updated card for %@", merchant);
  };

  session.onError = ^(NSInteger errorCode, NSString *errorMessage) {
      NSLog(@"Error: %ld - %@", (long)errorCode, errorMessage);
  };

  session.onExit = ^{
      NSLog(@"User exited the SDK");
  };

  session.onEvent = ^(NSInteger event, Merchant *merchant, NSString *taskId, BOOL sendCard) {
      NSLog(@"event code: %ld, merchant: %@, taskId: %@, sendCard: %d",
            (long)event, merchant, taskId, sendCard);
  };
  ```
</CodeGroup>

**After**

<CodeGroup>
  ```swift Swift theme={"system"}
  class MyViewController: UIViewController, KnotEventDelegate {
      func onSuccess(merchant: String) {
          print("Successfully updated card for \(merchant)")
      }

      func onError(error: KnotError) {
          print("Error: \(error.errorDescription)")
      }

      func onEvent(event: KnotEvent) {
          print("Event: \(event.event)")
      }

      func onExit() {
          print("User exited the SDK")
      }
  }
  ```

  ```
  // MyViewController.m
  #import "MyViewController.h"

  @interface MyViewController : UIViewController <KnotEventDelegate>
  @end

  // MyViewController.h
  @implementation MyViewController

  - (void)onSuccessWithMerchant:(NSString *)merchant {
      NSLog(@"Successfully updated card for %@", merchant);
  }

  - (void)onErrorWithError:(KnotError *)error {
      // Assuming `KnotError` has an `errorDescription` property
      NSLog(@"Error: %@", error.errorDescription);
  }

  - (void)onEventWithEvent:(KnotEvent *)event {
      // Assuming `KnotEvent` has an `event` property or method
      NSLog(@"Event: %@", event.event);
  }

  - (void)onExit {
      NSLog(@"User exited the SDK");
  }

  @end 
  ```
</CodeGroup>

**SendCard**

<Warning>
  Most apps do not use the explicit `sendCard` method, as it is rarely applicable to the integration with the Knot SDK.
</Warning>

The `sendCard` parameter has been deprecated and its functionality is incorporated into the `metaData` dictionary within `KnotEvent` when the `KnotEvent.event` equals `AUTHENTICATED`. This change enhances flexibility by allowing additional contextual data to be included in events without requiring separate parameters. Previously, `sendCard` was accessed as a standalone value, but now developers can retrieve it from the `metaData` dictionary in the event callback. This approach ensures better extensibility and consistency across different event types. To access the `sendCard` value, simply extract it from the event’s `metaData` dictionary.

<CodeGroup>
  ```swift Swift theme={"system"}
  class MyViewController: UIViewController, KnotEventDelegate {
      func onSuccess(merchant: String) {
          print("Successfully updated card for \(merchant)")
      }

      func onError(error: KnotError) {
          print("Error: \(error.errorDescription)")
      }

      func onEvent(event: KnotEvent) {
          if event.event == "AUTHENTICATED" {
             print("Event.AUTHENTICATED sendCard: \(event.metaData["sendCard"] as? Bool)")
          }
      }

      func onExit() {
          print("User exited the SDK")
      }
  }}
  ```

  ```
  // MyViewController.h
  @interface MyViewController : UIViewController <KnotEventDelegate>
  @end

  // MyViewController.m

  #import "MyViewController.h"

  @implementation MyViewController

  - (void)onSuccessWithMerchant:(NSString *)merchant {
      NSLog(@"Successfully updated card for %@", merchant);
  }

  - (void)onErrorWithError:(KnotError *)error {
      // Assuming KnotError has a property named errorDescription
      NSLog(@"Error: %@", error.errorDescription);
  }

  - (void)onEventWithEvent:(KnotEvent *)event {
      // Assuming KnotEvent has an 'event' property (NSString *) and 'metaData' (NSDictionary *)
      if ([event.event isEqualToString:@"AUTHENTICATED"]) {
          // Safely extract the "sendCard" value from event.metaData
          NSNumber *sendCardNumber = event.metaData[@"sendCard"];
          BOOL sendCard = [sendCardNumber boolValue];

          NSLog(@"Event.AUTHENTICATED sendCard: %d", sendCard);
      }
  }

  - (void)onExit {
      NSLog(@"User exited the SDK");
  }

  @end
  ```
</CodeGroup>

**Event Names**

The SDK now maps raw event names to standardized event names for easier handling.

| Event Name Prior to 1.0     | 1.0 Event Name                |
| :-------------------------- | :---------------------------- |
| refresh session request     | REFRESH\_SESSION\_REQUEST     |
| merchant clicked            | MERCHANT\_CLICKED             |
| login started               | LOGIN\_STARTED                |
| authenticated               | AUTHENTICATED                 |
| otp required                | OTP\_REQUIRED                 |
| security questions required | SECURITY\_QUESTIONS\_REQUIRED |
| approval required           | APPROVAL\_REQUIRED            |

### Error Handling

Error handling has been improved with more structured and meaningful error messages.

**Changes**

* Errors are now encapsulated in the `KnotError` enum.
* Each error has a **human-readable description** (`errorDescription`) and a **unique error code** (`errorCode`).
* Improved clarity and consistency across error messages.

**Before**

<CodeGroup>
  ```swift Swift theme={"system"}
  session.onError = { errorCode, errorMessage in
      print("Error: \(errorCode) - \(errorMessage)")
  }
  ```

  ```objectivec Objective-C theme={"system"}
  session.onError = ^(NSInteger errorCode, NSString *errorMessage) {
      NSLog(@"Error: %ld - %@", (long)errorCode, errorMessage);
  };
  ```
</CodeGroup>

**After**

<CodeGroup>
  ```swift Swift theme={"system"}
  func onError(error: KnotError) {
      switch error {
      case .invalidSession:
          print("Error: Session is invalid. Please check your session ID.")
      case .expiredSession:
          print("Error: Session has expired. Please start a new session.")
      case .invalidClientId:
          print("Error: Invalid client ID. Ensure your credentials are correct.")
      case .internalError:
          print("Error: An internal error occurred. Try again later.")
      }
  }
  ```

  ```objectivec Objective-C theme={"system"}
  - (void)onErrorWithError:(KnotError)error {
      switch (error) {
          case KnotErrorInvalidSession:
              NSLog(@"Error: Session is invalid. Please check your session ID.");
              break;
          case KnotErrorExpiredSession:
              NSLog(@"Error: Session has expired. Please start a new session.");
              break;
          case KnotErrorInvalidClientId:
              NSLog(@"Error: Invalid client ID. Ensure your credentials are correct.");
              break;
          case KnotErrorInternalError:
              NSLog(@"Error: An internal error occurred. Try again later.");
              break;
      }
      
      // If you also need the string description or error code:
      NSString *description = KnotErrorDescription(error);
      NSString *code = KnotErrorCode(error);
      NSLog(@"Additional info => Description: %@, Code: %@", description, code);
  }
  ```
</CodeGroup>

**Error Types**

The Knot SDK provides predefined error cases for you to handle based on your own needs.

| Error Case       | Description                 |
| :--------------- | :-------------------------- |
| .invalidSession  | The session is invalid.     |
| .expiredSession  | The session has expired.    |
| .invalidClientId | The client ID is invalid.   |
| .internalError   | An internal error occurred. |

### Closing the SDK

<Warning>
  Most apps do not use the explicit `close` method, as it is infrequently applicable to the integration with the Knot SDK.
</Warning>

**Changes**

* Closing the SDK is now statically accessed via `Knot.close()` as opposed to being bound to the session object.

**Before**

<CodeGroup>
  ```swift Swift theme={"system"}
  session.close()
  ```

  ```objectivec Objective-C theme={"system"}
  [session close];
  ```
</CodeGroup>

**After**

<CodeGroup>
  ```swift Swift theme={"system"}
  Knot.close()
  ```

  ```objectivec Objective-C theme={"system"}
  [Knot close];
  ```
</CodeGroup>
