Skip to content

App crashing on version 6.6.3 #982

@kgArrk

Description

@kgArrk

✍️ Issue Description

My app was working fine with the Iterable sdk v6.5.12. I updated the sdk version to 6.6.3. After that I started facing a crash on the app launch. So what we are doing here is we are downloading a fresh instance of our app without having any previous versions of our app. The app launches well, after login we kill the app. Now whenever we launch the app it crashes every time.
Please provide a clear and concise description of the issue you are experiencing.

📋 Steps to Reproduce

  1. Delete any previous app. Reinstall the app again with the latest iterable sdk 6.6.3.
  2. Login into the app.
  3. Kill the app and remove from the stack.
  4. Now launch the app again it crashes every time and in the Xcode I saw that it gives the BAD ACCESS error.
    (List all necessary steps to reliably reproduce the issue.)

👤 Iterable orgId: Enter your organization id

📦 Iterable SDK version: 6.6.3

📲 iOS SDK version: iOS 26, iOS 15.8.3, iOS 18.3.1

The issue is occurring only on 6.6.3, everything was working fine with the 6.5.12. Further I am also putting the method below where the crash is occurring .
Method Name:
func data(forKey key: String) -> Data? {
var keychainQueryDictionary = setupKeychainQueryDictionary(forKey: key)

    // Limit search results to one
    keychainQueryDictionary[SecMatchLimit] = SecMatchLimitOne
    
    // Specify we want Data/CFData returned
    keychainQueryDictionary[SecReturnData] = CFBooleanTrue
    
    // Search
    var result: AnyObject?
    let status = SecItemCopyMatching(keychainQueryDictionary as CFDictionary, &result)
    
    return status == noErr ? result as? Data : nil
}

Line :45

Class Name : KeychainWrapper.

Please find below our code where we are using the Iterable Config .

import Foundation
import IterableSDK

protocol PushNotificationsService {
func launch(with launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
func register(deviceToken: Data)
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
completionHandler: @escaping (UIBackgroundFetchResult) -> Void
)
var handleDeepLinkNotification: ArgumentedClosure? { get set }
}

final class IterablePushNotificationsService: NSObject, PushNotificationsService, IterableInAppDelegate {
private let userService: RegisteredUserServiceProtocol
private let appId: String
private let interactions: InteractionsFactoryProtocol
private let notificationsCoreData: NotificationsCoreDataProtocol
private let eventBroadcaster: EventBroadcasterProtocol
private let config = IterableConfig()
private let observer = RegisteredUserObserver()
private let center = UNUserNotificationCenter.current()
private let iterableAPIService: IterableAPIServiceProtocol

var handleDeepLinkNotification: ArgumentedClosure<URL>?

deinit {
    userService.removeObserver(observer)
}

init(
    userService: RegisteredUserServiceProtocol,
    details: ConfigurationDetailsProviderProtocol,
    interactions: InteractionsFactoryProtocol,
    notificationsCoreData: NotificationsCoreDataProtocol,
    iterableAPIService: IterableAPIServiceProtocol,
    eventBroadcaster: EventBroadcasterProtocol
) {
    self.interactions = interactions
    self.userService = userService
    appId = details.iterableAppID()
    self.notificationsCoreData = notificationsCoreData
    self.iterableAPIService = iterableAPIService
    self.eventBroadcaster = eventBroadcaster
    super.init()

    observer.updateHandler = { [weak self] user in
        guard let self = self else { return }
        guard user.email != IterableAPI.email else { return }

        IterableAPI.logoutUser()
        IterableAPI.setEmail(user.email)
    }

    userService.addObserver(observer)
}

func launch(with launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
    center.delegate = self
    config.urlDelegate = self
    config.authDelegate = self
    config.inAppDelegate = self
    config.inAppDisplayInterval = 0.0
    config.allowedProtocols = ["nxtr"]
    
    IterableAPI.initialize(
        apiKey: appId,
        launchOptions: launchOptions,
        config: config
    )
}

func onNew(message: IterableInAppMessage) -> InAppShowResponse {
    let blockedScreens: Set<ScreenName> = [
        .offerDetail,
        .offersNearMe,
        .offersNearMeFilter,
        .webBrowser,
        .SSOVerification,
        .productBundle,
        .cardDuration,
        .cardDeliveryOptions,
        .cashbackApplication,
        .cardDeliveryHomeAddressLookup,
        .addresInput,
        .cardDeliveryPOS,
        .personalDetails,
        .photoPicker,
        .confirmPersonalDetails,
        .paymentAdditionalDetails,
        .billingAdrresInfo,
        .cardOnWay,
        .cardEditHolder,
        .paymentSheet,
        .paymentConfirmation,
        .cardDetail,
        .cardPurachaseSummary,
        .passIDCheckpoint,
        .passRejected,
        .passTruthfulness,
        .journeySuccess,
        .passCancelConfirmation,
        .passIDRemainingSteps,
        .referFDE,
        .passWalkThrough,
        .passDocumentSelection,
        .passDocumentPicker,
        .passDocumentScan,
        .passConfirmDetails,
        .passFlagDetails,
        .passPhotoGuidelines,
        .passPhotoAcknowledgement,
        .passPhotoPopover,
        .passphotoCapture,
        .passPhotoValidation
    ]
    let current = ScreenTracker.currentScreen
    if blockedScreens.contains(current) {
        return .skip
    }
    return .show
}

func register(deviceToken: Data) {
    IterableAPI.register(token: deviceToken)
}

func application(
    _ application: UIApplication,
    didReceiveRemoteNotification userInfo: [AnyHashable: Any],
    completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
    IterableAppIntegration.application(
        application,
        didReceiveRemoteNotification: userInfo,
        fetchCompletionHandler: completionHandler
    )
}

}

// MARK: - IterableURLDelegate

extension IterablePushNotificationsService: IterableURLDelegate {
func handle(iterableURL url: URL, inContext context: IterableActionContext)
-> Bool {
if !url.isWebURL() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.handleDeepLinkNotification?(url)
}
return true
}
return false
}
}

// MARK: - UNUserNotificationCenterDelegate

extension IterablePushNotificationsService: UNUserNotificationCenterDelegate {
public func userNotificationCenter(
_: UNUserNotificationCenter,
willPresent _: UNNotification,
withCompletionHandler completionHandler:
@escaping (UNNotificationPresentationOptions) -> Void
) {
eventBroadcaster.broadcast(.fetchNewNotifications)
completionHandler([.badge, .sound, .alert])
}

public func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    didReceive response: UNNotificationResponse,
    withCompletionHandler completionHandler: @escaping () -> Void
) {
    IterableAPI.inAppManager.isAutoDisplayPaused = true
    try? CoreDataService.shared.readNotificationsWith(
        notificationId: response.notification.request.identifier
    )
    eventBroadcaster.broadcast(.fetchNewNotifications)
    var title: String?
    if let aps = response.notification.request.content.userInfo["aps"]
        as? [String: Any],
        let alert = aps["alert"] as? [String: Any],
        let alertTitle = alert["title"] as? String {
        title = alertTitle
    }

    if let url = response.notification.request.content.userInfo["url"]
        as? String {
        guard let webUrl = URL(string: url) else { return }
        if webUrl.isWebURL() {
            logWebViewWith(link: url, title: title)
        } else {
            logNotification(link: url)
        }
    }
    IterableAppIntegration.userNotificationCenter(
        center,
        didReceive: response,
        withCompletionHandler: completionHandler
    )
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) {
        IterableAPI.inAppManager.isAutoDisplayPaused = false
    }

    if let itbl = response.notification.request.content.userInfo["itbl"]
        as? [String: Any],
        let currentMessageId = itbl["messageId"] as? String,
        let templateId = itbl["templateId"],
        let campaignId = itbl["campaignId"] as? Int64 {

        let trackingInfo: [AnyHashable: Any] = [
            "templateId": templateId,
            "messageId": currentMessageId,
            "campaignId": campaignId,
        ]
        IterableAPI.track(pushOpen: trackingInfo, dataFields: nil)
    }
}

}

// MARK: - IterableAuthDelegate

extension IterablePushNotificationsService: IterableAuthDelegate {
func onAuthFailure(_ authFailure: IterableSDK.AuthFailure) {
IterableAPI.setEmail(userService.optionalUser()?.email ?? "")
}

func onAuthTokenRequested(completion: @escaping AuthTokenRetrievalHandler) {
    guard let email = userService.optionalUser()?.email else { return }

    iterableAPIService.fetchIterableJWTAuthToken(email: email) { result in
        switch result {
        case .success(let response):
            completion(response.iterableJwt)
            UIApplication.shared.registerForRemoteNotifications()
        case .failure(let error):
            IterableAPI.setEmail(email)
        }
    }
}

}

extension IterablePushNotificationsService {
private struct ScreenInteractions {
static let drawerScreenName: String = "notification_drawer"
static let selectWebURLAction: String = "open_web_url"
}

fileprivate func logNotification(link: String) {
    guard let contentType = DeeplinkItemType(link: link) else { return }
    let contentID = contentType.urlExtractor?.magicTokenFrom(link) ?? ""

    interactions
        .eventBuilder
        .buttonTap()
        .tappedOn(contentType.analyticsName)
        .ofType(.notificationItem(contentType))
        .inScreen(ScreenInteractions.drawerScreenName)
        .with(
            .init(
                section: EventInteractionSection.notification,
                contentId: contentID
            )
        )
        .create()
        .add(to: interactions.eventBroadcaster)
}

fileprivate func logWebViewWith(link: String, title: String?) {
    interactions
        .eventBuilder
        .buttonTap()
        .tappedOn(ScreenInteractions.selectWebURLAction)
        .ofType(.notificationItem(.webURL))
        .inScreen(ScreenInteractions.drawerScreenName)
        .with(
            .init(
                section: EventInteractionSection.notification,
                data1: ("notification_title", title),
                data2: ("notification_url", link)
            )
        )
        .create()
        .add(to: interactions.eventBroadcaster)
}

}


⚠️ Beta Software Notice

Important: Our team does not provide support for issues encountered on beta or pre-release versions of operating systems, development tools, or other software. Please verify that the issue occurs on stable, officially released software before submitting this report. Thank you for your understanding.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions