На данный момент Carrot quest для iOS можно установить с помощью CocoaPod.
Добавьте следующую строчку в pod файл:
pod 'CarrotquestSDK'
Для работы с Carrot quest для iOS вам понадобится API Key и User Auth Key. Вы можете найти эти ключи на вкладке "Настройки > Разработчикам":
Для инициализации Carrot quest вам нужно добавить следующий код в файл AppDelegate вашего приложения:
import CarrotSDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey:Any]?) -> Bool {
....
Carrot.shared.setup(
withApiKey: API-KEY,
successHandler: {
print("Carrotquest SDK connected")
},
errorHandler: { error in
print("Carrotquest SDK error: " + error)
})
....
}
Если в вашем приложении присутствует авторизация пользователей, вы можете передать ID пользователя в Carrot quest. Существует два способа авторизации: напрямую передать userAuthKey, передать hash генерируемый у вас на бэке.
Carrot.shared.auth(
withUserId: userId,
withUserAuthKey: userAuthKey,
successHandler: { carrotId in
print("Carrotquest SDK user auth successed, CarrotId = \(carrotId)")
},
errorHandler: { error in
print("Carrotquest SDK user auth error: " + error)
})
Carrot.shared.hashedAuth(
withUserId: userId,
withHash: hash,
successHandler: { carrotId in
print("Carrotquest SDK user auth successed, CarrotId = \(carrotId)")
},
errorHandler: { error in
print("Carrotquest SDK user auth error: " + error)
})
Для реализации функции выхода:
Carrot.shared.logout(
successHandler: {
print("Carrotquest SDK user logout successed")
},
errorHandler: { error in
print("Carrotquest SDK user logout error: " + error)
})
Вы можете установить необходимые свойства пользователя с помощью:
Carrot.shared.setUserProperty(userProperties)
Где userProperties
это объект типа [UserProperty]
.
Для описания свойств пользователя используйте класс UserProperty
:
UserProperty(key: key, value: value)
UserProperty(key: key, value: value, operation: .updateOrCreate)
Более подробно про Operations
можно прочитать в разделе «Свойства пользователя».
Внимание!
Поле key
не может начинаться с символа $
.
Для установки системных свойств реализовано 2 класса CarrotUserProperty
и EcommerceUserProperty
.
Для отслеживания событий используйте:
Carrot.shared.trackEvent(withName: name, withParams: params)
где params
— дополнительные параметры для события в виде JSON-строки.
Вы можете дать пользователю мобильного приложения возможность перейти в чат с оператором из любого места. Это можно реализовать двумя разными путями - через плавающую кнопку, либо напрямую вызвав метод открытия чата в любое нужное время.
Виджет предоставляющий быстрый доступ к чату. Добавить кнопку можно с помощью следующего метода:
Carrot.shared.showButton(in: view)
Для того чтобы скрыть кнопку возпльзуйтесь методом:
Carrot.shared.hideButton()
Открыть чат можно также, вызвав из произвольного места (после инициализации) следующий код:
Carrot.shared.openChat()
Для отслеживания количества непрочтенных диалогов:
Carrot.shared.getUnreadConversationsCount({ count in
print("Carrotquest SDK dialogs count: \(count)")
})
и для количества непрочтенных сообщений:
Carrot.shared.getUnreadMessagesCount({ count in
print("Carrotquest SDK messages count: \(count)")
})
Для работы с уведомлениями SDK использует сервис Firebase Cloud Messaging. В связи с этим необходимо получить ключ и отправить его в Carrot. Вы можете найти поле для ввода ключа на вкладке Настройки > Разработчикам. Процесс настройки сервиса Firebase Cloud Messaging описан здесь.
Далее, в делегате MessagingDelegate необходимо установить fcmToken для Carrot SDK:
import FirebaseMessaging
import CarrotSDK
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
if let fcmToken = fcmToken {
CarrotNotificationService.shared.setToken(fcmToken)
} else {
print("Carrotquest SDK error: fcmToken not found")
}
...
}
}
Для отображения уведомлений, необходимо добавить код в UNUserNotificationCenterDelegate:
import CarrotSDK
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let notificationService = CarrotNotificationService.shared
if notificationService.canHandle(notification) {
notificationService.show(notification, completionHandler: completionHandler)
} else {
// Логика для пользовательских уведомлений
}
}
}
Для обработки кликов на уведомления:
import CarrotSDK
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let notificationService = CarrotNotificationService.shared
if notificationService.canHandle(response) {
notificationService.clickNotification(notificationResponse: response)
} else {
// Логика для пользовательских уведомлений
}
completionHandler()
}
}
Для инициализации Carrot quest вам нужно добавить следующий код в файл AppDelegate вашего приложения:
#import "CarrotSDK/CarrotSDK.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
....
Carrot *carrot = [Carrot shared];
[
carrot
setupWithApiKey: API-KEY
successHandler: ^(){
NSLog(@"Carrotquest SDK connected");
}
errorHandler: ^(NSString *error){
NSLog(@"Carrotquest SDK error: %@", error);
}];
....
return YES;
}
Если в вашем приложении присутствует авторизация пользователей, вы можете передать ID пользователя в Carrot quest. Существует два способа авторизации: напрямую передать userAuthKey, передать hash генерируемый у вас на бэке.
Carrot *carrot = [Carrot shared];
[
carrot
authWithUserId: userId
withUserAuthKey: userAuthKey
successHandler: ^(NSString *carrotId){
NSLog(@"Carrotquest SDK user auth successed, CarrotId: %@", carrotId);
}
errorHandler: ^(NSString *error){
NSLog(@"Carrotquest SDK user auth error: %@", error);
}];
Carrot *carrot = [Carrot shared];
[
carrot
authWithUserId: userId
withHash: hash
successHandler: ^(NSString *carrotId){
NSLog(@"Carrotquest SDK user auth successed, CarrotId: %@", carrotId);
}
errorHandler: ^(NSString *error){
NSLog(@"Carrotquest SDK user auth error: %@", error);
}];
Для реализации функции выхода:
Carrot *carrot = [Carrot shared];
[
carrot
logoutWithSuccessHandler: ^(){
NSLog(@"Carrotquest SDK user logout successed");
} errorHandler: ^(NSString *error){
NSLog(@"Carrotquest SDK user logout error: %@", error);
}];
Вы можете установить необходимые свойства пользователя с помощью:
Carrot *carrot = [Carrot shared];
[
carrot
setUserProperty:userProperties
]
Где userProperties
это объект типа [UserProperty]
.
Для описания свойств пользователя используйте класс UserProperty
:
Carrot *carrot = [Carrot shared];
UserProperty *userProp = [[UserProperty alloc] initWithKey: key value: value];
UserProperty *userProp = [[UserProperty alloc] initWithKey: key value: value operation: @"updateOrCreate"];
Более подробно про Operations
можно прочитать в разделе «Свойства пользователя».
Внимание!
Поле key
не может начинаться с символа $
.
Для установки системных свойств реализовано 2 класса CarrotUserProperty
и EcommerceUserProperty
.
Для отслеживания событий используйте:
Carrot *carrot = [Carrot shared];
[
carrot
trackEventWithName: name
withParams: params
];
где params
— дополнительные параметры для события в виде JSON-строки.
Вы можете дать пользователю мобильного приложения возможность перейти в чат с оператором из любого места. Это можно реализовать двумя разными путями - через плавающую кнопку, либо напрямую вызвав метод открытия чата в любое нужное время.
Виджет предоставляющий быстрый доступ к чату. Добавить кнопку можно с помощью следующего метода:
Carrot *carrot = [Carrot shared];
[carrot showButtonIn: self.view];
Для того чтобы скрыть кнопку возпльзуйтесь методом:
Carrot *carrot = [Carrot shared];
[carrot hideButton];
Открыть чат можно также, вызвав из произвольного места (после инициализации) следующий код:
Carrot *carrot = [Carrot shared];
[carrot openChat];
Для отслеживания количества непрочтенных диалогов:
Carrot *carrot = [Carrot shared];
[
carrot
getUnreadConversationsCount:^(NSInteger count){
NSLog(@"Carrotquest SDK dialogs count: %ld", (long)count);
}];
и для количества непрочтенных сообщений:
Carrot.shared.getUnreadMessagesCount({ count in
print("Carrotquest SDK messages count: \(count)")
})
Carrot *carrot = [Carrot shared];
[
carrot
getUnreadMessagesCount:^(NSInteger count){
NSLog(@"Carrotquest SDK dialogs count: %ld", (long)count);
}];
Для работы с уведомлениями SDK использует сервис Firebase Cloud Messaging. В связи с этим необходимо получить ключ и отправить его в Carrot. Вы можете найти поле для ввода ключа на вкладке Настройки > Разработчикам. Процесс настройки сервиса Firebase Cloud Messaging описан здесь.
Далее, в делегате MessagingDelegate необходимо установить fcmToken для Carrot SDK:
#import "CarrotSDK/CarrotSDK.h"
#import <Firebase.h>
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
CarrotNotificationService *service = [CarrotNotificationService shared];
[service setToken: fcmToken];
}
Для отображения уведомлений, необходимо добавить код в AppDelegate:
#import <UserNotifications/UserNotifications.h>
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
CarrotNotificationService *service = [CarrotNotificationService shared];
if ([service canHandle:notification]) {
[service show:notification appGroudDomain:nil completionHandler:completionHandler];
} else {
// Логика для пользовательских уведомлений
}
}
Для обработки кликов на уведомления:
#import <UserNotifications/UserNotifications.h>
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void(^)(void))completionHandler {
CarrotNotificationService *service = [CarrotNotificationService shared];
if ([service canHandleWithResponse:response]) {
[service clickNotificationWithNotificationResponse:response appGroudDomain:nil openLink:true];
} else {
// Логика для пользовательских уведомлений
}
}
Подробнее о том, зачем нужен пункт appGroudDomain можно почитать тут.
Подробнее о том, зачем нужен пункт openLink можно почитать тут.
Мы используем 2 канала доставки сообщений, поэтому в некоторых случаях уведомления могут дублироваться. Например: при выходе из приложения, или при очень быстром удалении уведомления, возможно получение повтороного уведомления. Для предотвращения такого поведения нужно создать Notification Service Extension. В Xcode, в списке файлов выберите свой проект, а затем File/New/Target/Notification Service Extension.
После чего необходимо зарегистрировать AppGroup в Apple Developer Portal. Identifier App Group должен быть уникальным, и начинаться на "group." иначе Xcode его не примет.
Теперь необходимо добавить Identifier в Xcode:
1) В списке файлов выберите свой проект.
2) В списке targets выберете пункт с именем вашего проекта.
3) Во вкладке "Singing & Capabitities" нажмите на "+ Capability".
4) В выпадающем списке найдите найдите и выберите App Group.
5) На вкладке появится пустой список для идентификаторов App Group. Добавте туда Identifier, который зарегистрировали в Apple Developer Portal ранее.
6) Вернитесь к списку Targets. Аналогичным образом добавте App Group к вашему Notification Service Extension.
Внесите изменения в метод инициализирующий библиотеку:
Carrot.shared.setup(
...
withAppGroup: <group_id>,
...
)
Теперь нужно добавить логику в ваш Notification Service Extension. В списке файлов, должна была появиться новая папка с именем вашего Notification Service Extension. Добавте код в файл NotificationService.swift:
import UserNotifications
import CarrotSDK
class NotificationService: CarrotNotificationServiceExtension {
override func setup() {
self.apiKey = <api_key>
self.domainIdentifier = <group_id>
}
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
<ваша логика>
super.didReceive(request, withContentHandler: contentHandler)
}
}
Обновите ваш pod файл, добавьте:
target 'NotificationService' do
inherit! :search_paths
pod 'CarrotquestSDK'
end
И напоследок, нужно передать Identifier зарегистрированный в Apple Developer Portal ранее в метод show в UNUserNotificationCenterDelegate:
let domain = "Identifier зарегистрированный в Apple Developer Portal ранее"
notificationService.show(notification, appGroudDomain: domain, completionHandler: completionHandler)
Для того, чтобы SDK автоматически подтягивал и русскую локализацию, кроме стандартной, английской, необходимо убедиться, что в Xcode проекте такая локализация включена.
Если вы используете Xcode 15 и выше, и CocoaPods 1.12.1 и ниже, то у вас возникнет ошибка директорий, вроде такой:
Чтобы исправить это, добавьте следующий код в конец своего podfile:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.base_configuration_reference.is_a? Xcodeproj::Project::Object::PBXFileReference
xcconfig_path = config.base_configuration_reference.real_path
IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR"))
end
end
end
end
Возможно, в будущем, CocoaPods обновится, и этот код придется удалить, но в данный момент, он необходим.
Небольшой словарь терминов, перед тем как мы начнем:
Universal link (еще его называют Deeplink, но это не терминология Apple):
https://example.com/section
URL scheme:
example://section
Итак, вы можете приложить ссылку к пушу.
Однако, не все так просто. Внутри обработчика пуша лежит функция:
if let clickActionUrl = URL(string: "Ваша ссылка") {
UIApplication.shared.open(clickActionUrl, options: [:])
}
Простейшая логика. Однако, по какой-то причине, функция iOS для открытия ссылок, указанная выше, не распознает универсальную ссылку приложения, если она вызывается из этого же приложения. Это отправит пользователя прямо в браузер.
Поэтому, есть два возможных варианта решения проблемы:
Если в вашем приложении настроены URL Scheme то все уже готово. Просто приложите нужную схему к пушу.
Далее прикладываю небольшой туториал по настройке URL Scheme.
URL Scheme - это более простой и надежный способ открыть нужную страницу в приложении, в отличии от Universal Link. Однако, они не выглядят как ссылка из интернета:
deeplink://test
Перейдем к настройке. Выберите цель в настройках проекта Xcode и перейдите на вкладку «Информация». Внизу страницы вы найдете раздел «URL Types».
Нажав +
, мы можем создать новый тип. В качестве идентификатора люди часто повторно используют пакет приложения. Для схем URL-адресов мы рекомендуем использовать название приложения (или сокращенное название), чтобы оно было как можно более кратким. В нем не должно быть никаких специальных символов. Мы будем использовать deeplink
в качестве примера.
Ваше приложение готово распознать URL схему, теперь нам нужно обработать его, когда мы его получим.
Приложение фиксирует открытие следующим образом в более ранних приложениях, в которых есть только AppDelegate
.
extension AppDelegate {
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool {
print(url)
return true
}
}
Для новых приложений, включающих SceneDelegate, необходимо добавить обработчик еще и туда. Важно отметить, что метод AppDelegateне будет вызван, даже если вы его реализуете.
extension SceneDelegate {
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let firstUrl = URLContexts.first?.url else {
return
}
print(firstUrl.absoluteString)
}
}
Если хотите проверить ссылку, введите ее в браузере Safari. Так же, доступен вариант для быстрой проверки на симуляторе. Вот команда для терминала:
xcrun simctl openurl booted "deeplink://test"
Вернитесь к обработчику кликов на пуши, и передайте аргумент false в параметр openLink:
CarrotNotificationService.shared.clickNotification(
notificationResponse: response,
openLink: false
)
Затем, нужно достать ссылку из объекта response, который пришел в пуше. Мы заранее подготовили для этого функцию:
let link: String? = CarrotNotificationService.shared.getLink(from: response)
Обратите внимание, что функция возвращает опционал, потому что пуш не всегда содержит ссылку.
Таким образом, в методе обработки кликов на пуши, у вас получится что-то такое:
import CarrotSDK
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let notificationService = CarrotNotificationService.shared
if notificationService.canHandle(response) {
notificationService.clickNotification(notificationResponse: response, openLink: false)
if let link = CarrotNotificationService.shared.getLink(from: response) {
print(link)
// Обработчик открытия Universal link
}
completionHandler()
}
}
Для отключения дебажных логов от встроенного в SDK moya, и от самого SDK, необходимо добавить специальный ключ в info.plist вашего проекта.
XML (Plist)
<key>moyaLog</key>
<string>0</string>
0 - логи выключены
1 - логи включены