# iOS(Swift)

**Pre-requisites**

&#x20;Conscent.ai iOS SDK supports **iOS 13.0** and above.

<details>

<summary>Installation Steps</summary>

You can download the CCPlugin.xcframework File from [here](https://github.com/tsbmediaventure/ConsCent-docs/tree/master/docs/mobile/IOS%20V1%20SDK) and add it to your project.

Make sure you change the embed mode for CCPlugin.xcframework to "**Embed & Sign**".

</details>

<details>

<summary>Initialize the SDK</summary>

1. Import the CCPlugin framework into your ViewController class.

```swift
import CCPlugin
```

2. In your ViewController class, configure the plugin by providing the client ID and the desired environment mode.

```swift
CCPlugin.shared.configure(mode: .sandbox, clientID: "your-client-id")
```

* yourClientId - Pass your clientId received from Conscent.ai.
* Mode - configuration testing of different environments available.&#x20;

<pre class="language-swift"><code class="lang-swift"><strong>Api Mode can be set as :
</strong>   Mode.sandbox
   Mode.production
</code></pre>

3. You need to set the scrollDepth for the paywall by accessing the scrollDepth property of the CCPlugin.shared instance and modifying its value.

```swift
// Retrieve and set the scroll depth
let screenHeight = scrollView.bounds.height
let scrollDepth: Int = Int(scrollView.contentOffset.y)
CCplugin.shared.scrollDepth = scrollDepth
```

4. You have to confirm UIScrollViewDelegate and you need to set scrollDepth and scrollDepthPercentage.

```swift
  func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    let scrollDepth: Int = Int(scrollView.contentOffset.y)
    CCplugin.shared.scrollDepth = scrollDepth
    let contentHeight = scrollView.contentSize.height
    let scrollViewHeight = scrollView.bounds.height
    let scrollOffset = scrollView.contentOffset.y
    // Calculate the scroll percentage
    let scrollDepthPercentage = (scrollOffset / (contentHeight - scrollViewHeight)) * 100.0
    // Use the scrollPercentage as needed (e.g., update a label or send to analytics)
    print("Scroll Depth: \(scrollDepthPercentage)%")
    CCplugin.shared.scrollDepthPercentage = scrollDepthPercentage
  }
  func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    let contentHeight = scrollView.contentSize.height
    let scrollViewHeight = scrollView.bounds.height
    let scrollOffset = scrollView.contentOffset.y
    // Calculate the scroll percentage
    let scrollDepthPercentage = (scrollOffset / (contentHeight - scrollViewHeight)) * 100.0
    // Use the scrollPercentage as needed (e.g., update a label or send to analytics)
    print("Scroll Depth: \(scrollDepthPercentage)%")
    CCplugin.shared.scrollDepth = Int(scrollOffset)
    CCplugin.shared.scrollDepthPercentage = scrollDepthPercentage
  }
```

5. You need to set the pageLength for the paywall by accessing the pageLength property of the CCPlugin.shared instance and modifying its value.

```swift
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    debugPrint("pageLength:\(scrollView.contentSize.height)")
    CCplugin.shared.pageLength = Int(scrollView.contentSize.height)
  }
```

Enabling the debug mode:

*The debugMode property of the CCPlugin.shared instance can be set to true or false to enable or disable debug mode. When debug mode is enabled, toasts will be shown if the content ID or client ID entered is incorrect. This is useful for development purposes.*

```swift
CCplugin.shared.debugMode = false
```

</details>

<details>

<summary>Initialize the paywall</summary>

In order to ensure that the Conscent.ai Paywall appears on the targeted pages and the deep insights and analytics are collected optimally you need to implement the following method on all the content/article pages.

```swift
CCplugin.shared.showPayWall(contentID: contentID,
           title: contentID,
           categories: ["category1","category2","category3"] ,
           sections: ["section12","section14"],
           tags: ["premium"],
           contentUrl: "https://www.google.com/",
           authorName: "abc",
           parentView: view,
           eventParamsDelegate: self,
           googleLogInDelegate: self,
           completiondelegate: self
    )                                    
```

</details>

| Parameters                    | Description                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| contentID (string)            | This will be your article or content id for which detail needs to be checked.                                                                                                                                                                                                                                                                                                                                                       |
| parentView                    | Pass the view on which you are going to show your content.                                                                                                                                                                                                                                                                                                                                                                          |
| completionDelegate            | This will be used to handle the success and failure cases. Pass the class as the delegate where you want to handle success or failure. This delegate is of the protocol CCPluginCompletionHandlerDelegate, which has three methods: purchasedOrNot(), onPaywallVisible(paywallType, paywallDisplayType, paywallHeight), and onCustomLinkSlot(link, contentId) that will be triggered in case of success and failure of the process. |
| subscriberDelegate(optional)  | <p>This is an optional callback that will be called if you pass your class as its delegate. It will be triggered when the subscription button is tapped. If you don't pass it in your delegate, it will not show the subscription view.</p><p>subscriberDelegate, which has one method: subscribeBtnTap() which will be triggered whenever the user clicks the Subscribe Button.</p>                                                |
| signInDelegate(optional)      | <p>This is an optional callback that will be called if you pass your class as its delegate. It will be triggered when the sign-in button is tapped. If you don't pass it in your delegate, it will not show the sign-in view. </p><p>signInDelegate, which has one method: signInTap() that will be triggered when the user clicks the signin button.</p>                                                                           |
| eventParamsDelegate(optional) | This will be used to get the events params. Pass the class as the delegate where you want to handle success. This delegate is of the protocol CCPluginEventParamsDelegate, which has methods: success(**paywallId**: String, **contentId**: String, **paywallType**: String, **clientId**: String, **anonId**: String) that will be triggered in case of google login click.                                                        |
| googleLogInDelegate(optional) | This will be used to trigger your Google sign. This delegate is of the protocol CCPluginGoogleLogInDelegate, which has methods: startGoogleLogin() that will be triggered in case of google login click.                                                                                                                                                                                                                            |

> **Mandatory Step**
>
> * In your Project go to your target and in the URL types add a new one with URL schemes "conscent".
> * This is important to handle redirection or app launches from the browser.
> * call below function inside of `openURLContexts` scene delegate(inbuilt in iOS).

<figure><img src="/files/BeOSswGXnZ7feoramcTk" alt=""><figcaption><p>Atached a screenshot for the reference:</p></figcaption></figure>

```swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    if let url = URLContexts.first?.url {
       CCplugin.shared.handleRelaunchApp(url: url)
    }
}
```

> You need to call **CCplugin.shared.exitSDK()** while leaving the scope of current controller.

```swift
override func willMove(toParent parent: UIViewController?) {
    super.willMove(toParent: parent)
    if parent == nil {
      // Back button action was triggered
      debugPrint("Back button pressed")
      CCplugin.shared.exitSDK()
    }
  }
```

**Call the below function and pass the userId, after the user has logged in:**

```swift
CCplugin.shared.setClientUserId(clientUserId: "Your_User_Id")
```

<details>

<summary>Login Functionality</summary>

Call this method to invoke our Login System

```swift
CCplugin.shared.onlyLoginFlow(  clientID: clientID, parentView: self.view)
```

</details>

<details>

<summary>Auto Login Functionality</summary>

The client can use his Login System using this functionality:&#x20;

Generate token API is a post API that gets email, and phone number as body parameters and generates an auto login token.

* username: API Key -  present on conscent dashboard
* password: API Secret - present on conscent dashboard

```
ConscentBaseUrl:

SANDBOX: https://sandbox-api.conscent.in
PRODUCTION:  https://api.conscent.in
```

```swift
fileprivate func autoLogIn(emailMobile: String?) {
        // Define the API endpoint URL
        if let apiURL = URL(string: "\(ConscentBaseUrl)/api/v1/client/generate-temp-token") {
            // Create the request object
            var request = URLRequest(url: apiURL)
            request.httpMethod = "POST"
            
            // Define the request body parameters (if any)
            var parameters: [String: Any] = [:]
            if let input = emailMobile, !input.isEmpty {
                if input.contains("@") {
                    parameters["email"] = input
                } else {
                    parameters["phoneNumber"] = input
                }
            }

            do {
                let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [])
                request.httpBody = jsonData
                request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            } catch {
                print("Error creating JSON data: \(error)")
                return
            }
            
            // Set the Basic Authentication header
                let username = "J1EFAQR-H0N4921-QCXKVNH-6W9ZYY9"
                let password = "CFR472795Q42TTQJFV84M37A5G4SJ1EFAQRH0N4921QCXKVNH6W9ZYY9"
                if let data = "\(username):\(password)".data(using: .utf8) {
                    let base64Credentials = data.base64EncodedString()
                    let authString = "Basic \(base64Credentials)"
                    request.addValue(authString, forHTTPHeaderField: "Authorization")
                }

            // Create a URLSession instance
            let session = URLSession.shared

            // Create the data task
            let task = session.dataTask(with: request)
            { (data, response, error) in
                // Check for any errors
                if let error = error {
                    print("Error: \(error)")
                    return
                }
                
                // Ensure there is a valid HTTP response
                guard let httpResponse = response as? HTTPURLResponse else {
                    print("Invalid response")
                    return
                }
                
                // Check the response status code
                if httpResponse.statusCode == 201 {
                    // Successful request
                    if let responseData = data {
                        // Process the response data
                        let responseString = String(data: responseData, encoding: .utf8)
                        print("Response: \(responseString ?? "")")
                        do {
                            if let json = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers) as? [String: AnyObject] {
                                if let tempAuthToken = json["tempAuthToken"] as? String {
                                    CCplugin.shared.configure(mode: .stage, clientID: "6336e56f047afa7cb875739e")
                                    CCplugin.shared.debugMode = true
                                    DispatchQueue.main.async {
                                        if let input = emailMobile, !input.isEmpty {
                                            if input.contains("@") {
                                                CCplugin.shared.autoLogIn(contentID: "Client-Story-Id-1", clientID: "6336e56f047afa7cb875739e", token: tempAuthToken, email: input, parentView: self.view, autoLogInDelegate: self)
                                            } else {
                                                CCplugin.shared.autoLogIn(contentID: "Client-Story-Id-1", clientID: "6336e56f047afa7cb875739e", token: tempAuthToken, phone: input, parentView: self.view, autoLogInDelegate: self)
                                            }
                                        }
                                    }
                                }
                            }
                        } catch let error {
                            print(error)
                        }
                    }
                } else {
                    // Request failed
                    print("Request failed: \(httpResponse.statusCode)")
                }
            }

            // Start the data task
            task.resume()
        }
    }

```

**CCPluginAutoLogInDelegate:**

This will be used to handle the success and failure cases. Pass the class as the delegate where you want to handle success or failure.&#x20;

This delegate is of the protocol CCPluginAutoLogInDelegate, which has two methods:

&#x20;autoLogInsuccess() and autoLogInfailure() that will be triggered in case of success and failure of the process.<br>

**CCPluginUserDetailsDelegate:**

This delegate is of the protocol CCPluginUserDetailsDelegate, which has two methods:&#x20;

success() and failure() that will be triggered in case of success and failure of the process.

```swift
extension AccountViewController: CCPluginUserDetailsDelegate {
    func success(userDetails: String) {
        debugPrint(userDetails)
        if let jsonData = userDetails.data(using: .utf8) {
            do {
                if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
                    // Use the `json` object
                    if let phoneNumber = json["phoneNumber"] as? String {
                        Helper.userName = phoneNumber
                    } else if let email = json["email"] as? String {
                        Helper.userName = email
                    }
                }
            } catch {
                print("Error converting data to JSON: \(error)")
            }
        }
    }
    
    func failure(error: String) {
        debugPrint(error)
    }
}
```

</details>

<details>

<summary>Logout Functionality</summary>

**CCPluginlogout:**

Pass the class as the delegate where you want to handle success or failure.&#x20;

This delegate is of the protocol CCPluginlogout, which has two methods:&#x20;

success() and failure() that will be triggered in case of success and failure of the process.

```swift
CCplugin.shared.getlogout(logoutBtnDelegate: self)
```

```swift
extension AccountViewController: CCPluginlogout {
    func succes(successData: String) {
        debugPrint(successData)
    }
    
    func fail(error: String) {
        debugPrint(error)
    }
}
```

</details>

### Demo APP [<mark style="color:orange;">Link</mark>](https://github.com/RoshanSharma8245/Demo-Blog-IOS)


---

# 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://docs.conscent.ai/version-1.0/mobile-sdk/ios-swift.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.
