# Batch 3.0

Batch SDK v3 is a major release, which introduces breaking changes from 2.x. This guide describes how to update your application when using a previous version.

{% hint style="danger" %}
If your application is still using Batch SDK v1 please follow our [migration guide from V1](/developer/sdk/ios/advanced/migration-guides/2x-migration.md) beforehand.
{% endhint %}

## Upgrading the SDK version

***

⚠️ Batch SDK 3.0 now requires Xcode 16.3 and iOS 15.0 or higher.

To upgrade from v2 to v3, you need to change the SDK version according to your package manager:

{% tabs %}
{% tab title="SPM" %}
Update by using the "update package" option from Xcode or updating your `package.swift`.

{% code title="Package.swift" %}

```swift
.package(url: "https://github.com/BatchLabs/Batch-iOS-SDK", from: "3.0.1")
```

{% endcode %}
{% endtab %}

{% tab title="CocoaPods" %}
Update your `Podfile` as following and run `pod update`.

{% code title="Podfile" %}

```swift
pod 'Batch', '~> 3.0'
```

{% endcode %}
{% endtab %}

{% tab title="Carthage" %}
Update your `Cartfile` if necessary and run `carthage update Batch`.

{% code title="Cartfile" %}

```swift
github "BatchLabs/Batch-iOS-SDK" ~> 3.0
```

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

## Messaging migration

***

Batch SDK v3 adds compatibility for Mobile Landings with Push v2  which can be created from the Batch Dashboard's drag & drop composer.

### In-App Message Interception

The method `batchInAppMessageReady` has been removed from the `BatchMessagingDelegate` protocol. Please replace its usage with the new `BatchInAppDelegate` protocol.

Use the property access `BatchMessaging.inAppDelegate` to set your custom delegate.

So if you were doing:

{% tabs %}
{% tab title="Swift" %}

```swift
// Application delegate

var inAppMsgDelegate = InAppMsgDelegate()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  BatchMessaging.delegate = inAppMsgDelegate
}

// InAppMsgDelegate implementation

@objc
class InAppMsgDelegate: NSObject, BatchMessagingDelegate {
    func batchInAppMessageReady(message: BatchInAppMessage) {
        // Your implementation
    }
}

```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
// Application delegate

@property InAppMsgDelegate *inAppMsgDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.inAppMsgDelegate = [InAppMsgDelegate new];
  BatchMessaging.delegate = self.inAppMsgDelegate;
}

// InAppMsgDelegate implementation

@interface InAppMsgDelegate : NSObject <BatchMessagingDelegate>
@end

@implementation InAppMsgDelegate

- (void)batchInAppMessageReady:(nonnull BatchInAppMessage*)message
{
 // Your implementation
}

@end

```

{% endtab %}
{% endtabs %}

You should now do:

{% tabs %}
{% tab title="Swift" %}

```swift
// Application delegate

var inAppMsgDelegate = InAppMsgDelegate()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  BatchMessaging.inAppDelegate = inAppMsgDelegate
}

// InAppMsgDelegate implementation

@objc
class InAppMsgDelegate: NSObject, BatchInAppDelegate {
    func batchInAppMessageReady(message: BatchInAppMessage) {
        // Your implementation
    }
}

```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
// Application delegate

@property InAppMsgDelegate *inAppMsgDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.inAppMsgDelegate = [InAppMsgDelegate new];
  BatchMessaging.inAppDelegate = self.inAppMsgDelegate;
}

// InAppMsgDelegate implementation

@interface InAppMsgDelegate : NSObject <BatchInAppDelegate>
@end

@implementation InAppMsgDelegate

- (void)batchInAppMessageReady:(nonnull BatchInAppMessage*)message
{
 // Your implementation
}

@end

```

{% endtab %}
{% endtabs %}

For more information, please see the In-App messaging [manual mode](/developer/sdk/ios/mobile-landings.md#manual-mode) section.

### Messaging Delegate&#x20;

The following methods in `BatchMessagingDelegate` have been removed:

* `batchMessageWasCancelledByAutoclose`
* `batchMessageWasCancelledByUserAction`
* `batchMessageWasCancelledByError`
* `batchWebViewMessageDidTriggerAction`

Please update your implementation to use the `batchMessageDidDisappear:(NSString *_Nullable)messageIdentifier reason:(BatchMessagingCloseReason)reason;` method. The new `BatchMessagingCloseReason` enum will provide the context about why the message was closed.

WebView actions will now trigger the updated `batchMessageDidTriggerAction` method, with the `analyticsID` of the action being passed as the `ctaIdentifier`.

The `index` (NSInteger) parameter in `batchMessageDidTriggerAction` has been replaced by `ctaIdentifier` (NSString). The method signature is now&#x20;

```swift
batchMessageDidTriggerAction:(BatchMessageAction *_Nonnull)action
                   messageIdentifier:(NSString *_Nullable)identifier
                       ctaIdentifier:(NSString *_Nonnull)ctaIdentifier;
```

{% hint style="warning" %}
For older MEP (Mobile Engagement Platform) messages, `ctaIdentifier` will be a string in the format `"mepCtaIndex:" + index`.
{% endhint %}

The constant `BatchMessageGlobalActionIndex` now returns a NSString instead of an NSInteger. Update any comparisons or usage accordingly.

So if you were doing:

{% tabs %}
{% tab title="Swift" %}

```swift
// Application delegate

var messagingDelegate = MsgDelegate()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  BatchMessaging.delegate = inAppMsgDelegate
}

// BatchMessagingDelegate implementation

class SampleBatchMessagingDelegate: NSObject, BatchMessagingDelegate {
    
    public func batchMessageDidAppear(messageIdentifier: String?) {
        print("SampleBatchMessagingDelegate - batchMessageDidAppear: \(messageIdentifier)")
    }
    
    public func batchMessageDidTriggerAction(_ action: BatchMessageAction, messageIdentifier identifier: String?, actionIndex index: Int) {
        print("SampleBatchMessagingDelegate - batchMessageDidTriggerAction: \(messageIdentifier)")
    }
   
    public func batchWebViewMessageDidTriggerAction(_ action: BatchMessageAction?, messageIdentifier: String?, analyticsIdentifier: String?) {
        print("SampleBatchMessagingDelegate - batchWebViewMessageDidTriggerAction \(String(describing:action)), tracking ID: \(messageIdentifier ?? "<nil>"), analyticsIdentifier:  \(analyticsIdentifier ?? "<nil>")")
    }

    public func batchMessageWasCancelledByAutoclose(_ messageIdentifier: String?) {
        print("SampleBatchMessagingDelegate - batchMessageWasCancelledByAutoclose: \(messageIdentifier)")
    }

    public func batchMessageWasCancelledByUserAction(_ messageIdentifier: String?) {
        print("SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: \(messageIdentifier)")
    }
    
    public func batchMessageWasCancelledByError(_ messageIdentifier: String?) {
        print("SampleBatchMessagingDelegate - batchMessageWasCancelledByError: \(messageIdentifier)")
    }
    
    public func batchMessageDidDisappear(messageIdentifier: String?) {
        print("SampleBatchMessagingDelegate - batchMessageDidDisappear: \(messageIdentifier)")
    }
}
```

{% endtab %}

{% tab title="Objective-C" %}

<pre class="language-objectivec"><code class="lang-objectivec">// AppDelegate.m
@property SampleBatchMessagingDelegate *messagingDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.messagingDelegate = [SampleBatchMessagingDelegate new];
  BatchMessaging.delegate = self.messagingDelegate;
}
<strong>
</strong><strong>// Header file (.h)
</strong>@interface SampleBatchMessagingDelegate : NSObject &#x3C;BatchMessagingDelegate>

@end

// Implementation file (.m)

@implementation SampleBatchMessagingDelegate

- (void)batchMessageDidAppear:(NSString* _Nullable)messageIdentifier
{
    NSLog(@"SampleBatchMessagingDelegate - batchMessageDidAppear: %@", messageIdentifier);
}

- (void)batchMessageDidTriggerAction:(BatchMessageAction * _Nonnull)action messageIdentifier:(NSString *)identifier actionIndex:(NSInteger)index
{
    NSLog(@"SampleBatchMessagingDelegate - batchMessageDidTriggerAction: %@", messageIdentifier);
}

- (void)batchWebViewMessageDidTriggerAction:(BatchMessageAction * _Nonnull)action messageIdentifier:(NSString *)identifier analyticsIdentifier:(NSString *)analyticsIdentifierex
{
    NSLog(@"SampleBatchMessagingDelegate - batchWebViewMessageDidTriggerAction: %@", messageIdentifier);
}

- (void)batchMessageWasCancelledByAutoclose:(NSString * _Nullable)messageIdentifier
{
    NSLog(@"SampleBatchMessagingDelegate - batchWebVbatchMessageWasCancelledByAutocloseiewMessageDidTriggerAction: %@", messageIdentifier);
}

- (void)batchMessageWasCancelledByUserAction:(NSString * _Nullable)messageIdentifier
{
    NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: %@", messageIdentifier);
}

- (void)batchMessageDidDisappear:(NSString* _Nullable)messageIdentifier
{
    NSLog(@"SampleBatchMessagingDelegate - batchMessageDidDisappear: %@", messageIdentifier);
}

@end
</code></pre>

{% endtab %}
{% endtabs %}

You should now do:

{% tabs %}
{% tab title="Swift" %}

```swift
// Application delegate

var messagingDelegate = MsgDelegate()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  BatchMessaging.delegate = messagingDelegate
}

// BatchMessagingDelegate implementation

class SampleBatchMessagingDelegate: NSObject, BatchMessagingDelegate {
    
    public func batchMessageDidAppear(messageIdentifier: String?) {
        print("SampleBatchMessagingDelegate - batchMessageDidAppear: \(messageIdentifier)")
    }
    
    public func batchMessageDidTriggerAction(_ action: BatchMessageAction, messageIdentifier identifier: String?, ctaIdentifier: String) {
        print("SampleBatchMessagingDelegate - batchMessageDidTriggerAction: \(messageIdentifier)")
        // For MEP messages, ctaIdentifier might be "mepCtaIndex:0", "mepCtaIndex:1", etc.
    }
    
    public func batchMessageDidDisappear(_ messageIdentifier: String?, reason: BatchMessagingCloseReason) {
        switch(reason) {
        case .action:
            print("SampleBatchMessagingDelegate - batchMessageDidDisappear: \(messageIdentifier)")
        case .auto:
            print("SampleBatchMessagingDelegate - batchMessageWasCancelledByAutoclose: \(messageIdentifier)")
        case .user:
            print("SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: \(messageIdentifier)")
        case .error:
            print("SampleBatchMessagingDelegate - batchMessageWasCancelledByError: \(messageIdentifier)")
        }
    }
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
// AppDelegate.m
@property SampleBatchMessagingDelegate *messagingDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.messagingDelegate = [SampleBatchMessagingDelegate new];
  BatchMessaging.delegate = self.messagingDelegate;
}

// Header file (.h)
@interface SampleBatchMessagingDelegate : NSObject <BatchMessagingDelegate>

@end

// Implementation file (.m)
@implementation SampleBatchMessagingDelegate

- (void)batchMessageDidAppear:(NSString* _Nullable)messageIdentifier
{
    NSLog(@"SampleBatchMessagingDelegate - batchMessageDidAppear: %@", messageIdentifier);
}

- (void)batchMessageDidTriggerAction:(BatchMessageAction * _Nonnull)action messageIdentifier:(NSString *)identifier ctaIdentifier:(NSString *_Nonnull)ctaIdentifier
{
    NSLog(@"SampleBatchMessagingDelegate - batchMessageDidTriggerAction: %@", messageIdentifier);
    // For MEP messages, ctaIdentifier might be "mepCtaIndex:0", "mepCtaIndex:1", etc.
}

- (void)batchMessageDidDisappear:(NSString* _Nullable)messageIdentifier reason:(BatchMessagingCloseReason)reason
{
    switch (reason) {
         case BatchMessagingCloseReasonAction:
             NSLog(@"SampleBatchMessagingDelegate - batchMessageDidDisappear: %@", messageIdentifier ?: @"<nil>");
             break;
         case BatchMessagingCloseReasonAuto:
             NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByAutoclose: %@", messageIdentifier ?: @"<nil>");
             break;
         case BatchMessagingCloseReasonUser:
             NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: %@", messageIdentifier ?: @"<nil>");
             break;
         case BatchMessagingCloseReasonError:
             NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByError: %@", messageIdentifier ?: @"<nil>");
             break;
     }
}

@end
```

{% endtab %}
{% endtabs %}

For more information, please see the [listening lifecycle event](/developer/sdk/ios/mobile-landings.md#listening-to-lifecycle-events-and-reacting-to-button-actions) section.

***

To see in details what's precisely changed since V2 please consult our [changelog](https://doc.batch.com/developer/sdk/ios/advanced/migration-guides/pages/CbI3l2jLv4VlFCg9QQzg#id-3.0.0) or visit the [APIs Reference](https://batchlabs.github.io/Batch-iOS-SDK/documentation/batch).


---

# 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://doc.batch.com/developer/sdk/ios/advanced/migration-guides/3x-migration.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.
