### Installation Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Instructions for installing necessary tools and fastlane. ```APIDOC ## Installation Make sure you have the latest version of the Xcode command line tools installed: ```sh xcode-select --install ``` For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) ``` -------------------------------- ### Install Xcode Command Line Tools Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Ensures the necessary Xcode command line tools are present on the system. ```sh xcode-select --install ``` -------------------------------- ### iOS Framework Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Builds the Apptentive xcframework binary. ```APIDOC ## ios framework ### Description Builds Apptentive xcframework binary ### Method fastlane ### Endpoint ios framework ### Request Example ```sh [bundle exec] fastlane ios framework ``` ``` -------------------------------- ### Configure Person and Device Custom Data in Swift Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Demonstrates how to set user profile attributes, custom person/device data, and configure mParticle integration. ```swift import ApptentiveKit class UserProfileManager { func updateUserProfile(user: User) { // Set person information Apptentive.shared.personName = user.displayName Apptentive.shared.personEmailAddress = user.email // Set custom person data (String, Bool, Int, Double supported) Apptentive.shared.personCustomData["user_id"] = user.id Apptentive.shared.personCustomData["account_type"] = "premium" Apptentive.shared.personCustomData["lifetime_value"] = 149.99 Apptentive.shared.personCustomData["has_completed_onboarding"] = true Apptentive.shared.personCustomData["signup_date"] = "2024-01-15" Apptentive.shared.personCustomData["purchase_count"] = 12 } func updateDeviceInfo() { // Set custom device data Apptentive.shared.deviceCustomData["app_version"] = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String Apptentive.shared.deviceCustomData["device_storage_gb"] = getAvailableStorageGB() Apptentive.shared.deviceCustomData["push_enabled"] = isPushEnabled() Apptentive.shared.deviceCustomData["preferred_language"] = Locale.current.languageCode } // For mParticle integration func configureMParticle(userId: String) { Apptentive.shared.mParticleID = userId } // Access custom data func printCustomData() { for key in Apptentive.shared.personCustomData.keys { print("\(key): \(Apptentive.shared.personCustomData[key] ?? "nil")") } } } ``` -------------------------------- ### iOS Beta Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Deploys the Operator app to TestFlight. ```APIDOC ## ios beta ### Description Deploys Operator app to TestFlight ### Method fastlane ### Endpoint ios beta ### Request Example ```sh [bundle exec] fastlane ios beta ``` ``` -------------------------------- ### Register Apptentive SDK Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/README.md Initialize the SDK early in the application lifecycle using your Apptentive app key and signature. ```Swift Apptentive.shared.register(with: .init(key: "<#Your Apptentive App Key#>", signature: "<#Your Apptentive App Signature#>")) ``` -------------------------------- ### Register Apptentive SDK Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Initialize the SDK using Apptentive credentials during the application lifecycle. Registration supports both completion handlers and async/await patterns. ```swift import ApptentiveKit // In AppDelegate or App init @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Create credentials from your Apptentive Dashboard let credentials = Apptentive.AppCredentials( key: "IOS-YOUR-APP-KEY", signature: "your-app-signature" ) // Optional: Configure theme before registration Apptentive.shared.theme = .apptentive // or .none for iOS default // Optional: Enable secure token storage in iOS Keychain Apptentive.shared.shouldUseSecureTokenStorage = true // Register with completion handler Apptentive.shared.register(with: credentials, region: .us) { result in switch result { case .success: print("Apptentive SDK registered successfully") case .failure(let error): print("Registration failed: \(error.localizedDescription)") } } return true } } // Async/await alternative Task { do { try await Apptentive.shared.register(with: credentials, region: .eu) print("SDK registered") } catch { print("Registration error: \(error)") } } ``` -------------------------------- ### iOS Format Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Runs the swift-format formatter in-place on all swift files. ```APIDOC ## ios format ### Description Runs the swift-format formatter in-place on all swift files ### Method fastlane ### Endpoint ios format ### Request Example ```sh [bundle exec] fastlane ios format ``` ``` -------------------------------- ### iOS Lint All Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Runs the swift-format linter on all swift files in the repository. ```APIDOC ## ios lint_all ### Description Runs the swift-format linter on all swift files in repo ### Method fastlane ### Endpoint ios lint_all ### Request Example ```sh [bundle exec] fastlane ios lint_all ``` ``` -------------------------------- ### iOS Documentation Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Rebuilds the documentation for the iOS project. ```APIDOC ## ios documentation ### Description Rebuilds documentation ### Method fastlane ### Endpoint ios documentation ### Request Example ```sh [bundle exec] fastlane ios documentation ``` ``` -------------------------------- ### Import ApptentiveKit Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/README.md Include the ApptentiveKit module in your Swift files to access SDK functionality. ```Swift import ApptentiveKit ``` -------------------------------- ### iOS Lint Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Runs the swift-format linter on ApptentiveKit. ```APIDOC ## ios lint ### Description Runs the swift-format linter on ApptentiveKit ### Method fastlane ### Endpoint ios lint ### Request Example ```sh [bundle exec] fastlane ios lint ``` ``` -------------------------------- ### Configure Apptentive UI Appearance Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Set Apptentive's theme, custom fonts, and specific UI element colors and images for surveys, Message Center, dialogs, and buttons. This configuration should be done before Apptentive registration. You can also use an asset catalog for a more integrated approach. ```swift import ApptentiveKit import UIKit class AppearanceConfiguration { static func configureApptentiveAppearance() { // Set theme before registration Apptentive.shared.theme = .apptentive // Cross-platform Apptentive look // or .customerOnly to use only your asset catalog colors // or .customerBasedOnApptentive to override Apptentive with your colors // or .none for default iOS appearance // Custom font (applies to all Apptentive UI) Apptentive.fontName = "Avenir-Medium" // Survey customization UIColor.apptentiveSubmitButton = .systemBlue UIColor.apptentiveSubmitButtonTitle = .white UIColor.apptentiveQuestionLabel = .label UIColor.apptentiveChoiceLabel = .label UIColor.apptentiveError = .systemRed UIColor.apptentiveGroupedBackground = .systemGroupedBackground UIColor.apptentiveTextInputBorder = .separator // Survey images UIImage.apptentiveRadioButton = UIImage(systemName: "circle") UIImage.apptentiveRadioButtonSelected = UIImage(systemName: "circle.inset.filled") UIImage.apptentiveCheckbox = UIImage(systemName: "square") UIImage.apptentiveCheckboxSelected = UIImage(systemName: "checkmark.square.fill") // Message Center customization UIColor.apptentiveMessageBubbleInbound = .systemGray4 UIColor.apptentiveMessageBubbleOutbound = .systemBlue UIColor.apptentiveMessageLabelInbound = .label UIColor.apptentiveMessageLabelOutbound = .white UIColor.apptentiveMessageCenterBackground = .systemBackground UIImage.apptentiveMessageSendButton = UIImage(systemName: "paperplane.fill") UIImage.apptentiveMessageAttachmentButton = UIImage(systemName: "paperclip") // Dialog customization (Love Dialog, Prompts) UIColor.apptentiveDialogTitle = .label UIColor.apptentiveDialogMessage = .secondaryLabel UIColor.apptentiveDialogButtonLabel = .label CGFloat.apptentiveDialogCornerRadius = 20 // Button styling UIButton.apptentiveStyle = .radius(8.0) // or .pill for rounded ends // Close button UIBarButtonItem.apptentiveClose = UIBarButtonItem( image: UIImage(systemName: "xmark.circle.fill"), style: .plain, target: nil, action: nil ) // Presentation style UIModalPresentationStyle.apptentive = .formSheet // Table view style for surveys UITableView.Style.apptentive = .insetGrouped } } // Asset Catalog approach: Name colors in your asset catalog: // - Apptentive/Survey/SubmitButton // - Apptentive/Survey/QuestionText // - Apptentive/MessageCenter/MessageBubbleInbound // - Apptentive/Dialog/Background // etc. ``` -------------------------------- ### Manage Message Center in Swift Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Provides methods to present the Message Center, check its availability, observe unread message counts, and send diagnostic attachments. ```swift import ApptentiveKit class SupportViewController: UIViewController { @IBAction func openMessageCenter(_ sender: Any) { // Present Message Center Apptentive.shared.presentMessageCenter(from: self) { result in switch result { case .success(let wasShown): print("Message Center presented: \(wasShown)") case .failure(let error): print("Failed to present Message Center: \(error)") } } } func openMessageCenterWithContext() { // Include custom data with the first message var customData = CustomData() customData["order_id"] = "ORD-12345" customData["user_tier"] = "premium" customData["app_section"] = "checkout" Task { let shown = try await Apptentive.shared.presentMessageCenter( from: self, with: customData ) print("Message Center shown with context: \(shown)") } } // Check availability before showing func showSupportOption() async { do { let canShow = try await Apptentive.shared.canShowMessageCenter() supportButton.isEnabled = canShow } catch { supportButton.isEnabled = false } } // Monitor unread message count (KVO-observable) func observeUnreadMessages() { // unreadMessageCount is @objc dynamic observation = Apptentive.shared.observe(\.unreadMessageCount, options: [.new]) { apptentive, change in DispatchQueue.main.async { self.updateBadge(count: change.newValue ?? 0) } } } // Send hidden messages (useful for debugging or context) func sendDiagnosticInfo() { // Send text attachment Apptentive.shared.sendAttachment("Device: \(UIDevice.current.model), OS: \(UIDevice.current.systemVersion)") // Send image attachment if let screenshot = captureScreenshot() { Apptentive.shared.sendAttachment(screenshot) } // Send file data with MIME type if let logData = getLogFileData() { Apptentive.shared.sendAttachment(logData, mediaType: "text/plain") } } } ``` -------------------------------- ### iOS Certs Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Retrieves development certificates for the iOS project. ```APIDOC ## ios certs ### Description Gets development certs ### Method fastlane ### Endpoint ios certs ### Request Example ```sh [bundle exec] fastlane ios certs ``` ``` -------------------------------- ### iOS Clean Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Cleans the build areas for the iOS project. ```APIDOC ## ios clean ### Description Clean build areas ### Method fastlane ### Endpoint ios clean ### Request Example ```sh [bundle exec] fastlane ios clean ``` ``` -------------------------------- ### Login User with JWT Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Logs in a user with a JWT. The JWT must be signed with your Apptentive secret, and the 'sub' claim identifies the user for conversation matching. Handles success and failure cases, including already logged-in states. ```swift import ApptentiveKit class AuthenticationManager { func loginUser(jwt: String) { // JWT should be signed with your Apptentive secret // The 'sub' claim identifies the user for conversation matching Apptentive.shared.logIn(with: jwt) { result in switch result { case .success: print("User logged in to Apptentive") case .failure(let error): if case ApptentiveError.alreadyLoggedIn(let subject, let id) = error { print("Already logged in as \(subject) (ID: \(id))") } else { print("Login failed: \(error)") } } } } // Async/await version func loginUserAsync(jwt: String) async { do { try await Apptentive.shared.logIn(with: jwt) print("Login successful") } catch ApptentiveError.loginCalledBeforeRegister { print("SDK must be registered before login") } catch ApptentiveError.activeConversationPending { print("Wait for SDK to connect before logging in") } catch { print("Login error: \(error)") } } } ``` -------------------------------- ### iOS Test Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Runs tests for the iOS project. ```APIDOC ## ios test ### Description Run tests ### Method fastlane ### Endpoint ios test ### Request Example ```sh [bundle exec] fastlane ios test ``` ``` -------------------------------- ### Present Message Center Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/README.md Open the Message Center interface from a UIViewController to allow customer communication. ```Swift @IBAction func openMessageCenter(sender: UIButton) { // ... Apptentive.shared.presentMessageCenter(from: self) // where `self` is a UIViewController instance. } ``` -------------------------------- ### Run iOS fastlane Actions Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Executes specific build and maintenance tasks for the iOS project. ```sh [bundle exec] fastlane ios clean ``` ```sh [bundle exec] fastlane ios test ``` ```sh [bundle exec] fastlane ios coverage ``` ```sh [bundle exec] fastlane ios lint ``` ```sh [bundle exec] fastlane ios lint_all ``` ```sh [bundle exec] fastlane ios format ``` ```sh [bundle exec] fastlane ios documentation ``` ```sh [bundle exec] fastlane ios framework ``` ```sh [bundle exec] fastlane ios zipArtifacts ``` ```sh [bundle exec] fastlane ios certs ``` ```sh [bundle exec] fastlane ios beta ``` -------------------------------- ### Implement Custom Interaction Presenter Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Override default presentation behavior by subclassing InteractionPresenter and assigning it to Apptentive.shared.interactionPresenter before SDK registration. ```swift import ApptentiveKit class CustomInteractionPresenter: InteractionPresenter { override func presentSurvey(with viewModel: SurveyViewModel) async throws { // Custom survey presentation let customSurveyVC = CustomSurveyViewController(viewModel: viewModel) let navController = ApptentiveNavigationController(rootViewController: customSurveyVC) try await presentViewController(navController) viewModel.launch() } override func presentMessageCenter(with viewModel: MessageCenterViewModel) async throws { // Custom Message Center presentation let customMC = CustomMessageCenterViewController(viewModel: viewModel) let navController = ApptentiveNavigationController(rootViewController: customMC) try await presentViewController(navController) viewModel.launch() } override func presentViewController(_ viewControllerToPresent: UIViewController) async throws { // Custom presentation logic viewControllerToPresent.modalPresentationStyle = .fullScreen guard let presenter = validatedPresentingViewController else { throw InteractionPresenterError.noPresentingViewController } await withCheckedContinuation { continuation in presenter.present(viewControllerToPresent, animated: true) { continuation.resume() } } } } // Set custom presenter before registration Apptentive.shared.interactionPresenter = CustomInteractionPresenter() ``` -------------------------------- ### iOS Coverage Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Generates a code coverage report for the iOS project. ```APIDOC ## ios coverage ### Description Generates a code coverage report ### Method fastlane ### Endpoint ios coverage ### Request Example ```sh [bundle exec] fastlane ios coverage ``` ``` -------------------------------- ### Handle Authentication Failures Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Sets up the Apptentive delegate to handle authentication failures, typically caused by an invalid or expired JWT. The delegate method typically refreshes the JWT and calls `updateToken`. ```swift func setupAuthDelegate() { Apptentive.shared.delegate = self } extension AuthenticationManager: ApptentiveDelegate { func authenticationDidFail(with error: Error) { // Called when API request fails due to invalid/expired JWT print("Auth failed: \(error)") // Typically: refresh the JWT and call updateToken Task { let newJwt = await fetchNewJWTFromServer() try? await Apptentive.shared.updateToken(newJwt) } } } ``` -------------------------------- ### Engage Apptentive Events Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/README.md Record events within your view controllers to trigger interactions like surveys or notes. ```Swift @IBAction func completePurchase(sender: UIButton) { // ... Apptentive.shared.engage("purchase_complete", from: self) // where `self` is a UIViewController instance. } ``` -------------------------------- ### Observe Apptentive Events Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Listen for .apptentiveEventEngaged notifications to track user interactions in external analytics services. ```swift import ApptentiveKit class AnalyticsTracker { func startObserving() { NotificationCenter.default.addObserver( self, selector: #selector(handleApptentiveEvent), name: .apptentiveEventEngaged, object: nil ) } @objc func handleApptentiveEvent(_ notification: Notification) { guard let userInfo = notification.userInfo else { return } let eventType = userInfo["eventType"] as? String let interactionType = userInfo["interactionType"] as? String let interactionID = userInfo["interactionID"] as? String let eventSource = userInfo["eventSource"] as? String print("Apptentive Event: \(eventType ?? "unknown")") print(" Interaction: \(interactionType ?? "none") (ID: \(interactionID ?? "n/a"))") print(" Source: \(eventSource ?? "unknown")") // Track in your analytics Analytics.track("apptentive_event", properties: [ "event_type": eventType ?? "", "interaction_type": interactionType ?? "" ]) } deinit { NotificationCenter.default.removeObserver(self) } } ``` -------------------------------- ### Engage Events and Interactions Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Trigger interactions by engaging events at specific points in the user journey. Events can include custom data and support pre-check validation. ```swift import ApptentiveKit class ProductViewController: UIViewController { func userCompletedPurchase() { // Simple event engagement Apptentive.shared.engage(event: "purchase_completed", from: self) { result in switch result { case .success(let didShowInteraction): print("Event engaged, interaction shown: \(didShowInteraction)") case .failure(let error): print("Engage failed: \(error)") } } } func userViewedProduct(productId: String, category: String) { // Event with custom data var event = Event(name: "product_viewed") event.customData["product_id"] = productId event.customData["category"] = category event.customData["price"] = 29.99 event.customData["in_stock"] = true Task { let shown = try await Apptentive.shared.engage(event: event, from: self) if shown { print("An interaction was displayed") } } } // Using string literal for simple events func onScreenAppear() { Apptentive.shared.engage(event: "home_screen_viewed", from: self) } // Check if an event can show an interaction before engaging func checkAndEngageEvent() async { do { let canShow = try await Apptentive.shared.canShowInteraction(event: "feedback_prompt") if canShow { let _ = try await Apptentive.shared.engage(event: "feedback_prompt", from: self) } else { // Handle case where no interaction is configured showCustomFeedbackUI() } } catch { print("Error: \(error)") } } } ``` -------------------------------- ### Handle Apptentive Push Notifications Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Implement the UNUserNotificationCenterDelegate methods to allow Apptentive to process incoming push notifications for Message Center replies. Ensure Apptentive's SDK methods are called within the delegate callbacks. ```swift import ApptentiveKit import UserNotifications class NotificationHandler: NSObject, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // Let Apptentive handle its notifications Apptentive.shared.didReceiveRemoteNotification(userInfo, fetchCompletionHandler: completionHandler) } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // Handle notification tap Apptentive.shared.didRecevieUserNotificationResponse(response, withCompletionHandler: completionHandler) } } ``` -------------------------------- ### iOS Zip Artifacts Source: https://github.com/apptentive/apptentive-kit-ios/blob/main/fastlane/README.md Zips all xcarchive and xcframework artifacts. ```APIDOC ## ios zipArtifacts ### Description Zips all xcarchive and xcframework ### Method fastlane ### Endpoint ios zipArtifacts ### Request Example ```sh [bundle exec] fastlane ios zipArtifacts ``` ``` -------------------------------- ### Logout User Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Logs out the current user from Apptentive. This action also encrypts and secures conversation data associated with the user. Handles success and failure cases. ```swift func logoutUser() { // Logs out and encrypts/secures conversation data Apptentive.shared.logOut { result in switch result { case .success: print("User logged out successfully") case .failure(let error): print("Logout failed: \(error)") } } } ``` -------------------------------- ### Refresh JWT Token Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Updates the JWT for the currently logged-in conversation. Handles potential errors such as a mismatched subject claim or other general errors. ```swift func refreshToken(newJwt: String) async { // Update JWT for currently logged-in conversation do { try await Apptentive.shared.updateToken(newJwt) } catch ApptentiveError.mismatchedSubClaim { print("JWT subject doesn't match current user") } catch { print("Token update failed: \(error)") } } ``` -------------------------------- ### Dismiss Apptentive Interactions Source: https://context7.com/apptentive/apptentive-kit-ios/llms.txt Programmatically close active interactions like surveys or Message Center. Note that Apple's native rating dialog cannot be dismissed via this method. ```swift import ApptentiveKit class InteractionController { func dismissApptentiveUI(animated: Bool = true) { // Dismiss surveys, Message Center, or dialogs // Note: Cannot dismiss Apple's SKStoreReviewController rating dialog Apptentive.shared.dismissAllInteractions(animated: animated) } func handleAppBackgrounding() { // Example: Dismiss on app background NotificationCenter.default.addObserver( forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main ) { [weak self] _ in self?.dismissApptentiveUI(animated: false) } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.