Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MBX-3168: IDFA Example sample #450

Merged
merged 8 commits into from
Oct 9, 2024
10 changes: 10 additions & 0 deletions Example/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
474F37A32C16F5B000F38BB0 /* NotificationCenterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCenterView.swift; sourceTree = "<group>"; };
474F37AD2C170FB600F38BB0 /* NotificationCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCellView.swift; sourceTree = "<group>"; };
477480792C174BAA00580FB2 /* Payload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Payload.swift; sourceTree = "<group>"; };
47912FD92CB42D640063387D /* AppDelegate_IDFA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate_IDFA.swift; sourceTree = "<group>"; };
47D63E2C2C2EAD220055E7D8 /* Mindbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Mindbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
47FFE2252C187D3C0007E2F6 /* SwiftDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDataManager.swift; sourceTree = "<group>"; };
4AF2BFD8ABA97C73F589C5DB /* Pods_MindboxNotificationServiceExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MindboxNotificationServiceExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -164,6 +165,7 @@
0AEDBC6D2BB6F8F200EE8722 = {
isa = PBXGroup;
children = (
47912FD82CB4130C0063387D /* Samples */,
0AEDBC782BB6F8F200EE8722 /* Example */,
0A0DE3462BB8455A00812E73 /* MindboxNotificationServiceExtension */,
0AD271D32BB9D81E00750279 /* MindboxNotificationContentExtension */,
Expand Down Expand Up @@ -256,6 +258,14 @@
path = ChooseInAppMessagesDelegate;
sourceTree = "<group>";
};
47912FD82CB4130C0063387D /* Samples */ = {
isa = PBXGroup;
children = (
47912FD92CB42D640063387D /* AppDelegate_IDFA.swift */,
);
path = Samples;
sourceTree = "<group>";
};
47FFE2242C187D360007E2F6 /* Services */ = {
isa = PBXGroup;
children = (
Expand Down
39 changes: 16 additions & 23 deletions Example/Example/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,40 @@
//

import Mindbox
import Foundation
import UIKit

@main
class AppDelegate: MindboxAppDelegate {
final class AppDelegate: MindboxAppDelegate {

//https://developers.mindbox.ru/docs/ios-sdk-initialization
// https://developers.mindbox.ru/docs/ios-sdk-initialization
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
super.application(application, didFinishLaunchingWithOptions: launchOptions)

do {
// To run the application on a physical device you need to change the endpoint
// You should also change the application bundle ID in all targets, more details in the readme
// You can still run the application on the simulator to see In-Apps
let mindboxSdkConfig = try MBConfiguration(
//To run the application on a physical device you need to change the endpoint
//You should also change the application bundle ID in all targets, more details in the readme
//You can still run the application on the simulator to see In-Apps
endpoint: "Mpush-test.ReleaseExample.IosApp",
domain: "api.mindbox.ru",
subscribeCustomerIfCreated: true,
shouldCreateCustomer: true
)
Mindbox.shared.initialization(configuration: mindboxSdkConfig)
} catch {
print(error)
} catch {
print(error.localizedDescription)
}
//https://developers.mindbox.ru/docs/ios-send-push-notifications-appdelegate

// https://developers.mindbox.ru/docs/ios-send-push-notifications-appdelegate
registerForRemoteNotifications()

return true
}

func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

//https://developers.mindbox.ru/docs/ios-send-push-notifications-appdelegate
// https://developers.mindbox.ru/docs/ios-send-push-notifications-appdelegate
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
Expand All @@ -56,13 +49,13 @@ class AppDelegate: MindboxAppDelegate {
completionHandler([.list, .badge, .sound, .banner])
}

//https://developers.mindbox.ru/docs/ios-sdk-handle-tap
// https://developers.mindbox.ru/docs/ios-sdk-handle-tap
override func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
//https://developers.mindbox.ru/docs/ios-sdk-methods
// https://developers.mindbox.ru/docs/ios-sdk-methods
print("Is mindbox notification: \(Mindbox.shared.isMindboxPush(userInfo: response.notification.request.content.userInfo))")
if let mindboxPushNotification = Mindbox.shared.getMindboxPushData(userInfo: response.notification.request.content.userInfo),
Mindbox.shared.isMindboxPush(userInfo: response.notification.request.content.userInfo),
Expand All @@ -73,13 +66,13 @@ class AppDelegate: MindboxAppDelegate {
super.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
}

//https://developers.mindbox.ru/docs/ios-send-push-notifications-appdelegate
// https://developers.mindbox.ru/docs/ios-send-push-notifications-appdelegate
func registerForRemoteNotifications() {
UNUserNotificationCenter.current().delegate = self
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
UNUserNotificationCenter.current().requestAuthorization(options: [ .alert, .sound, .badge]) { granted, error in
print("Permission granted: \(granted)")
print("Permission granted to allow local and remote notifications for your app: \(granted)")
if let error = error {
print("NotificationsRequestAuthorization failed with error: \(error.localizedDescription)")
}
Expand Down
2 changes: 2 additions & 0 deletions Example/Example/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
Expand Down
3 changes: 1 addition & 2 deletions Example/Example/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
final class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?

Expand All @@ -26,4 +26,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
window.makeKeyAndVisible()
}
}

22 changes: 22 additions & 0 deletions Example/Example/Services/SwiftDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public struct SwiftDataManager {
}

private init() {
SwiftDataManager.createDirectoryForSwiftData()

let schema = Schema([
Item.self,
])
Expand Down Expand Up @@ -59,6 +61,26 @@ public struct SwiftDataManager {
}
}
}

private static func createDirectoryForSwiftData() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что за рефактор?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Давно про это тебе рассказывал. Там CoreData под капотом ругается на первый запуск у всех. И выводит это в std. Мешает читать консоль. В нашем случае решил обработать ситуацию и пофиксить, чтобы и у клиентов вопросов меньше было, и нам самим удобно было

Что выводит
CoreData: error: Failed to stat path '/private/var/mobile/Containers/Shared/AppGroup/7E0865CC-DA07-473B-B7ED-18417EFD4D65/Library/Application Support/default.store', errno 2 / No such file or directory.
CoreData: error: Executing as effective user 501
CoreData: error: Failed to statfs file; errno 2 / No such file or directory.
CoreData: error: Logging status information for directory path: /private/var/mobile/Containers/Shared/AppGroup/7E0865CC-DA07-473B-B7ED-18417EFD4D65/Library/Application Support
CoreData: error: Executing as effective user 501
CoreData: error: Information for /
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		838860801
CoreData: error:   File Size: 		544 bytes
CoreData: error:   File inode: 		2
CoreData: error:   File user ID: 		0
CoreData: error:   File group ID: 		0
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is readable
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		838860801
CoreData: error:   File Size: 		224 bytes
CoreData: error:   File inode: 		1152921500312264884
CoreData: error:   File user ID: 		0
CoreData: error:   File group ID: 		0
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is readable
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private/var
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		16777224
CoreData: error:   File Size: 		1152 bytes
CoreData: error:   File inode: 		2
CoreData: error:   File user ID: 		0
CoreData: error:   File group ID: 		0
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is not readable with errno 1
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private/var/mobile
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		16777220
CoreData: error:   File Size: 		480 bytes
CoreData: error:   File inode: 		2
CoreData: error:   File user ID: 		501
CoreData: error:   File group ID: 		501
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   711
CoreData: error:   component is not a symbolic link
CoreData: error:   component is not readable with errno 1
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private/var/mobile/Containers
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		16777220
CoreData: error:   File Size: 		160 bytes
CoreData: error:   File inode: 		45
CoreData: error:   File user ID: 		501
CoreData: error:   File group ID: 		501
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is not readable with errno 1
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private/var/mobile/Containers/Shared
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		16777220
CoreData: error:   File Size: 		96 bytes
CoreData: error:   File inode: 		11907
CoreData: error:   File user ID: 		0
CoreData: error:   File group ID: 		501
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is not readable with errno 1
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private/var/mobile/Containers/Shared/AppGroup
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		16777220
CoreData: error:   File Size: 		8352 bytes
CoreData: error:   File inode: 		11908
CoreData: error:   File user ID: 		501
CoreData: error:   File group ID: 		501
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is not readable with errno 1
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private/var/mobile/Containers/Shared/AppGroup/7E0865CC-DA07-473B-B7ED-18417EFD4D65
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		16777220
CoreData: error:   File Size: 		256 bytes
CoreData: error:   File inode: 		41717936
CoreData: error:   File user ID: 		501
CoreData: error:   File group ID: 		501
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is readable
CoreData: error:   component is not writeable with errno 1
CoreData: error: Information for /private/var/mobile/Containers/Shared/AppGroup/7E0865CC-DA07-473B-B7ED-18417EFD4D65/Library
CoreData: error:   File Device ID: 	0
CoreData: error:   Device ID: 		16777220
CoreData: error:   File Size: 		128 bytes
CoreData: error:   File inode: 		41717938
CoreData: error:   File user ID: 		501
CoreData: error:   File group ID: 		501
CoreData: error:   File Permissions: 	
CoreData: error: d
CoreData: error:   755
CoreData: error:   component is not a symbolic link
CoreData: error:   component is readable
CoreData: error:   component is writeable
CoreData: error: Failed to stat path '/private/var/mobile/Containers/Shared/AppGroup/7E0865CC-DA07-473B-B7ED-18417EFD4D65/Library/Application Support', errno 2 / No such file or directory.
CoreData: error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (512)
CoreData: error: userInfo:
CoreData: error: 	reason : Failed to create file; code = 2
CoreData: error: storeType: SQLite
CoreData: error: configuration: default
CoreData: error: URL: file:///private/var/mobile/Containers/Shared/AppGroup/7E0865CC-DA07-473B-B7ED-18417EFD4D65/Library/Application%20Support/default.store
CoreData: annotation: options:
CoreData: annotation: 	NSMigratePersistentStoresAutomaticallyOption : 1
CoreData: annotation: 	NSInferMappingModelAutomaticallyOption : 1
CoreData: annotation: 	NSPersistentStoreRemoteChangeNotificationOptionKey : 1
CoreData: annotation: 	NSPersistentHistoryTrackingKey : 1
CoreData: error: <NSPersistentStoreCoordinator: 0x301768380>: Attempting recovery from error encountered during addPersistentStore: 0x3032f5ad0 Error Domain=NSCocoaErrorDomain Code=512 "The file couldn’t be saved." UserInfo={reason=Failed to create file; code = 2}
CoreData: error: During recovery, parent directory path reported as missing
CoreData: error: Recovery attempt while adding <NSPersistentStoreDescription: 0x3032f5ad0> (type: SQLite, url: file:///private/var/mobile/Containers/Shared/AppGroup/7E0865CC-DA07-473B-B7ED-18417EFD4D65/Library/Application%20Support/default.store) was successful!

let fileManager = FileManager.default
let appGroupIdentifier = "group.cloud.Mindbox.cloud.Mindbox.ReleaseExampleIos"
if let appGroupURL = fileManager.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) {
let applicationSupportURL = appGroupURL.appendingPathComponent("Library/Application Support")

if !fileManager.fileExists(atPath: applicationSupportURL.path) {
do {
try fileManager.createDirectory(at: applicationSupportURL, withIntermediateDirectories: true, attributes: nil)
} catch {
print("Failed to create Application Support directory: \(error)")
}
} else {
print("Application Support directory already exists at \(applicationSupportURL.path)")
}
} else {
fatalError("Could not find App Group container URL.")
}
}
}

private extension SwiftDataManager {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ import Mindbox
class ChooseInAppMessagesDelegate: InAppMessagesDelegate {

private init() {}
static var shared = ChooseInAppMessagesDelegate()
static let shared = ChooseInAppMessagesDelegate()

//https://developers.mindbox.ru/docs/in-app
// https://developers.mindbox.ru/docs/in-app
func inAppMessageTapAction(id: String, url: URL?, payload: String) {
//Here you can add your custom logic
print("inAppMessageTapAction")
print(id)
print(url ?? "")
print(payload)
print("InApp ID: \(id)")
print("InApp URL: \(String(describing: url))")
print("InApp Payload: \(payload)")
}

//https://developers.mindbox.ru/docs/in-app
// https://developers.mindbox.ru/docs/in-app
func inAppMessageDismissed(id: String) {
//Here you can add your custom logic
print("inAppMessageDismissed")
print(id)
print("InApp ID: \(id)")
}

func select(chooseInappMessageDelegate: ChooseInappMessageDelegate) {
Expand Down
6 changes: 3 additions & 3 deletions Example/Example/ViewModels/MainViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Observation
var deviceUUID: String = ""
var APNSToken: String = ""

//https://developers.mindbox.ru/docs/ios-sdk-methods
// https://developers.mindbox.ru/docs/ios-sdk-methods
func setupData() {
self.SDKVersion = Mindbox.shared.sdkVersion
Mindbox.shared.getDeviceUUID { deviceUUID in
Expand All @@ -32,7 +32,7 @@ import Observation
ChooseInAppMessagesDelegate.shared.select(chooseInappMessageDelegate: .InAppMessagesDelegate)
}

//https://developers.mindbox.ru/docs/in-app-targeting-by-custom-operation
// https://developers.mindbox.ru/docs/in-app-targeting-by-custom-operation
func showInAppWithExecuteSyncOperation () {
let json = """
{ "viewProduct":
Expand All @@ -53,7 +53,7 @@ import Observation
}
}

//https://developers.mindbox.ru/docs/in-app-targeting-by-custom-operation
// https://developers.mindbox.ru/docs/in-app-targeting-by-custom-operation
func showInAppWithExecuteAsyncOperation () {
let json = """
{ "viewProduct":
Expand Down
62 changes: 62 additions & 0 deletions Example/Samples/AppDelegate_IDFA.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// AppDelegate_IDFA.swift
// Example
//
// Created by Sergei Semko on 10/7/24.
// Copyright © 2024 Mindbox. All rights reserved.
//

import UIKit
import Mindbox
import AppTrackingTransparency

// This is only one use case. It is necessary to adapt the approach to your specific use case.

@main
class AppDelegate_IDFA: MindboxAppDelegate {

//https://developers.mindbox.ru/docs/ios-sdk-initialization
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
super.application(application, didFinishLaunchingWithOptions: launchOptions)

if ATTrackingManager.trackingAuthorizationStatus != .notDetermined {
initializeMindbox()
}

// ...
return true
}

// If you're using scenes (iOS 13.0+), UIKit will not call this method. Use `sceneDidBecomeActive(_:)` instead.
override func applicationDidBecomeActive(_ application: UIApplication) {
if ATTrackingManager.trackingAuthorizationStatus == .notDetermined {
DispatchQueue.main.async {
ATTrackingManager.requestTrackingAuthorization { status in
self.initializeMindbox()
}
}
}
}

func initializeMindbox() {
do {
// To run the application on a physical device you need to change the endpoint
// You should also change the application bundle ID in all targets, more details in the readme
// You can still run the application on the simulator to see In-Apps
let mindboxSdkConfig = try MBConfiguration(
endpoint: "Mpush-test.ReleaseExample.IosApp",
domain: "api.mindbox.ru",
subscribeCustomerIfCreated: true,
shouldCreateCustomer: true
)
Mindbox.shared.initialization(configuration: mindboxSdkConfig)
} catch {
print(error.localizedDescription)
}
}

// ...
}