[< Back](../readme.md)




# Integration Guide for `PenNav P&P` Native iOS Libraries in Flutter


#### Requirements

- iOS 13.0 or later
- iPadOS 13.0 or later

#### Prerequisites
- Flutter SDK installed.
- Basic knowledge of Flutter and iOS development.
- Penguin native iOS libraries (Penguin.xcframework, PenguinRenderer.xcframework, PenNavUI.xcframework).
- Mapbox Account: Register for a Mapbox account to obtain an access token for Mapbox services.

## Steps
### **Step 1 : Install Mapbox Maps SDK v10.6.4 for iOS**

To install the Mapbox Maps SDK for iOS and get authorization, follow these steps:


#### **1. Register and Get Authorization**

1. **Create a Mapbox Account:**
   - Go to [Mapbox's Sign Up page](https://www.mapbox.com/signup/) and create a free account.

2. **Get Your Access Token:**
   - After logging in, go to your [Mapbox account dashboard](https://account.mapbox.com/).
   - Navigate to the "Access Tokens" section.
   - Copy your default access token or create a new token with the desired permissions.
3. **Set Up Your Secret Token (Important)**

   - For guidance on configuring your secret token, please refer to the Mapbox installation guide at: [Mapbox iOS Maps Installation](https://docs.mapbox.com/ios/maps/guides/install/).

4. **Configure your public token**
    To configure your public access token, follow these steps:

    - Open your project's Info.plist file
    - Hover over a key and click the plus button
    - Type MBXAccessToken into the key field
    - Click the value field and paste in your public access token.

    <video width="640" height="480" controls>
      <source src="https://docs.mapbox.com/ios/assets/medias/MapsInstallPublicToken-eb2f6fbf8715def5ae8eaa35a5b562c4.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
--- 

### **Step 2 : Add Native Libraries to Your Flutter Project**

  1. **Create the Frameworks Folder:**
     - Open Finder and navigate to your Flutter project’s `ios` directory.
     - Right-click inside the `ios` folder, select **New Folder**, and name the folder **Frameworks**.

  2. **Move .xcframework Files:**
     - Locate your `.xcframework` files in Finder.
     - Select the files, right-click, and choose **Copy**.
     - Navigate to the newly created **Frameworks** folder.
     - Right-click inside the **Frameworks** folder and select **Paste** to move the files.

  #### Update the Xcode Project

  1. **Open Xcode Workspace:**
     - Open the `ios/Runner.xcworkspace` file in Xcode.

  2. **Add .xcframework Files to Xcode:**
     - Drag and drop the `.xcframework` files into the "Frameworks" group in the Xcode project navigator.
     - Ensure the **Copy items if needed** checkbox is selected.

  #### Update Build Settings

  1. **Configure Framework Search Paths:**
     - Select the **Runner** target in Xcode.
     - Go to the **Build Settings** tab.
     - Add `$(SRCROOT)/Frameworks` to the **Framework Search Paths**.

  2. **Verify Framework Embedding:**
     - In the **General** tab of the Runner target, check that the frameworks are listed under **Frameworks, Libraries, and Embedded Content**.
     - Ensure the frameworks are set to **Embed & Sign**.


---



### **Step 3 : Configuring Privacy Permissions in `Info.plist`**

In the iOS project, modify the `Info.plist` file to include the following keys. Set their data types to `String` and provide descriptive values that explain the necessity of your app's access to these privacy-sensitive resources:

- `NSLocationAlwaysAndWhenInUseUsageDescription`
- `NSLocationWhenInUseUsageDescription`
- `NSBluetoothAlwaysUsageDescription`
- `NSMotionUsageDescription`

Ensure that each key is assigned a string value detailing the purpose for which your application requires access to the respective data.


---




### **Step 4 : Modify the Podfile**

1. Navigate to your Flutter project's `ios` directory:
   ```sh
   cd path/to/your/flutter/project/ios
   ```

2. Open the `Podfile` in a text editor:
   ```sh
   open Podfile
   ```

3. Update your `Podfile` to include the Mapbox Maps SDK dependency and apply the necessary build setting. Your `Podfile` should look like this:

      ```ruby
      target 'Runner' do
        use_frameworks!
        use_modular_headers!

        pod 'MapboxMaps', '10.16.4' 

        flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
        target 'RunnerTests' do
          inherit! :search_paths
        end
      end

      post_install do |installer|
        installer.pods_project.targets.each do |target|
          target.build_configurations.each do |config|
            config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
          end
        end
      end
      ```

#### **3. Install CocoaPods Dependencies**

1. Install the CocoaPods dependencies by running:
   ```sh
   pod install
   ```

2. This will create or update the `Pods` directory and the `.xcworkspace` file.

#### **4. Open the Xcode Workspace**

1. Open the generated `.xcworkspace` file to make sure the Mapbox SDK is correctly integrated:
   ```sh
   open Runner.xcworkspace
   ```

2. Always use this `.xcworkspace` file to open your project in Xcode, as it includes the CocoaPods dependencies.


---

####   Native iOS configuration steps
   - **For detailed instructions on how to configure and initialize the Penguin SDKs, please start by checking out the [Configuration Steps](configuringPanNavUI.md#configuration-steps). It is important to begin here to ensure a proper setup.**

--- 

### **Step 5 : Create the Flutter Platform View Factory View**



- **Implement the View Factory:**
  Create `PenguinViewFactory.swift` in `ios/Runner`.

  ```swift
  import Flutter
  import UIKit

  class PenguinViewFactory: NSObject, FlutterPlatformViewFactory {
      private var messenger: FlutterBinaryMessenger

      init(messenger: FlutterBinaryMessenger) {
          self.messenger = messenger
          super.init()
      }

      func create(
          withFrame frame: CGRect,
          viewIdentifier viewId: Int64,
          arguments args: Any?
      ) -> FlutterPlatformView {
          return PenguinView(
              frame: frame,
              viewIdentifier: viewId,
              arguments: args,
              binaryMessenger: messenger)
      }

      public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
          return FlutterStandardMessageCodec.sharedInstance()
      }
  }
  ```
--- 
### **Step 6 : Implement the Custom View:**
  Create `PenguinView.swift` in `ios/Runner`.

  ```swift
  import Flutter
  import UIKit

  class PenguinView: NSObject, FlutterPlatformView {
      private var _view: UIView

      init(
          frame: CGRect,
          viewIdentifier viewId: Int64,
          arguments args: Any?,
          binaryMessenger messenger: FlutterBinaryMessenger?
      ) {
          _view = UIView()
          super.init()

          // Initialize and configure the view using Penguin libraries
          // Example:
          // let penguinView = PenguinLibraryView(frame: frame)
          // _view.addSubview(penguinView)
      }

      func view() -> UIView {
          return _view
      }
  }
  ```
--- 

### **Step 7 : Register the Platform View in AppDelegate**

- **Modify `AppDelegate.swift`:**

  ```swift
  import UIKit
  import Flutter

  @UIApplicationMain
  @objc class AppDelegate: FlutterAppDelegate {
      override func application(
          _ application: UIApplication,
          didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
          GeneratedPluginRegistrant.register(with: self)

          let penguinFactory = PenguinViewFactory(messenger: self.registrar(forPlugin: "penguin")!.messenger())
          self.registrar(forPlugin: "PenguinView")!.register(penguinFactory, withId: "penguin_lib")

          return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
  }
  ```
---

### **Step 8 : Use the Platform View in Flutter**

- **Modify Your Dart Code:**

  ```dart
  import 'package:flutter/material.dart';
  import 'package:flutter/services.dart';

  void main() {
    runApp(MyApp());
  }

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      const viewType = 'penguin_lib';
      final creationParams = <String, dynamic>{};

      return MaterialApp(
        home: Scaffold(
          body: Container(
            child: Platform.isIOS
                ? UiKitView(
                    viewType: viewType,
                    layoutDirection: TextDirection.ltr,
                    creationParams: creationParams,
                    onPlatformViewCreated: onPlatformViewCreated,
                    creationParamsCodec: const StandardMessageCodec(),
                  )
                : AndroidView(
                    viewType: viewType,
                    layoutDirection: TextDirection.ltr,
                    creationParams: creationParams,
                    onPlatformViewCreated: onPlatformViewCreated,
                    creationParamsCodec: const StandardMessageCodec(),
                  ),
          ),
        ),
      );
    }

    Future<void> onPlatformViewCreated(int id) async {
      // Handle platform view creation
    }
  }
  ```

### **Test Your Integration**

- Build and run your app on an iOS device or simulator.
- Verify that the custom native view appears and functions as expected.

### Tips:
- Ensure all framework dependencies are correctly resolved.
- Check that you have the appropriate permissions and entitlements if required by the native libraries.
- Debug using Xcode if you encounter any issues related to the view or integration.

[< Back](../readme.md)