From 9ca9011d74b54c89b5255d3678a1ed3bad670549 Mon Sep 17 00:00:00 2001 From: Arnaud Roland Date: Thu, 27 Jul 2023 15:23:48 +0200 Subject: [PATCH] release: SDK 1.20.0 --- Package.swift | 4 +- Sources/Batch.xcodeproj/project.pbxproj | 179 ++--- Sources/Batch/BAErrorHelper.h | 21 +- Sources/Batch/BANotificationCenter.h | 4 +- Sources/Batch/Batch.h | 12 +- Sources/Batch/BatchActions.h | 146 ++-- Sources/Batch/BatchCore.h | 382 +++++----- Sources/Batch/BatchEventData.h | 119 ++- Sources/Batch/BatchEventDataPrivate.h | 18 +- Sources/Batch/BatchEventDispatcher.h | 147 ++-- Sources/Batch/BatchInbox.h | 361 ++++----- Sources/Batch/BatchInbox.m | 17 + Sources/Batch/BatchInboxPrivate.h | 4 +- Sources/Batch/BatchLogger.h | 10 +- Sources/Batch/BatchMessaging.h | 427 +++++------ Sources/Batch/BatchMessaging.m | 9 + Sources/Batch/BatchMessagingModels.h | 267 +++---- Sources/Batch/BatchMessagingPrivate.h | 66 +- Sources/Batch/BatchPush.h | 507 ++++++------- Sources/Batch/BatchPushPrivate.h | 54 +- Sources/Batch/BatchUser.h | 688 ++++++++++-------- Sources/Batch/BatchUser.m | 8 + Sources/Batch/BatchUserAttribute.h | 44 +- Sources/Batch/BatchUserAttributePrivate.h | 6 +- Sources/Batch/BatchUserProfile.h | 38 +- Sources/Batch/Defined.h | 210 +++--- Sources/Batch/Kernel/Concurrent/BAPromise.h | 8 +- .../Batch/Kernel/Concurrent/BATaskDebouncer.h | 6 +- .../Kernel/Crypto/BAEncryptionProtocol.h | 1 - Sources/Batch/Kernel/Crypto/BASHA.h | 4 +- .../Dependency Injection/BAInjectable.h | 4 +- .../Kernel/Dependency Injection/BAInjection.h | 42 +- .../Private/BAInjectionRegistry.h | 32 +- .../Private/BAOverlayedInjectable-Private.h | 2 +- .../Foundation/BADateProviderProtocol.h | 2 +- .../Kernel/Foundation/BAMultiDelegatesProxy.h | 3 +- .../Kernel/Foundation/BAMutableDateProvider.h | 2 +- .../Kernel/Foundation/BASystemDateProvider.h | 2 +- .../Batch/Kernel/Foundation/BATZAwareDate.h | 14 +- Sources/Batch/Kernel/GZip/BATGZIP.h | 3 +- Sources/Batch/Kernel/GZip/BATGZIP.m | 20 +- .../Helpers/BADelegatedApplicationDelegate.h | 5 +- Sources/Batch/Kernel/Helpers/BADirectories.h | 4 +- Sources/Batch/Kernel/Helpers/BAEmailUtils.h | 24 + Sources/Batch/Kernel/Helpers/BAEmailUtils.m | 28 + Sources/Batch/Kernel/Helpers/BAHTTPHeaders.h | 4 +- Sources/Batch/Kernel/Helpers/BAJson.h | 17 +- Sources/Batch/Kernel/Helpers/BAOSHelper.h | 2 +- .../Helpers/BAPartialApplicationDelegate.h | 18 +- Sources/Batch/Kernel/Helpers/BAStringUtils.h | 2 +- .../Batch/Kernel/Helpers/BATJsonDictionary.h | 18 +- Sources/Batch/Kernel/Helpers/BAWindowHelper.h | 8 +- Sources/Batch/Kernel/Helpers/BAWindowHelper.m | 9 + Sources/Batch/Kernel/Logger/BALogger.h | 40 +- .../Batch/Kernel/Logger/BALoggerProtocol.h | 4 +- Sources/Batch/Kernel/Logger/BALoggerUnified.h | 2 +- .../Kernel/MessagePack/BATMessagePackReader.h | 25 +- .../Kernel/MessagePack/BATMessagePackWriter.h | 21 +- Sources/Batch/Kernel/MessagePack/msgpack-c.h | 160 ++-- .../Kernel/Parameters/BANetworkParameters.m | 73 +- .../Kernel/Parameters/BAPropertiesCenter.h | 2 +- .../Batch/Kernel/Parameters/BAUserDefaults.h | 13 +- .../Kernel/Reachability/BAReachability.h | 29 +- Sources/Batch/Kernel/Xson/BATJsonDictionary.h | 13 +- .../Batch/Modules/Actions/BAActionsCenter.h | 14 +- .../Actions/BAUserDataBuiltinActions.h | 2 +- .../Actions/BAUserEventBuiltinActions.h | 2 +- .../Modules/Core/BAApplicationLifecycle.h | 18 +- Sources/Batch/Modules/Core/BABundleInfo.h | 4 +- .../Modules/Core/BACenterMulticastDelegate.h | 3 +- Sources/Batch/Modules/Core/BAConfiguration.h | 6 +- Sources/Batch/Modules/Core/BACoreCenter.h | 13 +- Sources/Batch/Modules/Core/BACoreCenter.m | 29 +- Sources/Batch/Modules/Core/BAInstallationID.h | 2 +- .../Core/BANotificationAuthorization.h | 36 +- .../Core/BANotificationAuthorization.m | 6 + Sources/Batch/Modules/Core/BASessionManager.h | 7 +- .../BATUserActivity.h} | 7 +- Sources/Batch/Modules/Core/BATUserActivity.m | 27 + .../Modules/Core/BATrackingAuthorization.h | 16 +- Sources/Batch/Modules/Core/BAUserProfile.h | 7 +- .../Modules/Debug/BADBGCustomDataModels.h | 2 +- .../Debug/BADBGFindMyInstallationHelper.h | 2 +- .../Debug/BADBGLCDetailsViewController.h | 2 +- Sources/Batch/Modules/Debug/BADBGModule.h | 2 +- .../Modules/Debug/BADBGNameValueListItem.h | 2 +- .../Display Receipt/BADisplayReceipt.h | 18 +- .../Display Receipt/BADisplayReceiptCache.h | 4 +- .../BADisplayReceiptWebserviceClient.h | 4 +- .../BAEventDispatcherCenter.h | 19 +- .../Event Dispatcher/BAMessageEventPayload.h | 11 +- .../Event Dispatcher/BAPushEventPayload.h | 4 +- Sources/Batch/Modules/Inbox/BAInbox.h | 18 +- .../Modules/Inbox/BAInboxDBHelperProtocol.h | 11 +- .../Modules/Inbox/BAInboxDatasourceProtocol.h | 25 +- .../Inbox/BAInboxFetchWebserviceClient.h | 18 +- .../Modules/Inbox/BAInboxSQLiteDatasource.h | 16 +- .../Batch/Modules/Inbox/BAInboxSQLiteHelper.h | 2 +- .../Inbox/BAInboxSyncWebserviceClient.h | 17 +- .../Modules/Inbox/BAInboxWebserviceResponse.h | 8 +- .../Batch/Modules/Lisp/BALEvaluationContext.h | 19 - Sources/Batch/Modules/Lisp/BALOperators.h | 32 - Sources/Batch/Modules/Lisp/BALOperators.m | 566 -------------- Sources/Batch/Modules/Lisp/BALSExpression.h | 27 - Sources/Batch/Modules/Lisp/BALSExpression.m | 125 ---- Sources/Batch/Modules/Lisp/BALValues.h | 110 --- Sources/Batch/Modules/Lisp/BALValues.m | 277 ------- Sources/Batch/Modules/Lisp/BALispParser.h | 42 -- Sources/Batch/Modules/Lisp/BALispParser.m | 271 ------- .../Evaluation Contexts/BALCachingContext.h | 27 - .../Evaluation Contexts/BALCachingContext.m | 48 -- .../Evaluation Contexts/BALEventContext.h | 23 - .../Evaluation Contexts/BALEventContext.m | 157 ---- .../Lisp/Evaluation Contexts/BALMetaContext.h | 28 - .../Lisp/Evaluation Contexts/BALMetaContext.m | 37 - .../BALNativeAttributeContext.m | 27 - .../BALUserAttributeContext.h | 21 - .../BALUserAttributeContext.m | 120 --- .../Modules/Local Campaigns/BALocalCampaign.h | 28 +- .../Local Campaigns/BALocalCampaignsCenter.h | 24 +- .../BALocalCampaignsGlobalCappings.h | 4 +- .../Local Campaigns/BALocalCampaignsManager.h | 33 +- .../Local Campaigns/BALocalCampaignsParser.h | 13 +- .../Outputs/BALocalCampaignOutputProtocol.h | 6 +- .../BALocalCampaignsFilePersistence.h | 2 +- .../Persistence/BALocalCampaignsPersisting.h | 4 +- .../Signals/BALocalCampaignSignalProtocol.h | 2 +- .../Signals/BAPublicEventTrackedSignal.h | 4 +- .../Tracker/BALocalCampaignTrackerProtocol.h | 8 +- .../Tracker/BALocalCampaignsTracker.h | 3 +- .../Local Campaigns/Triggers/BAEventTrigger.h | 2 +- .../Triggers/BANextSessionTrigger.h | 2 +- .../BABatchMessagingDelegateWrapper.h | 26 +- .../Messaging/BADelegatedUIAlertController.h | 8 +- Sources/Batch/Modules/Messaging/BAMSGAction.h | 2 +- Sources/Batch/Modules/Messaging/BAMSGCTA.h | 2 +- .../Modules/Messaging/BAMSGImageDownloader.h | 7 +- .../Batch/Modules/Messaging/BAMSGMessage.h | 75 +- .../Modules/Messaging/BAMSGOverlayWindow.h | 2 +- .../Modules/Messaging/BAMSGOverlayWindow.m | 8 + .../Modules/Messaging/BAMSGPayloadParser.h | 5 +- ...AMessagingAnalyticsDeduplicatingDelegate.h | 5 +- .../Messaging/BAMessagingAnalyticsDelegate.h | 15 +- .../Modules/Messaging/BAMessagingCenter.h | 48 +- .../Modules/Messaging/BAMessagingCenter.m | 72 +- .../Batch/Modules/Messaging/BATHtmlParser.h | 18 +- .../Messaging/BATMessagingCloseErrorCause.h | 10 +- Sources/Batch/Modules/Messaging/CSS/BACSS.h | 23 +- .../Messaging/CSS/BACSSImportProvider.h | 2 +- .../Batch/Modules/Messaging/CSS/BACSSParser.h | 8 +- .../Batch/Modules/Messaging/CSS/BACSSToken.h | 8 +- .../Modules/Messaging/GIF/BATGIFAnimator.h | 6 +- .../Batch/Modules/Messaging/GIF/BATGIFFile.h | 19 +- .../Messaging/UI/BAMSGBannerViewController.h | 2 +- .../UI/BAMSGBaseBannerViewController.h | 34 +- .../Messaging/UI/BAMSGImageViewController.h | 8 +- .../UI/BAMSGInterstitialViewController.h | 31 +- .../Messaging/UI/BAMSGModalViewController.h | 2 +- .../Modules/Messaging/UI/BAMSGStackView.h | 15 +- .../Modules/Messaging/UI/BAMSGStackViewItem.h | 14 +- .../Modules/Messaging/UI/BAMSGVideoView.h | 1 - .../Messaging/UI/BAMSGViewController.h | 36 +- .../Messaging/UI/BAMSGViewController.m | 3 + .../Messaging/UI/BAMSGWebviewViewController.h | 8 +- .../Webview/BATWebviewBridgeLegacyWKHandler.h | 8 +- .../Webview/BATWebviewBridgeWKHandler.h | 4 +- .../Webview/BATWebviewJavascriptBridge.h | 48 +- .../Messaging/Webview/BATWebviewUtils.h | 2 +- .../Widgets/BAMSGActivityIndicatorView.h | 5 +- .../Widgets/BAMSGBaseContainerView.h | 5 +- .../Modules/Messaging/Widgets/BAMSGButton.h | 5 +- .../Modules/Messaging/Widgets/BAMSGButton.m | 6 + .../Messaging/Widgets/BAMSGCloseButton.h | 5 +- .../Messaging/Widgets/BAMSGCountdownView.h | 3 +- .../Messaging/Widgets/BAMSGGradientView.h | 7 +- .../Messaging/Widgets/BAMSGImageView.h | 2 +- .../Modules/Messaging/Widgets/BAMSGLabel.h | 11 +- .../Modules/Messaging/Widgets/BAMSGLabel.m | 7 +- .../Widgets/BAMSGPannableAlertContainerView.h | 7 +- .../BAMSGPannableAnchoredContainerView.h | 2 +- .../Widgets/BAMSGPannableContainerView.h | 2 +- .../Messaging/Widgets/BAMSGRemoteImageView.h | 6 +- .../Messaging/Widgets/BAMSGStylableView.h | 12 +- .../Messaging/Widgets/BAMSGStylableView.m | 6 +- .../Messaging/Widgets/BAMSGViewToolbox.h | 9 +- Sources/Batch/Modules/Metrics/BACounter.h | 2 +- Sources/Batch/Modules/Metrics/BAMetric.h | 28 +- .../Batch/Modules/Metrics/BAMetricManager.h | 4 +- .../Batch/Modules/Metrics/BAMetricProtocol.h | 4 +- .../Batch/Modules/Metrics/BAMetricRegistry.h | 12 +- .../Metrics/BAMetricWebserviceClient.h | 4 +- Sources/Batch/Modules/Metrics/BAObservation.h | 2 +- Sources/Batch/Modules/Opt Out/BAOptOut.h | 14 +- .../Modules/Opt Out/BAOptOutEventTracker.h | 2 +- .../Opt Out/BAOptOutWebserviceClient.h | 2 +- Sources/Batch/Modules/Push/BAPushCenter.h | 94 ++- .../Modules/Push/BAPushSystemHelperProtocol.h | 17 +- Sources/Batch/Modules/Tracker/BAEvent.h | 54 +- .../Modules/Tracker/BAEventDBHelperProtocol.h | 5 +- .../Tracker/BAEventDatasourceProtocol.h | 4 +- .../Modules/Tracker/BAEventSQLiteDatasource.h | 15 +- .../Modules/Tracker/BAEventSQLiteHelper.h | 2 +- .../Batch/Modules/Tracker/BATrackerCenter.h | 27 +- .../Batch/Modules/Tracker/BATrackerSender.h | 6 +- .../Modules/Tracker/BATrackerSignpostHelper.h | 4 +- Sources/Batch/Modules/User/BAUserAttribute.h | 7 +- Sources/Batch/Modules/User/BAUserCenter.h | 2 +- Sources/Batch/Modules/User/BAUserDataDiff.h | 26 +- Sources/Batch/Modules/User/BAUserDataEditor.h | 61 +- Sources/Batch/Modules/User/BAUserDataEditor.m | 278 +++---- .../Batch/Modules/User/BAUserDataManager.h | 11 +- .../Batch/Modules/User/BAUserDataManager.m | 123 +++- .../Batch/Modules/User/BAUserDataOperation.h | 3 +- .../Modules/User/BAUserDatasourceProtocol.h | 28 +- .../Modules/User/BAUserEmailSubscription.h | 29 + .../Modules/User/BAUserEmailSubscription.m | 108 +++ .../Modules/User/BAUserSQLiteDatasource.h | 6 +- Sources/Batch/PrivateUmbrellaHeader.h | 16 +- Sources/Batch/Versions.h | 6 +- .../Batch/Webservices/BAWebserviceMetrics.h | 8 +- .../Webservices/BAWebserviceURLBuilder.h | 6 +- Sources/Batch/Webservices/Core/BAConnection.h | 51 +- .../Webservices/Core/BAConnectionDelegate.h | 5 +- .../Webservices/Core/BAURLSessionProtocol.h | 6 +- .../Webservices/Core/BAWebserviceClient.h | 9 +- .../Core/BAWebserviceClientExecutor.h | 2 +- .../Webservices/Core/BAWebserviceJsonClient.h | 2 +- .../Core/BAWebserviceMsgPackClient.h | 2 +- .../Crypto/BAWebserviceAESGCMCryptor.h | 2 +- .../Crypto/BAWebserviceAESGCMGzipCryptor.h | 4 +- .../Webservices/Crypto/BAWebserviceCryptor.h | 6 +- .../Crypto/BAWebserviceCryptorFactory.h | 10 +- .../Crypto/BAWebserviceStubCryptor.h | 2 +- .../Crypto/HMAC/BATWebserviceHMAC.h | 37 +- .../BALocalCampaignsJITService.h | 11 +- .../BAEventTrackerService.h | 4 +- .../BALocalCampaignsService.h | 4 +- .../BAPushTokenService.h | 3 +- .../BAUserDataServices.h | 5 +- .../Query Models/BAWSQuery.h | 3 +- .../Query Models/BAWSQueryAttributes.h | 2 +- .../Query Models/BAWSQueryAttributesCheck.h | 3 +- .../Query Models/BAWSQueryLocalCampaigns.h | 4 +- .../Response Models/BAWSResponse.h | 1 - .../BAWSResponseAttributesCheck.h | 3 +- .../BAWSResponseLocalCampaigns.h | 2 +- .../Query/BAQueryWebserviceClient.h | 4 +- .../Query/BAQueryWebserviceClientDatasource.h | 13 +- .../Query/BAQueryWebserviceClientDelegate.h | 7 +- .../BAQueryWebserviceIdentifiersProviding.h | 2 +- ...andardQueryWebserviceIdentifiersProvider.h | 2 +- Sources/batchTests/DataUtils.swift | 4 +- Sources/batchTests/InvocationRecorders.h | 4 +- .../Concurrent/batchTaskDebouncerTest.swift | 4 +- .../batchTests/Kernel/Crypto/batchAESTests.m | 6 +- .../batchTests/Kernel/Crypto/shaTests.swift | 2 +- .../dependencyInjectionTests.swift | 19 +- Sources/batchTests/Kernel/GZip/gzipTests.m | 14 +- .../Kernel/Helpers/emailTests.swift | 28 + .../Kernel/Helpers/osHelperTests.swift | 22 +- .../Kernel/Helpers/swiftSwizzling.swift | 2 +- .../Kernel/Logger/internalLoggerTests.swift | 3 +- .../MessagePack/messagePackReaderTests.swift | 9 +- .../MessagePack/messagePackWriterTests.swift | 13 +- .../Modules/Actions/groupActionTest.swift | 35 +- .../displayReceiptSwiftTests.swift | 70 +- .../Modules/Lisp/batchContextTests.swift | 224 ------ .../Modules/Lisp/batchLispTests.swift | 376 ---------- .../localCampaignsManagerTests.swift | 8 +- .../localCampaignsParserTests.swift | 14 +- .../localCampaignsTrackerTests.swift | 11 +- .../Webview/webviewBridgeLegacyTests.swift | 63 +- .../Webview/webviewBridgeWKHandlerTests.swift | 36 +- .../webviewJavascriptBridgeTests.swift | 88 ++- .../Webview/webviewTestHelpers.swift | 3 +- .../Messaging/Webview/webviewUtilsTests.swift | 3 +- .../Modules/Messaging/cssTests.swift | 2 - ...gAnalyticsDeduplicatingDelegateTests.swift | 22 +- .../Modules/User/batchUserDiffTests.swift | 33 +- .../User/batchUserEditorPublicAPITests.m | 4 + .../User/batchUserEmailSubscriptionTests.m | 92 +++ .../batchTests/Modules/User/batchUserTests.m | 36 +- .../Modules/batchUserDataEditorTests.swift | 42 +- .../batchTests/Stubs/DeeplinkDelegateStub.h | 4 +- .../Crypto/HMAC/webserviceHMACTests.swift | 42 +- .../Crypto/webserviceAESGCMCryptorTests.m | 14 +- .../eventTrackerServiceTests.swift | 27 +- .../pushTokenServiceTests.swift | 1 - Sources/batchTests/XCTest+BAPromise.swift | 15 +- Sources/batchTests/batchEventDataTests.swift | 17 +- .../contents.xcworkspacedata | 7 + Tools/Bridgy/Sources/Bridgy/Generator.swift | 7 + Tools/Dockerfile.format | 18 + Tools/Package.resolved | 14 + Tools/Package.swift | 19 + Tools/Scripts/format-check.sh | 28 + Tools/Scripts/format.sh | 26 + .../generate_private_umbrella_header.sh | 0 Tools/Scripts/generate_sdk_report_size.sh | 44 ++ {Sources => Tools/Scripts}/make_doc.sh | 0 .../strip_public_swift_framework.sh | 0 Tools/Sources/Tools/.gitkeep | 0 302 files changed, 4369 insertions(+), 6012 deletions(-) mode change 100755 => 100644 Sources/Batch/Kernel/Foundation/BAMultiDelegatesProxy.h create mode 100644 Sources/Batch/Kernel/Helpers/BAEmailUtils.h create mode 100644 Sources/Batch/Kernel/Helpers/BAEmailUtils.m rename Sources/Batch/Modules/{Lisp/Evaluation Contexts/BALNativeAttributeContext.h => Core/BATUserActivity.h} (52%) create mode 100644 Sources/Batch/Modules/Core/BATUserActivity.m delete mode 100644 Sources/Batch/Modules/Lisp/BALEvaluationContext.h delete mode 100644 Sources/Batch/Modules/Lisp/BALOperators.h delete mode 100644 Sources/Batch/Modules/Lisp/BALOperators.m delete mode 100644 Sources/Batch/Modules/Lisp/BALSExpression.h delete mode 100644 Sources/Batch/Modules/Lisp/BALSExpression.m delete mode 100644 Sources/Batch/Modules/Lisp/BALValues.h delete mode 100644 Sources/Batch/Modules/Lisp/BALValues.m delete mode 100644 Sources/Batch/Modules/Lisp/BALispParser.h delete mode 100644 Sources/Batch/Modules/Lisp/BALispParser.m delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.h delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.m delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.h delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.m delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.h delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.m delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALNativeAttributeContext.m delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.h delete mode 100644 Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.m mode change 100755 => 100644 Sources/Batch/Modules/Tracker/BAEvent.h create mode 100644 Sources/Batch/Modules/User/BAUserEmailSubscription.h create mode 100644 Sources/Batch/Modules/User/BAUserEmailSubscription.m create mode 100644 Sources/batchTests/Kernel/Helpers/emailTests.swift delete mode 100644 Sources/batchTests/Modules/Lisp/batchContextTests.swift delete mode 100644 Sources/batchTests/Modules/Lisp/batchLispTests.swift create mode 100644 Sources/batchTests/Modules/User/batchUserEmailSubscriptionTests.m create mode 100644 Tools/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata create mode 100644 Tools/Dockerfile.format create mode 100644 Tools/Package.resolved create mode 100644 Tools/Package.swift create mode 100644 Tools/Scripts/format-check.sh create mode 100755 Tools/Scripts/format.sh rename {Sources => Tools/Scripts}/generate_private_umbrella_header.sh (100%) create mode 100644 Tools/Scripts/generate_sdk_report_size.sh rename {Sources => Tools/Scripts}/make_doc.sh (100%) rename Tools/{ => Scripts}/strip_public_swift_framework.sh (100%) create mode 100644 Tools/Sources/Tools/.gitkeep diff --git a/Package.swift b/Package.swift index cd8d70f..23cd05a 100644 --- a/Package.swift +++ b/Package.swift @@ -18,8 +18,8 @@ let package = Package( targets: [ .binaryTarget( name: "Batch", - url: "https://download.batch.com/sdk/ios/spm/BatchSDK-ios_spm-xcframework-1.19.5.zip", - checksum: "9dec44e2163ac9ca28e8874985af8defb102c12ae8c7a98e6a51d83119b778cc" + url: "https://download.batch.com/sdk/ios/spm/BatchSDK-ios_spm-xcframework-1.20.0.zip", + checksum: "90c5ed03fab1c1708f54eb6eaa8180962e14659cc76fe0bd7f561273818eec94" ) ] ) \ No newline at end of file diff --git a/Sources/Batch.xcodeproj/project.pbxproj b/Sources/Batch.xcodeproj/project.pbxproj index 4d2647e..0a5e281 100644 --- a/Sources/Batch.xcodeproj/project.pbxproj +++ b/Sources/Batch.xcodeproj/project.pbxproj @@ -49,6 +49,9 @@ 029B335E1A39A1F7006B9DC6 /* batchParametersTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 029B334E1A39A1F7006B9DC6 /* batchParametersTests.m */; }; 029B335F1A39A1F7006B9DC6 /* batchPropertiesCenterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 029B334F1A39A1F7006B9DC6 /* batchPropertiesCenterTests.m */; }; 029B33601A39A1F7006B9DC6 /* batchUserDefaultsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 029B33501A39A1F7006B9DC6 /* batchUserDefaultsTests.m */; }; + 1E104EAF28E6F43D00E998AE /* BAUserEmailSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E104EAD28E6F43D00E998AE /* BAUserEmailSubscription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1E104EB028E6F43D00E998AE /* BAUserEmailSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E104EAE28E6F43D00E998AE /* BAUserEmailSubscription.m */; }; + 1E104EB628EB289400E998AE /* batchUserEmailSubscriptionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E104EB528EB289400E998AE /* batchUserEmailSubscriptionTests.m */; }; 1E2C31B527CF740E00A4CB6E /* BAMetricRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E2C31B327CF740E00A4CB6E /* BAMetricRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1E2C31B627CF740E00A4CB6E /* BAMetricRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E2C31B427CF740E00A4CB6E /* BAMetricRegistry.m */; }; 1E45578527CE1B510048D3A8 /* BALocalCampaignsJITService.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E45578327CE1B510048D3A8 /* BALocalCampaignsJITService.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -62,10 +65,9 @@ 1EA42DFA26A85D7D004CC618 /* BADBGFindMyInstallationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA42DF726A84C71004CC618 /* BADBGFindMyInstallationHelper.m */; }; 1EA42DFB26A85DF9004CC618 /* BADBGFindMyInstallationHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EA42DF926A84C99004CC618 /* BADBGFindMyInstallationHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1EA42E0426A9A736004CC618 /* FindMyInstallationHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA42E0226A9A716004CC618 /* FindMyInstallationHelperTests.m */; }; - 1EC9657127AD7879007D66AD /* BALocalCampaignsGlobalCappings.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EC9656F27AD7879007D66AD /* BALocalCampaignsGlobalCappings.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1EC9657227AD7879007D66AD /* BALocalCampaignsGlobalCappings.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC9657027AD7879007D66AD /* BALocalCampaignsGlobalCappings.m */; }; - 1EF1974427673BBE00386DF0 /* BAInjectionRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF1974227673BBE00386DF0 /* BAInjectionRegistrar.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1EF1974527673BBE00386DF0 /* BAInjectionRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF1974327673BBE00386DF0 /* BAInjectionRegistrar.m */; }; + 1EB69D3B290C09B9003E1EF7 /* BAEmailUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EB69D39290C09B9003E1EF7 /* BAEmailUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1EB69D3C290C09B9003E1EF7 /* BAEmailUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB69D3A290C09B9003E1EF7 /* BAEmailUtils.m */; }; + 1EB69D3E290C0F5A003E1EF7 /* emailTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EB69D3D290C0F5A003E1EF7 /* emailTests.swift */; }; 1EBDBC5F27146B8B006DC662 /* BAMetric.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF8BA98271462D90063E117 /* BAMetric.m */; }; 1EBDBC6027146C97006DC662 /* BAMetric.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF8BA9A271462F80063E117 /* BAMetric.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1EBDBC6327157A3A006DC662 /* BACounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EBDBC6127157A3A006DC662 /* BACounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -80,9 +82,10 @@ 1EBDBC8427188D40006DC662 /* metricTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EBDBC8327188D40006DC662 /* metricTests.m */; }; 1EBDBC86271D9936006DC662 /* metricManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EBDBC85271D9936006DC662 /* metricManagerTests.m */; }; 1EC803AB27D2477E00CCE8E5 /* localCampaignsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EC803AA27D2477E00CCE8E5 /* localCampaignsManagerTests.swift */; }; + 1EC9657127AD7879007D66AD /* BALocalCampaignsGlobalCappings.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EC9656F27AD7879007D66AD /* BALocalCampaignsGlobalCappings.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1EC9657227AD7879007D66AD /* BALocalCampaignsGlobalCappings.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC9657027AD7879007D66AD /* BALocalCampaignsGlobalCappings.m */; }; 1EF1974427673BBE00386DF0 /* BAInjectionRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF1974227673BBE00386DF0 /* BAInjectionRegistrar.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1EF1974527673BBE00386DF0 /* BAInjectionRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF1974327673BBE00386DF0 /* BAInjectionRegistrar.m */; }; - 5105747D21358C2A00789F86 /* batchLispTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5105747C21358C2A00789F86 /* batchLispTests.swift */; }; 510BD5C522E0B4BA00D8CBA1 /* BAWSResponseAttributesCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 510BD5BD22E0B4BA00D8CBA1 /* BAWSResponseAttributesCheck.m */; }; 510BD5C622E0B4BA00D8CBA1 /* BAWSResponseAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 510BD5BE22E0B4BA00D8CBA1 /* BAWSResponseAttributes.m */; }; 510BD5C722E0B4BA00D8CBA1 /* BAWSResponseAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 510BD5BF22E0B4BA00D8CBA1 /* BAWSResponseAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -132,6 +135,8 @@ 514FFCCE250903F3009D6A20 /* batchUNUserNotificationCenterDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 514FFCCD250903F3009D6A20 /* batchUNUserNotificationCenterDelegateTests.m */; }; 51512E1825B1996B005D85C3 /* BATWebviewJavascriptBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 51512E1625B1996B005D85C3 /* BATWebviewJavascriptBridge.h */; settings = {ATTRIBUTES = (Private, ); }; }; 51512E1925B1996B005D85C3 /* BATWebviewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 51512E1725B1996B005D85C3 /* BATWebviewJavascriptBridge.m */; }; + 5157117229DAD6EC0002A9CD /* BATUserActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 5157117029DAD6EC0002A9CD /* BATUserActivity.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5157117329DAD6EC0002A9CD /* BATUserActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 5157117129DAD6EC0002A9CD /* BATUserActivity.m */; }; 5158BB7C22F1EFF200ED0C6C /* BAWebserviceClientExecutor.h in Headers */ = {isa = PBXBuildFile; fileRef = 5158BB7A22F1EFF100ED0C6C /* BAWebserviceClientExecutor.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5158BB7D22F1EFF200ED0C6C /* BAWebserviceClientExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5158BB7B22F1EFF100ED0C6C /* BAWebserviceClientExecutor.m */; }; 5159B4DF25E0044C008082FA /* internalLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5159B4DE25E0044C008082FA /* internalLoggerTests.swift */; }; @@ -145,7 +150,6 @@ 5162B2F52571561900607780 /* BAMSGWebviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5162B2F32571561900607780 /* BAMSGWebviewViewController.m */; }; 5166D7D525ED3EEE00F36A5E /* BATMessagingCloseErrorCause.h in Headers */ = {isa = PBXBuildFile; fileRef = 5166D7D425ED3ED700F36A5E /* BATMessagingCloseErrorCause.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5166D7DF25ED464700F36A5E /* BATMessagingCloseErrorCause.m in Sources */ = {isa = PBXBuildFile; fileRef = 5166D7DE25ED464700F36A5E /* BATMessagingCloseErrorCause.m */; }; - 51675F0C21383D6A000E7B9F /* batchContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51675F0B21383D6A000E7B9F /* batchContextTests.swift */; }; 51696F7A25263BFC00951CA4 /* BAApplicationLifecycle.h in Headers */ = {isa = PBXBuildFile; fileRef = 51696F7825263BFC00951CA4 /* BAApplicationLifecycle.h */; settings = {ATTRIBUTES = (Private, ); }; }; 51696F7B25263BFC00951CA4 /* BAApplicationLifecycle.m in Sources */ = {isa = PBXBuildFile; fileRef = 51696F7925263BFC00951CA4 /* BAApplicationLifecycle.m */; }; 516A3B8E22FC4A6400E6A2FD /* BAInjectionRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 516A3B8C22FC4A6400E6A2FD /* BAInjectionRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -350,15 +354,6 @@ 517D709622BBC45900E374FB /* BADBGLCDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 51ECF38A2007DBF60086C9CC /* BADBGLCDetailsViewController.m */; }; 517D709722BBC45900E374FB /* BADBGCustomDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 51E042AE200CF85A00B30D49 /* BADBGCustomDataViewController.m */; }; 517D709822BBC45900E374FB /* BADBGCustomDataModels.m in Sources */ = {isa = PBXBuildFile; fileRef = 51E042B2200D000800B30D49 /* BADBGCustomDataModels.m */; }; - 517D709922BBC45900E374FB /* BALMetaContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 51675F0821383619000E7B9F /* BALMetaContext.m */; }; - 517D709A22BBC45900E374FB /* BALCachingContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 51675F0E213842B4000E7B9F /* BALCachingContext.m */; }; - 517D709B22BBC45900E374FB /* BALEventContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 51952CFF2139828900D8E357 /* BALEventContext.m */; }; - 517D709C22BBC45900E374FB /* BALNativeAttributeContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 51093AB121400FD200C4C1BA /* BALNativeAttributeContext.m */; }; - 517D709D22BBC45900E374FB /* BALUserAttributeContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 51F8403C214188040009DFB1 /* BALUserAttributeContext.m */; }; - 517D709E22BBC45900E374FB /* BALispParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 510574762135862000789F86 /* BALispParser.m */; }; - 517D709F22BBC45900E374FB /* BALOperators.m in Sources */ = {isa = PBXBuildFile; fileRef = 5105746F2135861F00789F86 /* BALOperators.m */; }; - 517D70A022BBC45900E374FB /* BALSExpression.m in Sources */ = {isa = PBXBuildFile; fileRef = 510574732135862000789F86 /* BALSExpression.m */; }; - 517D70A122BBC45900E374FB /* BALValues.m in Sources */ = {isa = PBXBuildFile; fileRef = 510574712135861F00789F86 /* BALValues.m */; }; 517D70A222BBC45900E374FB /* BAWSQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 02849A1E19B9EFBA0013408B /* BAWSQuery.m */; }; 517D70A622BBC45900E374FB /* BAWSQueryPushToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 02849A2619B9EFBA0013408B /* BAWSQueryPushToken.m */; }; 517D70A822BBC45900E374FB /* BAWSQueryTracking.m in Sources */ = {isa = PBXBuildFile; fileRef = 02849A2C19B9EFBA0013408B /* BAWSQueryTracking.m */; }; @@ -526,16 +521,6 @@ 517D716A22BBC50E00E374FB /* BADBGLCDetailsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ECF3892007DBF60086C9CC /* BADBGLCDetailsViewController.h */; settings = {ATTRIBUTES = (Private, ); }; }; 517D716B22BBC50E00E374FB /* BADBGCustomDataViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E042AD200CF85A00B30D49 /* BADBGCustomDataViewController.h */; settings = {ATTRIBUTES = (Private, ); }; }; 517D716C22BBC50E00E374FB /* BADBGCustomDataModels.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E042B1200D000800B30D49 /* BADBGCustomDataModels.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D716D22BBC50E00E374FB /* BALMetaContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 51675F0721383619000E7B9F /* BALMetaContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D716E22BBC50E00E374FB /* BALCachingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 51675F0D213842B4000E7B9F /* BALCachingContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D716F22BBC50E00E374FB /* BALEventContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 51952CFE2139828900D8E357 /* BALEventContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D717022BBC50E00E374FB /* BALNativeAttributeContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 51093AB021400FD200C4C1BA /* BALNativeAttributeContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D717122BBC50E00E374FB /* BALUserAttributeContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F8403B214188040009DFB1 /* BALUserAttributeContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D717222BBC50E00E374FB /* BALEvaluationContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 510574782135862000789F86 /* BALEvaluationContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D717322BBC50E00E374FB /* BALispParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 510574702135861F00789F86 /* BALispParser.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D717422BBC50E00E374FB /* BALOperators.h in Headers */ = {isa = PBXBuildFile; fileRef = 510574742135862000789F86 /* BALOperators.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D717522BBC50E00E374FB /* BALSExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 510574752135862000789F86 /* BALSExpression.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 517D717622BBC50E00E374FB /* BALValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 510574772135862000789F86 /* BALValues.h */; settings = {ATTRIBUTES = (Private, ); }; }; 517D717822BBC50E00E374FB /* BAWSQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 02849A1D19B9EFBA0013408B /* BAWSQuery.h */; settings = {ATTRIBUTES = (Private, ); }; }; 517D717C22BBC50E00E374FB /* BAWSQueryPushToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 02849A2519B9EFBA0013408B /* BAWSQueryPushToken.h */; settings = {ATTRIBUTES = (Private, ); }; }; 517D717E22BBC50E00E374FB /* BAWSQueryTracking.h in Headers */ = {isa = PBXBuildFile; fileRef = 02849A2B19B9EFBA0013408B /* BAWSQueryTracking.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -797,6 +782,9 @@ 02F7846419B9EF5A0006FF07 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 02F7846B19B9EF5A0006FF07 /* BatchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BatchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02F7846E19B9EF5A0006FF07 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1E104EAD28E6F43D00E998AE /* BAUserEmailSubscription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAUserEmailSubscription.h; sourceTree = ""; }; + 1E104EAE28E6F43D00E998AE /* BAUserEmailSubscription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAUserEmailSubscription.m; sourceTree = ""; }; + 1E104EB528EB289400E998AE /* batchUserEmailSubscriptionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = batchUserEmailSubscriptionTests.m; path = User/batchUserEmailSubscriptionTests.m; sourceTree = ""; }; 1E2C31B327CF740E00A4CB6E /* BAMetricRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAMetricRegistry.h; sourceTree = ""; }; 1E2C31B427CF740E00A4CB6E /* BAMetricRegistry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAMetricRegistry.m; sourceTree = ""; }; 1E45578327CE1B510048D3A8 /* BALocalCampaignsJITService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALocalCampaignsJITService.h; sourceTree = ""; }; @@ -810,10 +798,9 @@ 1EA42DF726A84C71004CC618 /* BADBGFindMyInstallationHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BADBGFindMyInstallationHelper.m; sourceTree = ""; }; 1EA42DF926A84C99004CC618 /* BADBGFindMyInstallationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BADBGFindMyInstallationHelper.h; sourceTree = ""; }; 1EA42E0226A9A716004CC618 /* FindMyInstallationHelperTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FindMyInstallationHelperTests.m; sourceTree = ""; }; - 1EC9656F27AD7879007D66AD /* BALocalCampaignsGlobalCappings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALocalCampaignsGlobalCappings.h; sourceTree = ""; }; - 1EC9657027AD7879007D66AD /* BALocalCampaignsGlobalCappings.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALocalCampaignsGlobalCappings.m; sourceTree = ""; }; - 1EF1974227673BBE00386DF0 /* BAInjectionRegistrar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAInjectionRegistrar.h; sourceTree = ""; }; - 1EF1974327673BBE00386DF0 /* BAInjectionRegistrar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAInjectionRegistrar.m; sourceTree = ""; }; + 1EB69D39290C09B9003E1EF7 /* BAEmailUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAEmailUtils.h; sourceTree = ""; }; + 1EB69D3A290C09B9003E1EF7 /* BAEmailUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAEmailUtils.m; sourceTree = ""; }; + 1EB69D3D290C0F5A003E1EF7 /* emailTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = emailTests.swift; sourceTree = ""; }; 1EBDBC6127157A3A006DC662 /* BACounter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BACounter.h; sourceTree = ""; }; 1EBDBC6227157A3A006DC662 /* BACounter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BACounter.m; sourceTree = ""; }; 1EBDBC652715B1B5006DC662 /* BAMetricProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAMetricProtocol.h; sourceTree = ""; }; @@ -826,6 +813,8 @@ 1EBDBC8327188D40006DC662 /* metricTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = metricTests.m; sourceTree = ""; }; 1EBDBC85271D9936006DC662 /* metricManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = metricManagerTests.m; sourceTree = ""; }; 1EC803AA27D2477E00CCE8E5 /* localCampaignsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = localCampaignsManagerTests.swift; sourceTree = ""; }; + 1EC9656F27AD7879007D66AD /* BALocalCampaignsGlobalCappings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALocalCampaignsGlobalCappings.h; sourceTree = ""; }; + 1EC9657027AD7879007D66AD /* BALocalCampaignsGlobalCappings.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALocalCampaignsGlobalCappings.m; sourceTree = ""; }; 1EF1974227673BBE00386DF0 /* BAInjectionRegistrar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAInjectionRegistrar.h; sourceTree = ""; }; 1EF1974327673BBE00386DF0 /* BAInjectionRegistrar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAInjectionRegistrar.m; sourceTree = ""; }; 1EF8BA98271462D90063E117 /* BAMetric.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAMetric.m; sourceTree = ""; }; @@ -846,18 +835,6 @@ 51022DB01D23DA9700EDAA5C /* BAMSGStackViewHorizontalItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BAMSGStackViewHorizontalItem.h; path = Batch/Modules/Messaging/UI/BAMSGStackViewHorizontalItem.h; sourceTree = SOURCE_ROOT; }; 51022DB11D23DA9700EDAA5C /* BAMSGStackViewHorizontalItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BAMSGStackViewHorizontalItem.m; path = Batch/Modules/Messaging/UI/BAMSGStackViewHorizontalItem.m; sourceTree = SOURCE_ROOT; }; 5103E4491F97B09E00155F6A /* BAMSGWindowHolder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAMSGWindowHolder.h; sourceTree = ""; }; - 5105746F2135861F00789F86 /* BALOperators.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALOperators.m; sourceTree = ""; }; - 510574702135861F00789F86 /* BALispParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALispParser.h; sourceTree = ""; }; - 510574712135861F00789F86 /* BALValues.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALValues.m; sourceTree = ""; }; - 510574732135862000789F86 /* BALSExpression.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALSExpression.m; sourceTree = ""; }; - 510574742135862000789F86 /* BALOperators.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALOperators.h; sourceTree = ""; }; - 510574752135862000789F86 /* BALSExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALSExpression.h; sourceTree = ""; }; - 510574762135862000789F86 /* BALispParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALispParser.m; sourceTree = ""; }; - 510574772135862000789F86 /* BALValues.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALValues.h; sourceTree = ""; }; - 510574782135862000789F86 /* BALEvaluationContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALEvaluationContext.h; sourceTree = ""; }; - 5105747C21358C2A00789F86 /* batchLispTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = batchLispTests.swift; sourceTree = ""; }; - 51093AB021400FD200C4C1BA /* BALNativeAttributeContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALNativeAttributeContext.h; sourceTree = ""; }; - 51093AB121400FD200C4C1BA /* BALNativeAttributeContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALNativeAttributeContext.m; sourceTree = ""; }; 510BD5BD22E0B4BA00D8CBA1 /* BAWSResponseAttributesCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAWSResponseAttributesCheck.m; sourceTree = ""; }; 510BD5BE22E0B4BA00D8CBA1 /* BAWSResponseAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAWSResponseAttributes.m; sourceTree = ""; }; 510BD5BF22E0B4BA00D8CBA1 /* BAWSResponseAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BAWSResponseAttributes.h; sourceTree = ""; }; @@ -1040,6 +1017,8 @@ 5155F7C51EF98C6C00929DD8 /* BACenterMulticastDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BACenterMulticastDelegate.m; sourceTree = ""; }; 51563B1B2164FA5600C4560E /* BAUserDataDiff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BAUserDataDiff.h; sourceTree = ""; }; 51563B1C2164FA5600C4560E /* BAUserDataDiff.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAUserDataDiff.m; sourceTree = ""; }; + 5157117029DAD6EC0002A9CD /* BATUserActivity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BATUserActivity.h; sourceTree = ""; }; + 5157117129DAD6EC0002A9CD /* BATUserActivity.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BATUserActivity.m; sourceTree = ""; }; 5158BB7A22F1EFF100ED0C6C /* BAWebserviceClientExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BAWebserviceClientExecutor.h; sourceTree = ""; }; 5158BB7B22F1EFF100ED0C6C /* BAWebserviceClientExecutor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAWebserviceClientExecutor.m; sourceTree = ""; }; 5159B4DE25E0044C008082FA /* internalLoggerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = internalLoggerTests.swift; sourceTree = ""; }; @@ -1068,11 +1047,6 @@ 5162B2F32571561900607780 /* BAMSGWebviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAMSGWebviewViewController.m; sourceTree = ""; }; 5166D7D425ED3ED700F36A5E /* BATMessagingCloseErrorCause.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BATMessagingCloseErrorCause.h; sourceTree = ""; }; 5166D7DE25ED464700F36A5E /* BATMessagingCloseErrorCause.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BATMessagingCloseErrorCause.m; sourceTree = ""; }; - 51675F0721383619000E7B9F /* BALMetaContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALMetaContext.h; sourceTree = ""; }; - 51675F0821383619000E7B9F /* BALMetaContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALMetaContext.m; sourceTree = ""; }; - 51675F0B21383D6A000E7B9F /* batchContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = batchContextTests.swift; sourceTree = ""; }; - 51675F0D213842B4000E7B9F /* BALCachingContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALCachingContext.h; sourceTree = ""; }; - 51675F0E213842B4000E7B9F /* BALCachingContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALCachingContext.m; sourceTree = ""; }; 51696F7825263BFC00951CA4 /* BAApplicationLifecycle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAApplicationLifecycle.h; sourceTree = ""; }; 51696F7925263BFC00951CA4 /* BAApplicationLifecycle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAApplicationLifecycle.m; sourceTree = ""; }; 51697DCD22DC847D0043FE49 /* BAQueryWebserviceClientDatasource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAQueryWebserviceClientDatasource.h; sourceTree = ""; }; @@ -1136,8 +1110,6 @@ 5193FC9422F0830800F5C9B9 /* BAURLSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAURLSession.m; sourceTree = ""; }; 5193FC9522F0830800F5C9B9 /* BAURLSessionProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BAURLSessionProtocol.h; sourceTree = ""; }; 5193FC9622F0830900F5C9B9 /* BAURLSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BAURLSession.h; sourceTree = ""; }; - 51952CFE2139828900D8E357 /* BALEventContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALEventContext.h; sourceTree = ""; }; - 51952CFF2139828900D8E357 /* BALEventContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALEventContext.m; sourceTree = ""; }; 51977ED620DBCE490046B40D /* BAPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BAPromise.h; sourceTree = ""; }; 51977ED720DBCE490046B40D /* BAPromise.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAPromise.m; sourceTree = ""; }; 51977EDA20DC17040046B40D /* BAOptOutWebserviceClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAOptOutWebserviceClient.h; sourceTree = ""; }; @@ -1286,8 +1258,6 @@ 51F1FCFB20DAA0A7006EDE43 /* batchTaskDebouncerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = batchTaskDebouncerTest.swift; sourceTree = ""; }; 51F222AB1B4C16AC005DFBCE /* BatchLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BatchLogger.h; path = Batch/BatchLogger.h; sourceTree = SOURCE_ROOT; }; 51F58E35257FAA31000DE3E0 /* BAMessagingAnalyticsDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAMessagingAnalyticsDelegate.h; sourceTree = ""; }; - 51F8403B214188040009DFB1 /* BALUserAttributeContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BALUserAttributeContext.h; sourceTree = ""; }; - 51F8403C214188040009DFB1 /* BALUserAttributeContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BALUserAttributeContext.m; sourceTree = ""; }; 51F91A1E22DF1B00003A42F1 /* BAWebserviceURLBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAWebserviceURLBuilder.h; sourceTree = ""; }; 51F91A1F22DF1B00003A42F1 /* BAWebserviceURLBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAWebserviceURLBuilder.m; sourceTree = ""; }; 51FCC9312577EF9C00FA76C6 /* BAMSGActivityIndicatorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAMSGActivityIndicatorView.h; sourceTree = ""; }; @@ -1423,7 +1393,6 @@ 518E383A1EA8AADC009AB274 /* Inbox */, 51AE9EA120D930240084CF14 /* Opt Out */, 51ECF37420065AF40086C9CC /* Debug */, - 5105746E2135860500789F86 /* Lisp */, ); path = Modules; sourceTree = ""; @@ -1453,6 +1422,8 @@ 51B5E4881C849D8900047F6E /* BABundleInfo.m */, 51AE746620850217005186D7 /* BAInstallationID.h */, 51AE746720850217005186D7 /* BAInstallationID.m */, + 5157117029DAD6EC0002A9CD /* BATUserActivity.h */, + 5157117129DAD6EC0002A9CD /* BATUserActivity.m */, ); path = Core; sourceTree = ""; @@ -1654,7 +1625,6 @@ 629EF3BB243E2590006A47CC /* Inbox */, 62579A0E235DBBA30018B26C /* EventDispatcher */, 5122032422CA5BD6001A505F /* Messaging */, - 5105747B21358C1900789F86 /* Lisp */, 51A214EF25CC6073003FD6A6 /* Local Campaigns */, 51BD1924202074D200C2524D /* Actions */, 02849BDB19B9FA2D0013408B /* Core */, @@ -1938,36 +1908,12 @@ 517EAE411C1890540058D288 /* BAUserAttribute.h */, 517EAE421C1890540058D288 /* BAUserAttribute.m */, 51A31D811E27DC8B004CDD65 /* BAUserDataEnums.h */, + 1E104EAD28E6F43D00E998AE /* BAUserEmailSubscription.h */, + 1E104EAE28E6F43D00E998AE /* BAUserEmailSubscription.m */, ); path = User; sourceTree = ""; }; - 5105746E2135860500789F86 /* Lisp */ = { - isa = PBXGroup; - children = ( - 51675F0621383113000E7B9F /* Evaluation Contexts */, - 510574782135862000789F86 /* BALEvaluationContext.h */, - 510574702135861F00789F86 /* BALispParser.h */, - 510574762135862000789F86 /* BALispParser.m */, - 510574742135862000789F86 /* BALOperators.h */, - 5105746F2135861F00789F86 /* BALOperators.m */, - 510574752135862000789F86 /* BALSExpression.h */, - 510574732135862000789F86 /* BALSExpression.m */, - 510574772135862000789F86 /* BALValues.h */, - 510574712135861F00789F86 /* BALValues.m */, - ); - path = Lisp; - sourceTree = ""; - }; - 5105747B21358C1900789F86 /* Lisp */ = { - isa = PBXGroup; - children = ( - 5105747C21358C2A00789F86 /* batchLispTests.swift */, - 51675F0B21383D6A000E7B9F /* batchContextTests.swift */, - ); - path = Lisp; - sourceTree = ""; - }; 510BD5B822E0A55200D8CBA1 /* Query Services Implementations */ = { isa = PBXGroup; children = ( @@ -2090,6 +2036,7 @@ 51B4F4FF25D3F76F0077E948 /* osHelperTests.swift */, 515A74942510BE2200F05E80 /* swizzlingTests.m */, 515A74962510C17800F05E80 /* swiftSwizzling.swift */, + 1EB69D3D290C0F5A003E1EF7 /* emailTests.swift */, ); path = Helpers; sourceTree = ""; @@ -2187,6 +2134,7 @@ 93C78F5E220AE4120082A6F7 /* batchUserTests.m */, 51242703244D8F9700025DA3 /* batchUserDataEditorTests.swift */, 51E22DC62451CA3C00D02CA8 /* batchUserEditorPublicAPITests.m */, + 1E104EB528EB289400E998AE /* batchUserEmailSubscriptionTests.m */, ); name = User; sourceTree = ""; @@ -2352,6 +2300,8 @@ 93F04586224B7E8E0006C41A /* BADateFormatting.m */, 51D3E79C2328EF7100DF82AF /* BAWindowHelper.h */, 51D3E79D2328EF7100DF82AF /* BAWindowHelper.m */, + 1EB69D39290C09B9003E1EF7 /* BAEmailUtils.h */, + 1EB69D3A290C09B9003E1EF7 /* BAEmailUtils.m */, ); path = Helpers; sourceTree = ""; @@ -2374,23 +2324,6 @@ path = HMAC; sourceTree = ""; }; - 51675F0621383113000E7B9F /* Evaluation Contexts */ = { - isa = PBXGroup; - children = ( - 51675F0721383619000E7B9F /* BALMetaContext.h */, - 51675F0821383619000E7B9F /* BALMetaContext.m */, - 51675F0D213842B4000E7B9F /* BALCachingContext.h */, - 51675F0E213842B4000E7B9F /* BALCachingContext.m */, - 51952CFE2139828900D8E357 /* BALEventContext.h */, - 51952CFF2139828900D8E357 /* BALEventContext.m */, - 51093AB021400FD200C4C1BA /* BALNativeAttributeContext.h */, - 51093AB121400FD200C4C1BA /* BALNativeAttributeContext.m */, - 51F8403B214188040009DFB1 /* BALUserAttributeContext.h */, - 51F8403C214188040009DFB1 /* BALUserAttributeContext.m */, - ); - path = "Evaluation Contexts"; - sourceTree = ""; - }; 5169F9441F20C21F00274FF9 /* Persistence */ = { isa = PBXGroup; children = ( @@ -2918,18 +2851,8 @@ 517D716A22BBC50E00E374FB /* BADBGLCDetailsViewController.h in Headers */, 517D716B22BBC50E00E374FB /* BADBGCustomDataViewController.h in Headers */, 517D716C22BBC50E00E374FB /* BADBGCustomDataModels.h in Headers */, - 517D716D22BBC50E00E374FB /* BALMetaContext.h in Headers */, 510BD5D722E0B4D500D8CBA1 /* BAWSQueryAttributes.h in Headers */, - 517D716E22BBC50E00E374FB /* BALCachingContext.h in Headers */, - 517D716F22BBC50E00E374FB /* BALEventContext.h in Headers */, - 517D717022BBC50E00E374FB /* BALNativeAttributeContext.h in Headers */, - 517D717122BBC50E00E374FB /* BALUserAttributeContext.h in Headers */, - 517D717222BBC50E00E374FB /* BALEvaluationContext.h in Headers */, - 517D717322BBC50E00E374FB /* BALispParser.h in Headers */, - 517D717422BBC50E00E374FB /* BALOperators.h in Headers */, - 517D717522BBC50E00E374FB /* BALSExpression.h in Headers */, 5171445B22DCA29D001E99D7 /* BAStandardQueryWebserviceIdentifiersProvider.h in Headers */, - 517D717622BBC50E00E374FB /* BALValues.h in Headers */, 517D717822BBC50E00E374FB /* BAWSQuery.h in Headers */, 517D717C22BBC50E00E374FB /* BAWSQueryPushToken.h in Headers */, 517D717E22BBC50E00E374FB /* BAWSQueryTracking.h in Headers */, @@ -3036,6 +2959,9 @@ 1EBDBC76271709D1006DC662 /* BAMetricManager.h in Headers */, 1E45578527CE1B510048D3A8 /* BALocalCampaignsJITService.h in Headers */, 1E2C31B527CF740E00A4CB6E /* BAMetricRegistry.h in Headers */, + 5157117229DAD6EC0002A9CD /* BATUserActivity.h in Headers */, + 1EB69D3B290C09B9003E1EF7 /* BAEmailUtils.h in Headers */, + 1E104EAF28E6F43D00E998AE /* BAUserEmailSubscription.h in Headers */, 1EBDBC662715B2A2006DC662 /* BAMetricProtocol.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3125,7 +3051,7 @@ 517D701722BBC34A00E374FB = { CreatedOnToolsVersion = 11.0; DevelopmentTeam = U5K2ETC2Y6; - LastSwiftMigration = 1320; + LastSwiftMigration = 1410; ProvisioningStyle = Automatic; }; }; @@ -3185,7 +3111,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# workaround for bitcode generation problem with Xcode 7.3\nunset TOOLCHAINS\n\nexport CONFIGURATION=Release\n\n# define output folder environment variable\nUNIVERSAL_OUTPUTFOLDER=${PROJECT_DIR}/universal/Batch.embeddedframework\n\n# Step 1. Build Device and Simulator versions\nxcodebuild OTHER_CFLAGS=\"-fembed-bitcode\" -target Batch ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\"\nxcodebuild OTHER_CFLAGS=\"-fembed-bitcode\" -target Batch ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\"\n\n# Remove the old output folder\nrm -rf \"${UNIVERSAL_OUTPUTFOLDER}\"\n\n# Recreate it\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}\"\n\n# Copy the generated framework\ncp -R \"${BUILD_DIR}/${CONFIGURATION}-iphoneos/Batch.framework\" \"${UNIVERSAL_OUTPUTFOLDER}/\"\n\n# Remove the old binary\nrm \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/Batch\"\n\n# Extract Intel slices from the simulator binary\n# We can't support arm64 and arm64e for silicon macs in a fat framework, lipo will fail\nSIMULATOR_FRAMEWORK_PATH=\"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/Batch.framework/Batch\"\nlipo -extract \"i386\" -output \"${SIMULATOR_FRAMEWORK_PATH}-i386\" \"${SIMULATOR_FRAMEWORK_PATH}\"\nlipo -extract \"x86_64\" -output \"${SIMULATOR_FRAMEWORK_PATH}-x86_64\" \"${SIMULATOR_FRAMEWORK_PATH}\"\n\n# Create universal binary file using lipo\nlipo -create -output \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/Batch\" \"${BUILD_DIR}/${CONFIGURATION}-iphoneos/Batch.framework/Batch\" \"${SIMULATOR_FRAMEWORK_PATH}-i386\" \"${SIMULATOR_FRAMEWORK_PATH}-x86_64\" \n\n# make sure the resource directory exists\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle\"\nrm -R \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle/\"\n\n# Move ressources.\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/en.lproj/\" #this may not exist\ncp -R \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/en.lproj/\" \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle/\"\nrm -R \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/en.lproj/\"\ntouch \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle/.gitignore\"\n\n# Clean up framework for public use\ncd \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/\"\nsh ${PROJECT_DIR}/../Tools/strip_public_swift_framework.sh\n\n"; + shellScript = "# workaround for bitcode generation problem with Xcode 7.3\nunset TOOLCHAINS\n\nexport CONFIGURATION=Release\n\n# define output folder environment variable\nUNIVERSAL_OUTPUTFOLDER=${PROJECT_DIR}/universal/Batch.embeddedframework\n\n# Step 1. Build Device and Simulator versions\nxcodebuild OTHER_CFLAGS=\"-fembed-bitcode\" -target Batch ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\"\nxcodebuild OTHER_CFLAGS=\"-fembed-bitcode\" -target Batch ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\"\n\n# Remove the old output folder\nrm -rf \"${UNIVERSAL_OUTPUTFOLDER}\"\n\n# Recreate it\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}\"\n\n# Copy the generated framework\ncp -R \"${BUILD_DIR}/${CONFIGURATION}-iphoneos/Batch.framework\" \"${UNIVERSAL_OUTPUTFOLDER}/\"\n\n# Remove the old binary\nrm \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/Batch\"\n\n# Extract Intel slices from the simulator binary\n# We can't support arm64 and arm64e for silicon macs in a fat framework, lipo will fail\nSIMULATOR_FRAMEWORK_PATH=\"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/Batch.framework/Batch\"\nlipo -extract \"x86_64\" -output \"${SIMULATOR_FRAMEWORK_PATH}-x86_64\" \"${SIMULATOR_FRAMEWORK_PATH}\"\n\n# Create universal binary file using lipo\nlipo -create -output \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/Batch\" \"${BUILD_DIR}/${CONFIGURATION}-iphoneos/Batch.framework/Batch\" \"${SIMULATOR_FRAMEWORK_PATH}-x86_64\" \n\n# make sure the resource directory exists\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle\"\nrm -R \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle/\"\n\n# Move ressources.\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/en.lproj/\" #this may not exist\ncp -R \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/en.lproj/\" \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle/\"\nrm -R \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/en.lproj/\"\ntouch \"${UNIVERSAL_OUTPUTFOLDER}/Batch.bundle/.gitignore\"\n\n# Clean up framework for public use\ncd \"${UNIVERSAL_OUTPUTFOLDER}/Batch.framework/\"\nsh ${PROJECT_DIR}/../Tools/Scripts/strip_public_swift_framework.sh\n"; }; 516BBC0B22BD0D2900742649 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -3199,7 +3125,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# workaround for bitcode generation problem with Xcode 7.3\nunset TOOLCHAINS\n\nexport CONFIGURATION=Release\n\n# define output folder environment variable\nARCHIVES_OUTPUTFOLDER=${PROJECT_DIR}/universal/Archives\nDSYMS_OUTPUTFOLDER=${PROJECT_DIR}/universal/dSYMs\nXCFRAMEWORK_OUTPUT=${PROJECT_DIR}/universal/Batch.xcframework\n\n# Create the output folders\nmkdir -p \"${ARCHIVES_OUTPUTFOLDER}\"\nmkdir -p \"${DSYMS_OUTPUTFOLDER}\"\nrm -f \"${DSYMS_OUTPUTFOLDER}/*.dSYM\"\n\n# Step 1. Build Device, Simulator and macOS versions\nxcodebuild archive -scheme Batch -destination \"generic/platform=iOS\" -configuration ${CONFIGURATION} -archivePath \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive\" SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO OTHER_CFLAGS=\"-fembed-bitcode\" ARCHS=\"armv7 arm64 arm64e\" VALID_ARCHS=\"armv7 arm64 arm64e\"\nxcodebuild archive -scheme Batch -destination \"generic/platform=iOS Simulator\" -configuration ${CONFIGURATION} -archivePath \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive\" SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO OTHER_CFLAGS=\"-fembed-bitcode\"\nxcodebuild archive -scheme Batch -destination \"platform=macOS\" -configuration ${CONFIGURATION} -archivePath \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive\" SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO OTHER_CFLAGS=\"-fembed-bitcode\"\n\n# Step 2. Copy the dSYMs\n\ncp -a \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive/dSYMs/Batch.framework.dSYM\" \"${DSYMS_OUTPUTFOLDER}/Batch_iphoneos.framework.dSYM\"\ncp -a \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive/dSYMs/Batch.framework.dSYM\" \"${DSYMS_OUTPUTFOLDER}/Batch_iphonesimulator.framework.dSYM\"\ncp -a \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive/dSYMs/Batch.framework.dSYM\" \"${DSYMS_OUTPUTFOLDER}/Batch_macos.framework.dSYM\"\n\n# Step 3. Clean up the frameworks\n\npushd\n\ncd \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive/Products/Library/Frameworks/Batch.framework/\"\nsh ${PROJECT_DIR}/../Tools/strip_public_swift_framework.sh\n\ncd \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive/Products/Library/Frameworks/Batch.framework/\"\nsh ${PROJECT_DIR}/../Tools/strip_public_swift_framework.sh\n\ncd \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive/Products/Library/Frameworks/Batch.framework/Versions/A/\"\nsh ${PROJECT_DIR}/../Tools/strip_public_swift_framework.sh\n\n## 3.1: Fix Xcode not creating the \"PrivateHeaders\" folder, which can break Azure Pipelines\n## https://github.com/bamlab/react-native-batch-push/issues/67\nmkdir \"PrivateHeaders\"\n\npopd\n\n# Step 4. Make the xcframework\n# Remove the old xcframework\nrm -rf \"${XCFRAMEWORK_OUTPUT}\"\n\n# Build the xcframework\n\nxcodebuild -create-xcframework \\\n -framework \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -framework \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -framework \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -output \"${XCFRAMEWORK_OUTPUT}\"\n"; + shellScript = "# workaround for bitcode generation problem with Xcode 7.3\nunset TOOLCHAINS\n\nexport CONFIGURATION=Release\n\n# define output folder environment variable\nARCHIVES_OUTPUTFOLDER=${PROJECT_DIR}/universal/Archives\nDSYMS_OUTPUTFOLDER=${PROJECT_DIR}/universal/dSYMs\nXCFRAMEWORK_OUTPUT=${PROJECT_DIR}/universal/Batch.xcframework\n\n# Create the output folders\nmkdir -p \"${ARCHIVES_OUTPUTFOLDER}\"\nmkdir -p \"${DSYMS_OUTPUTFOLDER}\"\nrm -f \"${DSYMS_OUTPUTFOLDER}/*.dSYM\"\n\n# Step 1. Build Device, Simulator and macOS versions\nxcodebuild archive -scheme Batch -destination \"generic/platform=iOS\" -configuration ${CONFIGURATION} -archivePath \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive\" SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO OTHER_CFLAGS=\"-fembed-bitcode\" ARCHS=\"arm64 arm64e\" VALID_ARCHS=\"arm64 arm64e\"\nxcodebuild archive -scheme Batch -destination \"generic/platform=iOS Simulator\" -configuration ${CONFIGURATION} -archivePath \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive\" SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO OTHER_CFLAGS=\"-fembed-bitcode\"\nxcodebuild archive -scheme Batch -destination \"platform=macOS\" -configuration ${CONFIGURATION} -archivePath \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive\" SKIP_INSTALL=NO ONLY_ACTIVE_ARCH=NO OTHER_CFLAGS=\"-fembed-bitcode\"\n\n# Step 2. Copy the dSYMs\n\ncp -a \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive/dSYMs/Batch.framework.dSYM\" \"${DSYMS_OUTPUTFOLDER}/Batch_iphoneos.framework.dSYM\"\ncp -a \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive/dSYMs/Batch.framework.dSYM\" \"${DSYMS_OUTPUTFOLDER}/Batch_iphonesimulator.framework.dSYM\"\ncp -a \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive/dSYMs/Batch.framework.dSYM\" \"${DSYMS_OUTPUTFOLDER}/Batch_macos.framework.dSYM\"\n\n# Step 3. Clean up the frameworks\n\npushd\n\ncd \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive/Products/Library/Frameworks/Batch.framework/\"\nsh ${PROJECT_DIR}/../Tools/Scripts/strip_public_swift_framework.sh\n\ncd \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive/Products/Library/Frameworks/Batch.framework/\"\nsh ${PROJECT_DIR}/../Tools/Scripts/strip_public_swift_framework.sh\n\ncd \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive/Products/Library/Frameworks/Batch.framework/Versions/A/\"\nsh ${PROJECT_DIR}/../Tools/Scripts/strip_public_swift_framework.sh\n\n## 3.1: Fix Xcode not creating the \"PrivateHeaders\" folder, which can break Azure Pipelines\n## https://github.com/bamlab/react-native-batch-push/issues/67\nmkdir \"PrivateHeaders\"\n\npopd\n\n# Step 4. Make the xcframework\n# Remove the old xcframework\nrm -rf \"${XCFRAMEWORK_OUTPUT}\"\n\n# Build the xcframework\n\nxcodebuild -create-xcframework \\\n -framework \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphoneos.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -framework \"${ARCHIVES_OUTPUTFOLDER}/Batch-iphonesimulator.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -framework \"${ARCHIVES_OUTPUTFOLDER}/Batch-macos.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -output \"${XCFRAMEWORK_OUTPUT}\"\n"; }; 516C406723D9FD63000C11CF /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -3217,7 +3143,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "cd ${PROJECT_DIR}\nenv -i HOME=\"$HOME\" bash -l -c ./generate_private_umbrella_header.sh\n"; + shellScript = "cd ${PROJECT_DIR}\nenv -i HOME=\"$HOME\" bash -l -c ../Tools/Scripts/generate_private_umbrella_header.sh\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -3232,6 +3158,7 @@ 6295B154243F44520065059E /* inboxFetchWebserviceClientTests.m in Sources */, 51B4F50025D3F76F0077E948 /* osHelperTests.swift in Sources */, 62579A11235DBF7C0018B26C /* pushEventPayloadTests.m in Sources */, + 1EB69D3E290C0F5A003E1EF7 /* emailTests.swift in Sources */, 1EBDBC8427188D40006DC662 /* metricTests.m in Sources */, 51ACA05D2166193D006FAD04 /* batchUserDiffTests.swift in Sources */, 515A74972510C17800F05E80 /* swiftSwizzling.swift in Sources */, @@ -3240,7 +3167,6 @@ 51DD79BC25D2BE0F005E8D62 /* webviewBridgeLegacyTests.swift in Sources */, 51F1FCFC20DAA0A7006EDE43 /* batchTaskDebouncerTest.swift in Sources */, 5192784A25D1764D005C43B4 /* webviewJavascriptBridgeTests.swift in Sources */, - 5105747D21358C2A00789F86 /* batchLispTests.swift in Sources */, 51E22DC72451CA3C00D02CA8 /* batchUserEditorPublicAPITests.m in Sources */, 1EA32C6027B524600085D133 /* localCampaignsSQLTrackerTests.m in Sources */, 51C6A47225CA99DF00B07AB6 /* batchTestsBootstrap.m in Sources */, @@ -3254,6 +3180,7 @@ 51ECC06D22D4F8C800F1C5EC /* webserviceAESGCMCryptorTests.m in Sources */, 1EA42E0426A9A736004CC618 /* FindMyInstallationHelperTests.m in Sources */, 1EBDBC86271D9936006DC662 /* metricManagerTests.m in Sources */, + 1E104EB628EB289400E998AE /* batchUserEmailSubscriptionTests.m in Sources */, 628C158F24AB8E990026C4EC /* inboxSyncWebserviceClientTests.m in Sources */, 5192785025D17B80005C43B4 /* XCTest+BAPromise.swift in Sources */, 5159B4ED25E01BA9008082FA /* loggerSetupTests.m in Sources */, @@ -3263,7 +3190,6 @@ 629B42AE249119860025411E /* gzipTests.m in Sources */, 02849BFD19B9FA2D0013408B /* batchCoreTests.m in Sources */, 518D887023560C79007BF341 /* messagingAnalyticsDeduplicatingDelegateTests.swift in Sources */, - 51675F0C21383D6A000E7B9F /* batchContextTests.swift in Sources */, 514BA4A027D257F100B93FAF /* inboxFetcherTests.swift in Sources */, 939E058A222D2CC700E8D32D /* batchUserTests.m in Sources */, 510D906F24C83A81005981AC /* shaTests.swift in Sources */, @@ -3404,6 +3330,7 @@ 517D702222BBC45900E374FB /* BatchUserProfile.m in Sources */, 517D702322BBC45900E374FB /* BatchInbox.m in Sources */, 517D702422BBC45900E374FB /* BatchPush.m in Sources */, + 5157117329DAD6EC0002A9CD /* BATUserActivity.m in Sources */, 517D702522BBC45900E374FB /* BatchUser.m in Sources */, 517CC28825B6DAC200A3F380 /* BATWebviewBridgeLegacyWKHandler.m in Sources */, 517D702622BBC45900E374FB /* BatchUserAttribute.m in Sources */, @@ -3462,6 +3389,7 @@ 517D705722BBC45900E374FB /* BATrackerSender.m in Sources */, 517D705822BBC45900E374FB /* BATrackerSignpostHelper.m in Sources */, 517D705B22BBC45900E374FB /* BAMessagingCenter.m in Sources */, + 1E104EB028E6F43D00E998AE /* BAUserEmailSubscription.m in Sources */, 51379B8022FC5C0200AB7B82 /* BAInjectableImplementations.m in Sources */, 517D705C22BBC45900E374FB /* BADelegatedUIAlertController.m in Sources */, 517D705D22BBC45900E374FB /* BABatchMessagingDelegateWrapper.m in Sources */, @@ -3527,6 +3455,7 @@ 629B42A52490D8FA0025411E /* BATGZIP.m in Sources */, 629B42A12490C9120025411E /* BAWebserviceAESGCMGzipCryptor.m in Sources */, 517D708A22BBC45900E374FB /* BAUserDataBuiltinActions.m in Sources */, + 1EB69D3C290C09B9003E1EF7 /* BAEmailUtils.m in Sources */, 517D708B22BBC45900E374FB /* BAInbox.m in Sources */, 517D708C22BBC45900E374FB /* BAInboxFetchWebserviceClient.m in Sources */, 6231A5252458171100AFFA3D /* BAWebserviceJsonClient.m in Sources */, @@ -3548,15 +3477,6 @@ 517D709722BBC45900E374FB /* BADBGCustomDataViewController.m in Sources */, 627278E524A4FDA80067F036 /* BAInboxSyncWebserviceClient.m in Sources */, 517D709822BBC45900E374FB /* BADBGCustomDataModels.m in Sources */, - 517D709922BBC45900E374FB /* BALMetaContext.m in Sources */, - 517D709A22BBC45900E374FB /* BALCachingContext.m in Sources */, - 517D709B22BBC45900E374FB /* BALEventContext.m in Sources */, - 517D709C22BBC45900E374FB /* BALNativeAttributeContext.m in Sources */, - 517D709D22BBC45900E374FB /* BALUserAttributeContext.m in Sources */, - 517D709E22BBC45900E374FB /* BALispParser.m in Sources */, - 517D709F22BBC45900E374FB /* BALOperators.m in Sources */, - 517D70A022BBC45900E374FB /* BALSExpression.m in Sources */, - 517D70A122BBC45900E374FB /* BALValues.m in Sources */, 517D70A222BBC45900E374FB /* BAWSQuery.m in Sources */, 620F175224488AFB00D046D5 /* BADisplayReceiptCenter.m in Sources */, 510BD5C622E0B4BA00D8CBA1 /* BAWSResponseAttributes.m in Sources */, @@ -3628,12 +3548,14 @@ 02849C3419BA00350013408B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + DEFINES_MODULE = NO; }; name = Debug; }; 02849C3519BA00350013408B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + DEFINES_MODULE = NO; }; name = Release; }; @@ -3686,7 +3608,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -3738,7 +3660,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -3762,7 +3684,7 @@ ); HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/Batch/**"; INFOPLIST_FILE = batchTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3794,7 +3716,7 @@ GCC_PREFIX_HEADER = "$(SOURCE_ROOT)/Batch/batch-Prefix.pch"; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/Batch/**"; INFOPLIST_FILE = batchTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3900,7 +3822,7 @@ INFOPLIST_PREFIX_HEADER = Batch/Versions.h; INFOPLIST_PREPROCESS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3914,7 +3836,7 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.7; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -3925,7 +3847,6 @@ "ARCHS[sdk=iphoneos*]" = ( "$(ARCHS_STANDARD)", arm64e, - armv7s, ); BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_ANALYZER_NONNULL = YES; @@ -3952,7 +3873,7 @@ INFOPLIST_PREFIX_HEADER = Batch/Versions.h; INFOPLIST_PREPROCESS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3965,7 +3886,7 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; STRIP_STYLE = debugging; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.7; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/Sources/Batch/BAErrorHelper.h b/Sources/Batch/BAErrorHelper.h index 73e033c..493070e 100644 --- a/Sources/Batch/BAErrorHelper.h +++ b/Sources/Batch/BAErrorHelper.h @@ -8,32 +8,31 @@ #import -typedef NS_ENUM(NSInteger, BAInternalFailReason) -{ +typedef NS_ENUM(NSInteger, BAInternalFailReason) { /*! A network problem occurred. */ - BAInternalFailReasonNetworkError = -10, - + BAInternalFailReasonNetworkError = -10, + /*! Invalid API key. */ - BAInternalFailReasonInvalidAPIKey = -20, - + BAInternalFailReasonInvalidAPIKey = -20, + /*! Deactivated API Key. */ - BAInternalFailReasonDeactivatedAPIKey = -30, - + BAInternalFailReasonDeactivatedAPIKey = -30, + /*! Another problem occurred. A retry can succeed */ - BAInternalFailReasonUnexpectedError = -50, - + BAInternalFailReasonUnexpectedError = -50, + /*! Batch has been globally opted out from */ - BAInternalFailReasonOptedOut = -60 + BAInternalFailReasonOptedOut = -60 }; typedef NSInteger BatchFailReason; diff --git a/Sources/Batch/BANotificationCenter.h b/Sources/Batch/BANotificationCenter.h index 533704f..bb2850d 100644 --- a/Sources/Batch/BANotificationCenter.h +++ b/Sources/Batch/BANotificationCenter.h @@ -9,8 +9,8 @@ #import // Batch notifications: -#define kNotificationBatchStarts @"notification.start" -#define kNotificationBatchStops @"notification.stop" +#define kNotificationBatchStarts @"notification.start" +#define kNotificationBatchStops @"notification.stop" /*! @class BANotificationCenter diff --git a/Sources/Batch/Batch.h b/Sources/Batch/Batch.h index 6ecb1f9..141c632 100644 --- a/Sources/Batch/Batch.h +++ b/Sources/Batch/Batch.h @@ -14,14 +14,14 @@ FOUNDATION_EXPORT double BatchVersionNumber; //! Project version string for Batch. FOUNDATION_EXPORT const unsigned char BatchVersionString[]; +#import #import -#import +#import +#import +#import #import -#import #import -#import -#import -#import #import +#import +#import #import -#import diff --git a/Sources/Batch/BatchActions.h b/Sources/Batch/BatchActions.h index 7ef23ce..eb4c766 100644 --- a/Sources/Batch/BatchActions.h +++ b/Sources/Batch/BatchActions.h @@ -10,123 +10,97 @@ #pragma mark Action sources -/** - Represents an action source. - Can be used to get more information about the context of the action, such as the full push payload, if coming from a push. - */ +/// Represents an action source. +/// +/// Can be used to get more information about the context of the action, such as the full push payload, if coming from a +/// push. @protocol BatchUserActionSource @end -/** - Source that's only set when an action was manually triggered by +[BatchActions performActionIdentifiedBy:withArguments:] - */ +/// Source that's only set when an action was manually triggered by +/// ``BatchActions/performActionIdentifiedBy:withArguments:`` @interface BatchManualUserActionSource : NSObject @end #pragma mark Action model -typedef void (^BatchUserActionBlock)(NSString* _Nonnull identifier, NSDictionary* _Nonnull arguments, id _Nullable source); +typedef void (^BatchUserActionBlock)(NSString *_Nonnull identifier, + NSDictionary *_Nonnull arguments, + id _Nullable source); -/** - Represents an action that can be triggered by the user from anywhere. - */ +/// Represents an action that can be triggered by the user from anywhere. @interface BatchUserAction : NSObject -/** - Create a new BatchUserAction object with the following parameters - Be careful, as the action block can be invoked on any thread. You should never make any assumption about which thread you're on when this is called. - - @param identifier The unique action identifier. Should be unique in your app (not case-sensitive). - - @param actionBlock The action block that will be invoked when Batch wants to execute your action. Can be called from any thread: never make any assumption about which thread you're on when this is called. - - @returns A BatchUserAction instance constructed from the given parameters. - */ -+ (nonnull instancetype)userActionWithIdentifier:(nonnull NSString*)identifier +/// Create a new ``BatchUserAction`` object with the following parameters. +/// +/// - Important: Be careful, as the action block can be invoked on any thread. You should never make any assumption +/// about which thread you're on when this is called. +/// - Parameters: +/// - identifier: The unique action identifier. Should be unique in your app (not case-sensitive). +/// - actionBlock: The action block that will be invoked when Batch wants to execute your action. Can be called from +/// any thread: never make any assumption about which thread you're on when this is called. +/// - Returns: A ``BatchUserAction`` instance constructed from the given parameters. ++ (nonnull instancetype)userActionWithIdentifier:(nonnull NSString *)identifier actionBlock:(nonnull BatchUserActionBlock)actionBlock; -/** - Action identifier. Should be unique in your app. - */ +/// Action identifier. Should be unique in your app. @property (readonly, nonnull) NSString *identifier; -/** - Action block to invoke when Batch wants to perform your action. - Be careful, as it can be invoked on any thread. You should never make any assumption about which thread you're on when this is called. - */ +/// Action block to invoke when Batch wants to perform your action. +/// +/// - Important: Be careful, as it can be invoked on any thread. You should never make any assumption about which thread +/// you're on when this is called. @property (readonly, nonnull) BatchUserActionBlock actionBlock; @end #pragma mark Action module -/** - Batch's Actions module - */ +/// Batch's Actions module @interface BatchActions : NSObject -/** - Register an action with Batch. - If an action already exists for that identifier, it will be replaced. Identifiers are not case-sensitive. - Note that the action identifier cannot start with "batch.", as they are reserved by the SDK. - Trying to register such an action will throw an error. - - @param action The action to register - - @returns An NSError pointer if the action couldn't be registered, nil otherwise - */ -+ (nullable NSError*)registerAction:(nonnull BatchUserAction*)action; - -/** - Unregister an action from Batch. - - Trying to unregister an action that has not be registered will silently fail. - Note that trying to unregister an action that starts with "batch." will fail silently. - - @param actionIdentifier The action's identifier. Not case-sensitive - */ -+ (void)unregisterActionIdentifier:(nonnull NSString*)actionIdentifier NS_SWIFT_NAME(unregister(actionIdentifier:)); - -/** - Perform an action registered with Batch. - The action source will be BatchManualUserActionSource. - - Note that manually trying to trigger builtin actions (prefixed by "batch.") will not work. - - @param identifier The action identifier. Case-unsensitive. Cannot be nil. - - @param args A dictionary containing the action arguments. Cannot be nil. - - @returns YES if the action was performed, NO if no action was found or another error occurred - */ -+ (BOOL)performActionIdentifiedBy:(nonnull NSString*)identifier withArguments:(nonnull NSDictionary*)args NS_SWIFT_NAME(perform(actionIdentifier:arguments:)); +/// Register an action with Batch. +/// +/// If an action already exists for that identifier, it will be replaced. Identifiers are not case-sensitive. +/// - Note: The action identifier cannot start with "batch.", as they are reserved by the SDK. Trying to register such +/// an action will throw an error. +/// - Parameter action: The action to register ++ (nullable NSError *)registerAction:(nonnull BatchUserAction *)action; + +/// Unregister an action from Batch. +/// +/// - Note: Trying to unregister an action that has not be registered or to unregister an action that starts with +/// "batch." will silently fail. +/// - Parameter actionIdentifier: The action's identifier. Not case-sensitive. ++ (void)unregisterActionIdentifier:(nonnull NSString *)actionIdentifier NS_SWIFT_NAME(unregister(actionIdentifier:)); + +/// Perform an action registered with Batch. +/// +/// - Note: Manually trying to trigger builtin actions (prefixed by "batch.") will not work. +/// - Parameters: +/// - identifier: The action identifier. Case-unsensitive. Cannot be nil. +/// - args: A dictionary containing the action arguments. Cannot be nil. +/// - Returns: YES if the action was performed, NO if no action was found or another error occurred ++ (BOOL)performActionIdentifiedBy:(nonnull NSString *)identifier + withArguments:(nonnull NSDictionary *)args + NS_SWIFT_NAME(perform(actionIdentifier:arguments:)); @end -/** - BatchActions error code constants. - */ -enum -{ - /** - Internal error - */ +/// BatchActions error code constants. +enum { + + /// Internal error BatchActionErrorUnknown = -1001, - - /** - Can be multiple things: nil action, nil or empty identifier string, nil action block - */ + + /// Can be multiple things: nil action, nil or empty identifier string, nil action block BatchActionErrorInvalidArgument = -1002, - - /** - This action identifier is reserved and cannot be used. Note that actions cannot begin by "batch." - */ + + /// This action identifier is reserved and cannot be used. Note that actions cannot begin by "batch." BatchActionErrorReservedIdentifier = -1003 }; -/** - @typedef BatchActionError - */ +/// @typedef BatchActionError typedef NSInteger BatchActionError; diff --git a/Sources/Batch/BatchCore.h b/Sources/Batch/BatchCore.h index 6b9b49d..89c7391 100644 --- a/Sources/Batch/BatchCore.h +++ b/Sources/Batch/BatchCore.h @@ -6,253 +6,221 @@ // Copyright (c) Batch SDK. All rights reserved. // +#import +#import #import #import -#import -#import @protocol BatchDeeplinkDelegate; typedef NS_ENUM(NSUInteger, BatchOptOutNetworkErrorPolicy) { - /** - Ignore the error and proceed with the opt-out. - */ + + /// Ignore the error and proceed with the opt-out. BatchOptOutNetworkErrorPolicyIgnore, - - /** - Cancel the opt-out: please call the opt-out method again to retry. - */ + + /// Cancel the opt-out: please call the opt-out method again to retry. BatchOptOutNetworkErrorPolicyCancel, }; -/** - Batch's main entry point. - */ +/// Batch's main entry point. @interface Batch : NSObject -/** - Use the deeplink delegate object to process deeplink open requests from Batch. - - Setting a delegate will disable Batch's default behaviour, which is to call [[UIApplication sharedApplication] openURL:]. - This works for notifications and mobile landings/in-app messages, as opposed to disabling automatic deeplink handling. - It is weakly retained: make sure you retain your delegate in some place, like your application delegate. - - */ +/// Use the deeplink delegate object to process deeplink open requests from Batch. +/// +/// Setting a delegate will disable Batch's default behaviour, +/// which is to call `[[UIApplication sharedApplication] openURL:]`. +/// This works for notifications and mobile landings/in-app messages, as opposed to disabling automatic +/// deeplink handling. +/// - Important: It is weakly retained: make sure you retain your delegate in some place, like your application @property (class, weak, nullable, nonatomic) id deeplinkDelegate; -/** - Control whether Batch should enables the FindMyInstallation feature (default = YES) - If enabled Batch will copy the current installation id in the clipboard when the application is foregrounded 5 times within 12 seconds. - */ +/// Control whether Batch should enables the _FindMyInstallation_ feature (default = YES) +/// +/// If enabled Batch will copy the current installation id in the clipboard when the application is foregrounded 5 times +/// within 12 seconds. @property (class) BOOL enablesFindMyInstallation; -/** - @warning Never call this method: Batch only uses static methods. - */ +/// Init method +/// - Warning: Never call this method: Batch only uses static methods. - (nonnull instancetype)init NS_UNAVAILABLE; -/** - Start Batch. - You should call this method in application:didFinishLaunchingWithOptions: of your UIApplicationDelegate - - Note: This is the method that triggers the hooking or your Application to automatically handle some lifecycle events. - If you run into issues, you can try moving this method before other SDK initializations, or call [BatchPush disableAutomaticIntegration] before this method, and follow the "Manual Integration" advanced documentation. - - @param key Your APP's API Key, LIVE or DEV. You can find it on your dashboard. - */ +/// Start Batch. +/// +/// You should call this method in `application:didFinishLaunchingWithOptions:` of your `UIApplicationDelegate` +/// +/// - Note: This is the method that triggers the hooking or your Application to automatically handle some lifecycle +/// events. If you run into issues, you can try moving this method before other SDK initializations, or call +/// ``Batch/BatchPush/disableAutomaticIntegration`` before this method, and follow the "Manual Integration" advanced. +/// - Parameters: +/// - key: Your APP's API Key, LIVE or DEV. You can find it on your dashboard. + (void)startWithAPIKey:(NSString *_Nonnull)key NS_AVAILABLE_IOS(8_0); -/** - Handles a URL, if applicable. - Call this method in application:openURL:sourceApplication:annotation: of your UIApplicationDelegate - - @param url The URL given to you by iOS - - @return YES if Batch performed an action with this URL, NO otherwise. - */ -+ (BOOL)handleURL:(NSURL * _Nonnull)url __attribute__((warn_unused_result)) NS_AVAILABLE_IOS(8_0); - -/** - Check if Batch is running in development mode. - - @return YES if Batch is started AND if it uses a development API key. - */ -+ (BOOL)isRunningInDevelopmentMode __attribute__((warn_unused_result)) NS_AVAILABLE_IOS(8_0); - -/** - Access the default user profile object. - - @return An instance of BatchUserProfile, or nil - */ -+ (BatchUserProfile * _Nullable)defaultUserProfile __attribute__((warn_unused_result, deprecated("Please use Batch User instead"))) NS_AVAILABLE_IOS(8_0); - -/** - Control whether Batch should try to use the IDFA or if you forbid it to. (default = YES) - - @param use YES if Batch can try to use the IDFA, NO if you don't want Batch to use the IDFA. - - @warning If you disable this, you might not be able to use IDFA based debugging in your dashboard. - */ +/// Handles an URL, if applicable. +/// +/// Call this method in `application:openURL:sourceApplication:annotation:` of your `UIApplicationDelegate` +/// - Parameters: +/// - url: The URL given to you by iOS +/// - Returns: YES if Batch performed an action with this URL, NO otherwise. ++ (BOOL)handleURL:(NSURL *_Nonnull)url __attribute__((warn_unused_result))NS_AVAILABLE_IOS(8_0); + +/// Check if Batch is running in development mosde. +/// +/// - Returns: YES if Batch is started __AND__ if it uses a development API key. ++ (BOOL)isRunningInDevelopmentMode __attribute__((warn_unused_result))NS_AVAILABLE_IOS(8_0); + +/// Access the default user profile object. +/// +/// - Returns: An instance of ``BatchUserProfile``, or nil ++ (BatchUserProfile *_Nullable)defaultUserProfile + __attribute__((warn_unused_result, deprecated("Please use Batch User instead")))NS_AVAILABLE_IOS(8_0); + +/// Control whether Batch should try to use the IDFA or if you forbid it to. (default = YES) +/// - Warning: If you disable this, you might not be able to use IDFA based debugging in your dashboard. +/// - Parameters: +/// - use: YES if Batch can try to use the IDFA, NO if you don't want Batch to use the IDFA. + (void)setUseIDFA:(BOOL)use NS_AVAILABLE_IOS(8_0); -/** - Set if Batch can use advanced device identifiers (default = YES) - - Advanced device identifiers include information about the device itself, but nothing that - directly identify the user, such as but not limited to: - - - Device model - - - Device brand - - - Carrier name - - Setting this to false have a negative impact on core Batch features - You should only use it if you know what you are doing. - - @param use YES if Batch can try to use advanced device information, NO if you don't - - @warning Disabling this does not automatically disable IDFA collection, please use the appropriate methods to control this. - */ +/// Set if Batch can use advanced device identifiers (default = YES) +/// +/// Advanced device identifiers include information about the device itself, but nothing that directly identify the +/// user, such as but not limited to: +/// - Device model +/// - Device brand +/// - Carrier name +/// - Important: Disabling this does not automatically disable IDFA collection, please use the appropriate methods to +/// control this. +/// - Parameters: +/// - use: YES if Batch can try to use advanced device information, NO if you don't + (void)setUseAdvancedDeviceInformation:(BOOL)use NS_AVAILABLE_IOS(8_0); -/** - Set if Batch should send its logs to a custom object of yours. - Be careful with your implementation: setting this can impact stability and performance - - @param loggerDelegate An object implementing BatchLoggerDelegate. Weakly retained. - - @warning You should only use it if you know what you are doing. - */ +/// Set if Batch should send its logs to a custom object of yours. +/// +/// - Important: Be careful with your implementation: setting this can impact stability and performance. You should only +/// use it if you know what you are doing. +/// - Parameter loggerDelegate: An object implementing ``Batch/BatchLoggerDelegate``. Weakly retained. + (void)setLoggerDelegate:(id _Nullable)loggerDelegate NS_AVAILABLE_IOS(8_0); -/** - Get the debug view controller. - For development purposes only, this contains UI with multiple debug features allowing you to debug your Batch implementation more easily. - If you want to make it accessible in production, you should hide it in a hard to reproduce sequence. - - Should be presented modally. - */ -+ (UIViewController* _Nullable)debugViewController; - -/** - Toogle whether internal logs should be logged or not. - - If you have a BatchLoggerDelegate, please be careful: the internal logs are quite verbose. Your logger delegate method might be called often, make sure - it is performent enough and has a memory allocation limit. - - This can also be controlled using -BatchSDKEnableInternalLogs - - @param enableInternalLogs Whether to enable development logs. Default: false (unless enabled via CLI) - */ +/// Get the debug view controller. +/// +/// For development purposes only, this contains UI with multiple debug features allowing you to debug your Batch +/// implementation more easily. If you want to make it accessible in production, you should hide it in a hard to +/// reproduce sequence. +/// - Note: Should be presented modally. ++ (UIViewController *_Nullable)debugViewController; + +/// Toogle whether internal logs should be logged or not. +/// +/// If you have a ``Batch/BatchLoggerDelegate``, please be careful: the internal logs are quite verbose. +/// Your logger delegate method might be called often, make sure it is performent enough and has a memory allocation +/// limit. +/// This can also be controlled using `-BatchSDKEnableInternalLogs`. +/// - Parameter enableInternalLogs: Whether to enable development logs. Default: false (unless enabled via CLI). + (void)setInternalLogsEnabled:(BOOL)enableInternalLogs; -/** - Opt-out from Batch SDK usage. - A push opt-out command will be sent to Batch's servers if the user is connected to the internet. - If disconnected, notifications might not be disabled properly. Please use [Batch optOutWithCompletionHandler:] to handle - these cases more gracefully. - - Your app should be prepared to handle these cases. Some modules might behave unexpectedly - when the SDK is opted out from. - - Opting out will: - - Prevent [Batch startWithAPIKey:] from starting the SDK - - Disable any network capability from the SDK - - Disable all In-App campaigns - - Make the Inbox module return an error immediatly - - Make any call to -[BatchUserDataEditor save] do nothing - - Make any "track" methods from BatchUser ineffective - - Even if you opt-in afterwards, data generated (such as user data or tracked events) while opted out WILL be lost. - - If you also want to delete user data, please see [Batch optOutAndWipeData]. - - Calling this method when Batch hasn't started does nothing: Please call [Batch startWithAPIKey:] beforehand. - */ +/// Opt-out from Batch SDK usage. +/// +/// - Important: Calling this method when Batch hasn't started does nothing: Please call +/// ``Batch/Batch/startWithAPIKey:`` beforehand. +/// +/// A push opt-out command will be sent to Batch's servers if the user is connected to the internet. +/// If disconnected, notifications might not be disabled properly. Please use +/// ``Batch/Batch/optOutWithCompletionHandler:`` to handle these cases more gracefully. +/// +/// Your app should be prepared to handle these cases. Some modules might behave unexpectedly when the SDK is opted out +/// from. +/// +/// Opting out will: +/// - Prevent ``Batch/Batch/startWithAPIKey:`` from starting the SDK +/// - Disable any network capability from the SDK +/// - Disable all In-App campaigns +/// - Make the Inbox module return an error immediatly +/// - Make any call to ``Batch/BatchUserDataEditor/save`` do nothing +/// - Make any `track` methods from ``BatchUser`` ineffective +/// +/// Even if you opt-in afterwards, data generated (such as user data or tracked events) while opted out __WILL__ be +/// lost. +/// +/// If you also want to delete user data, please see ``Batch/Batch/optOutAndWipeData``. + (void)optOut; -/** - Opt-out from Batch SDK and wipe data. - An installation data wipe command will be sent to Batch's servers if the user is connected to the internet. - If disconnected, notifications might not be disabled properly. Please use [Batch optOutAndWipeDataWithCompletionHandler:] to handle - these cases more gracefully. - - See [Batch optOut] documentation for details - Note that once opted out, [Batch startWithAPIKey:] will essentially be a no-op - Your app should be prepared to handle these cases. - - Calling this method when Batch hasn't started does nothing: Please call [Batch startWithAPIKey:] beforehand. - */ +/// Opt-out from Batch SDK and wipe data. +/// +/// - Important: Calling this method when Batch hasn't started does nothing: Please call +/// ``Batch/Batch/startWithAPIKey:`` beforehand test. +/// +/// An installation data wipe command will be sent to Batch's servers if the user is connected to the internet. +/// If disconnected, notifications might not be disabled properly. Please use +/// ``Batch/Batch/optOutAndWipeDataWithCompletionHandler:`` to handle these cases more gracefully. +/// +/// See ``Batch/Batch/optOut`` documentation for details. +/// +/// - Note: Once opted out, ``Batch/Batch/startWithAPIKey:`` will essentially be a no-op. Your app should be prepared to +/// handle these cases. + (void)optOutAndWipeData; -/** - Opt-out from Batch SDK. - - See [Batch optOut] documentation for details. - - Use the completion handler to be informed about whether the opt-out request has been successfully sent to the server or not. - You'll also be able to control what to do in case of failure. - - Note: if the SDK has already been opted-out from, this method will instantly call the completion handler with a *failure* state. - - Calling this method when Batch hasn't started does nothing: Please call [Batch startWithAPIKey:] beforehand. - */ -+ (void)optOutWithCompletionHandler:(BatchOptOutNetworkErrorPolicy(^ _Nonnull)(BOOL success))handler; - -/** - Opt-out from Batch SDK and wipe data. - - See [Batch optOutAndWipeData] documentation for details. - - Use the completion handler to be informed about whether the opt-out request has been successfully sent to the server or not. - You'll also be able to control what to do in case of failure. - - Note: if the SDK has already been opted-out from, this method will instantly call the completion handler with a *failure* state. - - Calling this method when Batch hasn't started does nothing: Please call [Batch startWithAPIKey:] beforehand. - */ -+ (void)optOutAndWipeDataWithCompletionHandler:(BatchOptOutNetworkErrorPolicy(^ _Nonnull)(BOOL success))handler; - -/** - Opt-in to Batch SDK. - - Useful if you called [Batch optOut], [Batch optOutAndWipeData] or opted out by default in your Info.plist - You will need to call [Batch startWithAPIKey:@""] after this. - */ +/// Opt-out from Batch SDK. +/// +/// - Important: Calling this method when Batch hasn't started does nothing: Please call +/// ``Batch/Batch/startWithAPIKey:`` beforehand test. +/// +/// See ``Batch/Batch/optOut`` documentation for details. +/// +/// Use the completion handler to be informed about whether the opt-out request has been successfully sent to the server +/// or not. You'll also be able to control what to do in case of failure. +/// +/// - Note: if the SDK has already been opted-out from, this method will instantly call the completion handler with a +/// *failure* state. +/// +/// - Parameter handler: completion handler execetued when the opt-out request is finished. ++ (void)optOutWithCompletionHandler:(BatchOptOutNetworkErrorPolicy (^_Nonnull)(BOOL success))handler; + +/// Opt-out from Batch SDK and wipe data. +/// +/// - Important: Calling this method when Batch hasn't started does nothing: Please call +/// ``Batch/Batch/startWithAPIKey:`` beforehand test. +/// +/// See ``Batch/Batch/optOut`` documentation for details. +/// +/// Use the completion handler to be informed about whether the opt-out request has been successfully sent to the server +/// or not. You'll also be able to control what to do in case of failure. +/// +/// - Note: if the SDK has already been opted-out from, this method will instantly call the completion handler with a +/// *failure* state. +/// +/// - Parameter handler: Block execetued when the opt-out request is finished. ++ (void)optOutAndWipeDataWithCompletionHandler:(BatchOptOutNetworkErrorPolicy (^_Nonnull)(BOOL success))handler; + +/// Opt-in to Batch SDK. +/// +/// Useful if you called ``Batch/Batch/optOut``, ``Batch/Batch/optOutAndWipeData`` or opted out by default in your +/// Info.plist. +/// - Important: You will need to call ``Batch/Batch/startWithAPIKey:`` after this. + (void)optIn; -/** - Returns whether Batch has been opted out from or not - */ +/// Returns whether Batch has been opted out from or not + (BOOL)isOptedOut; -/** - If your app handle universal links, set your list of associated domains. - - If your site uses multiple subdomains (such as example.com, www.example.com, or support.example.com), - each requires its own entry like in the Associated Domains Entitlement, - - Make sure to only include the desired subdomain and the top-level domain. Don’t include path and query components or a trailing slash (/) - - @param domains An array of your supported associated domains. - */ -+ (void)setAssociatedDomains:(NSArray * _Nonnull) domains NS_AVAILABLE_IOS(8_0); +/// Set your list of associated domains, If your app handle universal links. +/// +/// If your site uses multiple subdomains (such as example.com, www.example.com, or support.example.com), each requires +/// its own entry like in the `Associated Domains Entitlement`file. +/// +/// - Important: Make sure to only include the desired subdomain and the top-level domain. Don’t include path and query +/// components or a trailing slash (/). +/// - Parameter domains: An array of your supported associated domains. ++ (void)setAssociatedDomains:(NSArray *_Nonnull)domains NS_AVAILABLE_IOS(8_0); @end -/** - BatchDeeplinkDelegate is the protocol to adopt when you want to set a deeplink delegate on the SDK. - - See Batch.deeplinkDelegate for more info. - */ +/// BatchDeeplinkDelegate is the protocol to adopt when you want to set a deeplink delegate on the SDK. +/// +/// See ``Batch/Batch/deeplinkDelegate`` for more info. @protocol BatchDeeplinkDelegate -/** - Method called when Batch needs to open a deeplink. - - This will be called on the main thread. - */ -- (void)openBatchDeeplink:(nonnull NSString*)deeplink; +/// Method called when Batch needs to open a deeplink. +/// +/// This will be called on the main thread. +/// - Parameter deeplink: deeplink url to open. +- (void)openBatchDeeplink:(nonnull NSString *)deeplink; @end diff --git a/Sources/Batch/BatchEventData.h b/Sources/Batch/BatchEventData.h index 9aa782d..a34d8aa 100644 --- a/Sources/Batch/BatchEventData.h +++ b/Sources/Batch/BatchEventData.h @@ -10,75 +10,74 @@ NS_ASSUME_NONNULL_BEGIN -/** - Object holding data to be associated to an event - - Keys should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ +/// Object holding data to be associated to an event +/// +/// - Note: Keys should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. @interface BatchEventData : NSObject -/** - Add a tag. - - @param tag Tag to add. Can't be longer than 64 characters, and can't be empty or null. For better results, you should trim/lowercase your strings, and use slugs when possible. - */ -- (void)addTag:(NSString*)tag NS_SWIFT_NAME(add(tag:)); +/// Add a tag. +/// +/// - Parameters: +/// - tag: Tag to add. Can't be longer than 64 characters, and can't be empty or null. For better results, you should +/// trim/lowercase your strings, and use slugs when possible. +- (void)addTag:(NSString *)tag NS_SWIFT_NAME(add(tag:)); -/** - Add a boolean attribute for the specified key. - - @param value Boolean value to add. - @param key Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)putBool:(BOOL)value forKey:(NSString*)key; +/// Add a boolean attribute for the specified key. +/// +/// - Parameters: +/// - value: Boolean value to add. +/// - key: Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 +/// characters. +- (void)putBool:(BOOL)value forKey:(NSString *)key; -/** - Add an integer (NSInteger) attribute for the specified key. - - @param value Integer value to add. - @param key Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)putInteger:(NSInteger)value forKey:(NSString*)key; +/// Add an integer (NSInteger) attribute for the specified key. +/// +/// - Parameters: +/// - value: Integer value to add. +/// - key: Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 +/// characters. +- (void)putInteger:(NSInteger)value forKey:(NSString *)key; -/** - Add a float attribute for the specified key. - - @param value Float value to add. - @param key Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)putFloat:(float)value forKey:(NSString*)key; +/// Add a float attribute for the specified key. +/// +/// - Parameters: +/// - value: Float value to add. +/// - key: Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 +/// characters. +- (void)putFloat:(float)value forKey:(NSString *)key; -/** - Add a double attribute for the specified key. - - @param value double value to add. - @param key Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)putDouble:(double)value forKey:(NSString*)key; +/// Add a double attribute for the specified key. +/// +/// - Parameters: +/// - value: Double value to add. +/// - key: Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 +/// characters. +- (void)putDouble:(double)value forKey:(NSString *)key; -/** - Add a string attribute for the specified key. - - @param value String value to add. Can't be longer than 64 characters, and can't be empty or nil. For better results, you should trim/lowercase your strings, and use slugs when possible. - @param key Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)putString:(NSString*)value forKey:(NSString*)key; +/// Add a string attribute for the specified key. +/// +/// - Parameters: +/// - value: String value to add. Can't be longer than 64 characters, and can't be empty or nil. For better results, +/// you should trim/lowercase your strings, and use slugs when possible. +/// - key: Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 +/// characters. +- (void)putString:(NSString *)value forKey:(NSString *)key; -/** -Add a date attribute for the specified key. +/// Add a date attribute for the specified key. +/// +/// - Parameters: +/// - value: Date value to add. Can't be nil. +/// - key: Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 +/// characters. +- (void)putDate:(NSDate *)value forKey:(NSString *)key; -@param value Date value to add. Can't be nil. -@param key Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -*/ -- (void)putDate:(NSDate*)value forKey:(NSString*)key; - -/** -Add an URL attribute for the specified key. - -@param value URL value to add. Can't be longer than 2048 characters, and can't be empty or nil. Must follow the format 'scheme://[authority][path][?query][#fragment]'. -@param key Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -*/ -- (void)putURL:(NSURL*)value forKey:(NSString*)key; +/// Add an URL attribute for the specified key. +/// - Parameters: +/// - value: URL value to add. Can't be longer than 2048 characters, and can't be empty or nil. Must follow the format +/// `scheme://[authority][path][?query][#fragment]`. +/// - key: Attribute key. Should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 +/// characters. +- (void)putURL:(NSURL *)value forKey:(NSString *)key; @end diff --git a/Sources/Batch/BatchEventDataPrivate.h b/Sources/Batch/BatchEventDataPrivate.h index aa210e5..7720378 100644 --- a/Sources/Batch/BatchEventDataPrivate.h +++ b/Sources/Batch/BatchEventDataPrivate.h @@ -19,17 +19,16 @@ NS_ASSUME_NONNULL_BEGIN -@interface BatchEventData () -{ - @public - NSMutableDictionary* _attributes; - NSMutableSet* _tags; +@interface BatchEventData () { + @public + NSMutableDictionary *_attributes; + NSMutableSet *_tags; BOOL _convertedFromLegacy; } -- (void)_copyLegacyData:(NSDictionary*)data; +- (void)_copyLegacyData:(NSDictionary *)data; -- (NSDictionary*)_internalDictionaryRepresentation; +- (NSDictionary *)_internalDictionaryRepresentation; @end @@ -42,12 +41,11 @@ typedef NS_ENUM(NSUInteger, BAEventAttributeType) { BAEventAttributeTypeURL, }; - @interface BATTypedEventAttribute : NSObject -+ (nonnull instancetype)attributeWithValue:(NSObject*)value type:(BAEventAttributeType)type; ++ (nonnull instancetype)attributeWithValue:(NSObject *)value type:(BAEventAttributeType)type; -- (NSString*)typeSuffix; +- (NSString *)typeSuffix; @property (nonatomic, nonnull) NSObject *value; diff --git a/Sources/Batch/BatchEventDispatcher.h b/Sources/Batch/BatchEventDispatcher.h index d5b1046..86b34db 100644 --- a/Sources/Batch/BatchEventDispatcher.h +++ b/Sources/Batch/BatchEventDispatcher.h @@ -8,133 +8,110 @@ #import -/** - Protocol to access data associated with a dispatched event. - */ +/// Protocol to access data associated with a dispatched event. @protocol BatchEventDispatcherPayload @required +/// Tracking Identifier @property (readonly, nullable) NSString *trackingId; + +/// Deeplink URL @property (readonly, nullable) NSString *deeplink; -/** - * Indicate if the action associated with the event is positive. - * A positive action is : - * - An Open for a push campaign - * - A CTA click or Global tap containing a deeplink or a custom action for an in-app campaign - */ +/// Indicate if the action associated with the event is positive. +/// +/// A positive action is : +/// - An Open for a push campaign. +/// - A CTA click or Global tap containing a deeplink or a custom action for an in-app campaign. @property (readonly) BOOL isPositiveAction; -/** - * Get the analytics identifier associated with the event. - * Only used for messages of type BatchEventDispatcherTypeMessagingWebViewClick and BatchEventDispatcherTypeMessagingClose. - * Matches the "analyticsID" parameter of various methods of the JavaScript SDK. - */ +/// Get the analytics identifier associated with the event. +/// +/// Only used for messages of type `BatchEventDispatcherTypeMessagingWebViewClick` and +/// `BatchEventDispatcherTypeMessagingClose`. Matches the `analyticsID` parameter of various methods of the +/// JavaScript SDK. @property (readonly, nullable) NSString *webViewAnalyticsIdentifier; -/** - * Message that originated this event, if this is a messaging event. Not applicable for notification events. - */ +/// Message that originated this event, if this is a messaging event. Not applicable for notification events. @property (readonly, nullable) BatchMessage *sourceMessage; -/** - * UserInfo of the originating remote notification, if this is a notification event. - * - * Applicable for messaging events if the message is a mobile landing. - */ +/// UserInfo of the originating remote notification, if this is a notification event. +/// +/// Applicable for messaging events if the message is a mobile landing. @property (readonly, nullable) NSDictionary *notificationUserInfo; -/** - * Read a value for a custom payload key - */ -- (nullable NSObject*)customValueForKey:(nonnull NSString*)key; +/// Read a value for a custom payload key +/// +/// - Parameters: +/// - key: custom payload key +- (nullable NSObject *)customValueForKey:(nonnull NSString *)key; @end -/** - Represents the type of a dispatched event. - */ +/// Represents the type of a dispatched event. typedef NS_ENUM(NSInteger, BatchEventDispatcherType) { - BatchEventDispatcherTypeNotificationOpen, - BatchEventDispatcherTypeMessagingShow, - BatchEventDispatcherTypeMessagingClose, - BatchEventDispatcherTypeMessagingCloseError, - BatchEventDispatcherTypeMessagingAutoClose, - BatchEventDispatcherTypeMessagingClick, - BatchEventDispatcherTypeMessagingWebViewClick, + BatchEventDispatcherTypeNotificationOpen, + BatchEventDispatcherTypeMessagingShow, + BatchEventDispatcherTypeMessagingClose, + BatchEventDispatcherTypeMessagingCloseError, + BatchEventDispatcherTypeMessagingAutoClose, + BatchEventDispatcherTypeMessagingClick, + BatchEventDispatcherTypeMessagingWebViewClick, }; -/** - Represents a dispatcher that can be registered to receive events. - */ +/// Represents a dispatcher that can be registered to receive events. @protocol BatchEventDispatcherDelegate - @optional -/** - Get the name of the dispatcher - */ -- (nonnull NSString*)name; + +/// The name of the dispatcher. +- (nonnull NSString *)name; @optional -/** - Get the version of the dispatcher - */ +/// The version of the dispatcher. - (NSUInteger)version; - @required -/** - Called when a new event happens in the Batch SDK. - - No guarantee about the thread this method will be called on is made. - - @param type The type of the event - @param payload The payload associated with the event - */ -- (void)dispatchEventWithType:(BatchEventDispatcherType)type - payload:(nonnull id)payload; +/// Called when a new event happens in the Batch +/// +/// - Parameters: +/// - type: The type of the event. +/// - payload: The payload associated with the event. +- (void)dispatchEventWithType:(BatchEventDispatcherType)type payload:(nonnull id)payload; @end -/** - Batch's Event Dispatcher module. - */ +/// Batch's Event Dispatcher module. @interface BatchEventDispatcher : NSObject -/** - Check if the event is associated with a push notification. - - @param eventType The type of the event - @return True if the event is associated with a push notification, false otherwise - */ +/// Check if the event is associated with a push notification. +/// +/// - Parameters: +/// - eventType: The type of the event. +/// - Returns:True if the event is associated with a push notification, false otherwise + (BOOL)isNotificationEvent:(BatchEventDispatcherType)eventType; -/** - Check if the event is associated with an in-app or landing message. - - @param eventType The type of the event - @return True if the event is associated with an in-app or landing message, false otherwise -*/ +/// Check if the event is associated with an in-app or landing message. +/// +/// - Parameters: +/// - eventType: The type of the event. +/// - Returns:True if the event is associated with an in-app or landing message, false otherwise. + (BOOL)isMessagingEvent:(BatchEventDispatcherType)eventType; -/** - Add an event dispatcher. - If that dispatcher is already added, it won't be added a second time. - - @param dispatcher The dispatcher to add - */ +/// Add an event dispatcher. +/// +/// If that dispatcher is already added, it won't be added a second time. +/// - Parameters: +/// - dispatcher: The dispatcher to add. + (void)addDispatcher:(nonnull id)dispatcher; -/** - Remove an event dispatcher. - If that dispatcher isn't already added, nothing will be done. - - @param dispatcher The dispatcher to remove - */ +/// Remove an event dispatcher. +/// +/// If that dispatcher isn't already added, nothing will be done. +/// - Parameter dispatcher: The dispatcher to remove. + (void)removeDispatcher:(nonnull id)dispatcher; @end diff --git a/Sources/Batch/BatchInbox.h b/Sources/Batch/BatchInbox.h index b463440..04b4694 100644 --- a/Sources/Batch/BatchInbox.h +++ b/Sources/Batch/BatchInbox.h @@ -6,234 +6,237 @@ // Copyright (c) Batch SDK. All rights reserved. // -#import #import #import +#import +/// Notification message object @interface BatchInboxNotificationContentMessage : NSObject -/** - Notification title (if present) - */ +/// Notification title (if present) @property (nonatomic, readonly, nullable) NSString *title; -/** - Notification subtitle (if present) - */ +/// Notification subtitle (if present) @property (nonatomic, readonly, nullable) NSString *subtitle; -/** - Notification alert body - */ +/// Notification alert body @property (nonatomic, readonly, nullable) NSString *body; @end -/** - BatchInboxNotificationContent is the model for notifications fetched using the Inbox API - Use it to display them in the way you like. - */ +/// The model for notifications fetched using the Inbox API. +/// +/// Use it to display them in the way you like. @interface BatchInboxNotificationContent : NSObject -/** - Unique notification identifier. Do not make assumptions about its format: it can change at any time. - */ +/// Unique notification identifier. +/// +/// Do not make assumptions about its format: it can change at any time. @property (nonatomic, readonly, nonnull) NSString *identifier; -/** - Notification message, if present. - This can be nil if filtering of silent notifications has been disabled on the inbox fetcher, meaning that this notification is silent (shows nothing to the user). - */ +/// Notification message, if present. +/// +/// This can be nil if filtering of silent notifications has been disabled on the inbox fetcher, meaning that this +/// notification is silent (shows nothing to the user). @property (nonatomic, readonly, nullable) BatchInboxNotificationContentMessage *message; -/** - Notification title (if present) - @deprecated - */ -@property (nonatomic, readonly, nullable) NSString *title __attribute__((deprecated("The title should be accessed via the message property"))); - -/** - Notification alert body - - For compatibility, this will be the empty string when representing a silent notification, if their filtering has been disabled on the fetcher. - @deprecated - */ -@property (nonatomic, readonly, nonnull) NSString *body __attribute__((deprecated("The body should be accessed via the message property"))); - -/** - URL of the rich notification attachment (image/audio/video) - */ +/// Notification title, if present. (Deprecated) +/// +/// - Warning: __Deprecated:__ The title should be accessed via the message property. +@property (nonatomic, readonly, nullable) NSString *title + __attribute__((deprecated("The title should be accessed via the message property"))); + +/// Notification alert body. (Deprecated) +/// +/// For compatibility, this will be the empty string when representing a silent notification, if their filtering has +/// been disabled on the fetcher. +/// - Warning: __Deprecated: __ The body should be accessed via the message property. +@property (nonatomic, readonly, nonnull) NSString *body + __attribute__((deprecated("The body should be accessed via the message property"))); + +/// URL of the rich notification attachment (image/audio/video). @property (nonatomic, readonly, nullable) NSURL *attachmentURL; -/** - Raw notification user data (also called payload) - */ +/// Raw notification user data (also called payload). @property (nonatomic, readonly, nonnull) NSDictionary *payload; -/** - Date at which the push notification has been sent to the device - */ +/// Date at which the push notification has been sent to the device. @property (nonatomic, readonly, nonnull) NSDate *date; -/** - Flag indicating whether this notification is unread or not - */ +/// Flag indicating whether this notification is unread or not. @property (nonatomic, readonly) BOOL isUnread; -/** - Flag indicating whether this notification is deleted or not. - - This might change if you hold a pointer to a notification that you asked to be deleted - @deprecated - */ -@property (nonatomic, readonly) BOOL isDeleted __attribute__((deprecated("You should refresh your copy of the data with allFetchedNotifications after using markNotificationAsDeleted."))); - -/** - Flag indicating whether this notification is silent or not - */ +/// Flag indicating whether this notification is deleted or not. (Deprecated) +/// +/// This might change if you hold a pointer to a notification that you asked to be deleted. +/// - Warning: __Deprecated:__ You should refresh your copy of the data with +/// ``BatchInboxFetcher/allFetchedNotifications`` after using ``BatchInboxFetcher/markNotificationAsDeleted:``. +@property (nonatomic, readonly) BOOL isDeleted __attribute__((deprecated( + "You should refresh your copy of the data with allFetchedNotifications after using markNotificationAsDeleted."))); + +/// Flag indicating whether this notification is silent or not. @property (nonatomic, readonly) BOOL isSilent; -/** - The push notification's source, indicating what made Batch send it. It can come from a push campaign via the API or the dashboard, or from the transactional API, for example. - */ +/// The push notification's source, indicating what made Batch send it. It can come from a push campaign via the API or +/// the dashboard, or from the transactional API, for example. @property (nonatomic, readonly) BatchNotificationSource source; +/// Whether the notification content has a landing message attached. +/// +/// - Returns: True if a landing message is attached, false otherwise. +@property (nonatomic, readonly) BOOL hasLandingMessage; + +/// Display the landing message attached to the notification content. +/// +/// Do nothing if no message is attached. +- (void)displayLandingMessage; + @end -/** - BatchInboxFetcher allows you to fetch notifications that have been sent to a user (or installation, more on that later) in their raw form, - allowing you to display them in a list, for example. This is also useful to display messages to users that disabled notifications. - - Once you get your BatchInboxFetcher instance, you should call fetchNewNotifications: to fetch the initial page of messages: nothing is done automatically. - This method is also useful to refresh the list. - - In an effort to minimize network and memory usage, messages are fetched by page (batches of messages): - this allows you to easily create an infinite list, loading more messages on demand. - While you can configure the maximum number of messages you want in a page, the actual number of returned messages can differ, as the SDK may filter some of the messages returned by the server (such as duplicate notifications, etc...). - - As BatchInboxFetcher caches answers from the server, instances of this class should be tied to the lifecycle of the UI consuming it. - For example, you should keep a reference to this object during your UIViewController's entire life. - Another reason to keep the object around, is that you cannot mark a message as read with another BatchInbox instance that the one - that gave you the message in the first place. - - A BatchInboxFetcher instance will hold to all fetched messages: be careful of how long you're keeping the instances around. - You can also set a upper messages limit, after which BatchInbox will stop fetching new messages, even if you call fetchNextPage. - */ -@interface BatchInboxFetcher: NSObject - -/** - This class should not be instanciated directly: use BatchInbox to get a correctly initialized instance. - */ +/// ``BatchInboxFetcher`` allows you to fetch notifications that have been sent to a user (or installation, more on that +/// later) in their raw form, allowing you to display them in a list, for example. This is also useful to display +/// messages to users that disabled notifications. +/// +/// Once you get your ``BatchInboxFetcher`` instance, you should call ``BatchInboxFetcher/fetchNewNotifications:`` to +/// fetch the initial page of messages: nothing is done automatically. This method is also useful to refresh the list. +/// +/// In an effort to minimize network and memory usage, messages are fetched by page (batches of messages): this allows +/// you to easily create an infinite list, loading more messages on demand. While you can configure the maximum number +/// of messages you want in a page, the actual number of returned messages can differ, as the SDK may filter some of +/// the messages returned by the server (such as duplicate notifications, etc...). +/// +/// As ``BatchInboxFetcher`` caches answers from the server, instances of this class should be tied to the lifecycle of +/// the UI consuming it. For example, you should keep a reference to this object during your UIViewController's entire +/// life. Another reason to keep the object around, is that you cannot mark a message as read with another BatchInbox +/// instance that the one that gave you the message in the first place. +/// +/// A ``BatchInboxFetcher`` instance will hold to all fetched messages: be careful of how long you're keeping the +/// instances around. You can also set a upper messages limit, after which BatchInbox will stop fetching new messages, +/// even if you call ``fetchNextPage:``. +@interface BatchInboxFetcher : NSObject + +/// This class should not be instanciated directly: use ``BatchInbox/fetcher`` or +/// ``BatchInbox/fetcherForUserIdentifier:authenticationKey:`` to get a correctly initialized instance. - (nonnull instancetype)init NS_UNAVAILABLE; -/** - Whether silent notifications should be filtered from the fetched notifications. This parameter should be set before the first fetch happens. - If set to false, silent notifications (notifications not showing a visible message to the user) will not be filtered by the SDK. - - For compatiblity, a notification content's `body` property will be the empty string rather than nil. - To differentiate silent notifications from visible ones, look at the `message` property: it will be nil if the notification is silent. - - Default: true - */ +/// Whether silent notifications should be filtered from the fetched notifications. +/// +/// This parameter should be set before the first fetch happens. +/// If set to false, silent notifications (notifications not showing a visible message to the +/// user) will not be filtered by the SDK. +/// +/// For compatiblity, a notification content's ``BatchInboxNotificationContent/body`` property will be the empty string +/// rather than nil. To differentiate silent notifications from visible ones, look at the +/// ``BatchInboxNotificationContent/message`` property: it will be nil if the notification is silent. +/// Default: true @property (nonatomic) BOOL filterSilentNotifications; -/** - Number of notifications to fetch on each call, up to 100 messages per page. - Note that the actual count of fetched messages might differ from the value you've set here. - */ +/// Number of notifications to fetch on each call, up to 100 messages per page. +/// +/// - Note: The actual count of fetched messages might differ from the value you've set here. @property (nonatomic) NSUInteger maxPageSize; -/** - Maximum number of notifications to fetch. This allows you to let Batch manage the upper limit itself, so you can be sure not to use a crazy amount of memory. - If you want to fetch unlimited messages, set this property to 0. - - Default value: 200 - */ +/// Maximum number of notifications to fetch. +/// +/// This allows you to let Batch manage the upper limit itself, so you can be +/// sure not to use a crazy amount of memory. If you want to fetch unlimited messages, set this property to 0. +/// Default value: 200 @property (nonatomic) NSUInteger limit; -/** - Returns a copy of all notifications that have been fetched until now, ordered by reverse chronological order (meaning that the first message is the newest one, and the last one the oldest). - Note that this array will be empty until you call fetchNextPage:, and will only grow on subsequent fetches. - - Warning: in this version, allFetchedNotifications always regenerates the public models when called. You should cache the return value of this property, and only call it when you know you need to refresh your copy of the data. - */ -@property (readonly, nonnull) NSArray *allFetchedNotifications; - -/** - Returns whether all of the user or installation's notifications have been fetched. - If this property returns YES, calling fetchNextPage will always return an error, as there is nothing left to fetch. - Also artificially returns YES if the maximum number of fetched messages has been reached. - */ +/// Get a copy of all notifications that have been fetched. +/// +/// - Note: This array will be empty until you call ``BatchInboxFetcher/fetchNextPage:`` and will only grow on +/// subsequent fetches. +/// - Important: In this version, ``BatchInboxFetcher/allFetchedNotifications`` always regenerates the public models +/// when called. You should cache the return value of this property, and only call it when you know you need to refresh +/// your copy of the data. +/// - Returns: A copy of all notifications that have been fetched until now, ordered by reverse chronological order +/// (meaning that the first message is the newest one, and the last one the oldest). +@property (readonly, nonnull) NSArray *allFetchedNotifications; + +/// Whether all of the user or installation's notifications have been fetched. +/// +/// - Note: If this property returns True, calling ``BatchInboxFetcher/fetchNextPage:`` will always return an error, as +/// there is nothing left to fetch. Also artificially returns True if the maximum number of fetched messages has been +/// reached. +/// - Returns: True if all notifications have been fetched, False otherwise. @property (readonly) BOOL endReached; -/** - Fetch new notifications. - While fetchNextPage: is used to fetch older notifications than the ones currently loaded, this method checks for new notifications. For example, this is the method you would call on initial load, or on a "pull to refresh". - If new notifications are found, the previously fetched ones will be kept if possible, but might be cleared to ensure consistency.For example, if a gap were to happen because of a refresh, old notifications would be removed from the cache. - - The completion handler is called on the main queue. - - @param completionHandler An optional completion handler can be executed on success or failure with either the fetched notifications or the detailed error. - */ -- (void)fetchNewNotifications:(void (^ _Nullable)(NSError* _Nullable error, NSArray* _Nullable notifications, BOOL foundNewNotifications, BOOL endReached))completionHandler; - -/** - Fetch a page of notifications. - The completion handler is called on the main queue. - Calling this method when no messages have been loaded will be equivalent to calling fetchNewNotifications: - - @param completionHandler An optional completion handler can be executed on success or failure with either the fetched notifications or the detailed error. - */ -- (void)fetchNextPage:(void (^ _Nullable)(NSError* _Nullable error, NSArray* _Nullable notifications, BOOL endReached))completionHandler; - -/** - Mark a specific notification as read. - The notification you provide will see its isUnread property updated. - - If you call fetchNewNotifications: right away (or get a new BatchInboxFetcher instance), you might have notifications that you've marked as read come back to an unread state, since the server may have not processed the request yet. - - @param notification The notification to be marked as read. - */ -- (void)markNotificationAsRead:(nonnull BatchInboxNotificationContent*)notification; - -/** - Marks all notifications as read. - - Note that you will have to call allFetchedNotifications again to update the isUnread status of your copy of the notifications. If you call fetchNewNotifications: right away (or get a new BatchInboxFetcher instance), you might have notifications that you've marked as read come back to an unread state, since the server may have not processed the request yet. - */ +/// Fetch new notifications. +/// +/// While``BatchInboxFetcher/fetchNextPage:`` is used to fetch older notifications than the ones currently loaded, this +/// method checks for new notifications. For example, this is the method you would call on initial load, or on a "pull +/// to refresh". If new notifications are found, the previously fetched ones will be kept if possible, but might be +/// cleared to ensure consistency.For example, if a gap were to happen because of a refresh, old notifications would be +/// removed from the cache. +/// - Parameters: +/// - completionHandler: An optional completion handler can be executed on success or failure with either the fetched +/// notifications or the detailed error. +- (void)fetchNewNotifications:(void (^_Nullable)(NSError *_Nullable error, + NSArray *_Nullable notifications, + BOOL foundNewNotifications, + BOOL endReached))completionHandler; + +/// Fetch a page of notifications. +/// +/// Calling this method when no messages have been loaded will be equivalent to calling +/// ``BatchInboxFetcher/fetchNewNotifications:`` +/// - Note: The completion handler is called on the main queue. +/// - Parameters: +/// - completionHandler: An optional completion handler can be executed on success or failure with either the fetched +/// notifications or the detailed error. +- (void)fetchNextPage:(void (^_Nullable)(NSError *_Nullable error, + NSArray *_Nullable notifications, + BOOL endReached))completionHandler; + +/// Mark a specific notification as read. +/// +/// The notification you provide will see its ``BatchInboxNotificationContent/isUnread`` property updated. +/// +/// - Important: If you call ``BatchInboxFetcher/fetchNewNotifications:`` right away (or get a new ``BatchInboxFetcher`` +/// instance), you might have notifications that you've marked as read come back to an unread state, since the server +/// may have not processed the request yet. +/// - Parameter notification: The notification to be marked as read. +- (void)markNotificationAsRead:(nonnull BatchInboxNotificationContent *)notification; + +/// Marks all notifications as read. +/// +/// Note that you will have to call ``BatchInboxFetcher/allFetchedNotifications`` again to update the +/// ``BatchInboxNotificationContent/isUnread`` status of your copy of the notifications. +/// - Important: If you call ``BatchInboxFetcher/fetchNewNotifications:`` right away (or get a new ``BatchInboxFetcher`` +/// instance), you might have notifications that you've marked as read come back to an unread state, since the server +/// may have not processed the request yet. - (void)markAllNotificationsAsRead; -/** - Mark a specific notification as deleted. - The notification you provide will see its isUnread property updated. - - If you call fetchNewNotifications: right away (or get a new BatchInboxFetcher instance), you might have notifications that you've marked as deleted come back, since the server may have not processed the request yet. - */ -- (void)markNotificationAsDeleted:(nonnull BatchInboxNotificationContent*)notification; +/// Mark a specific notification as deleted. +/// +/// The notification you provide will see its ``BatchInboxNotificationContent/isDeleted`` property updated. +/// +/// - Important: If you call ``BatchInboxFetcher/fetchNewNotifications:`` right away (or get a new ``BatchInboxFetcher`` +/// instance), you might have notifications that you've marked as deleted come back, since the server may have not +/// processed the request yet. +/// - Parameter notification: The notification to mark as deleted. +- (void)markNotificationAsDeleted:(nonnull BatchInboxNotificationContent *)notification; @end -/** - Batch's inbox module. Use this to get a configured instance of the inbox client. - */ +/// Batch's inbox module. Use this to get a configured instance of the inbox client. @interface BatchInbox : NSObject -/** - Get an inbox fetcher for the current installation ID - Batch must be started for this method to work. - - @return an instance of BatchInboxFetcher with the wanted configuration - */ -+ (nonnull BatchInboxFetcher*)fetcher; - -/** - Get an inbox fetcher for the specified user identifier. - Batch must be started for this method to work. - - @param identifier User identifier for which you want the notifications - @param authKey Secret authentication key: it should be computed your backend and given to this method - @return an instance of BatchInboxFetcher with the wanted configuration - */ -+ (nullable BatchInboxFetcher*)fetcherForUserIdentifier:(nonnull NSString*)identifier authenticationKey:(nonnull NSString*)authKey; +/// Get an inbox fetcher for the current installation ID. +/// +/// Batch must be started for this method to work. +/// - Returns: An instance of ``BatchInboxFetcher`` with the wanted configuration. ++ (nonnull BatchInboxFetcher *)fetcher; + +/// Get an inbox fetcher for the specified user identifier. +/// +/// Batch must be started for this method to work. +/// - Parameters: +/// - identifier: User identifier for which you want the notifications. +/// - authKey: Secret authentication key: it should be computed by your backend and given to this method. +/// - Returns: An instance of ``BatchInboxFetcher`` with the wanted configuration ++ (nullable BatchInboxFetcher *)fetcherForUserIdentifier:(nonnull NSString *)identifier + authenticationKey:(nonnull NSString *)authKey; @end diff --git a/Sources/Batch/BatchInbox.m b/Sources/Batch/BatchInbox.m index 3829ee1..76ae4fb 100644 --- a/Sources/Batch/BatchInbox.m +++ b/Sources/Batch/BatchInbox.m @@ -9,10 +9,13 @@ #import #import +#import #import #import +#import #define DEBUG_DOMAIN @"BatchInboxFetcher" +#define LOGGER_DOMAIN @"BatchInboxNotificationContent" @interface BatchInboxFetcher () @@ -306,6 +309,20 @@ - (void)_markAsDeleted { _isDeleted = true; } +- (BOOL)hasLandingMessage { + return [BatchMessaging messageFromPushPayload:_payload] != nil; +} + +- (void)displayLandingMessage { + BatchPushMessage *message = [BatchMessaging messageFromPushPayload:_payload]; + [message setIsDisplayedFromInbox:true]; + if (message) { + [[BAMessagingCenter instance] presentLandingMessage:message bypassDnD:true]; + } else { + [BALogger debugForDomain:LOGGER_DOMAIN message:@"No landing message is attached."]; + } +} + @end @implementation BatchInbox diff --git a/Sources/Batch/BatchInboxPrivate.h b/Sources/Batch/BatchInboxPrivate.h index 7b72413..44e1868 100644 --- a/Sources/Batch/BatchInboxPrivate.h +++ b/Sources/Batch/BatchInboxPrivate.h @@ -11,7 +11,7 @@ #import -@interface BatchInboxNotificationContentMessage() +@interface BatchInboxNotificationContentMessage () - (nonnull instancetype)initWithBody:(nonnull NSString *)body title:(nullable NSString *)title @@ -19,7 +19,7 @@ @end -@interface BatchInboxNotificationContent() +@interface BatchInboxNotificationContent () - (nullable instancetype)initWithInternalIdentifier:(nonnull NSString *)identifier rawPayload:(nonnull NSDictionary *)rawPayload diff --git a/Sources/Batch/BatchLogger.h b/Sources/Batch/BatchLogger.h index 8e77710..e61d5e5 100644 --- a/Sources/Batch/BatchLogger.h +++ b/Sources/Batch/BatchLogger.h @@ -6,8 +6,16 @@ // Copyright (c) Batch SDK. All rights reserved. // +/// Protocol to implement if you want to use ``Batch/Batch/setLoggerDelegate:`` to get Batch logs in a custom object of +/// yours. +/// +/// - Important: Be careful with your implementation: using this can impact stability and performance. You should only +/// use it if you know what you are doing. @protocol BatchLoggerDelegate -- (void)logWithMessage:(nonnull NSString*)message; +/// Delegated method to get Batch logs +/// +/// - Parameter message: Batch message +- (void)logWithMessage:(nonnull NSString *)message; @end diff --git a/Sources/Batch/BatchMessaging.h b/Sources/Batch/BatchMessaging.h index 516793a..ac26ec9 100644 --- a/Sources/Batch/BatchMessaging.h +++ b/Sources/Batch/BatchMessaging.h @@ -12,264 +12,237 @@ @class BatchInAppMessage, BatchMessage, BatchPushMessage, BatchMessageAction; -/** - Implement this protocol if you want to be notified of what happens to the messaging view (for example, perform some analytics on show/hide). - */ +/// Implement this protocol if you want to be notified of what happens to the messaging view (for example, perform some +/// analytics on show/hide). @protocol BatchMessagingDelegate @optional -/** - Called when the message view appeared on screen. - @param messageIdentifier Analytics message identifier string. Can be nil. - */ -- (void)batchMessageDidAppear:(NSString* _Nullable)messageIdentifier; - -/** - Called when the message view was dismissed by a user interaction (close button tap, swipe gesture...) - @param messageIdentifier Analytics message identifier string. Can be nil. - */ -- (void)batchMessageWasCancelledByUserAction:(NSString* _Nullable)messageIdentifier NS_SWIFT_NAME(batchMessageWasCancelledByUserAction(_:)); - -/** - Called when the message view was dismissed automatically after the auto closing countdown. - @param messageIdentifier Analytics message identifier string. Can be nil. - */ -- (void)batchMessageWasCancelledByAutoclose:(NSString* _Nullable)messageIdentifier NS_SWIFT_NAME(batchMessageWasCancelledByAutoclose(_:)); - -/** - Called when Batch needs to present a message in automatic mode. - - Implement this method if you need to specify the view controller that will present Batch content. - If you return nil, or don't implement this method, Batch will default to its normal presentation behaviour and use the topmost presented controller of your app's key window's root controller. - @return The view controller to present Batch content on. Batch will display its controller modally, therefore the view controller you return must be capable of presenting a modal view controller. - @note This method will not be called for some messages that need to be presented in their own window. - */ -- (UIViewController* _Nullable)presentingViewControllerForBatchUI; - -/** - Called when the message view will be dismissed due to the user pressing a CTA or the global tap action. - @param action Action that will be performed. Fields can be nil if the action was only to dismiss the message on tap. - DO NOT run the action yourself: the SDK will automatically do it. - @param index Index of the action/CTA. If the action comes from the "global tap action", the index will be BatchMessageGlobalActionIndex - If the index is greater than or equal to zero, you can cast the action to BatchMessageCTA to get the CTA's label. - @param identifier Analytics message identifier string. Can be nil. - */ -- (void)batchMessageDidTriggerAction:(BatchMessageAction * _Nonnull)action messageIdentifier:(NSString * _Nullable)identifier actionIndex:(NSInteger)index; - -/** - Called when the message view disappeared from the screen. - @param messageIdentifier Analytics message identifier string. Can be nil. - */ -- (void)batchMessageDidDisappear:(NSString* _Nullable)messageIdentifier; - -/** - Called when an In-App message should be presented to the user. - - @param message In-App message to show. - */ -- (void)batchInAppMessageReady:(nonnull BatchInAppMessage*)message NS_SWIFT_NAME(batchInAppMessageReady(message:)); - -/** - Called when the message view was closed because of an error - @param messageIdentifier Analytics message identifier string. Can be nil. - */ -- (void)batchMessageWasCancelledByError:(NSString* _Nullable)messageIdentifier NS_SWIFT_NAME(batchMessageWasCancelledByError(_:)); - -/** - Called when the WebView message view will be dismissed due to the user navigating away or triggering an action (using the Javascript SDK). - @param action Action that will be performed. Fields can be nil if the action was only to dismiss the message on tap. - DO NOT run the action yourself: the SDK will automatically do it. Can be nil. - @param messageIdentifier Analytics message identifier string. Can be nil. - @param analyticsIdentifier Click analytic identifier. Matches the "analyticsID" parameter of the Javascript call, - * or the 'batchAnalyticsID' query parameter of a link. - */ -- (void)batchWebViewMessageDidTriggerAction:(BatchMessageAction * _Nullable)action - messageIdentifier:(NSString * _Nullable)messageIdentifier - analyticsIdentifier:(NSString * _Nullable)analyticsIdentifier; +/// Called when the message view appeared on screen. +/// +/// - Parameter messageIdentifier: Analytics message identifier string. Can be nil. +- (void)batchMessageDidAppear:(NSString *_Nullable)messageIdentifier; + +/// Called when the message view was dismissed by a user interaction (close button tap, swipe gesture...) +/// +/// - Parameter messageIdentifier: Analytics message identifier string. Can be nil. +- (void)batchMessageWasCancelledByUserAction:(NSString *_Nullable)messageIdentifier + NS_SWIFT_NAME(batchMessageWasCancelledByUserAction(_:)); + +/// Called when the message view was dismissed automatically after the auto closing countdown. +/// +/// - Parameter messageIdentifier: Analytics message identifier string. Can be nil. +- (void)batchMessageWasCancelledByAutoclose:(NSString *_Nullable)messageIdentifier + NS_SWIFT_NAME(batchMessageWasCancelledByAutoclose(_:)); + +/// Called when Batch needs to present a message in automatic mode. +/// +/// Implement this method if you need to specify the view controller that will present Batch content. +/// If you return nil, or don't implement this method, Batch will default to its normal presentation behaviour and use +/// the topmost presented controller of your app's key window's root controller. +/// - Note:This method will not be called for some messages that need to be presented in their own window. +/// - Returns: The view controller to present Batch content on. Batch will display its controller modally, therefore the +/// view +/// controller you return must be capable of presenting a modal view controller. +- (UIViewController *_Nullable)presentingViewControllerForBatchUI; + +/// Called when the message view will be dismissed due to the user pressing a CTA or the global tap action. +/// +/// - Parameters: +/// - action: Action that will be performed. Fields can be nil if the action was only to dismiss the message on tap. +/// __DO NOT__ run the action yourself: the SDK will automatically do it. +/// - identifier: Analytics message identifier string. Can be nil. +/// - index: Index of the action/CTA. If the action comes from the "global tap action", the index +/// will be ``BatchMessageGlobalActionIndex`` If the index is greater than or equal to zero, +/// you can cast the action to ``BatchMessageCTA`` +- (void)batchMessageDidTriggerAction:(BatchMessageAction *_Nonnull)action + messageIdentifier:(NSString *_Nullable)identifier + actionIndex:(NSInteger)index; + +/// Called when the message view disappeared from the screen. +/// +/// - Parameter messageIdentifier: Analytics message identifier string. Can be nil. +- (void)batchMessageDidDisappear:(NSString *_Nullable)messageIdentifier; + +/// Called when an In-App message should be presented to the user. +/// +/// - Parameter message: In-App message to show. +- (void)batchInAppMessageReady:(nonnull BatchInAppMessage *)message NS_SWIFT_NAME(batchInAppMessageReady(message:)); + +/// Called when the message view was closed because of an error. +/// +/// - Parameter messageIdentifier: Analytics message identifier string. Can be nil. +- (void)batchMessageWasCancelledByError:(NSString *_Nullable)messageIdentifier + NS_SWIFT_NAME(batchMessageWasCancelledByError(_:)); + +/// Called when the WebView message view will be dismissed due to the user navigating away or triggering an action +/// (using the Javascript SDK). +/// +/// - Parameters: +/// - action: Action that will be performed. Fields can be nil if the action was only to dismiss the message on +/// tap. __DO NOT__ run the action yourself: the SDK will automatically do it. Can be nil. +/// - messageIdentifier: Analytics message identifier string. Can be nil. +/// - analyticsIdentifier: Click analytic identifier. Matches the `analyticsID` parameter of the Javascript call, +/// or the `batchAnalyticsID` query parameter of a link. +- (void)batchWebViewMessageDidTriggerAction:(BatchMessageAction *_Nullable)action + messageIdentifier:(NSString *_Nullable)messageIdentifier + analyticsIdentifier:(NSString *_Nullable)analyticsIdentifier; @end -/** - Batch's messaging module - */ +/// Batch's messaging module @interface BatchMessaging : NSObject -/** - Sets Batch's messaging delegate. The delegate is used for optionaly informing your code about analytics event, or handling In-App messages manually. - - - @param delegate Your messaging delegate, weakly retained. Set it to nil to remove it. - */ +/// Sets Batch's messaging delegate. The delegate is used for optionaly informing your code about analytics event, or +/// handling In-App messages manually. +/// +/// - Parameter delegate: Your messaging delegate, weakly retained. Set it to nil to remove it. + (void)setDelegate:(id _Nullable)delegate; -/** - Toggles whether Batch should change the shared AVAudioSession configuration by itelf. It is used to avoid stopping the user's music when displaying a video inapp, but this may have undesirable effects on your app. - - @param canReconfigureAVAudioSession Whether or not Batch can change the AVAudioSession. - */ +/// Toggles whether Batch should change the shared `AVAudioSession` configuration by itelf. +/// +/// It is used to avoid stopping the user's music when displaying a video inapp, +/// but this may have undesirable effects on your app. +/// - Parameter canReconfigureAVAudioSession: Whether or not Batch can change the `AVAudioSession`. + (void)setCanReconfigureAVAudioSession:(BOOL)canReconfigureAVAudioSession; -/** - Toggles whether Batch should display the messaging views automatically when coming from a notification. - Note that if automatic mode is enabled, manual integration methods will not work. - In-App messaging is not affected by this. If you want to manually display the In-App message, call setDelegate: with a delegate that implement batchInAppMessageReady: - - @param isAutomaticModeOn Whether to enable automatic mode or not - */ +/// Toggles whether Batch should display the messaging views automatically when coming from a notification. +/// +/// In-App messaging is not affected by this. If you want to manually display the In-App message, call +/// ``BatchMessaging/setDelegate:`` with a delegate that implement ``BatchMessagingDelegate/batchInAppMessageReady:``. +/// - Note: If automatic mode is enabled, manual integration methods will not work. +/// - Parameter isAutomaticModeOn: Whether to enable automatic mode or not. + (void)setAutomaticMode:(BOOL)isAutomaticModeOn NS_SWIFT_NAME(setAutomaticMode(on:)); -/** - Toogles whether BatchMessaging should enter its "do not disturb" (DnD) mode or exit it. - - While in DnD, Batch will not display landings, not matter if they've been triggered by notifications or an In-App Campaign, even in automatic mode. - - This mode is useful for times where you don't want Batch to interrupt your user, such as during a splashscreen, a video or an interstitial ad. - - If a message should have been displayed during DnD, Batch will enqueue it, overwriting any previously enqueued message. - When exiting DnD, Batch will not display the message automatically: you'll have to call the queue management methods to display the message, if you want to. - - See BatchMessaging.hasPendingMessage, popPendingMessage() or showPendingMessage() to manage enqueued messages. - - Note: This is only supported if automatic mode is enabled. Messages will not be enqueued, as they will be delivered to your delegate. - */ +/// Toogles whether BatchMessaging should enter its "do not disturb" (DnD) mode or exit it. +/// +/// While in DnD, Batch will not display landings, not matter if they've been triggered by notifications or an In-App +/// Campaign, even in automatic mode. +/// +/// This mode is useful for times where you don't want Batch to interrupt your user, such as during a splashscreen, a +/// video or an interstitial ad. +/// +/// If a message should have been displayed during DnD, Batch will enqueue it, overwriting any previously enqueued +/// message. When exiting DnD, Batch will not display the message automatically: you'll have to call the queue +/// management methods to display the message, if you want to. +/// +/// See ``BatchMessaging/hasPendingMessage`` ``BatchMessaging/popPendingMessage`` or +/// ``BatchMessaging/showPendingMessage`` to manage enqueued messages. +/// +/// - Note: This is only supported if automatic mode is enabled. Messages will not be enqueued, as they will be +/// delivered to your delegate. @property (class, nonatomic) BOOL doNotDisturb; -/** - Returns whether Batch has an enqueued message from "do not disturb" mode. - */ +/// Returns whether Batch has an enqueued message from "do not disturb" mode. @property (class, readonly) BOOL hasPendingMessage; -/** - Gets the pending message (if any), enqueued while Batch was (or still is) in "do not disturb" mode. - Note: Calling this will remove the pending message from Batch's queue: subsequent calls will return nil until a new message - has been enqueued. - - @return A BatchMessage instance if there was a pending message. - */ -+ (BatchMessage* _Nullable)popPendingMessage; - -/** - Shows the currently enqueued message, if any. - Removes the pending message from the queue (like if popPendingMessage was called). - - @return true if there was an enqueued message to show, false otherwise. Is a message was enqueued but failed to display, the return value will be true. - */ +/// Gets the pending message (if any), enqueued while Batch was (or still is) in "do not disturb" mode. +/// +/// - Note: Calling this will remove the pending message from Batch's queue: subsequent calls will return nil until a +/// new message has been enqueued. +/// - Returns: A ``BatchMessage`` instance if there was a pending message. ++ (BatchMessage *_Nullable)popPendingMessage; + +/// Shows the currently enqueued message, if any. +/// +/// Removes the pending message from the queue (like if ``BatchMessaging/popPendingMessage`` was called). +/// - Returns: True if there was an enqueued message to show, false otherwise. Is a message was enqueued but failed to +/// display, the return value will be true. + (BOOL)showPendingMessage; -/** - Override the font used in message views. - Not applicable for standard alerts. - - If a variant is missing but there is a base font present, the SDK will fallback on the base fond you provided rather than the system one. This can lead to missing styles. - Setting a nil base font override will disable all other overrides. - - @param font UIFont to use for normal text. Use 'nil' to revert to the system font. - - @param boldFont UIFont to use for bold text. Use 'nil' to revert to the system font. - */ -+ (void)setFontOverride:(nullable UIFont*)font boldFont:(nullable UIFont*)boldFont; - -/** - Override the font used in message views. - Not applicable for standard alerts. - - If a variant is missing but there is a base font present, the SDK will fallback on the base fond you provided rather than the system one. This can lead to missing styles. - Setting a nil base font override will disable all other overrides. - - @param font UIFont to use for normal text. Use 'nil' to revert to the system font. - - @param boldFont UIFont to use for bold text. Use 'nil' to revert to the system font. - - @param italicFont UIFont to use for italic text. Use 'nil' to revert to the system font. - - @param boldItalicFont UIFont to use for bolditalic text. Use 'nil' to revert to the system font. - */ -+ (void)setFontOverride:(nullable UIFont*)font boldFont:(nullable UIFont*)boldFont italicFont:(nullable UIFont*)italicFont boldItalicFont:(nullable UIFont*)boldItalicFont; - -/*! - Get a message model from the push payload, if it contains a valid Batch message. - Note that this does not guarantee that there's a fully valid message in it, but - it allows you to bail early and skip unnecessary work if there's nothing messaging-related in the payload. - - @param userData The notification's payload. Typically the verbatim userData dictionary given to you in the app delegate. - - @return A BatchPushMessage instance if a messaging payload was found. nil otherwise. - */ -+ (nullable BatchPushMessage*)messageFromPushPayload:(nonnull NSDictionary*)userData; - -/** - Try to load a messaging view controller for a given payload. - - Do not make assumptions about the returned UIViewController subclass as it can change in a future release. - - You can then display this view controller modally, or in a dedicated window. The view controller conforms to the BatchMessagingViewController - protocol, you can call "shouldDisplayInSeparateWindow" to know how this VC would like to be presented. - - You can also use "presentMessagingViewController" to tell Batch to try to display it itself. - - @warning This method should only be called on the UI thread - - @param message The notification's payload. Typically the verbatim userData dictionary given to you in the app delegate. - - @param error If there is an error creating the view controller, upon return contains an NSError object that describes the problem. - - @return The view controller you should present. nil if an error occurred. - */ -+ (UIViewController* _Nullable)loadViewControllerForMessage:(BatchMessage* _Nonnull)message - error:(NSError * _Nullable * _Nullable)error; - -/** - Try to automatically present the given Batch Messaging View Controller, in the most appropriate way. - - This method will do nothing if you don't give it a UIViewController loaded by [BatchMessaging loadViewControllerForMessage:error:] - */ -+ (void)presentMessagingViewController:(nonnull UIViewController*)vc; +/// Override the font used in message views. +/// +/// Not applicable for standard alerts. +/// If a variant is missing but there is a base font present, the SDK will fallback on the base fond you provided rather +/// than the system one. This can lead to missing styles. Setting a nil base font override will disable all other +/// overrides. +/// - Parameters: +/// - font: UIFont to use for normal text. Use 'nil' to revert to the system font. +/// - boldFont: UIFont to use for bold text. Use 'nil' to revert to the system font. ++ (void)setFontOverride:(nullable UIFont *)font boldFont:(nullable UIFont *)boldFont; + +/// Override the font used in message views. +/// +/// Not applicable for standard alerts. +/// If a variant is missing but there is a base font present, the SDK will fallback on the base fond you provided rather +/// than the system one. This can lead to missing styles. Setting a nil base font override will disable all other +/// overrides. +/// - Parameters: +/// - font: UIFont to use for normal text. Use 'nil' to revert to the system font. +/// - boldFont: UIFont to use for bold text. Use 'nil' to revert to the system font. +/// - italicFont: UIFont to use for italic text. Use 'nil' to revert to the system font. +/// - boldItalicFont: UIFont to use for bolditalic text. Use 'nil' to revert to the system font. ++ (void)setFontOverride:(nullable UIFont *)font + boldFont:(nullable UIFont *)boldFont + italicFont:(nullable UIFont *)italicFont + boldItalicFont:(nullable UIFont *)boldItalicFont; + +/// Toggles whether Batch should use dynamic type, adapting textual content to honor the user's font size settings. +/// +/// - Parameter enableDynamicType: Whether to enable dynamic type. (default = true). ++ (void)setEnableDynamicType:(BOOL)enableDynamicType; + +/// Get a message model from the push payload, if it contains a valid Batch message. +/// +/// - Note: This does not guarantee that there's a fully valid message in it, but it allows you to bail early and skip +/// unnecessary work if there's nothing messaging-related in the payload. +/// - Parameter userData: The notification's payload. Typically the verbatim `userData` dictionary given to you in the +/// app delegate. +/// - Returns: A ``BatchPushMessage`` instance if a messaging payload was found. nil otherwise. ++ (nullable BatchPushMessage *)messageFromPushPayload:(nonnull NSDictionary *)userData; + +/// Try to load a messaging view controller for a given payload. +/// +/// Do not make assumptions about the returned UIViewController subclass as it can change in a future release. +/// +/// You can then display this view controller modally, or in a dedicated window. The view controller conforms to the +/// ``BatchMessagingViewController`` protocol, you can call "shouldDisplayInSeparateWindow" to know how this VC would +/// like to be presented. +/// +/// You can also use ``BatchMessaging/presentMessagingViewController:`` to tell Batch to try to display it itself. +/// +/// - Parameters: +/// - message: The notification's payload. Typically the verbatim userData dictionary given to you in the app +/// delegate. +/// - error: If there is an error creating the view controller, upon return contains an NSError object that describes +/// the problem. +/// - Returns: The view controller you should present. nil if an error occurred. ++ (UIViewController *_Nullable)loadViewControllerForMessage:(BatchMessage *_Nonnull)message + error:(NSError *_Nullable *_Nullable)error; + +/// Try to automatically present the given Batch Messaging View Controller, in the most appropriate way. +/// +/// This method will do nothing if you don't give it a `UIViewController` loaded by +/// ``BatchMessaging/loadViewControllerForMessage:error:`` +/// - Parameter vc: The ViewController to present. ++ (void)presentMessagingViewController:(nonnull UIViewController *)vc; @end -/** - BatchMessaging error code constants. - */ -enum -{ - /** - The current iOS version is too old - */ +/// BatchMessaging error code constants. +enum { + + /// The current iOS version is too old BatchMessagingErrorIncompatibleIOSVersion = -1001, - - /** - Automatic mode hasn't been disabled - */ + + /// Automatic mode hasn't been disabled BatchMessagingErrorAutomaticModeNotDisabled = -1002, - - /** - Internal error - */ + + /// Internal error BatchMessagingErrorInternal = -1003, - - /** - No valid Batch message found - */ + + /// No valid Batch message found BatchMessagingErrorNoValidBatchMessage = -1004, - - /** - The method was called from the wrong thread - */ + + /// The method was called from the wrong thread BatchMessagingErrorNotOnMainThread = -1005, - - /** - Could not find a VC to display the landing on - */ + + /// Could not find a VC to display the landing on BatchMessagingErrorNoSuitableVCForDisplay = -1006, - - /** - Batch is opted-out from - */ + + /// Batch is opted-out from BatchMessagingErrorOptedOut = -1007 }; -/** - @typedef BatchMessagingError - */ +/// @typedef BatchMessagingError typedef NSInteger BatchMessagingError; diff --git a/Sources/Batch/BatchMessaging.m b/Sources/Batch/BatchMessaging.m index adb95ce..8d87b7e 100644 --- a/Sources/Batch/BatchMessaging.m +++ b/Sources/Batch/BatchMessaging.m @@ -434,6 +434,7 @@ - (nullable instancetype)initWithPayload:(nonnull NSDictionary @end -/** - Model describing an alert message's CTA - */ +/// Model describing an alert message's CTA @interface BatchAlertMessageCTA : NSObject -@property (nullable, readonly) NSString* label; -@property (nullable, readonly) NSString* action; -@property (nullable, readonly) NSDictionary* args; +@property (nullable, readonly) NSString *label; +@property (nullable, readonly) NSString *action; +@property (nullable, readonly) NSDictionary *args; @end -/** - Model describing the content of an alert message - */ +/// Model describing the content of an alert message @interface BatchAlertMessageContent : NSObject -@property (nullable, readonly) NSString* trackingIdentifier; -@property (nullable, readonly) NSString* title; -@property (nullable, readonly) NSString* body; -@property (nullable, readonly) NSString* cancelLabel; -@property (nullable, readonly) BatchAlertMessageCTA* acceptCTA; +@property (nullable, readonly) NSString *trackingIdentifier; +@property (nullable, readonly) NSString *title; +@property (nullable, readonly) NSString *body; +@property (nullable, readonly) NSString *cancelLabel; +@property (nullable, readonly) BatchAlertMessageCTA *acceptCTA; @end -/** - Model describing an interstitial message's CTA - */ +/// Model describing an interstitial message's CTA @interface BatchInterstitialMessageCTA : NSObject -@property (nullable, readonly) NSString* label; -@property (nullable, readonly) NSString* action; -@property (nullable, readonly) NSDictionary* args; +@property (nullable, readonly) NSString *label; +@property (nullable, readonly) NSString *action; +@property (nullable, readonly) NSDictionary *args; @end -/** - Model describing the content of an interstitial message - */ +/// Model describing the content of an interstitial message @interface BatchInterstitialMessageContent : NSObject -@property (nullable, readonly) NSString* trackingIdentifier; -@property (nullable, readonly) NSString* header; -@property (nullable, readonly) NSString* title; -@property (nullable, readonly) NSString* body; -@property (nullable, readonly) NSArray* ctas; -@property (nullable, readonly) NSString* mediaURL; -@property (nullable, readonly) NSString* mediaAccessibilityDescription; +@property (nullable, readonly) NSString *trackingIdentifier; +@property (nullable, readonly) NSString *header; +@property (nullable, readonly) NSString *title; +@property (nullable, readonly) NSString *body; +@property (nullable, readonly) NSArray *ctas; +@property (nullable, readonly) NSString *mediaURL; +@property (nullable, readonly) NSString *mediaAccessibilityDescription; @property (readonly) BOOL showCloseButton; @end - @interface BatchMessageAction : NSObject -@property (nullable, readonly) NSString * action; -@property (nullable, readonly) NSDictionary * args; +@property (nullable, readonly) NSString *action; +@property (nullable, readonly) NSDictionary *args; - (BOOL)isDismissAction; @end -@interface BatchMessageCTA: BatchMessageAction +@interface BatchMessageCTA : BatchMessageAction -@property (readonly, nullable) NSString *label; +@property (readonly, nullable) NSString *label; @end -/** - Model describing a banner message's global tap action - */ +/// Model describing a banner message's global tap action @interface BatchBannerMessageAction : BatchMessageAction @end -/** - Model describing an image message's global tap action - */ +/// Model describing an image message's global tap action @interface BatchImageMessageAction : BatchMessageAction @end -/** - Model describing a banner message's CTA - */ +/// Model describing a banner message's CTA @interface BatchBannerMessageCTA : NSObject -@property (nullable, readonly) NSString* label; -@property (nullable, readonly) NSString* action; -@property (nullable, readonly) NSDictionary* args; +@property (nullable, readonly) NSString *label; +@property (nullable, readonly) NSString *action; +@property (nullable, readonly) NSDictionary *args; @end -/** - Model describing the content of a banner message - */ +/// Model describing the content of a banner message @interface BatchBannerMessageContent : NSObject -@property (nullable, readonly) NSString* trackingIdentifier; -@property (nullable, readonly) NSString* title; -@property (nullable, readonly) NSString* body; -@property (nullable, readonly) NSArray* ctas; -@property (nullable, readonly) BatchBannerMessageAction* globalTapAction; -@property (nullable, readonly) NSString* mediaURL; -@property (nullable, readonly) NSString* mediaAccessibilityDescription; +@property (nullable, readonly) NSString *trackingIdentifier; +@property (nullable, readonly) NSString *title; +@property (nullable, readonly) NSString *body; +@property (nullable, readonly) NSArray *ctas; +@property (nullable, readonly) BatchBannerMessageAction *globalTapAction; +@property (nullable, readonly) NSString *mediaURL; +@property (nullable, readonly) NSString *mediaAccessibilityDescription; @property (readonly) BOOL showCloseButton; -// Expressed in seconds, 0 if should not automatically dismiss +/// Expressed in seconds, 0 if should not automatically dismiss @property (readonly) NSTimeInterval automaticallyDismissAfter; @end -/** - Model describing the content of an image message - */ +/// Model describing the content of an image message @interface BatchMessageImageContent : NSObject -@property CGSize imageSize; +@property CGSize imageSize; @property (nullable) NSString *imageURL; -@property NSTimeInterval globalTapDelay; -@property (nonnull) BatchImageMessageAction *globalTapAction; -@property BOOL isFullscreen; +@property NSTimeInterval globalTapDelay; +@property (nonnull) BatchImageMessageAction *globalTapAction; +@property BOOL isFullscreen; @property (nullable) NSString *imageDescription; -@property NSTimeInterval autoClose; -@property BOOL allowSwipeToDismiss; +@property NSTimeInterval autoClose; +@property BOOL allowSwipeToDismiss; @end -/** - Model describing the content of a modal message - */ +/// Model describing the content of a modal message @interface BatchMessageModalContent : NSObject -@property (nullable, readonly) NSString* trackingIdentifier; -@property (nullable, readonly) NSString* title; -@property (nullable, readonly) NSString* body; -@property (nullable, readonly) NSArray* ctas; -@property (nullable, readonly) BatchBannerMessageAction* globalTapAction; -@property (nullable, readonly) NSString* mediaURL; -@property (nullable, readonly) NSString* mediaAccessibilityDescription; +@property (nullable, readonly) NSString *trackingIdentifier; +@property (nullable, readonly) NSString *title; +@property (nullable, readonly) NSString *body; +@property (nullable, readonly) NSArray *ctas; +@property (nullable, readonly) BatchBannerMessageAction *globalTapAction; +@property (nullable, readonly) NSString *mediaURL; +@property (nullable, readonly) NSString *mediaAccessibilityDescription; @property (readonly) BOOL showCloseButton; -// Expressed in seconds, 0 if should not automatically dismiss +/// Expressed in seconds, 0 if should not automatically dismiss @property (readonly) NSTimeInterval automaticallyDismissAfter; @end -/** - Model describing the content of a webview message - */ +/// Model describing the content of a webview message @interface BatchMessageWebViewContent : NSObject -@property (nullable, readonly) NSURL* URL; -@property (nullable, readonly) NSString* trackingIdentifier; +@property (nullable, readonly) NSURL *URL; +@property (nullable, readonly) NSString *trackingIdentifier; @end -/** - Protocol representing a Batch Messaging VC. - */ +/// Protocol representing a Batch Messaging VC. @protocol BatchMessagingViewController @property (readonly) BOOL shouldDisplayInSeparateWindow; @end -/** - Represents a Batch Messaging message - */ +/// Represents a Batch Messaging message @interface BatchMessage : NSObject @end -/** - Represents a Batch Messaging message coming from an In-App Campaign - */ +/// Represents a Batch Messaging message coming from an In-App Campaign @interface BatchInAppMessage : BatchMessage -/** - User defined custom payload - */ -@property (nullable, readonly) NSDictionary* customPayload; - -/** - In-App message's visual contents - - Since the content can greatly change between formats, you will need to cast it to one of the classes - conforming to the BatchInAppMessageContent protocol, such as BatchAlertMessageContent or BatchInterstitialMessageContent. - - Use `-contentType` to help you in that task. - - More types might be added in the future, so don't make any assuptions on the kind of class returned by this property. - - Can be nil if an error occurred or if not applicable - */ +/// User defined custom payload +@property (nullable, readonly) NSDictionary *customPayload; + +/// In-App message's visual contents +/// +/// Since the content can greatly change between formats, you will need to cast it to one of the classes +/// conforming to the ``BatchInAppMessageContent`` protocol, such as ``BatchAlertMessageContent`` or +/// ``BatchInterstitialMessageContent``. +/// +/// Use `-contentType` to help you in that task. +/// +/// More types might be added in the future, so don't make any assuptions on the kind of class returned by this +/// property. +/// +/// Can be nil if an error occurred or if not applicable @property (nullable, readonly) id content; -/** - Get the campaign token. This is the same token as you see when opening the In-App Campaign in your browser, when on the dashboard. - Can be nil. - */ +/// Get the campaign token. This is the same token as you see when opening the In-App Campaign in your browser, when on +/// the dashboard. Can be nil. @property (nullable, readonly) NSString *campaignToken; -/** - The type of the content, used to cast to the right content class. - */ +/// The type of the content, used to cast to the right content class. @property (readonly) BatchMessagingContentType contentType; @end -/** - Represents a Batch Messaging message coming from a push - */ +/// Represents a Batch Messaging message coming from a push @interface BatchPushMessage : BatchMessage -/** - Original push payload - */ -@property (nonnull, readonly) NSDictionary* pushPayload; +/// Original push payload +@property (nonnull, readonly) NSDictionary *pushPayload; + +/// Property indicating whether this landing message has been triggered from an inbox notification. +@property (readonly) BOOL isDisplayedFromInbox; @end diff --git a/Sources/Batch/BatchMessagingPrivate.h b/Sources/Batch/BatchMessagingPrivate.h index 60c925f..5c7c704 100644 --- a/Sources/Batch/BatchMessagingPrivate.h +++ b/Sources/Batch/BatchMessagingPrivate.h @@ -9,75 +9,75 @@ // Expose private constructors // This header is private and should NEVER be distributed within the framework -#import #import -#import #import +#import +#import #import -@interface BatchAlertMessageCTA() +@interface BatchAlertMessageCTA () -- (nullable instancetype)_initWithInternalCTA:(nullable BAMSGCTA*)msgCTA; +- (nullable instancetype)_initWithInternalCTA:(nullable BAMSGCTA *)msgCTA; @end -@interface BatchAlertMessageContent() +@interface BatchAlertMessageContent () -@property (nullable, readwrite) NSString* trackingIdentifier; +@property (nullable, readwrite) NSString *trackingIdentifier; -- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageAlert*)msg; +- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageAlert *)msg; @end -@interface BatchInterstitialMessageCTA() +@interface BatchInterstitialMessageCTA () -- (nullable instancetype)_initWithInternalCTA:(nullable BAMSGCTA*)msgCTA; +- (nullable instancetype)_initWithInternalCTA:(nullable BAMSGCTA *)msgCTA; @end -@interface BatchInterstitialMessageContent() +@interface BatchInterstitialMessageContent () -@property (nullable, readwrite) NSString* trackingIdentifier; +@property (nullable, readwrite) NSString *trackingIdentifier; -- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageInterstitial*)msg; +- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageInterstitial *)msg; @end -@interface BatchBannerMessageContent() +@interface BatchBannerMessageContent () -@property (nullable, readwrite) NSString* trackingIdentifier; +@property (nullable, readwrite) NSString *trackingIdentifier; @end @interface BatchMessageImageContent () -@property (nullable, readwrite) NSString* trackingIdentifier; +@property (nullable, readwrite) NSString *trackingIdentifier; -- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageImage*)msg; +- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageImage *)msg; @end @interface BatchMessageModalContent () -@property (nullable, readwrite) NSString* trackingIdentifier; +@property (nullable, readwrite) NSString *trackingIdentifier; -- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageModal*)msg; +- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageModal *)msg; @end @interface BatchMessageWebViewContent () -@property (nullable, readwrite) NSString* trackingIdentifier; +@property (nullable, readwrite) NSString *trackingIdentifier; -- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageWebView*)msg; +- (nullable instancetype)_initWithInternalMessage:(nullable BAMSGMessageWebView *)msg; @end -@interface BatchMessage() +@interface BatchMessage () -+ (nullable instancetype)messageForPayload:(nonnull NSDictionary*)payload; ++ (nullable instancetype)messageForPayload:(nonnull NSDictionary *)payload; -@property (nonnull, readonly) NSDictionary* messagePayload; +@property (nonnull, readonly) NSDictionary *messagePayload; @property (nonnull) NSString *messageIdentifier; @property (nullable) NSString *devTrackingIdentifier; @@ -85,11 +85,11 @@ @end -@interface BatchInAppMessage() +@interface BatchInAppMessage () -+ (nullable instancetype)messageForPayload:(nonnull NSDictionary*)payload; ++ (nullable instancetype)messageForPayload:(nonnull NSDictionary *)payload; -- (void)setCampaign:(nonnull BALocalCampaign*)campaign; +- (void)setCampaign:(nonnull BALocalCampaign *)campaign; @property (nullable) NSString *campaignIdentifier; @@ -97,14 +97,20 @@ @end -@interface BatchMessageAction() +@interface BatchPushMessage () + +- (void)setIsDisplayedFromInbox:(BOOL)isDisplayedFromInbox; + +@end + +@interface BatchMessageAction () -- (nullable instancetype)_initWithInternalAction:(nullable BAMSGAction*)action; +- (nullable instancetype)_initWithInternalAction:(nullable BAMSGAction *)action; @end -@interface BatchMessageCTA() +@interface BatchMessageCTA () -- (nullable instancetype)_initWithInternalAction:(nullable BAMSGCTA*)action; +- (nullable instancetype)_initWithInternalAction:(nullable BAMSGCTA *)action; @end diff --git a/Sources/Batch/BatchPush.h b/Sources/Batch/BatchPush.h index f661e00..b3454da 100644 --- a/Sources/Batch/BatchPush.h +++ b/Sources/Batch/BatchPush.h @@ -10,60 +10,57 @@ #import #import -/** - Notification sent by Batch Push when it gets a remote notification. This includes the one your app is started with (even though it is only sent when Batch starts) - @deprecated See BatchPushOpenedNotification - */ -FOUNDATION_EXPORT NSString * _Nonnull const BatchPushReceivedNotification __attribute__((deprecated("Use BatchPushOpenedNotification, which is more predictable."))); - -/** - Notification sent by Batch Push when a notification has been opened by the user. - Background wakeups and notifications received while in the foreground (that are not presented to the user) will not trigger this notification. - If your application doesn't properly call Batch in your UNUserNotificationDelegate or doesn't setup any delegate at all, this notification WILL misbehave: - It might miss opens, or report background fetchs as opens. - - This notification's userInfo contains private keys that are not guaranteed to be the same between SDK releases, but you can use BatchPushOpenedNotificationPayloadKey to get the payload. - - Note: This notification will not be sent if Batch hasn't been started or has been opted out from. - */ -FOUNDATION_EXPORT NSString * _Nonnull const BatchPushOpenedNotification; - -/** - Key used to access the payload in the userInfo of a BatchPushOpenedNotification. - The value is a NSDictionary. - */ -FOUNDATION_EXPORT NSString * _Nonnull const BatchPushOpenedNotificationPayloadKey; - -/** - Key that Batch will read the placeholder from when converting a UIUserNotificationAction into a UNNotificationAction - */ -FOUNDATION_EXPORT NSString * _Nonnull const BatchUserActionInputTextFieldPlaceholderKey; - -/** - Notification sent by Batch Push when the alert view requesting users to allow push notifications was dismissed. - Notification's userInfo will contain a BatchPushUserDidAcceptKey regarding the choice made by the user, whose value is a boolean in an NSNumber. - */ -FOUNDATION_EXPORT NSString * _Nonnull const BatchPushUserDidAnswerAuthorizationRequestNotification; -FOUNDATION_EXPORT NSString * _Nonnull const BatchPushUserDidAcceptKey; - -/** - Remote notification types wrapper. - Wraps iOS remote notification types in a compatible way. - */ -typedef NS_OPTIONS(NSUInteger, BatchNotificationType) -{ - BatchNotificationTypeNone = 0, - BatchNotificationTypeBadge = 1 << 0, - BatchNotificationTypeSound = 1 << 1, - BatchNotificationTypeAlert = 1 << 2, +/// Notification sent by Batch Push when it gets a remote notification. (Deprecated) +/// +/// This includes the one your app is started with (even though it is only sent when Batch starts) +/// - Warning: __Deprecated:__ Use ``BatchPushOpenedNotification`` which is more predictable. +FOUNDATION_EXPORT NSString *_Nonnull const BatchPushReceivedNotification + __attribute__((deprecated("Use BatchPushOpenedNotification, which is more predictable."))); + +/// Notification sent by Batch Push when a notification has been opened by the user. +/// +/// Background wakeups and notifications received while in the foreground (that are not presented to the user) will not +/// trigger this notification. If your application doesn't properly call Batch in your `UNUserNotificationDelegate` or +/// doesn't setup any delegate at all, this notification __WILL__ misbehave: It might miss opens, or report background +/// fetchs as opens. +/// +/// This notification's userInfo contains private keys that are not guaranteed to be the same between SDK releases, but +/// you can use ``BatchPushOpenedNotificationPayloadKey`` to get the payload. +/// +/// - Note: This notification will not be sent if Batch hasn't been started or has been opted out from. +FOUNDATION_EXPORT NSString *_Nonnull const BatchPushOpenedNotification; + +/// Key used to access the payload in the userInfo of a ``BatchPushOpenedNotification``. +/// The value is a NSDictionary. +FOUNDATION_EXPORT NSString *_Nonnull const BatchPushOpenedNotificationPayloadKey; + +/// Key that Batch will read the placeholder from when converting a `UIUserNotificationAction` into a +/// `UNNotificationAction` +FOUNDATION_EXPORT NSString *_Nonnull const BatchUserActionInputTextFieldPlaceholderKey; + +/// Notification sent by Batch Push when the alert view requesting users to allow push notifications was dismissed. +/// +/// Notification's userInfo will contain a ``BatchPushUserDidAcceptKey`` regarding the choice made by the user, whose +/// value is a boolean in an NSNumber. +FOUNDATION_EXPORT NSString *_Nonnull const BatchPushUserDidAnswerAuthorizationRequestNotification; + +/// Key contain in userInfo when using a ``BatchPushUserDidAnswerAuthorizationRequestNotification`` +FOUNDATION_EXPORT NSString *_Nonnull const BatchPushUserDidAcceptKey; + +/// Remote notification types wrapper. +/// Wraps iOS remote notification types in a compatible way. +typedef NS_OPTIONS(NSUInteger, BatchNotificationType) { + BatchNotificationTypeNone = 0, + BatchNotificationTypeBadge = 1 << 0, + BatchNotificationTypeSound = 1 << 1, + BatchNotificationTypeAlert = 1 << 2, BatchNotificationTypeCarPlay = 1 << 3, BatchNotificationTypeCritical = 1 << 4, }; -/** - Notification sources - A notification source represents how the push was sent from Batch: via the Transactional API, or using a Push Campaign - */ +/// Notification sources +/// A notification source represents how the push was sent from Batch: via the Transactional API, or using a Push +/// Campaign. typedef NS_ENUM(NSUInteger, BatchNotificationSource) { BatchNotificationSourceUnknown, BatchNotificationSourceCampaign, @@ -71,247 +68,261 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { BatchNotificationSourceTrigger, }; -/** - Provides Batch-related Push methods - Actions you can perform in BatchPush. - */ +/// Provides Batch-related Push methods. +/// Actions you can perform in BatchPush. @interface BatchPush : NSObject -/** - Controls whether Batch should tell iOS 12+ that your application supports opening in-app notification settings from the system. - Supporting this also requires implementing the corresponding method in UNUserNotificationCenterDelegate. - */ +/// Controls whether Batch should tell iOS 12+ that your application supports opening in-app notification settings from +/// the system. Supporting this also requires implementing the corresponding method in +/// `UNUserNotificationCenterDelegate`. @property (class) BOOL supportsAppNotificationSettings; -/** - Do not call this method, as BatchPush only consists of static methods. - */ +/// Do not call this method, as BatchPush only consists of static methods. - (nonnull instancetype)init NS_UNAVAILABLE; -/** - Setup Batch Push system. - You can call this method from any thread. - - @deprecated - */ -+ (void)setupPush NS_AVAILABLE_IOS(8_0) __attribute__((deprecated("setupPush is deprecated. You don't need to do anything else besides removing this call, Batch Push will still work as expected."))); - -/** - Change the used remote notification types when registering. - This does NOT change the user preferences once already registered: to do so, you should point them to the native system settings. - Default value is: BatchNotificationTypeBadge | BatchNotificationTypeSound | BatchNotificationTypeAlert - - @param type A bit mask specifying the types of notifications the app accepts. -*/ +/// Setup Batch Push system. (Deprecated) +/// +/// You can call this method from any thread. +/// - Warning: __Deprecated:__ This method is deprectaed. You don't need to do anything else besides removing this call, +/// Batch Push will still work as expected. ++ (void)setupPush NS_AVAILABLE_IOS(8_0) + __attribute__((deprecated("setupPush is deprecated. You don't need to do anything else besides removing this call, " + "Batch Push will still work as expected."))); + +/// Change the used remote notification types when registering. +/// +/// This does __NOT__ change the user preferences once already registered: to do so, you should point them to the native +/// system settings. Default value is: `BatchNotificationTypeBadge | BatchNotificationTypeSound | +/// BatchNotificationTypeAlert`. +/// - Parameter type: A bit mask specifying the types of notifications the app accepts. + (void)setRemoteNotificationTypes:(BatchNotificationType)type NS_AVAILABLE_IOS(8_0); -/** - Call this method to trigger the iOS popup that asks the user if they wants to allow notifications to be displayed, then get a Push token. - The default registration is made with Badge, Sound and Alert. If you want another configuration: call `setRemoteNotificationTypes:`. - You should call this at a strategic moment, like at the end of your welcome. - - Batch will automatically ask for a push token when the user replies. - */ +/// Method to trigger the iOS popup that asks the user if they wants to allow notifications to be displayed, then +/// get a Push token. +/// +/// The default registration is made with Badge, Sound and Alert. +/// If you want another configuration: call ``BatchPush/setRemoteNotificationTypes:``. +/// You should call this at a strategic moment, like at the end of your welcome. +/// +/// Batch will automatically ask for a push token when the user replies. + (void)requestNotificationAuthorization NS_AVAILABLE_IOS(8_0); -/** - Call this method to ask iOS for a provisional notification authorization. - Batch will then automatically ask for a push token. - - Provisional authorization will NOT show a popup asking for user authorization, - but notifications will NOT be displayed on the lock screen, or as a banner when the phone is unlocked. - They will directly be sent to the notification center, accessible when the user swipes up on the lockscreen, or down from the statusbar when unlocked. - - This method does nothing on iOS 11 or lower. - */ +/// Method to ask iOS for a provisional notification authorization. +/// +/// Batch will then automatically ask for a push token. +/// Provisional authorization will __NOT__ show a popup asking for user authorization, +/// but notifications will __NOT__ be displayed on the lock screen, or as a banner when the phone is unlocked. +/// They will directly be sent to the notification center, accessible when the user swipes up on the lockscreen, or down +/// from the statusbar when unlocked. +/// +/// This method does nothing on iOS 11 or lower. + (void)requestProvisionalNotificationAuthorization NS_AVAILABLE_IOS(8_0); -/** - Ask iOS to refresh the push token. If the app didn't prompt the user for consent yet, this will not be done. - You should call this at the start of your app, to make sure Batch always gets a valid token after app updates. - */ +/// Ask iOS to refresh the push token. If the app didn't prompt the user for consent yet, this will not be done. +/// +/// You should call this at the start of your app, to make sure Batch always gets a valid token after app updates. + (void)refreshToken NS_AVAILABLE_IOS(8_0); -/** - Open the system settings on your applications' notification settings. - */ +/// Open the system settings on your applications' notification settings. + (void)openSystemNotificationSettings NS_AVAILABLE_IOS(8_0); -/** - Call this method to trigger the iOS popup that asks the user if they wants to allow Push Notifications, then get a Push token. - The default registration is made with Badge, Sound and Alert. If you want another configuration: call `setRemoteNotificationTypes:`. - You should call this at a strategic moment, like at the end of your welcome. - - Equivalent to calling +[BatchPush requestNotificationAuthorization] - */ -+ (void)registerForRemoteNotifications NS_AVAILABLE_IOS(8_0) __attribute__((deprecated("Use requestNotificationAuthorization and refreshToken separately. More info in our documentation."))); - -/** - Call this method to trigger the iOS popup that asks the user if they want to allow Push Notifications and register to APNS. - Default registration is made with Badge, Sound and Alert. If you want another configuration: call `setRemoteNotificationTypes:`. - You should call this at a strategic moment, like at the end of your welcome. - - @param categories A set of UIUserNotificationCategory or UNNotificationCategory instances that define the groups of actions a notification may include. If you try to register UIUserNotificationCategory instances on iOS 10, Batch will automatically do a best effort conversion to UNNotificationCategory. If you don't want this behaviour, please use the standard UIApplication methods. - - @deprecated - */ -+ (void)registerForRemoteNotificationsWithCategories:(nullable NSSet *)categories NS_AVAILABLE_IOS(8_0) __attribute__((deprecated("Use setNotificationCategories and registerForRemoteNotifications separately."))); - -/** - Set the notification action categories to iOS. - You should call this every time your app starts. - - @warning On versions prior to iOS 10, this call MUST be followed by registerForRemoteNotifications, or else the categories will NOT be updated. - - @param categories A set of UIUserNotificationCategory or UNNotificationCategory instances that define the groups of actions a notification may include. If you try to register UIUserNotificationCategory instances on iOS 10, Batch will automatically do a best effort conversion to UNNotificationCategory. If you don't want this behaviour, please use the standard UIApplication methods. - */ +/// Method to trigger the iOS popup that asks the user if they wants to allow Push Notifications, then get a Push token. +/// (Deprecated) +/// +/// The default registration is made with Badge, Sound and Alert. +/// If you want another configuration: call`setRemoteNotificationTypes:`. +/// You should call this at a strategic moment, like at the end of your welcome. +/// Equivalent to calling ``BatchPush/requestNotificationAuthorization`` +/// - Warning: __Deprecated:__ This method is deprectaed. Use ``BatchPush/requestNotificationAuthorization`` and +/// ``BatchPush/refreshToken`` separately. More info in our documentation. ++ (void)registerForRemoteNotifications NS_AVAILABLE_IOS(8_0)__attribute__(( + deprecated("Use requestNotificationAuthorization and refreshToken separately. More info in our documentation."))); + +/// Method to trigger the iOS popup that asks the user if they want to allow Push Notifications and register to APNS. +/// (Deprecated) +/// +/// Default registration is made with Badge, Sound and Alert. +/// If you want another configuration: call ``BatchPush/setRemoteNotificationTypes:``. +/// You should call this at a strategic moment, like at the end of your welcome. +/// +/// - Parameter categories: A set of `UIUserNotificationCategory` or `UNNotificationCategory` instances that define the +/// groups of actions a notification may include. If you try to register `UIUserNotificationCategory` instances on iOS +/// 10, Batch will automatically do a best effort conversion to `UNNotificationCategory`. If you don't want this +/// behaviour, please use the standard `UIApplication` methods. +/// - Warning: __Deprecated:__ Use ``BatchPush/setNotificationsCategories:`` and +/// ``BatchPush/registerForRemoteNotifications`` separately. ++ (void)registerForRemoteNotificationsWithCategories:(nullable NSSet *)categories + NS_AVAILABLE_IOS(8_0) + __attribute__((deprecated("Use setNotificationCategories and registerForRemoteNotifications separately."))); + +/// Set the notification action categories to iOS. +/// +/// You should call this every time your app starts. +/// - Important: On versions prior to iOS 10, this call __MUST__ be followed by +/// ``BatchPush/registerForRemoteNotifications``, or else the categories will __NOT__ be updated. +/// - Parameter categories: set of `UIUserNotificationCategory` or `UNNotificationCategory` instances that define the +/// groups of actions a notification may include. If you try to register `UIUserNotificationCategory` instances on iOS +/// 10, Batch will automatically do a best effort conversion to `UNNotificationCategory`. If you don't want this +/// behaviour, please use the standard `UIApplication` methods. + (void)setNotificationsCategories:(nullable NSSet *)categories NS_AVAILABLE_IOS(8_0); -/** - Clear the application's badge on the homescreen. - You do not need to call this if you already called dismissNotifications. - */ +/// Clear the application's badge on the homescreen. +/// +/// You do not need to call this if you already called ``BatchPush/dismissNotifications``. + (void)clearBadge NS_AVAILABLE_IOS(8_0); -/** - Clear the app's notifications in the notification center. Also clears your badge. - Call this when you want to remove the notifications. Your badge is removed afterwards, so if you want one, you need to set it up again. - - @waning Be careful, this method also clears your badge. - */ +/// Clear the app's notifications in the notification center. Also clears your badge. +/// +/// Call this when you want to remove the notifications. Your badge is removed afterwards, so if you want one, you need +/// to set it up again. +/// - Important: Be careful, this method also clears your badge. + (void)dismissNotifications NS_AVAILABLE_IOS(8_0); -/** - Set whether Batch Push should automatically try to handle deeplinks - By default, this is set to YES. You need to call everytime your app is restarted, this option is not persisted. - - If your goal is to implement a custom deeplink format, you should see Batch.deeplinkDelegate which allows you to manually handle the deeplink string, but doesn't - put the burden of parsing the notification payload on you. - - Please note that setting this to false will DISABLE the deeplink delegate, leaving the handling of the link - entirely up to you. - - @warning If Batch is set to handle your deeplinks, it will *automatically* call the fetch completion handler (if applicable) with UIBackgroundFetchResultNewData. - */ +/// Set whether Batch Push should automatically try to handle deeplinks. +/// +/// By default, this is set to __YES__. You need to call everytime your app is restarted, this option is not persisted. +/// +/// If your goal is to implement a custom deeplink format, you should see ``Batch/Batch/deeplinkDelegate`` which allows +/// you to manually handle the deeplink string, but doesn't put the burden of parsing the notification payload on you. +/// +/// - Note: Setting this to false will __DISABLE__ the deeplink delegate, leaving the handling of the link entirely up +/// to you. +/// - Important: If Batch is set to handle your deeplinks, it will *automatically* call the fetch completion handler (if +/// applicable) with `UIBackgroundFetchResultNewData. +/// - Parameter handleDeeplinks: Whether Batch should handle deeplinks automatically. + (void)enableAutomaticDeeplinkHandling:(BOOL)handleDeeplinks NS_AVAILABLE_IOS(8_0); -/** - Get Batch Push's deeplink from a notification's userInfo. - - @return Batch's Deeplink, or nil if not found. - */ +/// Get Batch Push's deeplink from a notification's userInfo. +/// +/// - Parameter userData The notification's payload. +/// - Returns: Batch's Deeplink, or nil if not found. + (nullable NSString *)deeplinkFromUserInfo:(nonnull NSDictionary *)userData NS_AVAILABLE_IOS(8_0); -/** - Get the last known push token. - - Your application should still register for remote notifications once per launch, in order to keep this value valid. - - @warning The returned token might be outdated and invalid if this method is called too early in your application lifecycle. - - @return A push token, nil if unavailable. - */ +/// Get the last known push token. +/// +/// Your application should still register for remote notifications once per launch, in order to keep this value valid. +/// - Important: The returned token might be outdated and invalid if this method is called too early in your application +/// lifecycle. +/// - Returns: A push token, nil if unavailable. + (nullable NSString *)lastKnownPushToken NS_AVAILABLE_IOS(8_0); -/** - Disable the push's automatic integration. If you call this, you are responsible of forwarding your application's delegate and UNUserNotificationCenterDelegate calls to Batch. If you don't, some parts of the SDK and Dashboard will break. Calling this method automatically calls disableAutomaticNotificationCenterIntegration. - - @warning This must be called before you start Batch, or it will have no effect. - */ +/// Disable the push's automatic integration. +/// +/// If you call this, you are responsible of forwarding your application's delegate and +/// `UNUserNotificationCenterDelegate` calls to Batch. If you don't, some parts of the SDK and Dashboard will break. +/// Calling this method automatically calls `disableAutomaticNotificationCenterIntegration`. +/// - Important: This must be called before you start Batch, or it will have no effect. + (void)disableAutomaticIntegration NS_AVAILABLE_IOS(8_0); -/** - Registers a device token to Batch. You should call this method in "application:didRegisterForRemoteNotificationsWithDeviceToken:". - - @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. - - @param token The untouched "deviceToken" NSData argument given to you in the application delegate method. - */ -+ (void)handleDeviceToken:(nonnull NSData*)token NS_AVAILABLE_IOS(8_0); - -/** -Check if the received push is a Batch one. - -@warning If you have a custom push implementation into your app you should call this method before doing anything else. - -@param userInfo The untouched "userInfo" NSDictionary argument given to you in the application delegate method. - -@return If it returns true, you should not handle the push. -*/ -+ (BOOL)isBatchPush:(nonnull NSDictionary*)userInfo NS_AVAILABLE_IOS(8_0); - -/** -Make Batch process a notification. You should call this method in "application:didReceiveRemoteNotification:" or "application:didReceiveRemoteNotification:fetchCompletionHandler:". - -@warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. - -@param userInfo The untouched "userInfo" NSDictionary argument given to you in the application delegate method. -*/ -+ (void)handleNotification:(nonnull NSDictionary*)userInfo __attribute__((deprecated("Implement UNUserNotificationCenterDelegate using BatchUNUserNotificationCenterDelegate or your own implementation"))); - -/** - Make Batch process a notification action. You should call this method in "application:handleActionWithIdentifier:forRemoteNotification:completionHandler:" or "application:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:". - - @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. - - @param userInfo The untouched "userInfo" NSDictionary argument given to you in the application delegate method. - - @param identifier The action's identifier. Used for tracking purposes: it can match your raw action name, or be a more user-friendly string; - */ -+ (void)handleNotification:(nonnull NSDictionary*)userInfo actionIdentifier:(nullable NSString*)identifier NS_AVAILABLE_IOS(8_0); +/// Registers a device token to Batch. +/// +/// You should call this method in `application:didRegisterForRemoteNotificationsWithDeviceToken:`. +/// - Important: If you didn't call ``BatchPush/disableAutomaticIntegration``, this method will have no effect. +/// If you called it but don't implement this method, Batch's push features will __NOT__ work. +/// - Parameter token: The untouched `deviceToken` NSData argument given to you in the application delegate method. ++ (void)handleDeviceToken:(nonnull NSData *)token NS_AVAILABLE_IOS(8_0); + +/// Check if the received push is a Batch one. +/// +/// - Important: If you have a custom push implementation into your app you should call this method before doing +/// anything else. +/// - Parameter userInfo: The untouched `userInfo` NSDictionary argument given to you in the application delegate +/// method. +/// - Returns: Wheter it is a Batch'sPush. If it returns true, you should not handle the push. ++ (BOOL)isBatchPush:(nonnull NSDictionary *)userInfo NS_AVAILABLE_IOS(8_0); + +/// Make Batch process a notification. (Deprecated) +/// +/// You should call this method in `application:didReceiveRemoteNotification:` or +/// `application:didReceiveRemoteNotification:fetchCompletionHandler:`. +/// - Important: If you didn't call ``BatchPush/disableAutomaticIntegration``, this method will have no effect. +/// If you called it but don't implement this method, Batch's push features will __NOT__ work. +/// - Parameter userInfo: The untouched `userInfo` NSDictionary argument given to you in the application delegate +/// method. +/// - Warning: __Deprecated:__ Implement `UNUserNotificationCenterDelegate` using +/// ``BatchUNUserNotificationCenterDelegate`` or your own implementation. ++ (void)handleNotification:(nonnull NSDictionary *)userInfo + __attribute__((deprecated("Implement UNUserNotificationCenterDelegate using BatchUNUserNotificationCenterDelegate " + "or your own implementation"))); + +/// Make Batch process a notification action. +/// +/// You should call this method in `application:handleActionWithIdentifier:forRemoteNotification:completionHandler:` +/// or `application:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:` +/// - Important: If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but +/// don't implement this method, Batch's push features will NOT work. +/// - Parameters: +/// - userInfo: The untouched `userInfo` NSDictionary argument given to you in the application delegate method. +/// - identifier: The action's identifier. Used for tracking purposes: it can match your raw action name, or be a more +/// user-friendly string. ++ (void)handleNotification:(nonnull NSDictionary *)userInfo + actionIdentifier:(nullable NSString *)identifier NS_AVAILABLE_IOS(8_0); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -/** - Make Batch process the user notification settings change. You should call this method in "application:didRegisterUserNotificationSettings:". - - @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. - - @param notificationSettings The untouched "notificationSettings" UIUserNotificationSettings* argument given to you in the application delegate method. - */ -+ (void)handleRegisterUserNotificationSettings:(nonnull UIUserNotificationSettings *)notificationSettings __attribute__((deprecated("Use BatchPush.requestNotificationAuthorization()"))); +/// Make Batch process the user notification settings change. (Deprecated) +/// +/// You should call this method in `application:didRegisterUserNotificationSettings:`. +/// - Important: If you didn't call ``BatchPush/disableAutomaticIntegration``, this method will have no effect. If you +/// called it but don't implement this method, Batch's push features will __NOT__ work. +/// - Parameter notificationSettings: The untouched `notificationSettings UIUserNotificationSettings*` argument given to +/// you in the application delegate method. +/// - Warning: __Deprecated:__ Use ``BatchPush/requestNotificationAuthorization``. ++ (void)handleRegisterUserNotificationSettings:(nonnull UIUserNotificationSettings *)notificationSettings + __attribute__((deprecated("Use BatchPush.requestNotificationAuthorization()"))); #pragma clang diagnostic pop #pragma mark UserNotifications methods -/** - Make Batch process a foreground notification. You should call this method if you set your own UNUserNotificationCenterDelegate, in userNotificationCenter:willPresentNotification:withCompletionHandler: - - @param center Original center argument - @param notification Original notification argument - @param willShowSystemForegroundAlert Whether you will tell the framework to show this notification, or not. Batch uses this value to adjust its behaviour accordingly for a better user experience. Return 'true' if you're returning .alert (or more) to iOS' completion handler. - */ -+ (void)handleUserNotificationCenter:(nonnull UNUserNotificationCenter *)center willPresentNotification:(nonnull UNNotification *)notification willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert NS_AVAILABLE_IOS(10_0) NS_SWIFT_NAME(handle(userNotificationCenter:willPresent:willShowSystemForegroundAlert:)); - -/** - Make Batch process a background notification open/action. You should call this method if you set your own UNUserNotificationCenterDelegate, in userNotificationCenter:didReceiveNotificationResponse: - - @param center Original center argument - @param response Original response argument - */ -+ (void)handleUserNotificationCenter:(nonnull UNUserNotificationCenter *)center didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response NS_AVAILABLE_IOS(10_0) NS_SWIFT_NAME(handle(userNotificationCenter:didReceive:)); +/// Make Batch process a foreground notification. +/// +/// You should call this method if you set your own `UNUserNotificationCenterDelegate`, +/// in `userNotificationCenter:willPresentNotification:withCompletionHandler:`. +/// - Parameters: +/// - center Original center argument +/// - notification Original notification argument +/// - willShowSystemForegroundAlert Whether you will tell the framework to show this notification, or not. Batch +/// uses this value to adjust its behaviour accordingly for a better user experience. Return 'true' if you're +/// returning .alert (or more) to iOS' completion handler. ++ (void)handleUserNotificationCenter:(nonnull UNUserNotificationCenter *)center + willPresentNotification:(nonnull UNNotification *)notification + willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert + NS_AVAILABLE_IOS(10_0)NS_SWIFT_NAME(handle(userNotificationCenter:willPresent:willShowSystemForegroundAlert:)); + +/// Make Batch process a background notification open/action. +/// +/// You should call this method if you set your own `UNUserNotificationCenterDelegate`, +/// in `userNotificationCenter:didReceiveNotificationResponse:`. +/// - Parameters: +/// - center: Original center argument. +/// - response: Original response argument. ++ (void)handleUserNotificationCenter:(nonnull UNUserNotificationCenter *)center + didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response NS_AVAILABLE_IOS(10_0) + NS_SWIFT_NAME(handle(userNotificationCenter:didReceive:)); @end -/** - Implementation of UNUserNotificationCenterDelegate that - - Foreground notifications will not be displayed with the default settings. Use the property `showForegroundNotifications` to control this. - - This class should not be subclassed. If you want to do so, please implement UNUserNotificationCenterDelegate directly - */ +/// Implementation of `UNUserNotificationCenterDelegate` that +/// Foreground notifications will not be displayed with the default settings. +/// +/// Use the property `showForegroundNotifications` to control this. +/// This class should not be subclassed. If you want to do so, please implement `UNUserNotificationCenterDelegate` +/// directly __attribute__((objc_subclassing_restricted)) -@interface BatchUNUserNotificationCenterDelegate : NSObject - -/// Shared singleton BatchUNUserNotificationCenterDelegate. -/// Using this allows you to set the instance as UNUserNotificationCenter's delegate without having to retain it yourself. -/// The shared instance is lazily loaded. -@property (class, retain, readonly, nonnull) BatchUNUserNotificationCenterDelegate* sharedInstance; - -/// Registers this class' sharedInstance as UNUserNotificationCenter's delegate. -/// Equivalent to calling [UNUserNotificationCenter currentNotificationCenter].delegate = BatchUNUserNotificationCenterDelegate.sharedInstance +@interface BatchUNUserNotificationCenterDelegate : NSObject + +/// Shared singleton `BatchUNUserNotificationCenterDelegate`. +/// +/// Using this allows you to set the instance as `UNUserNotificationCenter`'s delegate without having to retain it +/// yourself. The shared instance is lazily loaded. +@property (class, retain, readonly, nonnull) BatchUNUserNotificationCenterDelegate *sharedInstance; + +/// Registers this class' sharedInstance as `UNUserNotificationCenter's` delegate. +/// +/// Equivalent to calling `[UNUserNotificationCenter currentNotificationCenter].delegate = +/// BatchUNUserNotificationCenterDelegate.sharedInstance`. + (void)registerAsDelegate; /// Should iOS display notifications even if the app is in foreground? diff --git a/Sources/Batch/BatchPushPrivate.h b/Sources/Batch/BatchPushPrivate.h index c434687..a8aeb0b 100644 --- a/Sources/Batch/BatchPushPrivate.h +++ b/Sources/Batch/BatchPushPrivate.h @@ -11,43 +11,35 @@ #import -/* - Remote notification setting status - - See [BatchPush notificationSettingStatus] for more information. - */ +/// Remote notification setting status +/// +/// See `[BatchPush notificationSettingStatus]` for more information. typedef NS_ENUM(NSUInteger, BatchPushNotificationSettingStatus) { - /** - User did not make a choice yet. Default value. - */ + + /// User did not make a choice yet. Default value. BatchPushNotificationSettingStatusUndefined = 0, - - /** - User enabled notifications. - */ + + /// User enabled notifications. BatchPushNotificationSettingStatusEnabled = 1, - - /** - User disabled notifications. - */ + + /// User disabled notifications. BatchPushNotificationSettingStatusDisabled = 2, }; -@interface BatchPush() - - -/** - This property defines the status of the notification setting (or opt-in/opt-out) in your application. - It will be sent to the server, to let Batch know whether a user enabled or disabled notifications globally in your app's settings. - You can use it to implement your own "Notifications" setting toggle. - - This property has a default value of BatchPushNotificationSettingStatusUndefined, and will automatically change to - BatchPushNotificationSettingStatusEnabled if you prompt the user to allow notifications using Batch's methods. - If you have previously overriden the value to BatchPushNotificationSettingStatusDisabled, the property will not change. - - Note: This does NOT reflect the system settings. If the user opted out from iOS' settings, you will still get the original value you set previously here. - You will need to handle this case in your settings, and redirect the user to the system settings. - */ +@interface BatchPush () + +/// This property defines the status of the notification setting (or opt-in/opt-out) in your application. +/// It will be sent to the server, to let Batch know whether a user enabled or disabled notifications globally in your +/// app's settings. You can use it to implement your own "Notifications" setting toggle. + +/// This property has a default value of BatchPushNotificationSettingStatusUndefined, and will automatically change to +/// BatchPushNotificationSettingStatusEnabled if you prompt the user to allow notifications using Batch's methods. +/// If you have previously overriden the value to BatchPushNotificationSettingStatusDisabled, the property will not +/// change. + +/// - Note: This does NOT reflect the system settings. If the user opted out from iOS' settings, you will still get the +/// original value you set previously here. You will need to handle this case in your settings, and redirect the user to +/// the system settings. @property (class) BatchPushNotificationSettingStatus notificationSettingStatus; @end diff --git a/Sources/Batch/BatchUser.h b/Sources/Batch/BatchUser.h index 5f71dfd..9e37e46 100644 --- a/Sources/Batch/BatchUser.h +++ b/Sources/Batch/BatchUser.h @@ -6,360 +6,444 @@ // Copyright (c) Batch SDK. All rights reserved. // -#import -#import #import +#import +#import @class BatchUserDataEditor, BatchUserAttribute; -/** - Notification sent by Batch when the event tracker has finished sending notifications to the server. - Multiple events of this kind can occur in a short period of time. - - Note: If Batch isn't started or if it is opted-out from, this notification will NOT be emitted. - */ -FOUNDATION_EXPORT NSString * _Nonnull const BatchEventTrackerFinishedNotification; +/// Notification sent by Batch when the event tracker has finished sending notifications to the server. +/// +/// Multiple events of this kind can occur in a short period of time. +/// - Note: If Batch isn't started or if it is opted-out from, this notification will __NOT__ be emitted. +FOUNDATION_EXPORT NSString *_Nonnull const BatchEventTrackerFinishedNotification; -/** - Key of BatchEventTrackerFinishedNotification's userInfo, indicating whether the event tracker has successfully sent - events to the server or not. - */ -FOUNDATION_EXPORT NSString * _Nonnull const BatchEventTrackerFinishedWithSuccessKey; +/// Key of `BatchEventTrackerFinishedNotification's userInfo`, indicating whether the event tracker has successfully +/// sent events to the server or not. +FOUNDATION_EXPORT NSString *_Nonnull const BatchEventTrackerFinishedWithSuccessKey; +/// Error domain of error when ``BatchUserDataEditor`` fail. FOUNDATION_EXPORT NSErrorDomain const _Nonnull BatchUserDataEditorErrorDomain; -/** - User data editor error codes - */ -typedef NS_ERROR_ENUM(BatchUserDataEditorErrorDomain, BatchUserDataEditorError) { - /** - Internal error - */ + +/// User data editor error codes. +typedef NS_ERROR_ENUM(BatchUserDataEditorErrorDomain, BatchUserDataEditorError){ + + /// Internal error. BatchUserDataEditorErrorInternal = 0, - - /** - The key is invalid. This also applies to tag collection names, as they're considered keys - */ + + /// The key is invalid. This also applies to tag collection names, as they're considered keys. BatchUserDataEditorErrorInvalidKey = 1, - - /** - The value is invalid: see the error description for more info - */ + + /// The value is invalid: see the error description for more info. BatchUserDataEditorErrorInvalidValue = 2, }; -/** - Batch's User Module - */ +/// Enum defining the state of an email subscription +typedef NS_ENUM(NSUInteger, BatchEmailSubscriptionState) { + BatchEmailSubscriptionStateSubscribed = 0, + BatchEmailSubscriptionStateUnsubscribed = 1, +}; + +/// Batch's User Module @interface BatchUser : NSObject -/** - Get the unique installation ID, generated by Batch. - - @return Batch-generated installation ID. Might be nil if Batch isn't started. - */ -+ (nullable NSString*)installationID; - -/** - Get the user data editor - Do not forget to call save once you're done changing the attributes - - You can call this method from any thread. - - @return A BatchUserDataEditor instance - */ -+ (nonnull BatchUserDataEditor*)editor; - -/** - @return The custom language set with @p BatchUserDataEditor, or nil if none was set. - */ +/// Get the unique installation ID, generated by Batch. +/// +/// - Returns: Batch-generated installation ID. Might be nil if Batch isn't started. ++ (nullable NSString *)installationID; + +/// Get the user data editor. +/// +/// Do not forget to call save once you're done changing the attributes +/// You can call this method from any thread. +/// - Returns: A ``BatchUserDataEditor`` instance ++ (nonnull BatchUserDataEditor *)editor; + +/// Get the user language +/// +/// - Returns: The custom language set with ``BatchUserDataEditor``, or nil if none was set. + (nonnull NSString *)language; -/** - @return The region set with @p BatchUserDataEditor, or nil if none was set. - */ +/// Get the user region +/// +/// - Returns: The region set with ``BatchUserDataEditor``, or nil if none was set. + (nonnull NSString *)region; -/** - @return The custom identifier set with @p BatchUserDataEditor, or nil if none was set. - */ +/// Get the custom user identifier +/// +/// - Returns: The custom identifier set with ``BatchUserDataEditor``, or nil if none was set. + (nullable NSString *)identifier; -/** - Read the saved attributes. Reading is asynchronous so as not to interfere with saving operations. - - @param completionHandler Completion block that contains a dictionary of attributes. The keys are the ones used when setting the attributes, the values are of type BatchUserAttribute. See BatchUserAttribute for more information. - */ -+ (void)fetchAttributes:(void (^_Nonnull)(NSDictionary* _Nullable attributes))completionHandler; - -/** - Read the saved tag collections. Reading is asynchronous so as not to interfere with saving operations. - - @param completionHandler Completion block that contains a dictionary of sets of tags. The keys are the ones used when setting the tags collections. - - @note Tags are saved in lowercase. - */ -+ (void)fetchTagCollections:(void (^_Nonnull)(NSDictionary*>* _Nullable collections))completionHandler; - -/** - Track an event - You can call this method from any thread. Batch must be started at some point, or events won't be sent to the server. - - @param event The event name. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -+ (void)trackEvent:(nonnull NSString*)event; - -/** - Track an event - You can call this method from any thread. Batch must be started at some point, or events won't be sent to the server. - - @param event The event name. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - - @param label The event label (optional). Must be a string. - */ -+ (void)trackEvent:(nonnull NSString*)event withLabel:(nullable NSString*)label; - -/** - Track an event - You can call this method from any thread. Batch must be started at some point, or events won't be sent to the server. - - @deprecated See [BatchUser trackEvent:withLabel:associatedData:]. Data sent using this method might be truncated if it can't be converted to a BatchEventData instance. - - @param event The event name. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - - @param label The event label (optional). Must be a string. - - @param data The event data (optional). Must a serializable JSON Foundation dictionary (meaning that it must pass +[NSJSONSerialization isValidJSONObject]'s check). See NSJSONSerialization documentation for supported types, with the only difference that the top level object MUST BE a NSDictionary and not a NSArray. - */ -+ (void)trackEvent:(nonnull NSString*)event withLabel:(nullable NSString*)label data:(nullable NSDictionary*)data __attribute__((deprecated("Please migrate to [BatchUser trackEvent:withLabel:associatedData:]. Data sent using this method might be truncated if it can't be converted to a BatchEventData instance."))); - -/** - Track an event - You can call this method from any thread. Batch must be started at some point, or events won't be sent to the server. - - @param event The event name. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - - @param label The event label (optional). Must be a string. - - @param data The event data (optional). - */ -+ (void)trackEvent:(nonnull NSString*)event withLabel:(nullable NSString*)label associatedData:(nullable BatchEventData*)data NS_SWIFT_NAME(trackEvent(_:withLabel:data:)); - -/** - Track a transaction - You can call this method from any thread. Batch must be started at some point, or events won't be sent to the server. - - @param amount Transaction's amount. - */ +/// Read the saved attributes. Reading is asynchronous so as not to interfere with saving operations. +/// +/// - Parameter completionHandler: Completion block that contains a dictionary of attributes. +/// The keys are the ones used when setting the attributes, the values are of type BatchUserAttribute. +/// See ``BatchUserAttribute`` for more information. ++ (void)fetchAttributes: + (void (^_Nonnull)(NSDictionary *_Nullable attributes))completionHandler; + +/// Read the saved tag collections. +/// +/// Reading is asynchronous so as not to interfere with saving operations. +/// - Note:Tags are saved in lowercase. +/// - Parameter completionHandler: Completion block that contains a dictionary of sets of tags. +/// The keys are the ones used when setting the tags collections. ++ (void)fetchTagCollections: + (void (^_Nonnull)(NSDictionary *> *_Nullable collections))completionHandler; + +/// Track an event. +/// +/// You can call this method from any thread. Batch must be started at some point, or events won't be sent to the +/// server. +/// - Parameter event: The event name. It should be made of letters, numbers or underscores (`[a-z0-9_]`) +/// and can't be longer than 30 characters. ++ (void)trackEvent:(nonnull NSString *)event; + +/// Track an event. +/// +/// You can call this method from any thread. Batch must be started at some point, or events won't be sent to the +/// server. +/// - Parameters: +/// - event: The event name. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and can't be longer +/// than 30 characters. +/// - label: The event label (optional). Must be a string. ++ (void)trackEvent:(nonnull NSString *)event withLabel:(nullable NSString *)label; + +/// Track an event. (Deprecated) +/// +/// You can call this method from any thread. Batch must be started at some point, or events won't be sent to the +/// server. +/// - Parameters: +/// - event: The event name. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and can't be longer +/// than 30 characters. +/// - label: The event label (optional). Must be a string. +/// - data: The event data (optional). Must a serializable JSON Foundation dictionary (meaning that it must pass +/// `+[NSJSONSerialization isValidJSONObject]`'s check). See `NSJSONSerialization` documentation for supported types, +/// with the only difference that the top level object __MUST BE__ a NSDictionary and not a NSArray. +/// - Warning: __Deprecated:__ See ``BatchUser/trackEvent:withLabel:associatedData:``. Data sent using this method +/// might be truncated if it can't be converted to a BatchEventData instance. ++ (void)trackEvent:(nonnull NSString *)event + withLabel:(nullable NSString *)label + data:(nullable NSDictionary *)data __attribute__((deprecated( + "Please migrate to [BatchUser trackEvent:withLabel:associatedData:]. Data sent using this " + "method might be truncated if it can't be converted to a BatchEventData instance."))); + +/// Track an event. +/// +/// You can call this method from any thread. Batch must be started at some point, or events won't be sent to the +/// server. +/// +/// - Parameters: +/// - event: The event name. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and can't be longer +/// than 30 characters. +/// - label: The event label (optional). Must be a string. +/// - data: The event data (optional). ++ (void)trackEvent:(nonnull NSString *)event + withLabel:(nullable NSString *)label + associatedData:(nullable BatchEventData *)data NS_SWIFT_NAME(trackEvent(_:withLabel:data:)); + +/// Track a transaction +/// +/// You can call this method from any thread. Batch must be started at some point, or events won't be sent to the +/// server. +/// - Parameter amount: Transaction's amount. + (void)trackTransactionWithAmount:(double)amount; -/** - Track a transaction - You can call this method from any thread. Batch must be started at some point, or events won't be sent to the server. - - @param amount Transaction's amount. - - @param data The transaction data (optional). Must a serializable JSON Foundation dictionary (meaning that it must pass +[NSJSONSerialization isValidJSONObject]'s check). See NSJSONSerialization documentation for supported types, with the only difference that the top level object MUST BE a NSDictionary and not a NSArray. - */ -+ (void)trackTransactionWithAmount:(double)amount data:(nullable NSDictionary*)data; - -/** - Track a geolocation update - You can call this method from any thread. Batch must be started at some point, or location updates won't be sent to the server. - You'll usually call this method in your CLLocationManagerDelegate implementation - - @param location The user's location in the form of a CLLocation object, ideally the one provided by the system to your delegate. - */ -+ (void)trackLocation:(nonnull CLLocation*)location; - -/** - Print the currently known attributes and tags for a user to the logs (stderr/syslog). - */ +/// Track a transaction. +/// +/// You can call this method from any thread. Batch must be started at some point, or events won't be sent to the +/// server. +/// - Parameters: +/// - amount: Transaction's amount. +/// - data: The transaction data (optional). Must a serializable JSON Foundation dictionary (meaning that it must pass +/// `+[NSJSONSerialization isValidJSONObject]`'s check). See `NSJSONSerialization` documentation for supported types, +/// with the only difference that the top level object __MUST BE__ a NSDictionary and not a NSArray. ++ (void)trackTransactionWithAmount:(double)amount data:(nullable NSDictionary *)data; + +/// Track a geolocation update. +/// +/// You can call this method from any thread. Batch must be started at some point, or location updates won't be sent to +/// the server. You'll usually call this method in your `CLLocationManagerDelegate` implementation +/// - Parameter location: The user's location in the form of a `CLLocation` object, ideally the one provided by the +/// system to your delegate. ++ (void)trackLocation:(nonnull CLLocation *)location; + +/// Print the currently known attributes and tags for a user to the logs (stderr/syslog). + (void)printDebugInformation; @end +/// Provides user custom data methods +/// +/// # Setting an attribute +/// ```swift +/// // Get a new editor instance. +/// // You need to save this in a local variable until you call save +/// // Editor instances don't share changes, and calling save on an empty editor will do nothing +/// let editor = BatchUser.editor() +/// // Set an attribute. try? allows a potential error to be silently ignored +/// // This example is a valid key/attribute pair, and will not throw an error. +/// try? editor.set(attribute: 26, forKey:"age") +/// do { +/// // Invalid attribute name, $ is a forbidden character +/// try editor.set(attribute: "patricia", forKey: "fir$t_name") +/// } catch { +/// // Handle the error here. +/// // Error is of type BatchUserDataEditorError if you want to specifically +/// // handle it. +/// } +/// editor.save() // Don't forget to save the changes +/// ``` +/// +/// # Removing an attribute +/// ```swift +/// // Get a new editor instance. +/// // You need to save this in a local variable until you call save +/// // Editor instances don't share changes, and calling save on an empty editor will do nothing +/// let editor = BatchUser.editor() +/// editor.removeAttribute(forKey: "age") // Remove an attribute +/// editor.clearAttributes() // Removes all attributes +/// editor.save() // Don't forget to save the changes +/// ``` +/// +/// # Managing tag collections +/// ```swift +/// // Get a new editor instance. +/// // You need to save this in a local variable until you call save +/// // Editor instances don't share changes, and calling save on an empty editor will do nothing +/// let editor = BatchUser.editor() +/// editor.addTag("has_bought", inCollection: "actions") // Add a tag to the "actions" collection +/// editor.removeTag("has_bought", fromCollection: "actions") // Remove it +/// editor.clearTagCollection("actions") // Removes all tags from that collection +/// // editor.clearTags() // Removes all tag collections and tags +/// editor.save(); // Don't forget to save the changes +/// ``` @interface BatchUserDataEditor : NSObject -/** - Override the detected user language. - - @param language Language override: lowercase, ISO 639 formatted string. nil to reset. - */ -- (void)setLanguage:(nullable NSString*)language; - -/** - Override the detected user region. - - @param region Region override: uppercase, ISO 3166 formatted string. nil to reset. - */ -- (void)setRegion:(nullable NSString*)region; - -/** - Set the user identifier. - - @warning Be careful: you should make sure the identifier uniquely identifies a user. When pushing an identifier, all installations with that identifier will get the Push, which can cause some privacy issues if done wrong. - - @param identifier User identifier. - */ -- (void)setIdentifier:(nullable NSString*)identifier; - -/** - Set a custom user attribute for a key. - - The attribute can be one of the following types, or their native Swift equivalent - - - NSString - - Must not be longer than 64 characters. Can be empty. - For better results, you should make them upper/lowercase and trim the whitespaces. - - - NSNumber - - Anything bigger than a `long long` or a `double` will be rejected. - Unsigned values will be rejected. - Booleans are supported, but should be initialized with `[NSNumber numberWithBool:]` or `@YES/@NO`. - - - NSDate - - Note that since timezones are not supported, this will typically represent UTC dates. - Using any unsupported type as a value (NSNull, NSObject, NSArray, NSDictionary for example) will **NOT** work. - - - NSURL - - Must not be longer than 2048 characters. Can't be empty. - Must follow the format 'scheme://[authority][path][?query][#fragment]'. - - @param attribute The attribute value. If nil, the attribute will be removed. See method description for more info about what's allowed. - - @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)setAttribute:(nullable NSObject*)attribute forKey:(nonnull NSString*)key; +/// Override the detected user language. +/// +/// - Parameter language: Language override: lowercase, ISO 639 formatted string. nil to reset. +- (void)setLanguage:(nullable NSString *)language; + +/// Override the detected user region. +/// - Parameter region: Region override: uppercase, ISO 3166 formatted string. nil to reset. +- (void)setRegion:(nullable NSString *)region; + +/// Set the user identifier. +/// +/// - Important: Be careful: you should make sure the identifier uniquely identifies a user. When pushing an identifier, +/// all installations with that identifier will get the Push, which can cause some privacy issues if done wrong. +/// - Parameter identifier: User identifier. +- (void)setIdentifier:(nullable NSString *)identifier; + +/// Set the user email. +/// +/// - Important: This method requires to already have a registered identifier for the user +/// or to call ``BatchUserDataEditor/setIdentifier:`` method before this one. +/// - Parameters: +/// - email: User email. +/// - error Pointer to an error describing. Note that the error is only about validation and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setEmail:(nullable NSString *)email error:(NSError *_Nullable *_Nullable)error; + +/// Set the user email subscription state. +/// +/// - Parameters: +/// - state: Subscription state +- (void)setEmailMarketingSubscriptionState:(BatchEmailSubscriptionState)state; + +/// Set a custom user attribute for a key. +/// +/// The attribute can be one of the following types, or their native Swift equivalent. +/// - NSString +/// - Must not be longer than 64 characters. Can be empty. +/// - For better results, you should make them upper/lowercase and trim the whitespaces. +/// - NSNumber +/// - Anything bigger than a `long long` or a `double` will be rejected. +/// - Unsigned values will be rejected. +/// - Booleans are supported, but should be initialized with `[NSNumber numberWithBool:]` or `@YES/@NO`. +/// - NSDate +/// - Note that since timezones are not supported, this will typically represent UTC dates. +/// - Using any unsupported type as a value (`NSNull, NSObject, NSArray, NSDictionary` for example) will **NOT** work. +/// - NSURL +/// - Must not be longer than 2048 characters. Can't be empty. +/// - Must follow the format `scheme://[authority][path][?query][#fragment]`. +/// - Parameters: +/// - attribute: The attribute value. If nil, the attribute will be removed. See method description for more info +/// about what's allowed. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +- (void)setAttribute:(nullable NSObject *)attribute forKey:(nonnull NSString *)key; /// Set a boolean custom user attribute for a key. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setBooleanAttribute:(BOOL)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); +/// +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setBooleanAttribute:(BOOL)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); /// Set a date custom user attribute for a key. -/// Note that since timezones are not supported, this will typically represent UTC dates. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setDateAttribute:(nonnull NSDate*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); +/// +/// - Note: Since timezones are not supported, this will typically represent UTC dates. +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setDateAttribute:(nonnull NSDate *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); /// Set a string custom user attribute for a key. +/// /// Must not be longer than 64 characters. Can be empty. /// For better results, you should make them upper/lowercase and trim the whitespaces. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setStringAttribute:(nonnull NSString*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setStringAttribute:(nonnull NSString *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); /// Set a boolean custom user attribute for a key. +/// /// Anything bigger than a `long long` or a `double` will be rejected. /// Unsigned values will be rejected. /// Booleans are supported, but should be initialized with `[NSNumber numberWithBool:]` or `@YES/@NO`. -/// Note: `setBoolean/Integer/LongLong/Float/Double` should be preferred over this method, especially for booleans. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setNumberAttribute:(nonnull NSNumber*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); - -/// Set an NSInteger/Int custom user attribute for a key. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setIntegerAttribute:(NSInteger)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); - -/// Set an long long/Int64 custom user attribute for a key. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setLongLongAttribute:(long long)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); +/// - Note: `setBoolean/Integer/LongLong/Float/Double` should be preferred over this method, especially for booleans. +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setNumberAttribute:(nonnull NSNumber *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); + +/// Set an `NSInteger/Int` custom user attribute for a key. +/// +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setIntegerAttribute:(NSInteger)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); + +/// Set an `long long/Int64` custom user attribute for a key. +/// +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setLongLongAttribute:(long long)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); /// Set an float custom user attribute for a key. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setFloatAttribute:(float)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); +/// +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setFloatAttribute:(float)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); /// Set an double custom user attribute for a key. -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setDoubleAttribute:(double)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); +/// +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setDoubleAttribute:(double)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); /// Set an url custom user attribute for a key. +/// /// Must not be longer than 2048 characters. Can't be empty or nil. -/// Must follow the format 'scheme://[authority][path][?query][#fragment]' -/// @param attribute The attribute value. -/// @param key The attribute key. Can't be nil. It should be made of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. -/// @param error Pointer to an error describing. Note that the error is only about key/value validation, and doesn't mean the value has been sent to the server yet. -/// @returns A boolean indicating whether the attribute passed validation or not. -- (BOOL)setURLAttribute:(nonnull NSURL*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); - -/** - Removes an attribute for the specified key. - - @param key The attribute key. Can't be nil. - */ -- (void)removeAttributeForKey:(nonnull NSString*)key; - -/** - Removes all custom attributes. - - @warning Once saved, this action cannot be undone. - */ +/// Must follow the format `scheme://[authority][path][?query][#fragment]`. +/// - Parameters: +/// - attribute: The attribute value. +/// - key: The attribute key. Can't be nil. It should be made of letters, numbers or underscores (`[a-z0-9_]`) and +/// can't be longer than 30 characters. +/// - error: Pointer to an error describing. Note that the error is only about key/value validation, and doesn't +/// mean the value has been sent to the server yet. +/// - Returns: A boolean indicating whether the attribute passed validation or not. +- (BOOL)setURLAttribute:(nonnull NSURL *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(set(attribute:forKey:)); + +/// Removes an attribute for the specified key. +/// +/// - Parameter key: The attribute key. Can't be nil. +- (void)removeAttributeForKey:(nonnull NSString *)key; + +/// Removes all custom attributes. +/// +/// - Important: Once saved, this action cannot be undone. - (void)clearAttributes; -/** - Add a tag to the specified collection. If empty, the collection will be created automatically. - - @param tag The tag to add. Cannot be nil or empty. Must be a string no longer than 64 characters. - - @param collection The tag collection name. Cannot be nil. Must be a string of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)addTag:(nonnull NSString*)tag inCollection:(nonnull NSString*)collection; - -/** - Removes a tag from the specified collection. - - @param tag The tag to remove. Cannot be nil. If the tag doesn't exist, this method will do nothing. - - @param collection The tag collection name. Cannot be nil. Must be a string of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. If the collection doesn't exist, this method will do nothing, but apply won't fail. - */ -- (void)removeTag:(nonnull NSString*)tag fromCollection:(nonnull NSString*)collection; - -/** - Removes all tags. - - @warning Once saved, this action cannot be undone. - */ +/// Add a tag to the specified collection. If empty, the collection will be created automatically. +/// +/// - Parameters: +/// - tag: The tag to add. Cannot be nil or empty. Must be a string no longer than 64 characters. +/// - collection: The tag collection name. Cannot be nil. Must be a string of letters, numbers or underscores +/// (`[a-z0-9_]`) and can't be longer than 30 characters. +- (void)addTag:(nonnull NSString *)tag inCollection:(nonnull NSString *)collection; + +/// Removes a tag from the specified collection. +/// +/// - Parameters: +/// - tag: Removes a tag from the specified collection. +/// - collection: The tag collection name. Cannot be nil. Must be a string of letters, numbers or underscores +/// (`[a-z0-9_]`) and can't be longer than 30 characters. If the collection doesn't exist, this method will do +/// nothing, but apply won't fail. +- (void)removeTag:(nonnull NSString *)tag fromCollection:(nonnull NSString *)collection; + +/// Removes all tags. +/// +/// - Important: Once saved, this action cannot be undone. - (void)clearTags; -/** - Removes all tags from a collection. - - @warning Once applied, this action cannot be undone. - - @param collection The tag collection name. Cannot be nil. Must be a string of letters, numbers or underscores ([a-z0-9_]) and can't be longer than 30 characters. - */ -- (void)clearTagCollection:(nonnull NSString*)collection; - -/** - Save all of the pending changes made in that editor. - - @warning This action cannot be undone. - */ +/// Removes all tags from a collection. +/// +/// - Important: Once applied, this action cannot be undone. +/// - Parameter collection: The tag collection name. Cannot be nil. Must be a string of letters, numbers or underscores +/// (`[a-z0-9_]`) and can't be longer than 30 characters. +- (void)clearTagCollection:(nonnull NSString *)collection; + +/// Save all of the pending changes made in that editor. +/// +/// - Important:This action cannot be undone. - (void)save; @end diff --git a/Sources/Batch/BatchUser.m b/Sources/Batch/BatchUser.m index f7da3dc..b55f1cc 100644 --- a/Sources/Batch/BatchUser.m +++ b/Sources/Batch/BatchUser.m @@ -233,6 +233,14 @@ - (void)setIdentifier:(nullable NSString *)identifier { [_backingImpl setIdentifier:identifier]; } +- (BOOL)setEmail:(nullable NSString *)email error:(NSError **)error { + return [_backingImpl setEmail:email error:error]; +} + +- (void)setEmailMarketingSubscriptionState:(BatchEmailSubscriptionState)state { + [_backingImpl setEmailMarketingSubscriptionState:state]; +} + - (void)setAttribute:(nullable NSObject *)attribute forKey:(nonnull NSString *)key { [_backingImpl setAttribute:attribute forKey:key]; } diff --git a/Sources/Batch/BatchUserAttribute.h b/Sources/Batch/BatchUserAttribute.h index a57f2cf..bb88e08 100644 --- a/Sources/Batch/BatchUserAttribute.h +++ b/Sources/Batch/BatchUserAttribute.h @@ -8,6 +8,7 @@ #import +/// Types of user attribute typedef NS_ENUM(NSUInteger, BatchUserAttributeType) { BatchUserAttributeTypeString, BatchUserAttributeTypeLongLong, @@ -17,44 +18,33 @@ typedef NS_ENUM(NSUInteger, BatchUserAttributeType) { BatchUserAttributeTypeURL }; -@interface BatchUserAttribute: NSObject +/// Object used as value when using ``BatchUser/fetchAttributes:`` +@interface BatchUserAttribute : NSObject -/** - The value of the attribute. You can use the typed methods below to get a typed result. - */ +/// The value of the attribute. You can use the typed methods below to get a typed result. @property (nonatomic, nonnull) id value; -/** - The type of the value for the attribute. - */ +/// The type of the value for the attribute. @property (assign, nonatomic) BatchUserAttributeType type; -/** - Get the date value for date type attributes. - - @return A date value or nil if the attribute is not a date. - */ +/// Get the date value for date type attributes. +/// +/// - Returns: A date value or nil if the attribute is not a date. - (nullable NSDate *)dateValue; -/** - Get the string value for string type attributes. - - @return A string value or nil if the attribute is not a string. - */ +/// Get the string value for string type attributes. +/// +/// - Returns: A string value or nil if the attribute is not a string. - (nullable NSString *)stringValue; -/** - Get the number value for double, long long and bool type attributes. - - @return A string value or nil if the attribute is not a number. - */ +/// Get the number value for double, long long and bool type attributes. +/// +/// - Returns: A number value or nil if the attribute is not a number. - (nullable NSNumber *)numberValue; -/** - Get the url value for url type attributes. - - @return An url value or nil if the attribute is not an url. - */ +/// Get the url value for url type attributes. +/// +/// - Returns: An url value or nil if the attribute is not an url. - (nullable NSURL *)urlValue; @end diff --git a/Sources/Batch/BatchUserAttributePrivate.h b/Sources/Batch/BatchUserAttributePrivate.h index 62a1f70..bd18f05 100644 --- a/Sources/Batch/BatchUserAttributePrivate.h +++ b/Sources/Batch/BatchUserAttributePrivate.h @@ -8,8 +8,6 @@ // Expose private constructors // This header is private and should NEVER be distributed within the framework - -@interface BatchUserAttribute() -- (nullable instancetype)initWithValue:(nonnull id)value - type:(BatchUserAttributeType)type; +@interface BatchUserAttribute () +- (nullable instancetype)initWithValue:(nonnull id)value type:(BatchUserAttributeType)type; @end diff --git a/Sources/Batch/BatchUserProfile.h b/Sources/Batch/BatchUserProfile.h index 15a72ed..f2ddc0f 100644 --- a/Sources/Batch/BatchUserProfile.h +++ b/Sources/Batch/BatchUserProfile.h @@ -8,35 +8,27 @@ #import -/** - Describe a complete user profile. - Use this object to access all user info. - */ +/// Describe a complete user profile. +/// Use this object to access all user info. @interface BatchUserProfile : NSObject -/** - Set a custom user identifier to Batch, you should use this method if you have your own login system. - - @warning Be careful: Do not use it if you don't know what you are doing, giving a bad custom user ID can result in failure of targeted push notifications delivery. - - @deprecated - */ +/// Set a custom user identifier to Batch, you should use this method if you have your own login system. +/// +/// - Warning: **Deprecated:** Please use ``Batch/BatchUser`` instead. +/// - Important: Be careful: Do not use it if you don't know what you are doing, giving a bad custom user ID can result +/// in failure of targeted push notifications delivery. @property (strong, nonatomic) NSString *customIdentifier __attribute__((deprecated("Please use Batch User instead"))); -/** - The application language, default value is the device language. - Set to nil to reset to default value. - - @deprecated - */ +/// The application language, default value is the device language. +/// Set to nil to reset to default value. +/// +/// - Warning: **Deprecated:** Please use ``Batch/BatchUser`` instead. @property (strong, nonatomic) NSString *language __attribute__((deprecated("Please use Batch User instead"))); -/** - The application region, default value is the device region. - Set to nil to reset to default value. - - @deprecated - */ +/// The application region, default value is the device region. +/// Set to nil to reset to default value. +/// +/// - Warning: **Deprecated:** Please use ``Batch/BatchUser`` instead. @property (strong, nonatomic) NSString *region __attribute__((deprecated("Please use Batch User instead"))); @end diff --git a/Sources/Batch/Defined.h b/Sources/Batch/Defined.h index c7743fb..a663b6a 100644 --- a/Sources/Batch/Defined.h +++ b/Sources/Batch/Defined.h @@ -10,18 +10,18 @@ #include -#define ERROR_DOMAIN @"com.batch.ios" -#define NETWORKING_ERROR_DOMAIN @"com.batch.ios.networking" -#define MESSAGING_ERROR_DOMAIN @"com.batch.ios.messaging" +#define ERROR_DOMAIN @"com.batch.ios" +#define NETWORKING_ERROR_DOMAIN @"com.batch.ios.networking" +#define MESSAGING_ERROR_DOMAIN @"com.batch.ios.messaging" #define WEBVIEW_ERROR_DOMAIN @"com.batch.ios.webview" #define BRIDGE_ERROR_DOMAIN @"com.batch.ios.webview.bridge" #define INIT_AND_BLANK_ERROR_IF_NEEDED(error) \ -if (error == NULL) {\ - __autoreleasing NSError *fakeOutErr;\ - error = &fakeOutErr;\ -}\ -*error = nil; + if (error == NULL) { \ + __autoreleasing NSError *fakeOutErr; \ + error = &fakeOutErr; \ + } \ + *error = nil; // Enable IDFA related code // Even though IDFA collection is based on AdSupport being linked to the app, @@ -44,151 +44,151 @@ if (error == NULL) {\ #define BAGetStringifiedMacro(macro) BAStringifyValue(macro) #define BASDKVersionNSString @BAGetStringifiedMacro(BASDKVersion) -#define BAPrivateKeyStorage @"Pm1oZKMo" -#define BAPrivateKeyWebservice @"wgHD" -#define BAPrivateKeyWebserviceV2 @"jgfx" -#define BABastionBundleIdentifier @"com.bastionsdk" -#define BABundleIdentifier @"com.batch.ios" -#define BAProductIdentifier @"IOS-com.batch.ios" +#define BAPrivateKeyStorage @"Pm1oZKMo" +#define BAPrivateKeyWebservice @"wgHD" +#define BAPrivateKeyWebserviceV2 @"jgfx" +#define BABastionBundleIdentifier @"com.bastionsdk" +#define BABundleIdentifier @"com.batch.ios" +#define BAProductIdentifier @"IOS-com.batch.ios" // Read receipt -#define kParametersReadReceiptEventName @"_PUSH_RECEIVED" +#define kParametersReadReceiptEventName @"_PUSH_RECEIVED" // Application parameters. -#define kParametersLocalInstallIdentifierKey @"app.install.id" -#define kParametersLocalInstallDateIdentifierKey @"app.install.timestamp" -#define kParametersLocalIcloudIdentifierKey @"app.icloud.id" -#define kParametersLocalIcloudDateIdentifierKey @"app.icloud.timestamp" -#define kParametersLocalServerInstallIdentifierKey @"app.server.id" +#define kParametersLocalInstallIdentifierKey @"app.install.id" +#define kParametersLocalInstallDateIdentifierKey @"app.install.timestamp" +#define kParametersLocalIcloudIdentifierKey @"app.icloud.id" +#define kParametersLocalIcloudDateIdentifierKey @"app.icloud.timestamp" +#define kParametersLocalServerInstallIdentifierKey @"app.server.id" -#define kParametersPoolWebserviceMaxKey @"app.executor.maxpool" -#define kParametersSystemCurrentAppVersionKey @"app.version.current" -#define kParametersSystemPreviousAppVersionKey @"app.version.previous" +#define kParametersPoolWebserviceMaxKey @"app.executor.maxpool" +#define kParametersSystemCurrentAppVersionKey @"app.version.current" +#define kParametersSystemPreviousAppVersionKey @"app.version.previous" -#define kParametersIDsPatternKey @"app.ids.pattern" -#define kParametersIDsPatternValue @"s,da,ada,did,cus,tath,dla,dre,dtz,osv,de,apv,apc,bid,pl,lvl,mlvl,pid,plv,brv,attid_e" +#define kParametersIDsPatternKey @"app.ids.pattern" +#define kParametersIDsPatternValue \ + @"s,da,ada,did,cus,tath,dla,dre,dtz,osv,de,apv,apc,bid,pl,lvl,mlvl,pid,plv,brv,attid_e" -#define kParametersAdvancedIDsPatternKey @"app.ids.pattern_advanced" -#define kParametersAdvancedIDsPatternValue @"dty,sop" +#define kParametersAdvancedIDsPatternKey @"app.ids.pattern_advanced" +#define kParametersAdvancedIDsPatternValue @"dty,sop" -#define kParametersCustomUserIDKey @"app.id.custom" -#define kParametersAppLanguageKey @"app.language" -#define kParametersAppRegionKey @"app.region" -#define kParametersAppProfileVersionKey @"app.profile.version" +#define kParametersCustomUserIDKey @"app.id.custom" +#define kParametersAppLanguageKey @"app.language" +#define kParametersAppRegionKey @"app.region" +#define kParametersAppProfileVersionKey @"app.profile.version" -#define kParametersDateFormat @"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'" +#define kParametersDateFormat @"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'" // Push keys -#define kParametersPushTokenKey @"push.token" -#define kParametersPushTokenIsProductionKey @"push.token.isproduction" +#define kParametersPushTokenKey @"push.token" +#define kParametersPushTokenIsProductionKey @"push.token.isproduction" // Display receipt keys (sharing with extensions) -#define kParametersDisplayReceiptLastApiKey @"batch_shared_apikey" -#define kParametersDisplayReceiptInstallIdKey @"batch_shared_installid" -#define kParametersDisplayReceiptCustomIdKey @"batch_shared_customid" -#define kParametersDisplayReceiptOptOutKey @"batch_shared_optout" +#define kParametersDisplayReceiptLastApiKey @"batch_shared_apikey" +#define kParametersDisplayReceiptInstallIdKey @"batch_shared_installid" +#define kParametersDisplayReceiptCustomIdKey @"batch_shared_customid" +#define kParametersDisplayReceiptOptOutKey @"batch_shared_optout" // Latest notification authorization status sent to the server -#define kParametersNotificationAuthSentStatusKey @"notification.auth.sentstatus" -#define kParametersAppNotificationSettingsKey @"notification.auth.appsettings" +#define kParametersNotificationAuthSentStatusKey @"notification.auth.sentstatus" +#define kParametersAppNotificationSettingsKey @"notification.auth.appsettings" // Tracker parameters. -#define kParametersTrackerStateKey @"tracker.state" -#define kParametersTrackerStateValue @2 +#define kParametersTrackerStateKey @"tracker.state" +#define kParametersTrackerStateValue @2 -#define kParametersTrackerDBLimitKey @"tracker.db.limit" -#define kParametersTrackerDBLimitValue @10000 +#define kParametersTrackerDBLimitKey @"tracker.db.limit" +#define kParametersTrackerDBLimitValue @10000 -#define kParametersTrackerInitialDelayKey @"tracker.delay.initial" -#define kParametersTrackerInitialDelayValue @10 +#define kParametersTrackerInitialDelayKey @"tracker.delay.initial" +#define kParametersTrackerInitialDelayValue @10 -#define kParametersTrackerMaxDelayKey @"tracker.delay.max" -#define kParametersTrackerMaxDelayValue @120 +#define kParametersTrackerMaxDelayKey @"tracker.delay.max" +#define kParametersTrackerMaxDelayValue @120 -#define kParametersTrackerWebserviceEventLimitKey @"tracker.ws.limit" +#define kParametersTrackerWebserviceEventLimitKey @"tracker.ws.limit" #define kParametersTrackerWebserviceEventLimitValue @20 -#define kParametersTrackerDBVersion @"tracker.db.version" +#define kParametersTrackerDBVersion @"tracker.db.version" // Inbox Parameters. -#define kParametersInboxDBVersion @"inbox.db.version" +#define kParametersInboxDBVersion @"inbox.db.version" // User profile -#define kParametersUserProfileDataVersionKey @"user_profile.data.version" -#define kParametersUserProfileTransactionIDKey @"user_profile.trid" -#define kParametersUserProfileDBVersion @"user_profile.db.version" -#define kParametersUserStartCheckInitialDelay @1000 +#define kParametersUserProfileDataVersionKey @"user_profile.data.version" +#define kParametersUserProfileTransactionIDKey @"user_profile.trid" +#define kParametersUserProfileDBVersion @"user_profile.db.version" +#define kParametersUserStartCheckInitialDelay @1000 -#define kParametersInAppTrackerDBVersion @"messaging.inapp.db.version" +#define kParametersInAppTrackerDBVersion @"messaging.inapp.db.version" -#define kParametersLocalCampaignsInitialWSDelayKey @"lc.wsdelay.initial" +#define kParametersLocalCampaignsInitialWSDelayKey @"lc.wsdelay.initial" #define kParametersLocalCampaignsInitialWSDelayValue @5 -#define kParametersServerTimestamp @"ws.server.timestamp" -#define kParametersCipherV2LastFailure @"ws.cipherv2.lastfailure" -#define kCipherFallbackResetTime 172800 -#define kCipherFallbackHTTPErrorCode 487 +#define kParametersServerTimestamp @"ws.server.timestamp" +#define kParametersCipherV2LastFailure @"ws.cipherv2.lastfailure" +#define kCipherFallbackResetTime 172800 +#define kCipherFallbackHTTPErrorCode 487 // Webservice keys. // Maximum number of concurrent network requests for BAWebserviceClient -#define kWebserviceClientExecutorMaxConcurrency 2 - -#define kQueryWebserviceTypeStart @"START" -#define kQueryWebserviceTypePush @"PUSH" -#define kQueryWebserviceTypeTracking @"TRACKING" -#define kQueryWebserviceTypeAttributes @"ATTRIBUTES" -#define kQueryWebserviceTypeAttributesCheck @"ATTRIBUTES_CHECK" -#define kQueryWebserviceTypeLocalCampaigns @"LOCAL_CAMPAIGNS" - -#define kWebserviceKeyMainHeader @"header" -#define kWebserviceKeyMainStatus @"status" -#define kWebserviceKeyMainBody @"body" -#define kWebserviceKeyQueryIdentifier @"id" -#define kWebserviceKeyTimestamp @"ts" -#define kWebserviceKeyQueryType @"type" +#define kWebserviceClientExecutorMaxConcurrency 2 + +#define kQueryWebserviceTypeStart @"START" +#define kQueryWebserviceTypePush @"PUSH" +#define kQueryWebserviceTypeTracking @"TRACKING" +#define kQueryWebserviceTypeAttributes @"ATTRIBUTES" +#define kQueryWebserviceTypeAttributesCheck @"ATTRIBUTES_CHECK" +#define kQueryWebserviceTypeLocalCampaigns @"LOCAL_CAMPAIGNS" + +#define kWebserviceKeyMainHeader @"header" +#define kWebserviceKeyMainStatus @"status" +#define kWebserviceKeyMainBody @"body" +#define kWebserviceKeyQueryIdentifier @"id" +#define kWebserviceKeyTimestamp @"ts" +#define kWebserviceKeyQueryType @"type" // Various keys used in queries -#define kWebserviceKeyQuerySilentStart @"silent" +#define kWebserviceKeyQuerySilentStart @"silent" -#define kWebserviceKeyQueryEvents @"evts" +#define kWebserviceKeyQueryEvents @"evts" -#define kWebserviceKeyQueryToken @"tok" -#define kWebserviceKeyQueryProduction @"prod" -#define kWebserviceKeyQueryNotifType @"nty" +#define kWebserviceKeyQueryToken @"tok" +#define kWebserviceKeyQueryProduction @"prod" +#define kWebserviceKeyQueryNotifType @"nty" -#define kWebserviceKeyPushBatchData @"com.batch" -#define kWebserviceKeyPushDeeplink @"l" -#define kWebserviceKeyDeeplinkOpenInApp @"li" -#define kWebserviceKeyPushId @"i" -#define kWebserviceKeyPushOpenEventData @"od" -#define kWebserviceKeyPushType @"t" -#define kWebserviceKeyPushExperiment @"ex" -#define kWebserviceKeyPushVariant @"va" +#define kWebserviceKeyPushBatchData @"com.batch" +#define kWebserviceKeyPushDeeplink @"l" +#define kWebserviceKeyDeeplinkOpenInApp @"li" +#define kWebserviceKeyPushId @"i" +#define kWebserviceKeyPushOpenEventData @"od" +#define kWebserviceKeyPushType @"t" +#define kWebserviceKeyPushExperiment @"ex" +#define kWebserviceKeyPushVariant @"va" -#define kParametersWebserviceBase @"https://ws.batch.com" -#define kParametersDisplayReceiptWebserviceBase @"https://drws.batch.com" -#define kParametersMetricWebserviceBase @"https://wsmetrics.batch.com/api-sdk" +#define kParametersWebserviceBase @"https://ws.batch.com" +#define kParametersDisplayReceiptWebserviceBase @"https://drws.batch.com" +#define kParametersMetricWebserviceBase @"https://wsmetrics.batch.com/api-sdk" -#define kParametersWebserviceDomain kParametersWebserviceHost @"/i/" +#define kParametersWebserviceDomain kParametersWebserviceHost @"/i/" // URL shortnames -#define kParametersStartWebserviceShortname @"st" -#define kParametersPushWebserviceShortname @"t" -#define kParametersTrackingWebserviceShortname @"tr" -#define kParametersAttributesSendWebserviceShortname @"ats" -#define kParametersAttributesCheckWebserviceShortname @"atc" -#define kParametersInboxFetchWebserviceShortname @"inbox" -#define kParametersLocalCampaignsWebserviceShortname @"local" -#define kParametersLocalCampaignsJITWebserviceShortname @"lc_jit" - +#define kParametersStartWebserviceShortname @"st" +#define kParametersPushWebserviceShortname @"t" +#define kParametersTrackingWebserviceShortname @"tr" +#define kParametersAttributesSendWebserviceShortname @"ats" +#define kParametersAttributesCheckWebserviceShortname @"atc" +#define kParametersInboxFetchWebserviceShortname @"inbox" +#define kParametersLocalCampaignsWebserviceShortname @"local" +#define kParametersLocalCampaignsJITWebserviceShortname @"lc_jit" // start -#define kParametersStartWebserviceURL kParametersWebserviceDomain BAVersion @"/" kParametersStartWebserviceShortname +#define kParametersStartWebserviceURL kParametersWebserviceDomain BAVersion @"/" kParametersStartWebserviceShortname // local campaigns -#define kParametersLocalCampaignsWebserviceURL kParametersWebserviceDomain BAVersion @"/" kParametersLocalCampaignsWebserviceShortname - +#define kParametersLocalCampaignsWebserviceURL \ + kParametersWebserviceDomain BAVersion @"/" kParametersLocalCampaignsWebserviceShortname diff --git a/Sources/Batch/Kernel/Concurrent/BAPromise.h b/Sources/Batch/Kernel/Concurrent/BAPromise.h index 3bfc05f..480306b 100644 --- a/Sources/Batch/Kernel/Concurrent/BAPromise.h +++ b/Sources/Batch/Kernel/Concurrent/BAPromise.h @@ -9,20 +9,20 @@ typedef NS_ENUM(NSUInteger, BAPromiseStatus) { BAPromiseStatusRejected, }; -@interface BAPromise : NSObject +@interface BAPromise : NSObject @property BAPromiseStatus status; + (nonnull instancetype)resolved:(nullable ObjectType)value; -+ (nonnull instancetype)rejected:(nullable NSError*)error; ++ (nonnull instancetype)rejected:(nullable NSError *)error; - (void)resolve:(nullable ObjectType)value; -- (void)reject:(nullable NSError*)error; +- (void)reject:(nullable NSError *)error; - (void)then:(void (^_Nonnull)(ObjectType _Nullable value))thenBlock; -- (void)catch:(void (^_Nonnull)(NSError* _Nullable ))catchBlock; +- (void)catch:(void (^_Nonnull)(NSError *_Nullable))catchBlock; @end diff --git a/Sources/Batch/Kernel/Concurrent/BATaskDebouncer.h b/Sources/Batch/Kernel/Concurrent/BATaskDebouncer.h index 827ac1f..cd1a8fd 100644 --- a/Sources/Batch/Kernel/Concurrent/BATaskDebouncer.h +++ b/Sources/Batch/Kernel/Concurrent/BATaskDebouncer.h @@ -9,12 +9,14 @@ /** Allows deboucing of a task defined by a block. - + Warning: Calling "shedule" in between threads isn't supported. */ @interface BATaskDebouncer : NSObject -+ (instancetype)debouncerWithDelay:(NSTimeInterval)delayTime queue:(dispatch_queue_t)queue task:(dispatch_block_t)taskBlock; ++ (instancetype)debouncerWithDelay:(NSTimeInterval)delayTime + queue:(dispatch_queue_t)queue + task:(dispatch_block_t)taskBlock; - (void)schedule; diff --git a/Sources/Batch/Kernel/Crypto/BAEncryptionProtocol.h b/Sources/Batch/Kernel/Crypto/BAEncryptionProtocol.h index 0b0ee40..a073533 100644 --- a/Sources/Batch/Kernel/Crypto/BAEncryptionProtocol.h +++ b/Sources/Batch/Kernel/Crypto/BAEncryptionProtocol.h @@ -65,5 +65,4 @@ */ - (nullable NSData *)decryptData:(nullable NSData *)crypted; - @end diff --git a/Sources/Batch/Kernel/Crypto/BASHA.h b/Sources/Batch/Kernel/Crypto/BASHA.h index 2a81a24..847899b 100644 --- a/Sources/Batch/Kernel/Crypto/BASHA.h +++ b/Sources/Batch/Kernel/Crypto/BASHA.h @@ -14,12 +14,12 @@ NS_ASSUME_NONNULL_BEGIN /** Returns the raw SHA256 of a given NSData */ -+ (nullable NSData*)sha256HashOf:(nullable NSData*)data; ++ (nullable NSData *)sha256HashOf:(nullable NSData *)data; /** Returns the raw SHA1 of a given NSData */ -+ (nullable NSData*)sha1HashOf:(nullable NSData*)data; ++ (nullable NSData *)sha1HashOf:(nullable NSData *)data; @end diff --git a/Sources/Batch/Kernel/Dependency Injection/BAInjectable.h b/Sources/Batch/Kernel/Dependency Injection/BAInjectable.h index d5d69c9..493a85d 100644 --- a/Sources/Batch/Kernel/Dependency Injection/BAInjectable.h +++ b/Sources/Batch/Kernel/Dependency Injection/BAInjectable.h @@ -14,12 +14,12 @@ typedef _Nullable id (^BAInjectableInitializer)(void); /** Make an injectable using an initializer block. The initializer will be called on each injection. */ -+ (nonnull BAInjectable*)injectableWithInitializer:(nonnull BAInjectableInitializer)initializer; ++ (nonnull BAInjectable *)injectableWithInitializer:(nonnull BAInjectableInitializer)initializer; /** Make an injectable for an instance. The given instance will be returned directly. */ -+ (nonnull BAInjectable*)injectableWithInstance:(nullable id)instance; ++ (nonnull BAInjectable *)injectableWithInstance:(nullable id)instance; /** Resolve the instance diff --git a/Sources/Batch/Kernel/Dependency Injection/BAInjection.h b/Sources/Batch/Kernel/Dependency Injection/BAInjection.h index b5df51c..5cc1021 100644 --- a/Sources/Batch/Kernel/Dependency Injection/BAInjection.h +++ b/Sources/Batch/Kernel/Dependency Injection/BAInjection.h @@ -11,19 +11,19 @@ #import #define bainjection_instance_singleton(initializer) \ -static id instance = nil; \ -static dispatch_once_t once; \ -dispatch_once(&once, ^{ \ - instance = initializer; \ -}); \ -return instance; + static id instance = nil; \ + static dispatch_once_t once; \ + dispatch_once(&once, ^{ \ + instance = initializer; \ + }); \ + return instance; // Annotation that indicates that methods should be injected rather than initialized unless we're in a test case -#define BATCH_USE_INJECTION_OUTSIDE_TESTS +#define BATCH_USE_INJECTION_OUTSIDE_TESTS /** Handles dependency injection for Batch - + This class manages injectables, acts as a registry for them, initializes them, ... It also supports overlaying them for tests */ @@ -31,32 +31,30 @@ return instance; // Registry interaction -+ (void)registerInjectable:(nonnull BAInjectable*)injectable - forProtocol:(nonnull Protocol*)protocol; ++ (void)registerInjectable:(nonnull BAInjectable *)injectable forProtocol:(nonnull Protocol *)protocol; -+ (void)registerInjectable:(nonnull BAInjectable*)injectable - forClass:(nonnull Class)classToRegister; ++ (void)registerInjectable:(nonnull BAInjectable *)injectable forClass:(nonnull Class)classToRegister; // Overlays -+ (nonnull BAOverlayedInjectable*)overlayProtocol:(nonnull Protocol*)protocol - callback:(nonnull BAOverlayedInjectableCallback)callback; ++ (nonnull BAOverlayedInjectable *)overlayProtocol:(nonnull Protocol *)protocol + callback:(nonnull BAOverlayedInjectableCallback)callback; -+ (nonnull BAOverlayedInjectable*)overlayProtocol:(nonnull Protocol*)protocol - returnedInstance:(nullable id)instanceToReturn; ++ (nonnull BAOverlayedInjectable *)overlayProtocol:(nonnull Protocol *)protocol + returnedInstance:(nullable id)instanceToReturn; -+ (nonnull BAOverlayedInjectable*)overlayClass:(Class _Nonnull)classToOverlay - callback:(nonnull BAOverlayedInjectableCallback)callback; ++ (nonnull BAOverlayedInjectable *)overlayClass:(Class _Nonnull)classToOverlay + callback:(nonnull BAOverlayedInjectableCallback)callback; -+ (nonnull BAOverlayedInjectable*)overlayClass:(Class _Nonnull)classToOverlay - returnedInstance:(nullable id)instanceToReturn; ++ (nonnull BAOverlayedInjectable *)overlayClass:(Class _Nonnull)classToOverlay + returnedInstance:(nullable id)instanceToReturn; -+ (void)unregisterOverlay:(nonnull BAOverlayedInjectable*)overlay; ++ (void)unregisterOverlay:(nonnull BAOverlayedInjectable *)overlay; // Injection methods + (nullable id)injectClass:(Class _Nonnull)classToInject; -+ (nullable id)injectProtocol:(nonnull Protocol*)protocolToInject; ++ (nullable id)injectProtocol:(nonnull Protocol *)protocolToInject; @end diff --git a/Sources/Batch/Kernel/Dependency Injection/Private/BAInjectionRegistry.h b/Sources/Batch/Kernel/Dependency Injection/Private/BAInjectionRegistry.h index 2ff3f6f..9c94a5b 100644 --- a/Sources/Batch/Kernel/Dependency Injection/Private/BAInjectionRegistry.h +++ b/Sources/Batch/Kernel/Dependency Injection/Private/BAInjectionRegistry.h @@ -8,42 +8,40 @@ #import #import -#import #import +#import @interface BAInjectionRegistry : NSObject + (nonnull instancetype)sharedInstance; -- (void)registerInjectable:(nonnull BAInjectable*)injectable - forProtocol:(nonnull Protocol*)protocol -NS_SWIFT_NAME(register(injectable:forProtocol:)); +- (void)registerInjectable:(nonnull BAInjectable *)injectable + forProtocol:(nonnull Protocol *)protocol NS_SWIFT_NAME(register(injectable:forProtocol:)); -- (void)registerInjectable:(nonnull BAInjectable*)injectable - forClass:(nonnull Class)classToRegister -NS_SWIFT_NAME(register(injectable:forClass:)); +- (void)registerInjectable:(nonnull BAInjectable *)injectable + forClass:(nonnull Class)classToRegister NS_SWIFT_NAME(register(injectable:forClass:)); // Overlays -- (nonnull BAOverlayedInjectable*)overlayProtocol:(nonnull Protocol*)protocol - callback:(nonnull BAOverlayedInjectableCallback)callback; +- (nonnull BAOverlayedInjectable *)overlayProtocol:(nonnull Protocol *)protocol + callback:(nonnull BAOverlayedInjectableCallback)callback; -- (nonnull BAOverlayedInjectable*)overlayProtocol:(nonnull Protocol*)protocol - returnedInstance:(nullable id)instanceToReturn; +- (nonnull BAOverlayedInjectable *)overlayProtocol:(nonnull Protocol *)protocol + returnedInstance:(nullable id)instanceToReturn; -- (nonnull BAOverlayedInjectable*)overlayClass:(Class _Nonnull)classToOverlay - callback:(nonnull BAOverlayedInjectableCallback)callback; +- (nonnull BAOverlayedInjectable *)overlayClass:(Class _Nonnull)classToOverlay + callback:(nonnull BAOverlayedInjectableCallback)callback; -- (nonnull BAOverlayedInjectable*)overlayClass:(Class _Nonnull)classToOverlay - returnedInstance:(nullable id)instanceToReturn; +- (nonnull BAOverlayedInjectable *)overlayClass:(Class _Nonnull)classToOverlay + returnedInstance:(nullable id)instanceToReturn; -- (void)unregisterOverlay:(nonnull BAOverlayedInjectable*)overlay; +- (void)unregisterOverlay:(nonnull BAOverlayedInjectable *)overlay; // Injection methods // We need to differentiate them in Swift, else the protocol will end in "injectClass" and that's a crash! - (nullable id)injectClass:(Class _Nonnull)classToInject NS_SWIFT_NAME(inject(class:)); -- (nullable id)injectProtocol:(nonnull Protocol*)protocolToInject NS_SWIFT_NAME(inject(protocol:)); +- (nullable id)injectProtocol:(nonnull Protocol *)protocolToInject NS_SWIFT_NAME(inject(protocol:)); @end diff --git a/Sources/Batch/Kernel/Dependency Injection/Private/BAOverlayedInjectable-Private.h b/Sources/Batch/Kernel/Dependency Injection/Private/BAOverlayedInjectable-Private.h index 62c5d86..8fa9908 100644 --- a/Sources/Batch/Kernel/Dependency Injection/Private/BAOverlayedInjectable-Private.h +++ b/Sources/Batch/Kernel/Dependency Injection/Private/BAOverlayedInjectable-Private.h @@ -6,7 +6,7 @@ // #import -@interface BAOverlayedInjectable() +@interface BAOverlayedInjectable () - (nonnull instancetype)initWithCallback:(nonnull BAOverlayedInjectableCallback)callback; diff --git a/Sources/Batch/Kernel/Foundation/BADateProviderProtocol.h b/Sources/Batch/Kernel/Foundation/BADateProviderProtocol.h index c71c6e3..3f23df1 100644 --- a/Sources/Batch/Kernel/Foundation/BADateProviderProtocol.h +++ b/Sources/Batch/Kernel/Foundation/BADateProviderProtocol.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN */ @protocol BADateProviderProtocol -- (NSDate*)currentDate; +- (NSDate *)currentDate; @end diff --git a/Sources/Batch/Kernel/Foundation/BAMultiDelegatesProxy.h b/Sources/Batch/Kernel/Foundation/BAMultiDelegatesProxy.h old mode 100755 new mode 100644 index 34526e2..c5a29d8 --- a/Sources/Batch/Kernel/Foundation/BAMultiDelegatesProxy.h +++ b/Sources/Batch/Kernel/Foundation/BAMultiDelegatesProxy.h @@ -24,7 +24,8 @@ /*! @property mainDelegate @abstract Original delegate. - @discussion Main delegate is like any other delegate but it's used to get the value for method which need something to return. + @discussion Main delegate is like any other delegate but it's used to get the value for method which need something to + return. */ @property (nonatomic, strong, readonly) id mainDelegate; diff --git a/Sources/Batch/Kernel/Foundation/BAMutableDateProvider.h b/Sources/Batch/Kernel/Foundation/BAMutableDateProvider.h index bfd0515..34ed7fc 100644 --- a/Sources/Batch/Kernel/Foundation/BAMutableDateProvider.h +++ b/Sources/Batch/Kernel/Foundation/BAMutableDateProvider.h @@ -4,8 +4,8 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/Batch/Kernel/Foundation/BASystemDateProvider.h b/Sources/Batch/Kernel/Foundation/BASystemDateProvider.h index 432f5d4..2a8d54d 100644 --- a/Sources/Batch/Kernel/Foundation/BASystemDateProvider.h +++ b/Sources/Batch/Kernel/Foundation/BASystemDateProvider.h @@ -5,8 +5,8 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import +#import @interface BASystemDateProvider : NSObject diff --git a/Sources/Batch/Kernel/Foundation/BATZAwareDate.h b/Sources/Batch/Kernel/Foundation/BATZAwareDate.h index 9d2a1f9..81939fd 100644 --- a/Sources/Batch/Kernel/Foundation/BATZAwareDate.h +++ b/Sources/Batch/Kernel/Foundation/BATZAwareDate.h @@ -9,13 +9,13 @@ NS_ASSUME_NONNULL_BEGIN /** BATZAwareDate is a helper date class used to understand timezone aware dates. - + Dates can be communicated using timestamps, making them much cheaper to parse than string based date formats, but allows the offsetting of the underlying UTC timestamp to match a local time. - + If you give this date a NSDate representing "2017-02-03 08:00 UTC", and set "relativeToUserTZ" to YES, it will offset the UTC date so that it becomes "2017-02-03 08:00" in the local timezone. - + For example, if the current timezone is "UTC+2", "2017-02-03 08:00 UTC" would be offsetted to become "2017-02-03 06:00". */ @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN */ + (instancetype)date; -+ (instancetype)dateWithDate:(NSDate*)date relativeToUserTZ:(BOOL)useLocalTZ; ++ (instancetype)dateWithDate:(NSDate *)date relativeToUserTZ:(BOOL)useLocalTZ; /** Returns a timestamp according to the "relativeToUserTZ" parameter and the current timezone, @@ -35,11 +35,11 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSTimeInterval)offsettedTimeIntervalSince1970; -- (BOOL)isAfter:(BATZAwareDate*)date; +- (BOOL)isAfter:(BATZAwareDate *)date; -- (BOOL)isBefore:(BATZAwareDate*)date; +- (BOOL)isBefore:(BATZAwareDate *)date; -- (BOOL)isEqualToDate:(BATZAwareDate*)date; +- (BOOL)isEqualToDate:(BATZAwareDate *)date; @end diff --git a/Sources/Batch/Kernel/GZip/BATGZIP.h b/Sources/Batch/Kernel/GZip/BATGZIP.h index 41bbb00..04ca90b 100644 --- a/Sources/Batch/Kernel/GZip/BATGZIP.h +++ b/Sources/Batch/Kernel/GZip/BATGZIP.h @@ -7,8 +7,7 @@ #import - -@interface BATGZIP: NSObject +@interface BATGZIP : NSObject // Gzip data. If the data is already Gzipped, this returns the original data + (nullable NSData *)dataByGzipping:(nullable NSData *)data; diff --git a/Sources/Batch/Kernel/GZip/BATGZIP.m b/Sources/Batch/Kernel/GZip/BATGZIP.m index fe2a57e..9f8f32a 100644 --- a/Sources/Batch/Kernel/GZip/BATGZIP.m +++ b/Sources/Batch/Kernel/GZip/BATGZIP.m @@ -48,8 +48,13 @@ + (nullable NSData *)dataByGzipping:(nullable NSData *)data { zstream.next_out = outputBuffer; result = deflate(&zstream, Z_FINISH); if (result != Z_OK && result != Z_STREAM_END) { - [BALogger debugForDomain:LOCAL_DEBUG_DOMAIN - message:@"Gzip error: deflating didn't return Z_OK | Z_STREAM_END, bailing."]; + // See decompression for more info about what we do with Z_BUF_ERROR + if (result != Z_BUF_ERROR || zstream.avail_out != 0) { + [BALogger + debugForDomain:LOCAL_DEBUG_DOMAIN + message:@"Gzip error: deflating didn't return Z_OK | Z_STREAM_END | Z_BUF_ERROR, bailing."]; + return nil; + } } // avail_out is the number of bytes that zlib didn't use in the buffer [outputData appendBytes:outputBuffer length:CHUNK_SIZE - zstream.avail_out]; @@ -97,8 +102,15 @@ + (nullable NSData *)dataByGunzipping:(nullable NSData *)data { zstream.next_out = outputBuffer; result = inflate(&zstream, Z_FINISH); if (result != Z_OK && result != Z_STREAM_END) { - [BALogger debugForDomain:LOCAL_DEBUG_DOMAIN - message:@"Gzip error: inflating didn't return Z_OK | Z_STREAM_END, bailing."]; + // Z_BUF_ERROR means that zlib couln't find anything to inflate, but that doesn't mean that we have + // to stop, as compressed data might be found down the road. If avail_out was 0 we can continue as it means + // that zlib is progressing. Condition is an inverted (result == Z_BUF_ERROR && avail_out == 0) + if (result != Z_BUF_ERROR || zstream.avail_out != 0) { + [BALogger + debugForDomain:LOCAL_DEBUG_DOMAIN + message:@"Gzip error: inflating didn't return Z_OK | Z_STREAM_END | Z_BUF_ERROR, bailing."]; + return nil; + } } // avail_out is the number of bytes that zlib didn't use in the buffer [outputData appendBytes:outputBuffer length:CHUNK_SIZE - zstream.avail_out]; diff --git a/Sources/Batch/Kernel/Helpers/BADelegatedApplicationDelegate.h b/Sources/Batch/Kernel/Helpers/BADelegatedApplicationDelegate.h index 8f6f2b4..694e5d9 100644 --- a/Sources/Batch/Kernel/Helpers/BADelegatedApplicationDelegate.h +++ b/Sources/Batch/Kernel/Helpers/BADelegatedApplicationDelegate.h @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN /// Class that gets swizzled in place of the UIApplication delegate and forwards the methods to another delegate /// before calling the original implementation -@interface BADelegatedApplicationDelegate: NSObject +@interface BADelegatedApplicationDelegate : NSObject /// Whether this instance has already swizzled the delegate @property (readonly) BOOL didSwizzle; @@ -37,7 +37,8 @@ NS_ASSUME_NONNULL_BEGIN /*! @method swizzleAppDelegate: - @abstract Swizzle the current [UIApplication sharedApplication].delegate class. Note that calling this method multiple times is an error. Make sure to set a `batchDelegate` on this object to be informed of the calls. + @abstract Swizzle the current [UIApplication sharedApplication].delegate class. Note that calling this method multiple + times is an error. Make sure to set a `batchDelegate` on this object to be informed of the calls. @return Whether the operation succeeded */ - (BOOL)swizzleAppDelegate; diff --git a/Sources/Batch/Kernel/Helpers/BADirectories.h b/Sources/Batch/Kernel/Helpers/BADirectories.h index 42d9fec..699208a 100644 --- a/Sources/Batch/Kernel/Helpers/BADirectories.h +++ b/Sources/Batch/Kernel/Helpers/BADirectories.h @@ -52,13 +52,11 @@ */ + (NSString *)pathForAppCacheDirectory; - /*! @method pathForAppCacheDirectory @abstract The method to get the path to the shared directory with group name. @return The path to the shared directory */ -+ (NSURL *)pathForAppSharedDirectoryWithGroup:(NSString*)group; - ++ (NSURL *)pathForAppSharedDirectoryWithGroup:(NSString *)group; @end diff --git a/Sources/Batch/Kernel/Helpers/BAEmailUtils.h b/Sources/Batch/Kernel/Helpers/BAEmailUtils.h new file mode 100644 index 0000000..7a34aa8 --- /dev/null +++ b/Sources/Batch/Kernel/Helpers/BAEmailUtils.h @@ -0,0 +1,24 @@ +// +// Batch +// +// Copyright © Batch.com. All rights reserved. +// + +#import + +/// Email max length +#define EMAIL_MAX_LENGTH 128 + +NS_ASSUME_NONNULL_BEGIN + +@interface BAEmailUtils : NSObject + +/// Check wether email is valid ++ (BOOL)isValidEmail:(nonnull NSString *)email; + +/// Check wether email is too long ++ (BOOL)isEmailTooLong:(nonnull NSString *)email; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Kernel/Helpers/BAEmailUtils.m b/Sources/Batch/Kernel/Helpers/BAEmailUtils.m new file mode 100644 index 0000000..6e14b34 --- /dev/null +++ b/Sources/Batch/Kernel/Helpers/BAEmailUtils.m @@ -0,0 +1,28 @@ +// +// Batch +// +// Copyright © Batch.com. All rights reserved. +// + +#import "BAEmailUtils.h" + +/// Email regexp +#define EMAIL_VALUE_RULE @"^(\\S+@\\S+\\.\\S+)$" + +@implementation BAEmailUtils + ++ (BOOL)isValidEmail:(nonnull NSString *)email { + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:EMAIL_VALUE_RULE + options:0 + error:nil]; + NSRange matchingRange = [regex rangeOfFirstMatchInString:email options:0 range:NSMakeRange(0, email.length)]; + if (matchingRange.location == NSNotFound) { + return false; + } + return true; +} + ++ (BOOL)isEmailTooLong:(NSString *)email { + return [email length] > EMAIL_MAX_LENGTH; +} +@end diff --git a/Sources/Batch/Kernel/Helpers/BAHTTPHeaders.h b/Sources/Batch/Kernel/Helpers/BAHTTPHeaders.h index 86c25a3..8073b18 100644 --- a/Sources/Batch/Kernel/Helpers/BAHTTPHeaders.h +++ b/Sources/Batch/Kernel/Helpers/BAHTTPHeaders.h @@ -15,13 +15,13 @@ @abstract Generate a custom user agent from application an mobile infos. @return Formated string description of the user agent. */ -+ (NSString*)userAgent; ++ (NSString *)userAgent; /*! @method acceptLanguage @abstract Generate a custom accect language from device locale. @return Formated string. */ -+ (NSString*)acceptLanguage; ++ (NSString *)acceptLanguage; @end diff --git a/Sources/Batch/Kernel/Helpers/BAJson.h b/Sources/Batch/Kernel/Helpers/BAJson.h index 362f1a0..3ac9347 100644 --- a/Sources/Batch/Kernel/Helpers/BAJson.h +++ b/Sources/Batch/Kernel/Helpers/BAJson.h @@ -16,43 +16,42 @@ NS_ASSUME_NONNULL_BEGIN /** Serialize a Foundation object into a NSString. */ -+ (nullable NSString*)serialize:(nonnull id)object error:(NSError**)error; ++ (nullable NSString *)serialize:(nonnull id)object error:(NSError **)error; /** Serialize a Foundation object into a NSData. */ -+ (nullable NSData*)serializeData:(nonnull id)object error:(NSError**)error; ++ (nullable NSData *)serializeData:(nonnull id)object error:(NSError **)error; /** Deserialize a JSON NSString into a Foundation object. */ -+ (nullable id)deserialize:(nonnull NSString*)json error:(NSError**)error; ++ (nullable id)deserialize:(nonnull NSString *)json error:(NSError **)error; /** Deserialize a JSON NSString into a NSArray. */ -+ (nullable NSArray*)deserializeAsArray:(nonnull NSString*)json error:(NSError**)error; ++ (nullable NSArray *)deserializeAsArray:(nonnull NSString *)json error:(NSError **)error; /** Deserialize a JSON NSString into a NSDictionary. */ -+ (nullable NSDictionary*)deserializeAsDictionary:(nonnull NSString*)json error:(NSError**)error; ++ (nullable NSDictionary *)deserializeAsDictionary:(nonnull NSString *)json error:(NSError **)error; /** Deserialize a JSON NSData into a Foundation object. */ -+ (nullable id)deserializeData:(nonnull NSData*)jsonData error:(NSError**)error; ++ (nullable id)deserializeData:(nonnull NSData *)jsonData error:(NSError **)error; /** Deserialize a JSON NSData into a NSArray. */ -+ (nullable NSArray*)deserializeDataAsArray:(nonnull NSData*)jsonData error:(NSError**)error; ++ (nullable NSArray *)deserializeDataAsArray:(nonnull NSData *)jsonData error:(NSError **)error; /** Deserialize a JSON NSData into a NSDictionary. */ -+ (nullable NSDictionary*)deserializeDataAsDictionary:(nonnull NSData*)jsonData error:(NSError**)error; - ++ (nullable NSDictionary *)deserializeDataAsDictionary:(nonnull NSData *)jsonData error:(NSError **)error; @end diff --git a/Sources/Batch/Kernel/Helpers/BAOSHelper.h b/Sources/Batch/Kernel/Helpers/BAOSHelper.h index d3df0e9..4f6ea4e 100644 --- a/Sources/Batch/Kernel/Helpers/BAOSHelper.h +++ b/Sources/Batch/Kernel/Helpers/BAOSHelper.h @@ -21,6 +21,6 @@ /// Format is XXXYYYZZZ, where XXX is major, YYY minor, ZZZ patch. /// @param outVersion NSOperatingSystemVersion to write to. Must not be NULL or the method will return false. /// @return true on success, false on failure. outVersion will only be written to on success. -+ (BOOL)parseIntegerSystemVersion:(NSInteger)intSystemVersion out:(NSOperatingSystemVersion* _Nonnull)outVersion; ++ (BOOL)parseIntegerSystemVersion:(NSInteger)intSystemVersion out:(NSOperatingSystemVersion *_Nonnull)outVersion; @end diff --git a/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h b/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h index fe5c1a1..32859ce 100644 --- a/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h +++ b/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h @@ -20,18 +20,28 @@ NS_ASSUME_NONNULL_BEGIN - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo; -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler; +- (void)application:(UIApplication *)application + didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_AVAILABLE_IOS(8_0); +- (void)application:(UIApplication *)application + didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_AVAILABLE_IOS(8_0); #pragma clang diagnostic pop -- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)(void))completionHandler; +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(nullable NSString *)identifier + forRemoteNotification:(NSDictionary *)userInfo + completionHandler:(void (^)(void))completionHandler; -- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)(void))completionHandler; +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(nullable NSString *)identifier + forRemoteNotification:(NSDictionary *)userInfo + withResponseInfo:(NSDictionary *)responseInfo + completionHandler:(void (^)(void))completionHandler; @end diff --git a/Sources/Batch/Kernel/Helpers/BAStringUtils.h b/Sources/Batch/Kernel/Helpers/BAStringUtils.h index ee5b09d..653a9eb 100644 --- a/Sources/Batch/Kernel/Helpers/BAStringUtils.h +++ b/Sources/Batch/Kernel/Helpers/BAStringUtils.h @@ -15,6 +15,6 @@ @abstract Generate the hexadeciaml value of the data. @return Hexadecimal string. */ -+ (NSString *)hexStringValueForData:(NSData*)data; ++ (nonnull NSString *)hexStringValueForData:(nonnull NSData *)data; @end diff --git a/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h b/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h index c5713d9..13192de 100644 --- a/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h +++ b/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h @@ -14,29 +14,31 @@ NS_ASSUME_NONNULL_BEGIN */ @interface BATJsonDictionary : NSObject -- (instancetype)initWithDictionary:(NSDictionary*)dict errorDomain:(NSErrorDomain)errorDomain; +- (instancetype)initWithDictionary:(NSDictionary *)dict errorDomain:(NSErrorDomain)errorDomain; /** Get an object for the given key, check if it an instance of the wanted class and return it as is if it does. If an error occurs, the return value will be 'nil'. - If you allow a key to be nil/nonexistent, you'll have to check the error pointer to see if the value really was null or of the wrong kind. - + If you allow a key to be nil/nonexistent, you'll have to check the error pointer to see if the value really was null or + of the wrong kind. + NSNull values will be returned as nil. */ -- (nullable id)objectForKey:(NSString*)key kindOfClass:(Class)class allowNil:(BOOL)allowNil error:(NSError**)error; +- (nullable id)objectForKey:(NSString *)key kindOfClass:(Class)class allowNil:(BOOL)allowNil error:(NSError **)error; /** Get an object for the given key, check if it an instance of the wanted class and return it as is if it does. If an error occurs, or if the value is nil/nonexistent/[NSNull null], the return value will be the fallback. - + */ -- (nullable id)objectForKey:(NSString*)key kindOfClass:(Class)class fallback:(nullable id)fallback; +- (nullable id)objectForKey:(NSString *)key kindOfClass:(Class)class fallback:(nullable id)fallback; /** Writes the specified error in the error pointer, and return nil. - While this may sound a little stupid, it allows for one line error bailing, rather than copy pasting the same tedious 3 lines + While this may sound a little stupid, it allows for one line error bailing, rather than copy pasting the same tedious 3 + lines */ -- (nullable id)writeErrorAndReturnNil:(NSError*)error toErrorPointer:(NSError**)outErr; +- (nullable id)writeErrorAndReturnNil:(NSError *)error toErrorPointer:(NSError **)outErr; /** String prefix to prepend to the error localized descriptions. diff --git a/Sources/Batch/Kernel/Helpers/BAWindowHelper.h b/Sources/Batch/Kernel/Helpers/BAWindowHelper.h index fe3c6db..8a2d673 100644 --- a/Sources/Batch/Kernel/Helpers/BAWindowHelper.h +++ b/Sources/Batch/Kernel/Helpers/BAWindowHelper.h @@ -11,11 +11,13 @@ NS_ASSUME_NONNULL_BEGIN @interface BAWindowHelper : NSObject -+ (nullable UIWindowScene*)activeScene NS_AVAILABLE_IOS(13.0); ++ (nullable UIWindowScene *)activeScene NS_AVAILABLE_IOS(13.0); -+ (nullable UIWindowScene*)activeWindowScene NS_AVAILABLE_IOS(13.0); ++ (nullable UIWindowScene *)activeWindowScene NS_AVAILABLE_IOS(13.0); -+ (nullable UIWindow*)keyWindow; ++ (nullable UIWindow *)keyWindow; + ++ (nullable UIViewController *)frontmostViewController; @end diff --git a/Sources/Batch/Kernel/Helpers/BAWindowHelper.m b/Sources/Batch/Kernel/Helpers/BAWindowHelper.m index 07aa58f..6beef3a 100644 --- a/Sources/Batch/Kernel/Helpers/BAWindowHelper.m +++ b/Sources/Batch/Kernel/Helpers/BAWindowHelper.m @@ -55,4 +55,13 @@ + (nullable UIWindow *)keyWindowFromSceneAPI NS_AVAILABLE_IOS(13.0) { return nil; } ++ (UIViewController *)frontmostViewController { + UIWindow *overlayedWindow = [BAWindowHelper keyWindow]; + UIViewController *presentedVC = overlayedWindow.rootViewController; + while (presentedVC.presentedViewController) { + presentedVC = presentedVC.presentedViewController; + } + return presentedVC; +} + @end diff --git a/Sources/Batch/Kernel/Logger/BALogger.h b/Sources/Batch/Kernel/Logger/BALogger.h index 10fd719..ad81272 100644 --- a/Sources/Batch/Kernel/Logger/BALogger.h +++ b/Sources/Batch/Kernel/Logger/BALogger.h @@ -6,8 +6,8 @@ // Copyright (c) 2014 Batch SDK. All rights reserved. // -#import #import +#import #pragma mark - #pragma mark BALoggerLevel @@ -17,21 +17,19 @@ @abstract Log level. @discussion Types that will be used to log. */ -enum -{ - BALoggerLevelNone = 1 << 0, - BALoggerLevelPublic = 1 << 1, - BALoggerLevelError = 1 << 2, - BALoggerLevelWarning = 1 << 3, - BALoggerLevelDebug = 1 << 4, - BALoggerLevelAll = BALoggerLevelPublic | BALoggerLevelError | BALoggerLevelWarning | BALoggerLevelDebug +enum { + BALoggerLevelNone = 1 << 0, + BALoggerLevelPublic = 1 << 1, + BALoggerLevelError = 1 << 2, + BALoggerLevelWarning = 1 << 3, + BALoggerLevelDebug = 1 << 4, + BALoggerLevelAll = BALoggerLevelPublic | BALoggerLevelError | BALoggerLevelWarning | BALoggerLevelDebug }; /*! @typedef BALoggerLevel */ typedef NSUInteger BALoggerLevel; - #pragma mark - #pragma mark BALogger @@ -62,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN @param formatstring : Formated string and it's optional arguments. @param ... : Formated string parameters. */ -+ (void)publicForDomain:(nullable NSString *)name message:(NSString *)formatstring,... NS_FORMAT_FUNCTION(2,3); ++ (void)publicForDomain:(nullable NSString *)name message:(NSString *)formatstring, ... NS_FORMAT_FUNCTION(2, 3); /*! @method errorForDomain:message:… @@ -71,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN @param formatstring : Formated string and it's optional arguments. @param ... : Formated string parameters. */ -+ (void)errorForDomain:(nullable NSString *)name message:(NSString *)formatstring,... NS_FORMAT_FUNCTION(2,3); ++ (void)errorForDomain:(nullable NSString *)name message:(NSString *)formatstring, ... NS_FORMAT_FUNCTION(2, 3); /*! @method warningForDomain:message:… @@ -80,7 +78,7 @@ NS_ASSUME_NONNULL_BEGIN @param formatstring : Formated string and it's optional arguments. @param ... : Formated string parameters. */ -+ (void)warningForDomain:(nullable NSString *)name message:(NSString *)formatstring,... NS_FORMAT_FUNCTION(2,3); ++ (void)warningForDomain:(nullable NSString *)name message:(NSString *)formatstring, ... NS_FORMAT_FUNCTION(2, 3); /*! @method debugForDomain:message:… @@ -89,24 +87,28 @@ NS_ASSUME_NONNULL_BEGIN @param formatstring : Formated string and it's optional arguments. @param ... : Formated string parameters. */ -+ (void)debugForDomain:(nullable NSString *)name message:(NSString *)formatstring,... NS_FORMAT_FUNCTION(2,3); ++ (void)debugForDomain:(nullable NSString *)name message:(NSString *)formatstring, ... NS_FORMAT_FUNCTION(2, 3); /** delegateSource is weak-referenced, make sure you hold a strong reference to it. */ -+ (void)setLoggerDelegateSource:(id _Nullable)delegateSource; ++ (void)setLoggerDelegateSource:(id _Nullable)delegateSource; #pragma mark - Swift only methods /// See publicForDomain:message: -+ (void)__SWIFT_publicForDomain:(nullable NSString *)domain message:(NSString *)message NS_SWIFT_NAME(public(domain:message:)); ++ (void)__SWIFT_publicForDomain:(nullable NSString *)domain + message:(NSString *)message NS_SWIFT_NAME(public(domain:message:)); /// See errorForDomain:message: -+ (void)__SWIFT_errorForDomain:(nullable NSString *)domain message:(NSString *)message NS_SWIFT_NAME(error(domain:message:)); ++ (void)__SWIFT_errorForDomain:(nullable NSString *)domain + message:(NSString *)message NS_SWIFT_NAME(error(domain:message:)); /// See warningForDomain:message: -+ (void)__SWIFT_warningForDomain:(nullable NSString *)domain message:(NSString *)message NS_SWIFT_NAME(warning(domain:message:)); ++ (void)__SWIFT_warningForDomain:(nullable NSString *)domain + message:(NSString *)message NS_SWIFT_NAME(warning(domain:message:)); /// See debugForDomain:message: -+ (void)__SWIFT_debugForDomain:(nullable NSString *)domain message:(NSString *)message NS_SWIFT_NAME(debug(domain:message:)); ++ (void)__SWIFT_debugForDomain:(nullable NSString *)domain + message:(NSString *)message NS_SWIFT_NAME(debug(domain:message:)); @end diff --git a/Sources/Batch/Kernel/Logger/BALoggerProtocol.h b/Sources/Batch/Kernel/Logger/BALoggerProtocol.h index 595c71b..470342b 100644 --- a/Sources/Batch/Kernel/Logger/BALoggerProtocol.h +++ b/Sources/Batch/Kernel/Logger/BALoggerProtocol.h @@ -1,5 +1,5 @@ -#import #import +#import @protocol BALoggerProtocol @@ -9,6 +9,6 @@ @protocol BALoggerDelegateSource -@property (nonatomic, readonly) id loggerDelegate; +@property (nonatomic, readonly) id loggerDelegate; @end diff --git a/Sources/Batch/Kernel/Logger/BALoggerUnified.h b/Sources/Batch/Kernel/Logger/BALoggerUnified.h index a60f137..53262ee 100644 --- a/Sources/Batch/Kernel/Logger/BALoggerUnified.h +++ b/Sources/Batch/Kernel/Logger/BALoggerUnified.h @@ -1,5 +1,5 @@ -#import #import +#import @interface BALoggerUnified : NSObject diff --git a/Sources/Batch/Kernel/MessagePack/BATMessagePackReader.h b/Sources/Batch/Kernel/MessagePack/BATMessagePackReader.h index 0f6482e..86da79e 100644 --- a/Sources/Batch/Kernel/MessagePack/BATMessagePackReader.h +++ b/Sources/Batch/Kernel/MessagePack/BATMessagePackReader.h @@ -16,19 +16,19 @@ typedef enum : NSInteger { /// Initialize a MessagePack reader with raw data. /// @param data MessagePack data -- (nonnull instancetype)initWithData:(nonnull NSData*)data; +- (nonnull instancetype)initWithData:(nonnull NSData *)data; /// Read nil. /// @param error If an errors occurs, will contain the error. /// @returns wherther nil has been successfully read or not. -- (BOOL)readNilWithError:(NSError * _Nullable * _Nullable)error; +- (BOOL)readNilWithError:(NSError *_Nullable *_Nullable)error; /// Read a Bool. /// @param error If an errors occurs, will contain the error. /// @param allowNil whether a nil value is allowed /// @returns the value. If you set allowNil to true, you will need to /// read the error pointer to distinguish a genuine error from an expected nil value. -- (nullable NSNumber*)readBoolAllowingNil:(BOOL)allowNil error:(NSError * _Nullable * _Nullable)error; +- (nullable NSNumber *)readBoolAllowingNil:(BOOL)allowNil error:(NSError *_Nullable *_Nullable)error; /// Read an Integer. /// This method will read any signed or unsigned integer. @@ -36,7 +36,7 @@ typedef enum : NSInteger { /// @param allowNil whether a nil value is allowed /// @returns the value. If you set allowNil to true, you will need to /// read the error pointer to distinguish a genuine error from an expected nil value. -- (nullable NSNumber*)readIntegerAllowingNil:(BOOL)allowNil error:(NSError * _Nullable * _Nullable)error; +- (nullable NSNumber *)readIntegerAllowingNil:(BOOL)allowNil error:(NSError *_Nullable *_Nullable)error; /// Read a decimal. /// This method will read floats and doubles. @@ -44,21 +44,21 @@ typedef enum : NSInteger { /// @param allowNil whether a nil value is allowed /// @returns the value. If you set allowNil to true, you will need to /// read the error pointer to distinguish a genuine error from an expected nil value. -- (nullable NSNumber*)readDecimalAllowingNil:(BOOL)allowNil error:(NSError * _Nullable * _Nullable)error; +- (nullable NSNumber *)readDecimalAllowingNil:(BOOL)allowNil error:(NSError *_Nullable *_Nullable)error; /// Read a String. /// @param error If an errors occurs, will contain the error. /// @param allowNil whether a nil value is allowed /// @returns the value or nil if an error occurred. If you set allowNil to true, you will need to /// read the error pointer to distinguish a genuine error from an expected nil value. -- (nullable NSString*)readStringAllowingNil:(BOOL)allowNil error:(NSError * _Nullable * _Nullable)error; +- (nullable NSString *)readStringAllowingNil:(BOOL)allowNil error:(NSError *_Nullable *_Nullable)error; /// Read raw Data. /// @param error If an errors occurs, will contain the error. /// @param allowNil whether a nil value is allowed /// @returns the value or nil if an error occurred. If you set allowNil to true, you will need to /// read the error pointer to distinguish a genuine error from an expected nil value. -- (nullable NSData*)readDataAllowingNil:(BOOL)allowNil error:(NSError * _Nullable * _Nullable)error; +- (nullable NSData *)readDataAllowingNil:(BOOL)allowNil error:(NSError *_Nullable *_Nullable)error; /// Read a dictionary. /// The dictionary's keys can be of the following types: @@ -76,12 +76,13 @@ typedef enum : NSInteger { /// @param allowNil whether a nil value is allowed /// @returns the value or nil if an error occurred. If you set allowNil to true, you will need to /// read the error pointer to distinguish a genuine error from an expected nil value. -- (nullable NSDictionary*)readDictionaryAllowingNil:(BOOL)allowNil error:(NSError * _Nullable * _Nullable)error;; +- (nullable NSDictionary *)readDictionaryAllowingNil:(BOOL)allowNil error:(NSError *_Nullable *_Nullable)error; +; /// Read a dictionary header. /// @param error If an errors occurs, will contain the error. /// @returns the value or nil if an error occurred. -- (nullable NSNumber*)readDictionaryHeaderWithError:(NSError * _Nullable * _Nullable)error; +- (nullable NSNumber *)readDictionaryHeaderWithError:(NSError *_Nullable *_Nullable)error; /// Read an array. /// The array's objects can be of the following types: @@ -95,12 +96,12 @@ typedef enum : NSInteger { /// @param allowNil whether a nil value is allowed /// @returns the value or nil if an error occurred. If you set allowNil to true, you will need to /// read the error pointer to distinguish a genuine error from an expected nil value. -- (nullable NSArray*)readArrayAllowingNil:(BOOL)allowNil error:(NSError * _Nullable * _Nullable)error; +- (nullable NSArray *)readArrayAllowingNil:(BOOL)allowNil error:(NSError *_Nullable *_Nullable)error; /// Read an array header. /// @param error If an errors occurs, will contain the error. /// @returns the value or nil if an error occurred. -- (nullable NSNumber*)readArrayHeaderWithError:(NSError * _Nullable * _Nullable)error; +- (nullable NSNumber *)readArrayHeaderWithError:(NSError *_Nullable *_Nullable)error; /// Read any value. /// The result can be of the following types: @@ -112,6 +113,6 @@ typedef enum : NSInteger { /// NSDictionary /// @param error If an errors occurs, will contain the error. /// @returns the value or nil if an error occurred. Nil MessagePack values are represented as NSNull. -- (nullable id)readAnyWithError:(NSError * _Nullable * _Nullable)error; +- (nullable id)readAnyWithError:(NSError *_Nullable *_Nullable)error; @end diff --git a/Sources/Batch/Kernel/MessagePack/BATMessagePackWriter.h b/Sources/Batch/Kernel/MessagePack/BATMessagePackWriter.h index f413500..10b69ad 100644 --- a/Sources/Batch/Kernel/MessagePack/BATMessagePackWriter.h +++ b/Sources/Batch/Kernel/MessagePack/BATMessagePackWriter.h @@ -21,7 +21,7 @@ typedef enum : NSInteger { /// NSData /// NSArray /// NSDictionary -+ (BOOL)canPackArray:(nullable NSArray*)array; ++ (BOOL)canPackArray:(nullable NSArray *)array; /// Returns whether a dictionary is packable or not. /// The keys should conform to NSCopying, but only the following types are supported: @@ -35,7 +35,7 @@ typedef enum : NSInteger { /// NSData /// NSArray /// NSDictionary -+ (BOOL)canPackDictionary:(nullable NSDictionary, id>*)dictionary; ++ (BOOL)canPackDictionary:(nullable NSDictionary, id> *)dictionary; /// Write nil. - (void)writeNil; @@ -72,27 +72,27 @@ typedef enum : NSInteger { /// Write a number or nil. /// @param number number to pack -- (BOOL)writeNumber:(nullable NSNumber*)number error:(NSError * _Nullable * _Nullable)error; +- (BOOL)writeNumber:(nullable NSNumber *)number error:(NSError *_Nullable *_Nullable)error; /// Write an array length header. /// This method takes an NSUInteger for convinence, as it is /// [NSArray count]'s type, but MessagePack arrays cannot store /// more than UINT32_MAX elements. /// @param size size of the array. Must not be greater than UINT32_MAX -- (BOOL)writeArraySize:(NSUInteger)size error:(NSError * _Nullable * _Nullable)error; +- (BOOL)writeArraySize:(NSUInteger)size error:(NSError *_Nullable *_Nullable)error; /// Write an NSArray or nil. /// Note that not all kind of values can be packed. Call +(BOOL)canPackArray:(NSArray*)array /// if you want to know beforehand. /// @param array array to write -- (BOOL)writeArray:(nullable NSArray*)array error:(NSError * _Nullable * _Nullable)error; +- (BOOL)writeArray:(nullable NSArray *)array error:(NSError *_Nullable *_Nullable)error; /// Write a dictionary (map) size header. /// A map's size is the number of key/value pairs. /// This method takes an NSUInteger for convinence, but MessagePack arrays cannot store /// more than UINT32_MAX tuples. /// @param size length of the map. Must not be greater than UINT32_MAX -- (BOOL)writeDictionarySize:(NSUInteger)size error:(NSError * _Nullable * _Nullable)error; +- (BOOL)writeDictionarySize:(NSUInteger)size error:(NSError *_Nullable *_Nullable)error; /// Write an NSDictionary or nil. /// Note that not all kind of values can be packed. Call +(BOOL)canPackDictionary:(NSDictionary*)dictionary @@ -102,16 +102,17 @@ typedef enum : NSInteger { /// NSNumber (for bools, integers and decimals) /// NSString /// @param dictionary dictionary to write -- (BOOL)writeDictionary:(nullable NSDictionary, id>*)dictionary error:(NSError * _Nullable * _Nullable)error; +- (BOOL)writeDictionary:(nullable NSDictionary, id> *)dictionary + error:(NSError *_Nullable *_Nullable)error; /// Write a NSData or nil. -- (BOOL)writeData:(nullable NSData*)data error:(NSError * _Nullable * _Nullable)error; +- (BOOL)writeData:(nullable NSData *)data error:(NSError *_Nullable *_Nullable)error; /// Write a String or nil. -- (BOOL)writeString:(nullable NSString*)string error:(NSError * _Nullable * _Nullable)error; +- (BOOL)writeString:(nullable NSString *)string error:(NSError *_Nullable *_Nullable)error; /// The MessagePack data. Makes a copy on read, so you may want to cache this instead of repeatedly accessing it. -@property (nonnull, readonly) NSData* data; +@property (nonnull, readonly) NSData *data; @end diff --git a/Sources/Batch/Kernel/MessagePack/msgpack-c.h b/Sources/Batch/Kernel/MessagePack/msgpack-c.h index f5f33eb..ab0e6ae 100644 --- a/Sources/Batch/Kernel/MessagePack/msgpack-c.h +++ b/Sources/Batch/Kernel/MessagePack/msgpack-c.h @@ -27,47 +27,46 @@ THE SOFTWARE. struct bat_cmp_ctx_s; -typedef bool (*bat_cmp_reader)(struct bat_cmp_ctx_s *ctx, void *data, size_t limit); -typedef bool (*bat_cmp_skipper)(struct bat_cmp_ctx_s *ctx, size_t count); -typedef size_t (*bat_cmp_writer)(struct bat_cmp_ctx_s *ctx, const void *data, - size_t count); +typedef bool (*bat_cmp_reader)(struct bat_cmp_ctx_s *ctx, void *data, size_t limit); +typedef bool (*bat_cmp_skipper)(struct bat_cmp_ctx_s *ctx, size_t count); +typedef size_t (*bat_cmp_writer)(struct bat_cmp_ctx_s *ctx, const void *data, size_t count); enum { - BAT_CMP_TYPE_POSITIVE_FIXNUM, /* 0 */ - BAT_CMP_TYPE_FIXMAP, /* 1 */ - BAT_CMP_TYPE_FIXARRAY, /* 2 */ - BAT_CMP_TYPE_FIXSTR, /* 3 */ - BAT_CMP_TYPE_NIL, /* 4 */ - BAT_CMP_TYPE_BOOLEAN, /* 5 */ - BAT_CMP_TYPE_BIN8, /* 6 */ - BAT_CMP_TYPE_BIN16, /* 7 */ - BAT_CMP_TYPE_BIN32, /* 8 */ - BAT_CMP_TYPE_EXT8, /* 9 */ - BAT_CMP_TYPE_EXT16, /* 10 */ - BAT_CMP_TYPE_EXT32, /* 11 */ - BAT_CMP_TYPE_FLOAT, /* 12 */ - BAT_CMP_TYPE_DOUBLE, /* 13 */ - BAT_CMP_TYPE_UINT8, /* 14 */ - BAT_CMP_TYPE_UINT16, /* 15 */ - BAT_CMP_TYPE_UINT32, /* 16 */ - BAT_CMP_TYPE_UINT64, /* 17 */ - BAT_CMP_TYPE_SINT8, /* 18 */ - BAT_CMP_TYPE_SINT16, /* 19 */ - BAT_CMP_TYPE_SINT32, /* 20 */ - BAT_CMP_TYPE_SINT64, /* 21 */ - BAT_CMP_TYPE_FIXEXT1, /* 22 */ - BAT_CMP_TYPE_FIXEXT2, /* 23 */ - BAT_CMP_TYPE_FIXEXT4, /* 24 */ - BAT_CMP_TYPE_FIXEXT8, /* 25 */ - BAT_CMP_TYPE_FIXEXT16, /* 26 */ - BAT_CMP_TYPE_STR8, /* 27 */ - BAT_CMP_TYPE_STR16, /* 28 */ - BAT_CMP_TYPE_STR32, /* 29 */ - BAT_CMP_TYPE_ARRAY16, /* 30 */ - BAT_CMP_TYPE_ARRAY32, /* 31 */ - BAT_CMP_TYPE_MAP16, /* 32 */ - BAT_CMP_TYPE_MAP32, /* 33 */ - BAT_CMP_TYPE_NEGATIVE_FIXNUM /* 34 */ + BAT_CMP_TYPE_POSITIVE_FIXNUM, /* 0 */ + BAT_CMP_TYPE_FIXMAP, /* 1 */ + BAT_CMP_TYPE_FIXARRAY, /* 2 */ + BAT_CMP_TYPE_FIXSTR, /* 3 */ + BAT_CMP_TYPE_NIL, /* 4 */ + BAT_CMP_TYPE_BOOLEAN, /* 5 */ + BAT_CMP_TYPE_BIN8, /* 6 */ + BAT_CMP_TYPE_BIN16, /* 7 */ + BAT_CMP_TYPE_BIN32, /* 8 */ + BAT_CMP_TYPE_EXT8, /* 9 */ + BAT_CMP_TYPE_EXT16, /* 10 */ + BAT_CMP_TYPE_EXT32, /* 11 */ + BAT_CMP_TYPE_FLOAT, /* 12 */ + BAT_CMP_TYPE_DOUBLE, /* 13 */ + BAT_CMP_TYPE_UINT8, /* 14 */ + BAT_CMP_TYPE_UINT16, /* 15 */ + BAT_CMP_TYPE_UINT32, /* 16 */ + BAT_CMP_TYPE_UINT64, /* 17 */ + BAT_CMP_TYPE_SINT8, /* 18 */ + BAT_CMP_TYPE_SINT16, /* 19 */ + BAT_CMP_TYPE_SINT32, /* 20 */ + BAT_CMP_TYPE_SINT64, /* 21 */ + BAT_CMP_TYPE_FIXEXT1, /* 22 */ + BAT_CMP_TYPE_FIXEXT2, /* 23 */ + BAT_CMP_TYPE_FIXEXT4, /* 24 */ + BAT_CMP_TYPE_FIXEXT8, /* 25 */ + BAT_CMP_TYPE_FIXEXT16, /* 26 */ + BAT_CMP_TYPE_STR8, /* 27 */ + BAT_CMP_TYPE_STR16, /* 28 */ + BAT_CMP_TYPE_STR32, /* 29 */ + BAT_CMP_TYPE_ARRAY16, /* 30 */ + BAT_CMP_TYPE_ARRAY32, /* 31 */ + BAT_CMP_TYPE_MAP16, /* 32 */ + BAT_CMP_TYPE_MAP32, /* 33 */ + BAT_CMP_TYPE_NEGATIVE_FIXNUM /* 34 */ }; enum { @@ -93,40 +92,40 @@ enum { }; typedef struct bat_cmp_ext_s { - int8_t type; - uint32_t size; + int8_t type; + uint32_t size; } bat_cmp_ext_t; union bat_cmp_object_data_u { - bool boolean; - uint8_t u8; - uint16_t u16; - uint32_t u32; - uint64_t u64; - int8_t s8; - int16_t s16; - int32_t s32; - int64_t s64; - float flt; - double dbl; - uint32_t array_size; - uint32_t map_size; - uint32_t str_size; - uint32_t bin_size; - bat_cmp_ext_t ext; + bool boolean; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + int8_t s8; + int16_t s16; + int32_t s32; + int64_t s64; + float flt; + double dbl; + uint32_t array_size; + uint32_t map_size; + uint32_t str_size; + uint32_t bin_size; + bat_cmp_ext_t ext; }; typedef struct bat_cmp_ctx_s { - uint8_t error; - void *buf; - bat_cmp_reader read; - bat_cmp_skipper skip; - bat_cmp_writer write; + uint8_t error; + void *buf; + bat_cmp_reader read; + bat_cmp_skipper skip; + bat_cmp_writer write; } bat_cmp_ctx_t; typedef struct bat_cmp_object_s { - uint8_t type; - union bat_cmp_object_data_u as; + uint8_t type; + union bat_cmp_object_data_u as; } bat_cmp_object_t; /* @@ -146,9 +145,7 @@ typedef struct bat_cmp_object_s { * If you don't intend to write, `write` may be NULL, but calling `*write*` * functions will crash; there is no check. */ -void bat_cmp_init(bat_cmp_ctx_t *ctx, void *buf, bat_cmp_reader read, - bat_cmp_skipper skip, - bat_cmp_writer write); +void bat_cmp_init(bat_cmp_ctx_t *ctx, void *buf, bat_cmp_reader read, bat_cmp_skipper skip, bat_cmp_writer write); /* Returns CMP's version */ uint32_t bat_cmp_version(void); @@ -157,7 +154,7 @@ uint32_t bat_cmp_version(void); uint32_t bat_cmp_mp_version(void); /* Returns a string description of a CMP context's error */ -const char* bat_cmp_strerror(bat_cmp_ctx_t *ctx); +const char *bat_cmp_strerror(bat_cmp_ctx_t *ctx); /* Writes a signed integer to the backend */ bool bat_cmp_write_integer(bat_cmp_ctx_t *ctx, int64_t d); @@ -234,8 +231,7 @@ bool bat_cmp_write_array(bat_cmp_ctx_t *ctx, uint32_t size); bool bat_cmp_write_map(bat_cmp_ctx_t *ctx, uint32_t size); /* Writes an extended type to the backend */ -bool bat_cmp_write_ext(bat_cmp_ctx_t *ctx, int8_t type, uint32_t size, - const void *data); +bool bat_cmp_write_ext(bat_cmp_ctx_t *ctx, int8_t type, uint32_t size, const void *data); /* * Writes the extended type marker to the backend. This is useful if you want @@ -306,7 +302,7 @@ bool bat_cmp_read_str_size(bat_cmp_ctx_t *ctx, uint32_t *size); /* * Reads a string from the backend; according to the spec, the string's data - * ought to be encoded using UTF-8, + * ought to be encoded using UTF-8, */ bool bat_cmp_read_str(bat_cmp_ctx_t *ctx, char *data, uint32_t *size); @@ -379,9 +375,9 @@ bool bat_cmp_skip_object_flat(bat_cmp_ctx_t *ctx, bat_cmp_object_t *obj); */ bool bat_cmp_skip_object_limit(bat_cmp_ctx_t *ctx, bat_cmp_object_t *obj, uint32_t limit) #ifdef __GNUC__ - __attribute__((deprecated)) + __attribute__((deprecated)) #endif -; + ; #ifdef _MSC_VER #pragma deprecated(bat_cmp_skip_object_limit) @@ -458,14 +454,11 @@ bool bat_cmp_write_fixext16_marker(bat_cmp_ctx_t *ctx, int8_t type); bool bat_cmp_write_fixext16(bat_cmp_ctx_t *ctx, int8_t type, const void *data); bool bat_cmp_write_ext8_marker(bat_cmp_ctx_t *ctx, int8_t type, uint8_t size); -bool bat_cmp_write_ext8(bat_cmp_ctx_t *ctx, int8_t type, uint8_t size, - const void *data); +bool bat_cmp_write_ext8(bat_cmp_ctx_t *ctx, int8_t type, uint8_t size, const void *data); bool bat_cmp_write_ext16_marker(bat_cmp_ctx_t *ctx, int8_t type, uint16_t size); -bool bat_cmp_write_ext16(bat_cmp_ctx_t *ctx, int8_t type, uint16_t size, - const void *data); +bool bat_cmp_write_ext16(bat_cmp_ctx_t *ctx, int8_t type, uint16_t size, const void *data); bool bat_cmp_write_ext32_marker(bat_cmp_ctx_t *ctx, int8_t type, uint32_t size); -bool bat_cmp_write_ext32(bat_cmp_ctx_t *ctx, int8_t type, uint32_t size, - const void *data); +bool bat_cmp_write_ext32(bat_cmp_ctx_t *ctx, int8_t type, uint32_t size, const void *data); bool bat_cmp_read_pfix(bat_cmp_ctx_t *ctx, uint8_t *c); bool bat_cmp_read_nfix(bat_cmp_ctx_t *ctx, int8_t *c); @@ -557,13 +550,12 @@ bool bat_cmp_object_to_bin(bat_cmp_ctx_t *ctx, bat_cmp_object_t *obj, void *data * ============================================================================ */ -#define bat_cmp_write_int bat_cmp_write_integer -#define bat_cmp_write_sint bat_cmp_write_integer +#define bat_cmp_write_int bat_cmp_write_integer +#define bat_cmp_write_sint bat_cmp_write_integer #define bat_cmp_write_sinteger bat_cmp_write_integer -#define bat_cmp_write_uint bat_cmp_write_uinteger -#define bat_cmp_read_sinteger bat_cmp_read_integer +#define bat_cmp_write_uint bat_cmp_write_uinteger +#define bat_cmp_read_sinteger bat_cmp_read_integer #endif /* BAT_CMP_H__ */ /* vi: set et ts=2 sw=2: */ - diff --git a/Sources/Batch/Kernel/Parameters/BANetworkParameters.m b/Sources/Batch/Kernel/Parameters/BANetworkParameters.m index c315425..4ea83f4 100644 --- a/Sources/Batch/Kernel/Parameters/BANetworkParameters.m +++ b/Sources/Batch/Kernel/Parameters/BANetworkParameters.m @@ -30,45 +30,52 @@ @implementation BANetworkParameters // MCC+MNC + (NSString *)simOperatorCode { - static CTTelephonyNetworkInfo *telephonyNetworkInfo = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - telephonyNetworkInfo = [[CTTelephonyNetworkInfo alloc] init]; - }); - // TODO add cache - CTCarrier *carrier; - - if (@available(iOS 12.1, *)) { - // This APi is available from iOS 12.0, but returns nil - NSDictionary *carriers = [telephonyNetworkInfo serviceSubscriberCellularProviders]; - for (CTCarrier *candidateCarrier in carriers.allValues) { - // Try to find a SIM that's active. - // Note that for dual sim both can be active. We don't know which one is the default, so we just pick one. - if ([candidateCarrier.mobileCountryCode length] > 0 || [candidateCarrier.mobileNetworkCode length] > 0) { - carrier = candidateCarrier; - break; + if (@available(iOS 16.4, *)) { + // iOS 16.4 removed support for CTCarrier and returns garbage + return nil; + } else { + static CTTelephonyNetworkInfo *telephonyNetworkInfo = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + telephonyNetworkInfo = [[CTTelephonyNetworkInfo alloc] init]; + }); + // TODO add cache + CTCarrier *carrier; + + if (@available(iOS 12.1, *)) { + // This APi is available from iOS 12.0, but returns nil + NSDictionary *carriers = [telephonyNetworkInfo serviceSubscriberCellularProviders]; + for (CTCarrier *candidateCarrier in carriers.allValues) { + // Try to find a SIM that's active. + // Note that for dual sim both can be active. We don't know which one is the default, so we just pick + // one. + if ([candidateCarrier.mobileCountryCode length] > 0 || + [candidateCarrier.mobileNetworkCode length] > 0) { + carrier = candidateCarrier; + break; + } } + } else { + carrier = [telephonyNetworkInfo subscriberCellularProvider]; } - } else { - carrier = [telephonyNetworkInfo subscriberCellularProvider]; - } - NSString *mobileCountryCode = [carrier mobileCountryCode]; - NSString *mobileNetworkCode = [carrier mobileNetworkCode]; + NSString *mobileCountryCode = [carrier mobileCountryCode]; + NSString *mobileNetworkCode = [carrier mobileNetworkCode]; - if (mobileCountryCode == nil) { - mobileCountryCode = @""; - } + if (mobileCountryCode == nil) { + mobileCountryCode = @""; + } - if (mobileNetworkCode == nil) { - mobileNetworkCode = @""; - } + if (mobileNetworkCode == nil) { + mobileNetworkCode = @""; + } - NSString *operatorCode = [mobileCountryCode stringByAppendingString:mobileNetworkCode]; - if ([operatorCode length] > 0) { - return operatorCode; - } else { - return nil; + NSString *operatorCode = [mobileCountryCode stringByAppendingString:mobileNetworkCode]; + if ([operatorCode length] > 0) { + return operatorCode; + } else { + return nil; + } } } diff --git a/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.h b/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.h index 3e17a6e..c76ed6a 100644 --- a/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.h +++ b/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.h @@ -5,9 +5,9 @@ // Copyright (c) 2012 Batch SDK. All rights reserved. // +#import #import #import -#import /*! @class BAPropertiesCenter diff --git a/Sources/Batch/Kernel/Parameters/BAUserDefaults.h b/Sources/Batch/Kernel/Parameters/BAUserDefaults.h index b60116e..50f136e 100644 --- a/Sources/Batch/Kernel/Parameters/BAUserDefaults.h +++ b/Sources/Batch/Kernel/Parameters/BAUserDefaults.h @@ -32,7 +32,8 @@ @param suiteName : The name of the suite to use for the UserDefaults. @return Instance or nil. */ -- (instancetype _Nonnull)initWithCryptor:(id _Nullable)cryptor andSuiteName:( NSString* _Nullable)suiteName; +- (instancetype _Nonnull)initWithCryptor:(id _Nullable)cryptor + andSuiteName:(NSString *_Nullable)suiteName; /*! @method objectForKey: @@ -40,7 +41,7 @@ @param key : The stored key for that value. @return The value or nil. */ -- (id _Nullable)objectForKey:(NSString * _Nonnull)key; +- (id _Nullable)objectForKey:(NSString *_Nonnull)key; /*! @method setValue:forKey: @@ -48,14 +49,14 @@ @param value : The value to save. @param key : Key for that value. */ -- (void)setValue:(id _Nullable)value forKey:(NSString * _Nonnull)key; +- (void)setValue:(id _Nullable)value forKey:(NSString *_Nonnull)key; /*! @method removeObjectForKey: @abstract Remove the value and the key. @param key : The key to use for storage. */ -- (void)removeObjectForKey:(NSString * _Nonnull)key; +- (void)removeObjectForKey:(NSString *_Nonnull)key; /*! @method saveCustomObject:key: @@ -63,7 +64,7 @@ @param object : An object implementing NSCoding @param key : Unique key to same this object on. */ -- (void)saveCustomObject:(id _Nonnull)object key:(NSString * _Nonnull)key; +- (void)saveCustomObject:(id _Nonnull)object key:(NSString *_Nonnull)key; /*! @method loadCustomObjectWithKey: @@ -71,7 +72,7 @@ @param key : Stored key. @return The found object or NULL. */ -- (id _Nullable)loadCustomObjectWithKey:(NSString * _Nonnull)key; +- (id _Nullable)loadCustomObjectWithKey:(NSString *_Nonnull)key; /** Remove all k/v diff --git a/Sources/Batch/Kernel/Reachability/BAReachability.h b/Sources/Batch/Kernel/Reachability/BAReachability.h index cfdb4f1..4418f86 100644 --- a/Sources/Batch/Kernel/Reachability/BAReachability.h +++ b/Sources/Batch/Kernel/Reachability/BAReachability.h @@ -2,14 +2,14 @@ File: Reachability.h Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. Version: 3.0 - + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. - + In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the @@ -25,13 +25,13 @@ implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. - + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. - + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS @@ -40,26 +40,19 @@ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - + Copyright (c) 2014 Apple Inc. All Rights Reserved. - + */ #import #import #import - -typedef enum : NSInteger { - NotReachable = 0, - ReachableViaWiFi, - ReachableViaWWAN -} BANetworkStatus; - +typedef enum : NSInteger { NotReachable = 0, ReachableViaWiFi, ReachableViaWWAN } BANetworkStatus; extern NSString *kBAReachabilityChangedNotification; - @interface BAReachability : NSObject /*! @@ -73,7 +66,8 @@ extern NSString *kBAReachabilityChangedNotification; + (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress; /*! - * Checks whether the default route is available. Should be used by applications that do not connect to a particular host. + * Checks whether the default route is available. Should be used by applications that do not connect to a particular + * host. */ + (instancetype)reachabilityForInternetConnection; @@ -91,10 +85,9 @@ extern NSString *kBAReachabilityChangedNotification; - (BANetworkStatus)currentReachabilityStatus; /*! - * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand. + * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN + * on Demand. */ - (BOOL)connectionRequired; @end - - diff --git a/Sources/Batch/Kernel/Xson/BATJsonDictionary.h b/Sources/Batch/Kernel/Xson/BATJsonDictionary.h index 754fcd5..d8b884f 100644 --- a/Sources/Batch/Kernel/Xson/BATJsonDictionary.h +++ b/Sources/Batch/Kernel/Xson/BATJsonDictionary.h @@ -15,23 +15,24 @@ NS_ASSUME_NONNULL_BEGIN */ @interface BATJsonDictionary : NSObject -- (instancetype)initWithDictionary:(NSDictionary*)dict errorDomain:(NSErrorDomain)errorDomain; +- (instancetype)initWithDictionary:(NSDictionary *)dict errorDomain:(NSErrorDomain)errorDomain; /** Get an object for the given key, check if it an instance of the wanted class and return it as is if it does. If an error occurs, the return value will be 'nil'. - If you allow a key to be nil/nonexistent, you'll have to check the error pointer to see if the value really was null or of the wrong kind. - + If you allow a key to be nil/nonexistent, you'll have to check the error pointer to see if the value really was null or + of the wrong kind. + NSNull values will be returned as nil. */ -- (nullable id)objectForKey:(NSString*)key kindOfClass:(Class)class allowNil:(BOOL)allowNil error:(NSError**)error; +- (nullable id)objectForKey:(NSString *)key kindOfClass:(Class)class allowNil:(BOOL)allowNil error:(NSError **)error; /** Get an object for the given key, check if it an instance of the wanted class and return it as is if it does. If an error occurs, or if the value is nil/nonexistent/[NSNull null], the return value will be the fallback. - + */ -- (nullable id)objectForKey:(NSString*)key kindOfClass:(Class)class fallback:(nullable id)fallback; +- (nullable id)objectForKey:(NSString *)key kindOfClass:(Class)class fallback:(nullable id)fallback; /** String prefix to prepend to the error localized descriptions. diff --git a/Sources/Batch/Modules/Actions/BAActionsCenter.h b/Sources/Batch/Modules/Actions/BAActionsCenter.h index 39d7188..b92adee 100644 --- a/Sources/Batch/Modules/Actions/BAActionsCenter.h +++ b/Sources/Batch/Modules/Actions/BAActionsCenter.h @@ -10,23 +10,25 @@ #import #import -extern NSString * _Nonnull const kBAActionsReservedIdentifierPrefix; +extern NSString *_Nonnull const kBAActionsReservedIdentifierPrefix; @interface BAActionsCenter : NSObject + (instancetype _Nonnull)instance; -- (nullable NSError*)registerAction:(nonnull BatchUserAction*)action; +- (nullable NSError *)registerAction:(nonnull BatchUserAction *)action; -- (void)unregisterActionIdentifier:(nonnull NSString*)identifier; +- (void)unregisterActionIdentifier:(nonnull NSString *)identifier; /*! * Perform an action. Private version that allows "batch." actions to be fired * @returns YES if an action was found and performed, NO otherwise */ -- (BOOL)performAction:(nonnull NSString*)identifier withArgs:(nonnull NSDictionary*)args andSource:(nullable id)source; - -- (BOOL)publicPerformAction:(nonnull NSString*)identifier withArguments:(nonnull NSDictionary*)args; +- (BOOL)performAction:(nonnull NSString *)identifier + withArgs:(nonnull NSDictionary *)args + andSource:(nullable id)source; +- (BOOL)publicPerformAction:(nonnull NSString *)identifier + withArguments:(nonnull NSDictionary *)args; @end diff --git a/Sources/Batch/Modules/Actions/BAUserDataBuiltinActions.h b/Sources/Batch/Modules/Actions/BAUserDataBuiltinActions.h index 5ae7a69..03b358c 100644 --- a/Sources/Batch/Modules/Actions/BAUserDataBuiltinActions.h +++ b/Sources/Batch/Modules/Actions/BAUserDataBuiltinActions.h @@ -4,6 +4,6 @@ @interface BAUserDataBuiltinActions : NSObject -+ (BatchUserAction*)tagEditAction; ++ (BatchUserAction *)tagEditAction; @end diff --git a/Sources/Batch/Modules/Actions/BAUserEventBuiltinActions.h b/Sources/Batch/Modules/Actions/BAUserEventBuiltinActions.h index 7f36c9b..1255727 100644 --- a/Sources/Batch/Modules/Actions/BAUserEventBuiltinActions.h +++ b/Sources/Batch/Modules/Actions/BAUserEventBuiltinActions.h @@ -4,6 +4,6 @@ @interface BAUserEventBuiltinActions : NSObject -+ (BatchUserAction*)trackEventAction; ++ (BatchUserAction *)trackEventAction; @end diff --git a/Sources/Batch/Modules/Core/BAApplicationLifecycle.h b/Sources/Batch/Modules/Core/BAApplicationLifecycle.h index 70cc051..8deae6f 100644 --- a/Sources/Batch/Modules/Core/BAApplicationLifecycle.h +++ b/Sources/Batch/Modules/Core/BAApplicationLifecycle.h @@ -30,14 +30,16 @@ NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END -// The following documents the various notifications and callbacks with their corresponding UIApplication and UIScene +// The following documents the various notifications and callbacks with their corresponding UIApplication and UIScene // --------- // App is using UIScene on iOS 14 // --------- // -// Note that "application:didReceiveRemoteNotification:"/"application:didReceiveRemoteNotification:fetchCompletionHandler:" -// are NEVER called for standard notifications (unless it's a background fetch). UNUserNotificationCenter NEEDS to be implemented. +// Note that +// "application:didReceiveRemoteNotification:"/"application:didReceiveRemoteNotification:fetchCompletionHandler:" are +// NEVER called for standard notifications (unless it's a background fetch). UNUserNotificationCenter NEEDS to be +// implemented. // // Cold open // Lifecycle - application:didFinishLaunchingWithOptions: - State: Background - Scene: Unattached @@ -105,15 +107,15 @@ NS_ASSUME_NONNULL_END // Lifecycle - UISceneWillEnterForegroundNotification - State: Background - Scene: No UIScene // Lifecycle - UIApplicationWillEnterForegroundNotification - State: Background - Scene: No UIScene // Lifecycle - userNotificationCenter:didReceive: - State: Inactive - Scene: No UIScene -// Lifecycle - application:didReceiveRemoteNotification:fetchCompletionHandler: - State: Inactive - Scene: No UIScene // (only if no UN delegate) -// Lifecycle - UISceneDidActivateNotification - State: Inactive - Scene: No UIScene -// Lifecycle - UIApplicationDidBecomeActiveNotification - State: Active - Scene: No UIScene +// Lifecycle - application:didReceiveRemoteNotification:fetchCompletionHandler: - State: Inactive - Scene: No UIScene // +// (only if no UN delegate) Lifecycle - UISceneDidActivateNotification - State: Inactive - Scene: No UIScene Lifecycle - +// UIApplicationDidBecomeActiveNotification - State: Active - Scene: No UIScene // // Notification (no bg refresh) cold open (app is killed) // Lifecycle - application:didFinishLaunchingWithOptions: - State: Inactive - Scene: No UIScene // Lifecycle - UIApplicationDidFinishLaunchingNotification - State: Inactive - Scene: No UIScene -// Lifecycle - application:didReceiveRemoteNotification:fetchCompletionHandler: - State: Inactive - Scene: No UIScene // (only if no UN delegate) -// Lifecycle - userNotificationCenter:didReceive: - State: Inactive - Scene: No UIScene +// Lifecycle - application:didReceiveRemoteNotification:fetchCompletionHandler: - State: Inactive - Scene: No UIScene // +// (only if no UN delegate) Lifecycle - userNotificationCenter:didReceive: - State: Inactive - Scene: No UIScene // Lifecycle - UISceneDidActivateNotification - State: Inactive - Scene: No UIScene // Lifecycle - UIApplicationDidBecomeActiveNotification - State: Active - Scene: No UIScene // diff --git a/Sources/Batch/Modules/Core/BABundleInfo.h b/Sources/Batch/Modules/Core/BABundleInfo.h index e7fbd5a..a726d04 100644 --- a/Sources/Batch/Modules/Core/BABundleInfo.h +++ b/Sources/Batch/Modules/Core/BABundleInfo.h @@ -17,8 +17,8 @@ /** Returns the shared group id to use. -If it is found in the main bundle info plist under the key "BATCH_APP_GROUP_ID" and not empty, this value will be returned -Otherwise, it will be "group.{bundle_id}.batch +If it is found in the main bundle info plist under the key "BATCH_APP_GROUP_ID" and not empty, this value will be +returned Otherwise, it will be "group.{bundle_id}.batch */ + (nullable NSString *)sharedGroupId; + (nullable NSURL *)sharedGroupDirectory; diff --git a/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h b/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h index 523e950..dc7c725 100644 --- a/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h +++ b/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h @@ -45,7 +45,8 @@ @abstract Set the custom user identifier to Batch, you should use this method if you have your own login system. @discussion You can call this method from any thread. @param identifier : The unique user identifier. - @warning Be carefull: Do not use it if you don't know what you are doing, giving a bad custom user ID can result in failure into offer delivery and restore. + @warning Be carefull: Do not use it if you don't know what you are doing, giving a bad custom user ID can result in + failure into offer delivery and restore. */ + (void)setCustomUserIdentifier:(NSString *)identifier; diff --git a/Sources/Batch/Modules/Core/BAConfiguration.h b/Sources/Batch/Modules/Core/BAConfiguration.h index fab826e..b35b287 100644 --- a/Sources/Batch/Modules/Core/BAConfiguration.h +++ b/Sources/Batch/Modules/Core/BAConfiguration.h @@ -10,7 +10,7 @@ #import -extern NSString * _Nonnull const kBATConfigurationChangedNotification; +extern NSString *_Nonnull const kBATConfigurationChangedNotification; @protocol BatchLoggerDelegate; @@ -89,13 +89,13 @@ extern NSString * _Nonnull const kBATConfigurationChangedNotification; @method setAssociatedDomains @abstract Set the associated domains */ -- (void)setAssociatedDomains:(nonnull NSArray *)domains; +- (void)setAssociatedDomains:(nonnull NSArray *)domains; /*! @method associatedDomains @abstract Get the associated domains */ -- (nullable NSArray *)associatedDomains; +- (nullable NSArray *)associatedDomains; /** Developer's deeplink delegate diff --git a/Sources/Batch/Modules/Core/BACoreCenter.h b/Sources/Batch/Modules/Core/BACoreCenter.h index f1dd605..f652570 100644 --- a/Sources/Batch/Modules/Core/BACoreCenter.h +++ b/Sources/Batch/Modules/Core/BACoreCenter.h @@ -8,8 +8,8 @@ #import -#import #import +#import #import @@ -95,21 +95,22 @@ - Device model - Device brand - Carrier name - + Setting this to false have a negative impact on core Batch features You should only use it if you know what you are doing. - + @param use : YES if Batch can try to use advanced device information, NO if you don't - @warning Disabling this does not automatically disable IDFA collection, pleaseuse the appropriate methods to control this. + @warning Disabling this does not automatically disable IDFA collection, pleaseuse the appropriate methods to control + this. */ + (void)setUseAdvancedDeviceInformation:(BOOL)use; /** Opens the given deeplink. Allows for developers to override the behavior using a deeplink delegate. - + @param deeplink Doesn't need to be a valid NSURL, as it can be overriden. @param inApp Set to YES to open the url in app using a SFSafariViewController if available. */ -- (void)openDeeplink:(NSString*)deeplink inApp:(BOOL)inApp; +- (void)openDeeplink:(NSString *)deeplink inApp:(BOOL)inApp; @end diff --git a/Sources/Batch/Modules/Core/BACoreCenter.m b/Sources/Batch/Modules/Core/BACoreCenter.m index 4da9f5d..3b28c3d 100644 --- a/Sources/Batch/Modules/Core/BACoreCenter.m +++ b/Sources/Batch/Modules/Core/BACoreCenter.m @@ -37,9 +37,10 @@ #import +#import #import #import -#import +#import #define LOGGER_DOMAIN @"Core" @@ -165,6 +166,13 @@ - (void)excecuteStartWithAPIKey:(NSString *)key { NSString *apiKey = [key stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLPathAllowedCharacterSet]; + if ([[UIApplication sharedApplication] delegate] == NULL) { + [BALogger publicForDomain:nil + message:@"⚠️ Shared UIApplicationDelegate is not ready. If you'r using SwiftUI please " + @"ensure to set an explicite delegate. For more info, see documentation: " + @"https://doc.batch.com/ios/sdk-integration/initial-setup/#your-first-start"]; + } + // Try to save the developper key. NSError *e = [self.configuration setDevelopperKey:apiKey]; if (e != NULL) { @@ -381,7 +389,9 @@ - (BOOL)openDeeplinkURLInAppIfPossible:(NSURL *)deeplinkURL { @try { UIViewController *targetVC = [[BAWindowHelper keyWindow] rootViewController]; if (targetVC.presentedViewController != nil) { - targetVC = targetVC.presentedViewController; + while (targetVC.presentedViewController) { + targetVC = targetVC.presentedViewController; + } } SFSafariViewController *safari = [[SFSafariViewController alloc] initWithURL:deeplinkURL]; @@ -441,14 +451,18 @@ - (BOOL)openUniversalLinkIfPossible:(NSURL *)URL { message:@"Transferring universal link '%@' to UIApplication", URL.absoluteString]; // Transferring url to application:continueUserActivity:restorationHandler or scene:continueUserActivity: - NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb]; + BATUserActivity *userActivity = [[BATUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb]; userActivity.webpageURL = URL; - + // Telling Batch about this is only needed on SwiftUI apps + if ([BAApplicationLifecycle applicationUsesSwiftUILifecycle]) { + userActivity.hasUniversalLink = true; + } + Boolean errorAlreadyLogged = false; - + if (@available(iOS 13.0, *)) { if ([BAApplicationLifecycle applicationUsesUIScene]) { - UIScene* scene = [[UIApplication sharedApplication].connectedScenes allObjects].firstObject; + UIScene *scene = [[UIApplication sharedApplication].connectedScenes allObjects].firstObject; id sceneDelegate = [scene delegate]; if ([sceneDelegate respondsToSelector:@selector(scene:continueUserActivity:)]) { [sceneDelegate scene:scene continueUserActivity:userActivity]; @@ -461,7 +475,7 @@ - (BOOL)openUniversalLinkIfPossible:(NSURL *)URL { } } } - + id appDelegate = [UIApplication sharedApplication].delegate; if ([appDelegate respondsToSelector:@selector(application:continueUserActivity:restorationHandler:)]) { [appDelegate application:[UIApplication sharedApplication] @@ -476,7 +490,6 @@ - (BOOL)openUniversalLinkIfPossible:(NSURL *)URL { } return NO; - } // Check for potential incompatibilities/misconfigurations, and warn the developer diff --git a/Sources/Batch/Modules/Core/BAInstallationID.h b/Sources/Batch/Modules/Core/BAInstallationID.h index 8fe7786..9f0e487 100644 --- a/Sources/Batch/Modules/Core/BAInstallationID.h +++ b/Sources/Batch/Modules/Core/BAInstallationID.h @@ -2,7 +2,7 @@ @interface BAInstallationID : NSObject -+ (nullable NSString*)installationID; ++ (nullable NSString *)installationID; + (void)delete; diff --git a/Sources/Batch/Modules/Core/BANotificationAuthorization.h b/Sources/Batch/Modules/Core/BANotificationAuthorization.h index fad4c4b..0ca67a7 100644 --- a/Sources/Batch/Modules/Core/BANotificationAuthorization.h +++ b/Sources/Batch/Modules/Core/BANotificationAuthorization.h @@ -2,14 +2,16 @@ #import -typedef NS_OPTIONS(NSUInteger, BANotificationAuthorizationTypes) -{ - BANotificationAuthorizationTypesNone = 0, - BANotificationAuthorizationTypesBadge = 1 << 0, - BANotificationAuthorizationTypesSound = 1 << 1, - BANotificationAuthorizationTypesAlert = 1 << 2, - BANotificationAuthorizationTypesLockscreen = 1 << 3, - BANotificationAuthorizationTypesNotificationCenter = 1 << 4, +typedef NS_OPTIONS(NSUInteger, BANotificationAuthorizationTypes) { + BANotificationAuthorizationTypesNone = 0, + BANotificationAuthorizationTypesBadge = 1 << 0, + BANotificationAuthorizationTypesSound = 1 << 1, + BANotificationAuthorizationTypesAlert = 1 << 2, + BANotificationAuthorizationTypesLockscreen = 1 << 3, + BANotificationAuthorizationTypesNotificationCenter = 1 << 4, + // Scheduled Delivery is the iOS feature where notifications are delivered in a groupped + // summary at set times defined by the user + BANotificationAuthorizationTypesScheduledDelivery = 1 << 5, }; typedef NS_ENUM(NSUInteger, BANotificationAuthorizationStatus) { @@ -18,33 +20,33 @@ typedef NS_ENUM(NSUInteger, BANotificationAuthorizationStatus) { Not used anymore. */ BANotificationAuthorizationStatusUnsupported = 0, - + /** "Waiting for value" is the default state, when the OS hasn't called us back yet */ BANotificationAuthorizationStatusWaitingForValue = 1, - + /** Unknown is for future API compatibilty, when Apple adds states and we didn't This happened in iOS 12 with provisional notifications. */ BANotificationAuthorizationStatusUnknown = 2, - + /** The notification permission has not been requested yet */ BANotificationAuthorizationStatusNotRequested = 3, - + /** The notification permission has been granted */ BANotificationAuthorizationStatusGranted = 4, - + /** The notification permission has been deined */ BANotificationAuthorizationStatusDenied = 5, - + /** The notification permission is granted provisionally (iOS 12+) Implies BANotificationAuthorizationStatusNotRequested @@ -60,9 +62,9 @@ typedef NS_ENUM(NSUInteger, BANotificationAuthorizationStatus) { @property BatchPushNotificationSettingStatus applicationSetting; -- (nullable NSDictionary*)optionalDictionaryRepresentation; +- (nullable NSDictionary *)optionalDictionaryRepresentation; -- (nonnull NSDictionary*)dictionaryRepresentation; +- (nonnull NSDictionary *)dictionaryRepresentation; @end @@ -76,7 +78,7 @@ typedef NS_ENUM(NSUInteger, BANotificationAuthorizationStatus) { - (BOOL)shouldFetchSettings; -- (void)fetch:(void(^ _Nullable)(BANotificationAuthorizationSettings* _Nonnull))completionHandler; +- (void)fetch:(void (^_Nullable)(BANotificationAuthorizationSettings *_Nonnull))completionHandler; - (void)settingsMayHaveChanged; diff --git a/Sources/Batch/Modules/Core/BANotificationAuthorization.m b/Sources/Batch/Modules/Core/BANotificationAuthorization.m index 4b33687..46bee5a 100644 --- a/Sources/Batch/Modules/Core/BANotificationAuthorization.m +++ b/Sources/Batch/Modules/Core/BANotificationAuthorization.m @@ -152,6 +152,12 @@ - (void)fetchUN:(void (^_Nullable)(BANotificationAuthorizationSettings *_Nonnull types |= BANotificationAuthorizationTypesLockscreen; } + if (@available(iOS 15.0, *)) { + if ((settings.scheduledDeliverySetting & UNNotificationSettingEnabled) > 0) { + types |= BANotificationAuthorizationTypesScheduledDelivery; + } + } + baSettings.types = types; baSettings.applicationSetting = [BANotificationAuthorization applicationSettings]; diff --git a/Sources/Batch/Modules/Core/BASessionManager.h b/Sources/Batch/Modules/Core/BASessionManager.h index 204e6a8..cad6111 100644 --- a/Sources/Batch/Modules/Core/BASessionManager.h +++ b/Sources/Batch/Modules/Core/BASessionManager.h @@ -8,13 +8,14 @@ #import /** - Notification sent by Batch Push when it gets a remote notification. This includes the one your app is started with (even though it is only sent when Batch starts) + Notification sent by Batch Push when it gets a remote notification. This includes the one your app is started with + (even though it is only sent when Batch starts) */ -FOUNDATION_EXPORT NSString * _Nonnull const BATNewSessionStartedNotification; +FOUNDATION_EXPORT NSString *_Nonnull const BATNewSessionStartedNotification; /** This class manages a user session. - + A new session starts: - On a cold app start - If an app comes into foreground more than X seconds after the last diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALNativeAttributeContext.h b/Sources/Batch/Modules/Core/BATUserActivity.h similarity index 52% rename from Sources/Batch/Modules/Lisp/Evaluation Contexts/BALNativeAttributeContext.h rename to Sources/Batch/Modules/Core/BATUserActivity.h index 5fb5165..5f71ad4 100644 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALNativeAttributeContext.h +++ b/Sources/Batch/Modules/Core/BATUserActivity.h @@ -1,5 +1,4 @@ // -// BALNativeAttributeContext.h // Batch // // Copyright © Batch.com. All rights reserved. @@ -7,11 +6,11 @@ #import -#import - NS_ASSUME_NONNULL_BEGIN -@interface BALNativeAttributeContext : NSObject +@interface BATUserActivity : NSUserActivity + +@property (assign) BOOL hasUniversalLink; @end diff --git a/Sources/Batch/Modules/Core/BATUserActivity.m b/Sources/Batch/Modules/Core/BATUserActivity.m new file mode 100644 index 0000000..33643ed --- /dev/null +++ b/Sources/Batch/Modules/Core/BATUserActivity.m @@ -0,0 +1,27 @@ +// +// Batch +// +// Copyright © Batch.com. All rights reserved. +// + +#import "BATUserActivity.h" +#import + +@implementation BATUserActivity + ++ (void)initialize { + Method boolGetterMethod = class_getInstanceMethod([self class], @selector(exampleBoolGetter)); + + SEL targetSelector = NSSelectorFromString([NSString stringWithFormat:@"_%@%@", @"is", @"UniversalLink"]); + IMP implementation = imp_implementationWithBlock(^(id self) { + return [self hasUniversalLink]; + }); + class_addMethod([self class], targetSelector, implementation, method_getTypeEncoding(boolGetterMethod)); +} + +// Useless method that is used to get its type encoding +- (BOOL)exampleBoolGetter { + return true; +} + +@end diff --git a/Sources/Batch/Modules/Core/BATrackingAuthorization.h b/Sources/Batch/Modules/Core/BATrackingAuthorization.h index 55b7461..281a8e8 100644 --- a/Sources/Batch/Modules/Core/BATrackingAuthorization.h +++ b/Sources/Batch/Modules/Core/BATrackingAuthorization.h @@ -13,29 +13,29 @@ typedef NS_ENUM(NSUInteger, BATrackingAuthorizationStatus) { // iOS returned a tracking authorization status that we don't know about BATrackingAuthorizationStatusUnknown = 0, - + // Tracking has been disabled in Batch's configuration BATrackingAuthorizationStatusForbiddenByBatchConfig = 1, - + // User denied tracking (limitsAdTracking on iOS 13 and lower matches this) BATrackingAuthorizationStatusDenied = 2, - - // User agreed to tracking. On iOS 13 and lower this is the default value, but on iOS 14 this is only used when the user explicitly allowed tracking via AppTrackingTransparency + + // User agreed to tracking. On iOS 13 and lower this is the default value, but on iOS 14 this is only used when the + // user explicitly allowed tracking via AppTrackingTransparency BATrackingAuthorizationStatusAuthorized = 3, - + // iOS 14+: we don't know if the user allowed tracking BATrackingAuthorizationStatusNotDetermined = 4, - + // iOS 14+: Tracking is disabled by policy and can't be enabled by the user BATrackingAuthorizationStatusRestricted = 5, }; - @interface BATrackingAuthorization : NSObject @property (readonly) BATrackingAuthorizationStatus trackingAuthorizationStatus; -@property (nullable, readonly) NSUUID* attributionIdentifier; +@property (nullable, readonly) NSUUID *attributionIdentifier; - (void)settingsMayHaveChanged; diff --git a/Sources/Batch/Modules/Core/BAUserProfile.h b/Sources/Batch/Modules/Core/BAUserProfile.h index 7035272..7d3e29f 100644 --- a/Sources/Batch/Modules/Core/BAUserProfile.h +++ b/Sources/Batch/Modules/Core/BAUserProfile.h @@ -24,7 +24,8 @@ /*! @property customIdentifier @abstract Access a custom user identifier to Batch, you should use this method if you have your own login system. - @warning Be carefull: Do not use it if you don't know what you are doing, giving a bad custom user ID can result in failure into offer delivery and restore. + @warning Be carefull: Do not use it if you don't know what you are doing, giving a bad custom user ID can result in + failure into offer delivery and restore. */ @property (strong, nonatomic, nullable) NSString *customIdentifier; @@ -48,14 +49,14 @@ @discussion You can call this method from any thread. @return The unique instance of this object. @see BatchUserProfile */ -+ (BAUserProfile * _Nonnull)defaultUserProfile __attribute__((warn_unused_result)); ++ (BAUserProfile *_Nonnull)defaultUserProfile __attribute__((warn_unused_result)); /*! @method dictionaryRepresentation @abstract Key-Value dictionary representation of a user profile. @return The dictionary representation. */ -- (NSDictionary * _Nonnull)dictionaryRepresentation __attribute__((warn_unused_result)); +- (NSDictionary *_Nonnull)dictionaryRepresentation __attribute__((warn_unused_result)); /*! @method incrementVersion diff --git a/Sources/Batch/Modules/Debug/BADBGCustomDataModels.h b/Sources/Batch/Modules/Debug/BADBGCustomDataModels.h index 3f995e6..6bf9827 100644 --- a/Sources/Batch/Modules/Debug/BADBGCustomDataModels.h +++ b/Sources/Batch/Modules/Debug/BADBGCustomDataModels.h @@ -3,7 +3,7 @@ @interface BADBGCustomDataTagCollection : NSObject @property NSString *collectionName; -@property NSArray *tags; +@property NSArray *tags; @end diff --git a/Sources/Batch/Modules/Debug/BADBGFindMyInstallationHelper.h b/Sources/Batch/Modules/Debug/BADBGFindMyInstallationHelper.h index 440123d..782fb86 100644 --- a/Sources/Batch/Modules/Debug/BADBGFindMyInstallationHelper.h +++ b/Sources/Batch/Modules/Debug/BADBGFindMyInstallationHelper.h @@ -4,6 +4,6 @@ @property (class) BOOL enablesFindMyInstallation; -- (nonnull instancetype)initWithPasteboard:(nonnull UIPasteboard*)pasteboard; +- (nonnull instancetype)initWithPasteboard:(nonnull UIPasteboard *)pasteboard; @end diff --git a/Sources/Batch/Modules/Debug/BADBGLCDetailsViewController.h b/Sources/Batch/Modules/Debug/BADBGLCDetailsViewController.h index b26b695..7afddc8 100644 --- a/Sources/Batch/Modules/Debug/BADBGLCDetailsViewController.h +++ b/Sources/Batch/Modules/Debug/BADBGLCDetailsViewController.h @@ -4,6 +4,6 @@ @interface BADBGLCDetailsViewController : UITableViewController -- (void)setCampaign:(BALocalCampaign*)campaign; +- (void)setCampaign:(BALocalCampaign *)campaign; @end diff --git a/Sources/Batch/Modules/Debug/BADBGModule.h b/Sources/Batch/Modules/Debug/BADBGModule.h index 96797c6..cf84de2 100644 --- a/Sources/Batch/Modules/Debug/BADBGModule.h +++ b/Sources/Batch/Modules/Debug/BADBGModule.h @@ -2,6 +2,6 @@ @interface BADBGModule : NSObject -+ (UIViewController*)debugViewController; ++ (UIViewController *)debugViewController; @end diff --git a/Sources/Batch/Modules/Debug/BADBGNameValueListItem.h b/Sources/Batch/Modules/Debug/BADBGNameValueListItem.h index f13f425..297254e 100644 --- a/Sources/Batch/Modules/Debug/BADBGNameValueListItem.h +++ b/Sources/Batch/Modules/Debug/BADBGNameValueListItem.h @@ -1,6 +1,6 @@ #import -@interface BADBGNameValueCell: UITableViewCell +@interface BADBGNameValueCell : UITableViewCell @end @interface BADBGNameValueListItem : NSObject diff --git a/Sources/Batch/Modules/Display Receipt/BADisplayReceipt.h b/Sources/Batch/Modules/Display Receipt/BADisplayReceipt.h index 7be6a83..758170d 100644 --- a/Sources/Batch/Modules/Display Receipt/BADisplayReceipt.h +++ b/Sources/Batch/Modules/Display Receipt/BADisplayReceipt.h @@ -5,9 +5,9 @@ // Copyright © Batch.com. All rights reserved. // -#import -#import #import +#import +#import @interface BADisplayReceipt : NSObject @@ -18,13 +18,13 @@ @property (atomic, copy, readonly, nullable) NSDictionary *ed; - (nullable id)initWithTimestamp:(unsigned long long)timestamp - replay:(BOOL)replay - sendAttempt:(unsigned int)sendAttempt - openData:(nullable NSDictionary *)od - eventData:(nullable NSDictionary *)ed; -- (BOOL)packToWriter:(nonnull BATMessagePackWriter *)writer error:(NSError * _Nullable * _Nullable)error; -- (nullable NSData *)pack:(NSError * _Nullable * _Nullable)error; + replay:(BOOL)replay + sendAttempt:(unsigned int)sendAttempt + openData:(nullable NSDictionary *)od + eventData:(nullable NSDictionary *)ed; +- (BOOL)packToWriter:(nonnull BATMessagePackWriter *)writer error:(NSError *_Nullable *_Nullable)error; +- (nullable NSData *)pack:(NSError *_Nullable *_Nullable)error; -+ (nullable instancetype)unpack:(nonnull NSData *)data error:(NSError * _Nullable * _Nullable)error; ++ (nullable instancetype)unpack:(nonnull NSData *)data error:(NSError *_Nullable *_Nullable)error; @end diff --git a/Sources/Batch/Modules/Display Receipt/BADisplayReceiptCache.h b/Sources/Batch/Modules/Display Receipt/BADisplayReceiptCache.h index fd01491..ba591ef 100644 --- a/Sources/Batch/Modules/Display Receipt/BADisplayReceiptCache.h +++ b/Sources/Batch/Modules/Display Receipt/BADisplayReceiptCache.h @@ -17,9 +17,9 @@ + (nullable NSArray *)cachedFiles; // MARK: Methods updating user defaults -+ (void)saveApiKey:(nonnull NSString*)value; ++ (void)saveApiKey:(nonnull NSString *)value; + (nullable NSString *)apiKey; -+ (void)saveLastInstallId:(nonnull NSString*)value; ++ (void)saveLastInstallId:(nonnull NSString *)value; + (nullable NSString *)lastInstallId; + (void)saveIsOptOut:(BOOL)value; + (BOOL)isOptOut; diff --git a/Sources/Batch/Modules/Display Receipt/BADisplayReceiptWebserviceClient.h b/Sources/Batch/Modules/Display Receipt/BADisplayReceiptWebserviceClient.h index e9fc14c..fe79d49 100644 --- a/Sources/Batch/Modules/Display Receipt/BADisplayReceiptWebserviceClient.h +++ b/Sources/Batch/Modules/Display Receipt/BADisplayReceiptWebserviceClient.h @@ -12,7 +12,7 @@ @interface BADisplayReceiptWebserviceClient : BAWebserviceMsgPackClient - (nullable instancetype)initWithReceipts:(nonnull NSArray *)receipts - success:(void (^ _Nullable)(void))successHandler - error:(void (^ _Nullable)(NSError* _Nonnull error))errorHandler; + success:(void (^_Nullable)(void))successHandler + error:(void (^_Nullable)(NSError *_Nonnull error))errorHandler; @end diff --git a/Sources/Batch/Modules/Event Dispatcher/BAEventDispatcherCenter.h b/Sources/Batch/Modules/Event Dispatcher/BAEventDispatcherCenter.h index eec27d5..6fc5744 100644 --- a/Sources/Batch/Modules/Event Dispatcher/BAEventDispatcherCenter.h +++ b/Sources/Batch/Modules/Event Dispatcher/BAEventDispatcherCenter.h @@ -6,30 +6,31 @@ // #import -#import #import -#import #import +#import +#import #import #import @interface BAEventDispatcherCenter : NSObject -@property (readonly, nonnull) NSMutableSet> * dispatchers; +@property (readonly, nonnull) NSMutableSet> *dispatchers; -+ (nullable BAMessageEventPayload*)messageEventPayloadFromMessage:(nonnull BatchMessage*)message; ++ (nullable BAMessageEventPayload *)messageEventPayloadFromMessage:(nonnull BatchMessage *)message; -+ (nullable BAMessageEventPayload*)messageEventPayloadFromMessage:(nonnull BatchMessage *)message action:(nullable BAMSGAction*)msgAction; ++ (nullable BAMessageEventPayload *)messageEventPayloadFromMessage:(nonnull BatchMessage *)message + action:(nullable BAMSGAction *)msgAction; -+ (nullable BAMessageEventPayload*)messageEventPayloadFromMessage:(nonnull BatchMessage *)message - action:(nullable BAMSGAction*)msgAction - webViewAnalyticsIdentifier:(nullable NSString*)webViewAnalyticsIdentifier; ++ (nullable BAMessageEventPayload *)messageEventPayloadFromMessage:(nonnull BatchMessage *)message + action:(nullable BAMSGAction *)msgAction + webViewAnalyticsIdentifier:(nullable NSString *)webViewAnalyticsIdentifier; - (void)addEventDispatcher:(nonnull id)dispatcher; - (void)removeEventDispatcher:(nonnull id)dispatcher; -- (nonnull NSDictionary*)dispatchersAnalyticRepresentation; +- (nonnull NSDictionary *)dispatchersAnalyticRepresentation; - (void)dispatchEventWithType:(BatchEventDispatcherType)type payload:(nonnull id)payload; diff --git a/Sources/Batch/Modules/Event Dispatcher/BAMessageEventPayload.h b/Sources/Batch/Modules/Event Dispatcher/BAMessageEventPayload.h index 31c83dc..97b6ceb 100644 --- a/Sources/Batch/Modules/Event Dispatcher/BAMessageEventPayload.h +++ b/Sources/Batch/Modules/Event Dispatcher/BAMessageEventPayload.h @@ -7,8 +7,8 @@ #import #import -#import #import +#import @interface BAMessageEventPayload : NSObject @@ -16,13 +16,12 @@ @property (readonly, nullable) NSString *deeplink; @property (readonly) BOOL isPositiveAction; @property (readonly, nullable) BatchMessage *sourceMessage; -@property (readonly, nullable) NSDictionary *notificationUserInfo; +@property (readonly, nullable) NSDictionary *notificationUserInfo; @property (readonly, nullable) NSString *webViewAnalyticsIdentifier; -- (nonnull instancetype)initWithMessage:(nonnull BatchMessage *)message action:(nullable BAMSGAction*)action; +- (nonnull instancetype)initWithMessage:(nonnull BatchMessage *)message action:(nullable BAMSGAction *)action; - (nonnull instancetype)initWithMessage:(nonnull BatchMessage *)message - action:(nullable BAMSGAction*)action - webViewAnalyticsIdentifier:(nullable NSString*)webViewAnalyticsIdentifier; + action:(nullable BAMSGAction *)action + webViewAnalyticsIdentifier:(nullable NSString *)webViewAnalyticsIdentifier; @end - diff --git a/Sources/Batch/Modules/Event Dispatcher/BAPushEventPayload.h b/Sources/Batch/Modules/Event Dispatcher/BAPushEventPayload.h index d49742b..157b45b 100644 --- a/Sources/Batch/Modules/Event Dispatcher/BAPushEventPayload.h +++ b/Sources/Batch/Modules/Event Dispatcher/BAPushEventPayload.h @@ -7,8 +7,8 @@ #import #import -#import #import +#import @interface BAPushEventPayload : NSObject @@ -19,6 +19,6 @@ @property (readonly, nullable) NSDictionary *notificationUserInfo; @property (readonly, nullable) NSString *webViewAnalyticsIdentifier; -- (nonnull instancetype)initWithUserInfo:(nonnull NSDictionary*)userInfo; +- (nonnull instancetype)initWithUserInfo:(nonnull NSDictionary *)userInfo; @end diff --git a/Sources/Batch/Modules/Inbox/BAInbox.h b/Sources/Batch/Modules/Inbox/BAInbox.h index 9b61cd0..3923ebf 100644 --- a/Sources/Batch/Modules/Inbox/BAInbox.h +++ b/Sources/Batch/Modules/Inbox/BAInbox.h @@ -21,7 +21,7 @@ @property (nonatomic, nonnull) BAInboxNotificationContentIdentifiers *identifiers; @property (nonatomic, nonnull) NSDate *date; -@property (nonatomic, nullable) NSMutableArray *duplicateIdentifiers; +@property (nonatomic, nullable) NSMutableArray *duplicateIdentifiers; @property (nonatomic, nonnull) NSDictionary *payload; @property (nonatomic) BOOL isUnread; @property (nonatomic) BOOL isDeleted; @@ -49,7 +49,8 @@ - (nonnull instancetype)initForInstallation; -- (nullable instancetype)initForUserIdentifier:(nonnull NSString*)identifier authenticationKey:(nonnull NSString*)authKey; +- (nullable instancetype)initForUserIdentifier:(nonnull NSString *)identifier + authenticationKey:(nonnull NSString *)authKey; @property NSUInteger maxPageSize; @@ -57,20 +58,25 @@ @property BOOL performHandlersOnMainThread; -@property (readonly, nonnull) NSArray *allFetchedNotifications; +@property (readonly, nonnull) NSArray *allFetchedNotifications; @property (readonly) BOOL endReached; @property BOOL filterSilentNotifications; -- (void)fetchNewNotifications:(void (^ _Nullable)(NSError *_Nullable error, NSArray *_Nullable notifications, BOOL foundNewNotifications, BOOL endReached))completionHandler; +- (void)fetchNewNotifications:(void (^_Nullable)(NSError *_Nullable error, + NSArray *_Nullable notifications, + BOOL foundNewNotifications, + BOOL endReached))completionHandler; -- (void)fetchNextPage:(void (^ _Nullable)(NSError *_Nullable error, NSArray *_Nullable notifications, BOOL endReached))completionHandler; +- (void)fetchNextPage:(void (^_Nullable)(NSError *_Nullable error, + NSArray *_Nullable notifications, + BOOL endReached))completionHandler; - (void)markNotificationAsRead:(nonnull BatchInboxNotificationContent *)notification; - (void)markAllNotificationsAsRead; -- (void)markNotificationAsDeleted:(nonnull BatchInboxNotificationContent*)notification; +- (void)markNotificationAsDeleted:(nonnull BatchInboxNotificationContent *)notification; @end diff --git a/Sources/Batch/Modules/Inbox/BAInboxDBHelperProtocol.h b/Sources/Batch/Modules/Inbox/BAInboxDBHelperProtocol.h index b7a2d03..f4683bb 100644 --- a/Sources/Batch/Modules/Inbox/BAInboxDBHelperProtocol.h +++ b/Sources/Batch/Modules/Inbox/BAInboxDBHelperProtocol.h @@ -5,9 +5,9 @@ // Copyright © Batch.com. All rights reserved. // +#import #import #import -#import /*! @protocol BAInboxDBHelperProtocol @@ -30,7 +30,8 @@ @param statement precompiled statement to bind the notification @return YES if insertion has been populated, NO otherwise. */ -- (BOOL)bindNotification:(BAInboxNotificationContent*)notification withStatement:(sqlite3_stmt **)statement __attribute__((warn_unused_result)); +- (BOOL)bindNotification:(BAInboxNotificationContent *)notification + withStatement:(sqlite3_stmt **)statement __attribute__((warn_unused_result)); /*! @method insertFetchersStatementDescriptions @@ -45,6 +46,8 @@ @param statement precompiled statement to bind the notification @return YES if insertion has been populated, NO otherwise. */ -- (BOOL)bindFetcherNotification:(BAInboxNotificationContent*)notification withFetcherId:(long long)fetcherId statement:(sqlite3_stmt **)statement __attribute__((warn_unused_result)); - +- (BOOL)bindFetcherNotification:(BAInboxNotificationContent *)notification + withFetcherId:(long long)fetcherId + statement:(sqlite3_stmt **)statement __attribute__((warn_unused_result)); + @end diff --git a/Sources/Batch/Modules/Inbox/BAInboxDatasourceProtocol.h b/Sources/Batch/Modules/Inbox/BAInboxDatasourceProtocol.h index a46b56d..b936e3f 100644 --- a/Sources/Batch/Modules/Inbox/BAInboxDatasourceProtocol.h +++ b/Sources/Batch/Modules/Inbox/BAInboxDatasourceProtocol.h @@ -5,10 +5,10 @@ // Copyright © Batch.com. All rights reserved. // -#import #import -#import #import +#import +#import /*! @protocol BAInboxDatasourceProtocol @@ -32,19 +32,22 @@ @method notifications:withFetcherId @abstract Get a list of notifications */ --(nonnull NSArray *)notifications:(nonnull NSArray *)notificaitonIds withFetcherId:(long long)fetcherId; +- (nonnull NSArray *)notifications:(nonnull NSArray *)notificaitonIds + withFetcherId:(long long)fetcherId; /*! @method candidateNotificationsFromCursor:limit:fetcherId @abstract Get candidates notifcations from cache */ --(nullable NSArray *)candidateNotificationsFromCursor:(nullable NSString *)cursor limit:(NSUInteger)limit fetcherId:(long long)fetcherId; +- (nullable NSArray *)candidateNotificationsFromCursor:(nullable NSString *)cursor + limit:(NSUInteger)limit + fetcherId:(long long)fetcherId; /*! @method createFetcherIdWith:identifier @abstract Create or get the corresponding fetcher in db */ -- (long long)createFetcherIdWith:(BAInboxWebserviceClientType)type identifier:(nonnull NSString*)identifier; +- (long long)createFetcherIdWith:(BAInboxWebserviceClientType)type identifier:(nonnull NSString *)identifier; /*! @method insertResponse:withFetcherId @@ -62,36 +65,36 @@ @method updateNotification:withFetcherId @abstract Update the notification from a payload */ --(nullable NSString *)updateNotification:(nonnull NSDictionary *)dictionary withFetcherId:(long long)fetcherId; +- (nullable NSString *)updateNotification:(nonnull NSDictionary *)dictionary withFetcherId:(long long)fetcherId; /*! @method markAsDeleted @abstract Mark a notification as deleted */ --(BOOL)markAsDeleted:(nonnull NSString*)notificationId; +- (BOOL)markAsDeleted:(nonnull NSString *)notificationId; /*! @method markAsRead @abstract Mark a notification as read */ --(BOOL)markAsRead:(nonnull NSString*)notificationId; +- (BOOL)markAsRead:(nonnull NSString *)notificationId; /*! @method markAllAsRead:withFetcherId @abstract Mark all notifications before a specified time as read */ --(BOOL)markAllAsRead:(long long)time withFetcherId:(long long)fetcherId; +- (BOOL)markAllAsRead:(long long)time withFetcherId:(long long)fetcherId; /*! @method deleteNotifications @abstract Delete notifications */ --(BOOL)deleteNotifications:(nonnull NSArray *)notificaitonIds; +- (BOOL)deleteNotifications:(nonnull NSArray *)notificaitonIds; /*! @method cleanDatabase @abstract Clean old notifications from the database */ --(BOOL)cleanDatabase; +- (BOOL)cleanDatabase; @end diff --git a/Sources/Batch/Modules/Inbox/BAInboxFetchWebserviceClient.h b/Sources/Batch/Modules/Inbox/BAInboxFetchWebserviceClient.h index f01cdd6..cd99fc8 100644 --- a/Sources/Batch/Modules/Inbox/BAInboxFetchWebserviceClient.h +++ b/Sources/Batch/Modules/Inbox/BAInboxFetchWebserviceClient.h @@ -5,22 +5,24 @@ // Copyright © 2017 Batch. All rights reserved. // -#import -#import #import +#import #import +#import @interface BAInboxFetchWebserviceClient : BAGETWebserviceClient -- (nullable instancetype)initWithIdentifier:(nonnull NSString*)identifier +- (nullable instancetype)initWithIdentifier:(nonnull NSString *)identifier type:(BAInboxWebserviceClientType)type - authenticationKey:(nullable NSString*)authKey + authenticationKey:(nullable NSString *)authKey limit:(NSUInteger)limit fetcherId:(long long)fetcherId - fromToken:(nullable NSString*)from - success:(void (^ _Nullable)(BAInboxWebserviceResponse* _Nonnull response))successHandler - error:(void (^ _Nullable)(NSError* _Nonnull error))errorHandler; + fromToken:(nullable NSString *)from + success: + (void (^_Nullable)(BAInboxWebserviceResponse *_Nonnull response))successHandler + error:(void (^_Nullable)(NSError *_Nonnull error))errorHandler; -+ (nullable BAInboxNotificationContent *)parseRawNotification:(nonnull NSDictionary*)dictionary error:(NSError*_Nonnull*_Nullable)outErr; ++ (nullable BAInboxNotificationContent *)parseRawNotification:(nonnull NSDictionary *)dictionary + error:(NSError *_Nonnull *_Nullable)outErr; @end diff --git a/Sources/Batch/Modules/Inbox/BAInboxSQLiteDatasource.h b/Sources/Batch/Modules/Inbox/BAInboxSQLiteDatasource.h index ac15460..00f861c 100644 --- a/Sources/Batch/Modules/Inbox/BAInboxSQLiteDatasource.h +++ b/Sources/Batch/Modules/Inbox/BAInboxSQLiteDatasource.h @@ -5,27 +5,28 @@ // Copyright © Batch.com. All rights reserved. // +#import +#import #import #import -#import -#import /*! @class BAInboxSQLiteDatasource @abstract Implementation of BAInboxDatasourceProtocol using SQLLite */ -@interface BAInboxSQLiteDatasource : NSObject -{ +@interface BAInboxSQLiteDatasource : NSObject { sqlite3 *_database; - + sqlite3_stmt *_insertNotificationStatement; - + sqlite3_stmt *_insertFetcherStatement; } - (nonnull instancetype)init NS_UNAVAILABLE; -- (instancetype _Nullable)initWithFilename:(nonnull NSString *)name forDBHelper:(nonnull id)inboxDBHelper __attribute__((warn_unused_result)); +- (instancetype _Nullable)initWithFilename:(nonnull NSString *)name + forDBHelper:(nonnull id)inboxDBHelper + __attribute__((warn_unused_result)); - (long long)notificationTime:(nonnull NSString *)notificationId; @@ -35,5 +36,4 @@ */ @property (nonnull) id inboxDBHelper; - @end diff --git a/Sources/Batch/Modules/Inbox/BAInboxSQLiteHelper.h b/Sources/Batch/Modules/Inbox/BAInboxSQLiteHelper.h index 7c03af4..1601c7f 100644 --- a/Sources/Batch/Modules/Inbox/BAInboxSQLiteHelper.h +++ b/Sources/Batch/Modules/Inbox/BAInboxSQLiteHelper.h @@ -5,9 +5,9 @@ // Copyright © Batch.com. All rights reserved. // +#import #import #import -#import @interface BAInboxSQLiteHelper : NSObject diff --git a/Sources/Batch/Modules/Inbox/BAInboxSyncWebserviceClient.h b/Sources/Batch/Modules/Inbox/BAInboxSyncWebserviceClient.h index b4b3131..be812e2 100644 --- a/Sources/Batch/Modules/Inbox/BAInboxSyncWebserviceClient.h +++ b/Sources/Batch/Modules/Inbox/BAInboxSyncWebserviceClient.h @@ -5,22 +5,23 @@ // Copyright © Batch.com. All rights reserved. // -#import #import #import -#import #import +#import +#import @interface BAInboxSyncWebserviceClient : BAWebserviceJsonClient -- (nullable instancetype)initWithIdentifier:(nonnull NSString*)identifier +- (nullable instancetype)initWithIdentifier:(nonnull NSString *)identifier type:(BAInboxWebserviceClientType)type - authenticationKey:(nullable NSString*)authKey + authenticationKey:(nullable NSString *)authKey limit:(NSUInteger)limit fetcherId:(long long)fetcherId - candidates:(nonnull NSArray *)candidates - fromToken:(nonnull NSString*)from - success:(void (^ _Nullable)(BAInboxWebserviceResponse* _Nonnull response))successHandler - error:(void (^ _Nullable)(NSError* _Nonnull error))errorHandler; + candidates:(nonnull NSArray *)candidates + fromToken:(nonnull NSString *)from + success: + (void (^_Nullable)(BAInboxWebserviceResponse *_Nonnull response))successHandler + error:(void (^_Nullable)(NSError *_Nonnull error))errorHandler; @end diff --git a/Sources/Batch/Modules/Inbox/BAInboxWebserviceResponse.h b/Sources/Batch/Modules/Inbox/BAInboxWebserviceResponse.h index 59c6711..051cdd5 100644 --- a/Sources/Batch/Modules/Inbox/BAInboxWebserviceResponse.h +++ b/Sources/Batch/Modules/Inbox/BAInboxWebserviceResponse.h @@ -9,9 +9,9 @@ @interface BAInboxWebserviceResponse : NSObject -@property(nonatomic, assign) BOOL hasMore; -@property(nonatomic, assign) BOOL didTimeout; -@property(nonatomic, nullable) NSString *cursor; -@property(nonatomic, nonnull) NSArray *notifications; +@property (nonatomic, assign) BOOL hasMore; +@property (nonatomic, assign) BOOL didTimeout; +@property (nonatomic, nullable) NSString *cursor; +@property (nonatomic, nonnull) NSArray *notifications; @end diff --git a/Sources/Batch/Modules/Lisp/BALEvaluationContext.h b/Sources/Batch/Modules/Lisp/BALEvaluationContext.h deleted file mode 100644 index e8589f0..0000000 --- a/Sources/Batch/Modules/Lisp/BALEvaluationContext.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// EvaluationContext.h -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol BALEvaluationContext - -- (nullable BALValue*)resolveVariableNamed:(NSString*)name; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/BALOperators.h b/Sources/Batch/Modules/Lisp/BALOperators.h deleted file mode 100644 index b86ad97..0000000 --- a/Sources/Batch/Modules/Lisp/BALOperators.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Operators.h -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef BALValue* _Nonnull (^BALOperatorHandler)(id context, NSArray* values); - -@interface BALOperator : NSObject - -@property NSString *symbol; -@property BALOperatorHandler handler; - -- (instancetype)initWithSymbol:(NSString*)symbol handler:(BALOperatorHandler)handler; - -@end - -@interface BALOperatorProvider : NSObject - -- (BALOperator*)operatorForSymbol:(NSString*)symbol; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/BALOperators.m b/Sources/Batch/Modules/Lisp/BALOperators.m deleted file mode 100644 index f3de2a5..0000000 --- a/Sources/Batch/Modules/Lisp/BALOperators.m +++ /dev/null @@ -1,566 +0,0 @@ -// -// Operators.m -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import - -@implementation BALOperator - -- (instancetype)initWithSymbol:(NSString *)symbol handler:(BALOperatorHandler)handler; -{ - self = [super init]; - if (self) { - self.symbol = symbol; - self.handler = handler; - } - return self; -} - -@end - -@implementation BALOperatorProvider { - NSMutableDictionary *_operators; - NSNumberFormatter *_numberFormatter; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _operators = [NSMutableDictionary new]; - [self setupOperators]; - } - return self; -} - -- (void)setupOperators { - // (if condition then else?) - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"if" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - NSUInteger nbArgs = values.count; - if (nbArgs < 2 || nbArgs > 3) { - return - [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:@"if: should be called with 2 or 3 arguments"]; - } - - BALPrimitiveValue *trueValue = values[1]; - BALPrimitiveValue *falseValue; - if (nbArgs == 3) { - falseValue = values[2]; - } else { - falseValue = [BALPrimitiveValue nilValue]; - } - - BALPrimitiveValue *condition = values[0]; - if (condition.type == BALPrimitiveValueTypeNil) { - return falseValue; - } else if (condition.type == BALPrimitiveValueTypeBool) { - if (![condition.value isKindOfClass:[NSNumber class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:@"if: internal consistency error: boolean value should " - @"have an underlying NSNumber"]; - } - return [(NSNumber *)condition.value boolValue] ? trueValue : falseValue; - } else { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"if: condition should be nil or a boolean value"]; - } - }]]; - - [self - addOperator:[[BALOperator alloc] initWithSymbol:@"and" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] == 0) { - return [BALPrimitiveValue valueWithBoolean:true]; - } - - for (BALPrimitiveValue *atomValue in values) { - if (atomValue.type == BALPrimitiveValueTypeNil) { - // Nil values are like false - return [BALPrimitiveValue valueWithBoolean:false]; - } - - NSNumber *value = atomValue.value; - if (atomValue.type != BALPrimitiveValueTypeBool || - ![value isKindOfClass:[NSNumber class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"and: Cannot compare non boolean values"]; - } - - if (![value boolValue]) { - return [BALPrimitiveValue valueWithBoolean:false]; - } - } - - return [BALPrimitiveValue valueWithBoolean:true]; - }]]; - - [self addOperator:[[BALOperator alloc] initWithSymbol:@"or" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] == 0) { - return [BALPrimitiveValue valueWithBoolean:true]; - } - - for (BALPrimitiveValue *atomValue in values) { - if (atomValue.type == BALPrimitiveValueTypeNil) { - // Nil values are like false - continue; - } - - NSNumber *value = atomValue.value; - if (atomValue.type != BALPrimitiveValueTypeBool || - ![value isKindOfClass:[NSNumber class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"or: Cannot compare non boolean values"]; - } - - if ([value boolValue]) { - return [BALPrimitiveValue valueWithBoolean:true]; - } - } - - return [BALPrimitiveValue valueWithBoolean:false]; - }]]; - - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"=" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] <= 1) { - return [BALPrimitiveValue valueWithBoolean:true]; - } - - BALPrimitiveValue *firstAtomValue = values[0]; - id firstValue = firstAtomValue.value; - if (firstAtomValue == nil) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeInternal - message:@"=: first value shouldn't be nil"]; - } - - for (int i = 1; i < values.count; i++) { - BALPrimitiveValue *atomValue = values[i]; - - if (atomValue == nil) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:@"=: value can't be nil. Are we out of bounds?"]; - } - - if (firstAtomValue.type != atomValue.type) { - return [BALPrimitiveValue valueWithBoolean:false]; - } - - id value = atomValue.value; - - if (firstValue == value) { // Handles 'nil' and static strings - continue; - } - - if (![firstValue isEqual:value]) { - return [BALPrimitiveValue valueWithBoolean:false]; - } - } - - return [BALPrimitiveValue valueWithBoolean:true]; - }]]; - - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"not" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] != 1) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:@"not: only accepts one argument"]; - } - - BALPrimitiveValue *firstAtomValue = values[0]; - if (firstAtomValue.type != BALPrimitiveValueTypeBool) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:@"not: argument should be a boolean"]; - } - - id firstValue = firstAtomValue.value; - if (![firstValue isKindOfClass:[NSNumber class]]) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeInternal - message:@"not: first value should be a NSNumber"]; - } - - return [BALPrimitiveValue valueWithBoolean:![(NSNumber *)firstValue boolValue]]; - }]]; - - [self addOperator:[[BALOperator alloc] - initWithSymbol:@">" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - return [self - performNumberOperation:^BOOL(NSNumber *referenceValue, NSNumber *currentValue) { - return [referenceValue compare:currentValue] == NSOrderedDescending; - } - values:values - operatorSymbol:@">"]; - }]]; - - [self addOperator:[[BALOperator alloc] - initWithSymbol:@">=" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - return [self - performNumberOperation:^BOOL(NSNumber *referenceValue, NSNumber *currentValue) { - NSComparisonResult comp = [referenceValue compare:currentValue]; - return comp == NSOrderedDescending || comp == NSOrderedSame; - } - values:values - operatorSymbol:@">="]; - }]]; - - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"<" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - return [self - performNumberOperation:^BOOL(NSNumber *referenceValue, NSNumber *currentValue) { - return [referenceValue compare:currentValue] == NSOrderedAscending; - } - values:values - operatorSymbol:@"<="]; - }]]; - - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"<=" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - return [self - performNumberOperation:^BOOL(NSNumber *referenceValue, NSNumber *currentValue) { - NSComparisonResult comp = [referenceValue compare:currentValue]; - return comp == NSOrderedAscending || comp == NSOrderedSame; - } - values:values - operatorSymbol:@"<="]; - }]]; - - // Contains takes two arguments: - // - First is a set. If the argument is a string, it is automatically converted to a set - // - Second is a set (the searched one) - // It returns true if the second set contains ANY of the elements of the first set. - // - // Basically executes -[NSSet intersectsSet:] with safety and type checks - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"contains" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] != 2) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:@"contains: only accepts two arguments"]; - } - - // The set that the target should contain - BALPrimitiveValue *wantedSetPrimitive = values[0]; - // Automatically convert string primitives - if (wantedSetPrimitive.type == BALPrimitiveValueTypeString) { - wantedSetPrimitive = [BALPrimitiveValue - valueWithStringSet:[NSSet setWithObject:wantedSetPrimitive.value]]; - } - - // The set that should contains the wanted values - BALPrimitiveValue *targetSetPrimitive = values[1]; - // If the searched set is nil, return false - if (targetSetPrimitive.type == BALPrimitiveValueTypeNil) { - return [BALPrimitiveValue valueWithBoolean:false]; - } - - if (wantedSetPrimitive.type != BALPrimitiveValueTypeStringSet || - targetSetPrimitive.type != BALPrimitiveValueTypeStringSet) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"contains: all arguments should be string sets"]; - } - - NSSet *wantedSet = wantedSetPrimitive.value; - NSSet *targetSet = targetSetPrimitive.value; - - if (![wantedSet isKindOfClass:[NSSet class]] || - ![targetSet isKindOfClass:[NSSet class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:@"contains: internal consistency error: all arguments should " - @"be of underlying type NSSet"]; - } - - return [BALPrimitiveValue valueWithBoolean:[wantedSet intersectsSet:targetSet]]; - }]]; - - // ContainsAll takes two arguments: - // - First is a set. If the argument is a string, it is automatically converted to a set - // - Second is a set (the searched one) - // It returns true if the second set contains ALL of the elements of the first set. - // - // Basically executes -[NSSet isSubsetOfSet:] with safety and type checks - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"containsAll" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] != 2) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:@"contains: only accepts two arguments"]; - } - - // The set that the target should contain - BALPrimitiveValue *wantedSetPrimitive = values[0]; - // Automatically convert string primitives - if (wantedSetPrimitive.type == BALPrimitiveValueTypeString) { - wantedSetPrimitive = [BALPrimitiveValue - valueWithStringSet:[NSSet setWithObject:wantedSetPrimitive.value]]; - } - - // The set that should contains the wanted values - BALPrimitiveValue *targetSetPrimitive = values[1]; - // If the searched set is nil, return false - if (targetSetPrimitive.type == BALPrimitiveValueTypeNil) { - return [BALPrimitiveValue valueWithBoolean:false]; - } - - if (wantedSetPrimitive.type != BALPrimitiveValueTypeStringSet || - targetSetPrimitive.type != BALPrimitiveValueTypeStringSet) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"contains: all arguments should be string sets"]; - } - - NSSet *wantedSet = wantedSetPrimitive.value; - NSSet *targetSet = targetSetPrimitive.value; - - if (![wantedSet isKindOfClass:[NSSet class]] || - ![targetSet isKindOfClass:[NSSet class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:@"contains: internal consistency error: all arguments should " - @"be of underlying type NSSet"]; - } - - return [BALPrimitiveValue valueWithBoolean:[wantedSet isSubsetOfSet:targetSet]]; - }]]; - - // String and set manipulation operations - - [self addOperator:[[BALOperator alloc] initWithSymbol:@"lower" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - return [self - performStringOperation:^NSString *(NSString *valueToTransform) { - return valueToTransform.lowercaseString; - } - values:values - operatorName:@"lower"]; - }]]; - - [self addOperator:[[BALOperator alloc] initWithSymbol:@"upper" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - return [self - performStringOperation:^NSString *(NSString *valueToTransform) { - return valueToTransform.uppercaseString; - } - values:values - operatorName:@"upper"]; - }]]; - - // Casts - - // Returns the double value of a string - [self addOperator:[[BALOperator alloc] - initWithSymbol:@"parse-string" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] != 1) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"parse-string: only accepts a string argument"]; - } - - BALPrimitiveValue *value = values[0]; - if (value.type == BALPrimitiveValueTypeNil) { - return [BALPrimitiveValue nilValue]; - } - - if (value.type != BALPrimitiveValueTypeString) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"parse-string: only accepts a string argument"]; - } - NSString *strToParse = value.value; - - return [BALPrimitiveValue valueWithDouble:[strToParse doubleValue]]; - }]]; - - // Returns the string value of anything but a set - // Returns a nil value for nil inputs - [self - addOperator:[[BALOperator alloc] - initWithSymbol:@"write-to-string" - handler:^BALValue *(id _Nonnull context, - NSArray *_Nonnull values) { - if ([values count] != 1) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"write-to-string: only accepts a single, non-set argument"]; - } - - BALPrimitiveValue *value = values[0]; - NSObject *valueToStringify = value.value; - switch (value.type) { - case BALPrimitiveValueTypeString: - return value; - case BALPrimitiveValueTypeNil: - return [BALPrimitiveValue nilValue]; - case BALPrimitiveValueTypeBool: - if (![valueToStringify isKindOfClass:[NSNumber class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:@"write-to-string: internal consistency error: argument " - @"should be of underlying type NSNumber"]; - } - return [BALPrimitiveValue - valueWithString:((NSNumber *)valueToStringify).boolValue ? @"true" - : @"false"]; - case BALPrimitiveValueTypeDouble: - if (![valueToStringify isKindOfClass:[NSNumber class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:@"write-to-string: internal consistency error: argument " - @"should be of underlying type NSNumber"]; - } - return [BALPrimitiveValue - valueWithString:[self stringifyNumber:(NSNumber *)valueToStringify]]; - case BALPrimitiveValueTypeStringSet: - default: - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeError - message:@"write-to-string: only accepts a single, non-set argument"]; - } - }]]; -} - -/** - Perform a block on all values, after ensuring that all values are numbers - Stops on first false comparaison - */ -- (BALValue *)performNumberOperation:(BOOL (^)(NSNumber *referenceValue, NSNumber *currentValue))operation - values:(NSArray *)values - operatorSymbol:(NSString *)symbol { - if ([values count] < 2) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:[symbol stringByAppendingString:@": requires at least two arguments"]]; - } - - BALPrimitiveValue *referenceValue = values[0]; - if (referenceValue.type != BALPrimitiveValueTypeDouble) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:[symbol stringByAppendingString:@": arguments should be numbers"]]; - } - NSNumber *referenceNumber = referenceValue.value; - if (![referenceNumber isKindOfClass:[NSNumber class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:[symbol - stringByAppendingString:@": consistency error: underlying types should be NSNumbers"]]; - } - - for (int i = 1; i < values.count; i++) { - BALPrimitiveValue *atomValue = values[i]; - - if (atomValue == nil) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:[symbol stringByAppendingString:@": value can't be nil. Are we out of bounds?"]]; - } - - if (atomValue.type != BALPrimitiveValueTypeDouble) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:[symbol stringByAppendingString:@": arguments should be numbers"]]; - } - - if (![atomValue.value isKindOfClass:[NSNumber class]]) { - return - [BALErrorValue errorWithKind:BALErrorValueKindTypeInternal - message:[symbol stringByAppendingString: - @": consistency error: underlying types should be NSNumbers"]]; - } - - if (!operation(referenceNumber, atomValue.value)) { - return [BALPrimitiveValue valueWithBoolean:false]; - } - } - - return [BALPrimitiveValue valueWithBoolean:true]; -} - -/** - Perform a block on a string or every string in a string set - - Errors out if variable isn't a string/string set - */ -- (BALValue *)performStringOperation:(NSString * (^)(NSString *valueToTransform))operation - values:(NSArray *)values - operatorName:(NSString *) - operator{ - if ([values count] != 1) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError message:[operator stringByAppendingString:@": requires only one string/set argument"]]; - } - - BALPrimitiveValue *referenceValue = values[0]; - NSObject *value = referenceValue.value; - if (referenceValue.type == BALPrimitiveValueTypeNil) { - return [BALPrimitiveValue nilValue]; - } else if (referenceValue.type == BALPrimitiveValueTypeString) { - if (![value isKindOfClass:[NSString class]]) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeInternal message:[operator stringByAppendingString:@": consistency error: underlying types should be NSString"]]; - } - return [BALPrimitiveValue valueWithString:operation((NSString *)value)]; - } else if (referenceValue.type == BALPrimitiveValueTypeStringSet) { - NSSet *setValue = (NSSet *)value; - if (![setValue isKindOfClass:[NSSet class]]) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeInternal message:[operator stringByAppendingString:@": consistency error: underlying types should be NSString"]]; - } - - NSMutableSet *resultSet = [NSMutableSet setWithCapacity:setValue.count]; - for (NSString *element in setValue) { - [resultSet addObject:operation(element)]; - } - return [BALPrimitiveValue valueWithStringSet:resultSet]; - } - - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError message:[operator stringByAppendingString:@": argument should be a string or a set"]]; -} - -- (NSString *)stringifyNumber:(NSNumber *)number { - if (_numberFormatter == nil) { - _numberFormatter = [NSNumberFormatter new]; - _numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; - _numberFormatter.usesGroupingSeparator = false; - _numberFormatter.groupingSeparator = @""; - _numberFormatter.decimalSeparator = @"."; - } - - return [_numberFormatter stringFromNumber:number]; -} - -- (void)addOperator:(BALOperator *)operator{ - _operators[operator.symbol.lowercaseString] = operator; -} - -- (BALOperator *)operatorForSymbol:(NSString *)symbol { - return _operators[symbol]; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/BALSExpression.h b/Sources/Batch/Modules/Lisp/BALSExpression.h deleted file mode 100644 index 77f3fed..0000000 --- a/Sources/Batch/Modules/Lisp/BALSExpression.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// SExpression.h -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import -#import - -@class BALEvaluationContext; - -NS_ASSUME_NONNULL_BEGIN - -/** - A S-Expression is an executable list - */ - -@interface BALSExpression : BALValue - -@property (readonly) NSArray* values; - -+ (instancetype)expressionWithValues:(NSArray*)expressions; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/BALSExpression.m b/Sources/Batch/Modules/Lisp/BALSExpression.m deleted file mode 100644 index 7da70e2..0000000 --- a/Sources/Batch/Modules/Lisp/BALSExpression.m +++ /dev/null @@ -1,125 +0,0 @@ -// -// SExpression.m -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import -#import - -@implementation BALSExpression - -- (instancetype)initWithValues:(NSArray *)values; -{ - self = [super init]; - if (self) { - _values = [values copy]; - } - return self; -} - -+ (instancetype)expressionWithValues:(NSArray *)values { - return [[BALSExpression alloc] initWithValues:values]; -} - -- (BOOL)isEqual:(id)other { - if (other == self) { - return YES; - } else if (![other isKindOfClass:[BALSExpression class]]) { - return NO; - } else { - return [self.values isEqualToArray:((BALSExpression *)other).values]; - } -} - -- (nonnull BALValue *)reduce:(nonnull id)context { - if ([_values count] == 0) { - return [BALPrimitiveValue nilValue]; - } - - BALValue *firstValue = _values[0]; - if (![firstValue isKindOfClass:[BALOperatorValue class]]) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeError - message:@"S-Expressions should have an operator as their first value"]; - } - - NSMutableArray *arguments = - [[NSMutableArray alloc] initWithCapacity:MAX(0, _values.count - 1)]; - for (int i = 1; i < _values.count; i++) { - BALValue *val = _values[i]; - if ([val conformsToProtocol:@protocol(BALReducable)]) { - val = [(id)val reduce:context]; - } - - if (val == nil) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeInternal - message:@"Unexpected nil value while reducing S-Expression"]; - } - - if ([val isKindOfClass:[BALErrorValue class]]) { - return val; - } - - if (![val isKindOfClass:[BALPrimitiveValue class]]) { - return [BALErrorValue - errorWithKind:BALErrorValueKindTypeInternal - message:@"Error while reducing S-Expression: at this point, value should be a PrimitiveValue"]; - } - - [arguments addObject:(BALPrimitiveValue *)val]; - } - - BALOperator *operator=((BALOperatorValue *)firstValue).operator; - - if (operator== nil) { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeInternal - message:@"Can't reduce a S-Expression with a nil operator"]; - } - - return operator.handler(context, arguments); -} - -- (NSString *)description { - NSMutableString *desc = [NSMutableString new]; - - [desc appendString:@"("]; - - for (int i = 0; i < _values.count; i++) { - if (i != 0) { - [desc appendFormat:@" "]; - } - - [desc appendString:[_values[i] description]]; - } - - [desc appendString:@")"]; - - return desc; -} - -- (NSString *)debugDescription { - NSMutableString *desc = [NSMutableString new]; - - [desc appendString:@"\n"]; - [desc appendString:@"("]; - - for (int i = 0; i < _values.count; i++) { - [desc appendString:@"\n\t"]; - - NSString *subDesc = [_values[i] debugDescription]; - if ([subDesc hasPrefix:@"\n"]) { - subDesc = [subDesc stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""]; - } - subDesc = [subDesc stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]; - - [desc appendString:subDesc]; - } - - [desc appendString:@"\n"]; - [desc appendString:@")"]; - - return desc; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/BALValues.h b/Sources/Batch/Modules/Lisp/BALValues.h deleted file mode 100644 index 50ceb11..0000000 --- a/Sources/Batch/Modules/Lisp/BALValues.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Atoms.h -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import - -@class BALOperator; -@protocol BALEvaluationContext; - -NS_ASSUME_NONNULL_BEGIN - -/** - Root of everything. - - Everything in our LISP is a Value. - - A value is abstract, but has different concrete implementations: - - SExpression: An executable list of values, which should always begin by a Operator, if not empty - - Variable: A variable reference - - Error: An error, described by kind and message. Errors should bubble as soon as possible - - Primitive: A primitive value (Nil, Double, Bool, String, String Array) - - Operator: A builtin function - - Reducable values are not usuable as-is, and must be resolved to get a primitive value. - Reducing SExpressions is how you compute a result, as the program's root must be a S-Expression. - Operators cannot be reduced, and must only be used as the first value of a S-Expression - - Please note that all concepts here are the result of our take on LISP, and might be different than existing - implementations. - */ -@interface BALValue: NSObject -@end - -/** - Defines reducable values - - A reducable value can be reduced to another Value (usually a Primitive or Error) - */ -@protocol BALReducable - -- (BALValue*)reduce:(id)context; - -@end - -#pragma mark Values definitions - -typedef NS_ENUM(NSUInteger, BALErrorValueKind) { - BALErrorValueKindTypeInternal, - BALErrorValueKindTypeError, - BALErrorValueKindTypeParser, -}; - -@interface BALErrorValue : BALValue - -@property (readonly) BALErrorValueKind kind; -@property (readonly) NSString *message; - -+ (instancetype)errorWithKind:(BALErrorValueKind)kind message:(NSString*)message; - -@end - -typedef NS_ENUM(NSUInteger, BALPrimitiveValueType) { - BALPrimitiveValueTypeNil, - BALPrimitiveValueTypeString, - BALPrimitiveValueTypeDouble, - BALPrimitiveValueTypeBool, - BALPrimitiveValueTypeStringSet, - BALPrimitiveValueTypeURL -}; - -@interface BALPrimitiveValue : BALValue - -@property (readonly) BALPrimitiveValueType type; - -@property (readonly, nullable) id value; // What could go wrong - -+ (instancetype)nilValue; - -+ (nullable instancetype)valueWithString:(NSString*)value; - -+ (instancetype)valueWithDouble:(double)value; - -+ (instancetype)valueWithBoolean:(BOOL)value; - -+ (nullable instancetype)valueWithStringSet:(NSSet*)value; - -+ (nullable instancetype)valueWithURL:(NSURL*)value; - -@end - -@interface BALOperatorValue : BALValue - -@property (readonly) BALOperator *operator; - -+ (instancetype)operatorValueWithOperator:(BALOperator*)operator; - -@end - -@interface BALVariableValue : BALValue - -@property (readonly) NSString *name; - -+ (instancetype)variableWithName:(NSString*)name; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/BALValues.m b/Sources/Batch/Modules/Lisp/BALValues.m deleted file mode 100644 index 99fab9a..0000000 --- a/Sources/Batch/Modules/Lisp/BALValues.m +++ /dev/null @@ -1,277 +0,0 @@ -// -// Atoms.m -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import -#import -#import - -@implementation BALValue -@end - -@implementation BALErrorValue - -- (instancetype)initWithKind:(BALErrorValueKind)kind message:(NSString *)message; -{ - self = [super init]; - if (self) { - _kind = kind; - _message = message; - } - return self; -} - -+ (instancetype)errorWithKind:(BALErrorValueKind)kind message:(NSString *)message; -{ return [[BALErrorValue alloc] initWithKind:kind message:message]; } - -- (BOOL)isEqual:(id)other { - if (other == self) { - return YES; - } else if (![other isKindOfClass:[BALErrorValue class]]) { - return NO; - } else { - BALErrorValue *castedOther = other; - return self.kind == castedOther.kind && [self.message isEqualToString:castedOther.message]; - } -} - -- (NSString *)description { - NSString *kind; - switch (self.kind) { - case BALErrorValueKindTypeInternal: - kind = @"Internal error"; - break; - case BALErrorValueKindTypeError: - kind = @"Program error"; - break; - case BALErrorValueKindTypeParser: - kind = @"Parser error"; - break; - default: - kind = @"Unknown error kind."; - break; - } - - return [NSString stringWithFormat:@" Kind: %@, Message: \"%@\"", kind, self.message]; -} - -@end - -@implementation BALPrimitiveValue - -- (instancetype)initWithValue:(id)value type:(BALPrimitiveValueType)type { - self = [super init]; - if (self) { - _type = type; - _value = value; - } - return self; -} - -+ (instancetype)nilValue { - return [[BALPrimitiveValue alloc] initWithValue:nil type:BALPrimitiveValueTypeNil]; -} - -+ (nullable instancetype)valueWithString:(NSString *)value { - if ([value isKindOfClass:[NSString class]]) { - return [[BALPrimitiveValue alloc] initWithValue:value type:BALPrimitiveValueTypeString]; - } else { - return nil; - } -} - -+ (instancetype)valueWithDouble:(double)value { - return [[BALPrimitiveValue alloc] initWithValue:[NSNumber numberWithDouble:value] type:BALPrimitiveValueTypeDouble]; -} - -+ (instancetype)valueWithBoolean:(BOOL)value { - return [[BALPrimitiveValue alloc] initWithValue:[NSNumber numberWithBool:value] type:BALPrimitiveValueTypeBool]; -} - -+ (nullable instancetype)valueWithStringSet:(NSSet *)value { - if ([value isKindOfClass:[NSSet class]]) { - return [[BALPrimitiveValue alloc] initWithValue:[value copy] type:BALPrimitiveValueTypeStringSet]; - } else { - return nil; - } -} - -+ (nullable instancetype)valueWithURL:(NSURL *)value { - if ([value isKindOfClass:[NSURL class]]) { - return [[BALPrimitiveValue alloc] initWithValue:value type:BALPrimitiveValueTypeURL]; - } else { - return nil; - } -} - -- (BOOL)isEqual:(id)other { - if (other == self) { - return YES; - } else if (![other isKindOfClass:[BALPrimitiveValue class]]) { - return NO; - } else { - BALPrimitiveValue *castedOther = other; - // Pointer comparaison takes care of nil values - return self.type == castedOther.type && - (self.value == castedOther.value || [self.value isEqual:castedOther.value]); - } -} - -- (NSString *)description { - if (self.type == BALPrimitiveValueTypeNil) { - return @"Nil"; - } - - NSString *valueDescription = [self.value description]; - - if (self.type == BALPrimitiveValueTypeString) { - valueDescription = [NSString stringWithFormat:@"\"%@\"", [self escapeString:valueDescription]]; - } else if (self.type == BALPrimitiveValueTypeStringSet) { - valueDescription = [self setDescription:self.value]; - } - - return valueDescription; -} - -- (NSString *)debugDescription { - NSString *valueDescription = [self.value description]; - NSString *typeDescription; - switch (self.type) { - case BALPrimitiveValueTypeNil: - typeDescription = @"Nil"; - break; - case BALPrimitiveValueTypeBool: - typeDescription = @"Bool"; - break; - case BALPrimitiveValueTypeDouble: - typeDescription = @"Double"; - break; - case BALPrimitiveValueTypeString: - typeDescription = @"String"; - valueDescription = [NSString stringWithFormat:@"\"%@\"", [self escapeString:valueDescription]]; - break; - case BALPrimitiveValueTypeStringSet: - typeDescription = @"String Set"; - valueDescription = [self setDescription:self.value]; - break; - default: - typeDescription = @"Unknown primitive type."; - break; - } - - return [NSString stringWithFormat:@" Type: %@, Value: \"%@\"", typeDescription, valueDescription]; -} - -- (NSString *)escapeString:(NSString *)value { - value = [value stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; - value = [value stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; - value = [value stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; - value = [value stringByReplacingOccurrencesOfString:@"\t" withString:@"\\t"]; - value = [value stringByReplacingOccurrencesOfString:@"\'" withString:@"\\'"]; - value = [value stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; - - return value; -} - -- (NSString *)setDescription:(NSSet *)set { - if (![set isKindOfClass:[NSSet class]]) { - return @"[error]"; - } - - NSMutableString *desc = [NSMutableString new]; - - [desc appendString:@"["]; - - NSArray *array = [set allObjects]; - for (int i = 0; i < array.count; i++) { - if (i > 0) { - [desc appendString:@" "]; - } - [desc appendString:[NSString stringWithFormat:@"\"%@\"", [self escapeString:array[i]]]]; - } - - [desc appendString:@"]"]; - - return desc; -} - -@end - -@implementation BALOperatorValue - -- (instancetype)initWithOperator:(BALOperator *)operator{ - self = [super init]; - if (self) { - _operator = operator; - } - return self; -} - -+ (instancetype)operatorValueWithOperator:(BALOperator *)operator{ - return [[BALOperatorValue alloc] initWithOperator:operator]; -} - -- (BOOL)isEqual:(id)other { - if (other == self) { - return YES; - } else if (![other isKindOfClass:[BALOperatorValue class]]) { - return NO; - } else { - return [self.operator.symbol isEqualToString:((BALOperatorValue*)other).operator.symbol]; - } -} - -- (NSString *)description { - return self.operator.symbol; -} - -- (NSString *)debugDescription { - return [NSString stringWithFormat:@" Symbol: %@", self.operator.symbol]; -} - -@end - -@implementation BALVariableValue - -- (instancetype)initWithName:(NSString *)name { - self = [super init]; - if (self) { - _name = name; - } - return self; -} - -+ (instancetype)variableWithName:(NSString *)name { - return [[BALVariableValue alloc] initWithName:name]; -} - -- (BOOL)isEqual:(id)other { - if (other == self) { - return YES; - } else if (![other isKindOfClass:[BALVariableValue class]]) { - return NO; - } else { - return [self.name isEqualToString:((BALVariableValue *)other).name]; - } -} - -- (nonnull BALValue *)reduce:(nonnull id)context { - BALValue *resolved = [context resolveVariableNamed:self.name.lowercaseString]; - if (resolved == nil) { - resolved = [BALPrimitiveValue nilValue]; - } - return resolved; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"`%@`", self.name]; -} - -- (NSString *)debugDescription { - return [NSString stringWithFormat:@": %@", self.name]; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/BALispParser.h b/Sources/Batch/Modules/Lisp/BALispParser.h deleted file mode 100644 index 1b4151d..0000000 --- a/Sources/Batch/Modules/Lisp/BALispParser.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Parser.h -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import - -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - Simple LISP parser that errors out whenever anything unexpected happens, or ignores it. - - Not really robust, but will do the job as we control both ends. - - This parser also only supports parsing one list at a time, and nothing else. - - Note: This parser is NOT thread-safe, and can only be used once. - */ -@interface BALispParser : NSObject - -/** - Initialize the parser with for the given LISP S-Expression - It should start with ( and end with ) - */ -- (instancetype)initWithExpression:(NSString*)expression; - -/** - Parse. - - @return A S-Expression (which implements BALReducable), or an ErrorValue - */ -- (BALValue*)parse; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/BALispParser.m b/Sources/Batch/Modules/Lisp/BALispParser.m deleted file mode 100644 index ca75352..0000000 --- a/Sources/Batch/Modules/Lisp/BALispParser.m +++ /dev/null @@ -1,271 +0,0 @@ -// -// Parser.m -// BatchObjLisp -// -// Copyright © 2018 Batch. All rights reserved. -// - -#import - -#define TOKEN_DELIMITER_VARIABLE '`' -#define TOKEN_DELIMITER_STRING '"' -#define TOKEN_DELIMITER_LIST_START '(' -#define TOKEN_DELIMITER_STRING_ARRAY_START '[' - -@implementation BALispParser { - BOOL isConsumed; - NSUInteger _pos; // NEVER access/modify this directly: always use getNextChar - NSUInteger _maxPos; - NSString *input; - BOOL endReached; - BALOperatorProvider *operators; - NSNumberFormatter *numberFormatter; -} - -- (instancetype)initWithExpression:(NSString *)expression { - self = [super init]; - if (self) { - isConsumed = false; - input = [expression stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]; - _maxPos = MAX(0, input.length - 1); - endReached = _maxPos == 0 ? true : false; - _pos = 0; - operators = [BALOperatorProvider new]; - numberFormatter = [NSNumberFormatter new]; - numberFormatter.allowsFloats = true; - numberFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; - numberFormatter.numberStyle = NSNumberFormatterNoStyle; - numberFormatter.groupingSeparator = @","; - numberFormatter.decimalSeparator = @"."; - } - return self; -} - -- (BALValue *)parse { - if (isConsumed) { - return [self errorWithMessage:@"This parser has already been consumed. Please instanciate a new one."]; - } - - isConsumed = true; - - if ([self getNextChar] == TOKEN_DELIMITER_LIST_START) { - return [self parseList]; - } - return [self errorWithPositionAndMessage:[NSString stringWithFormat:@"Expected %c", TOKEN_DELIMITER_LIST_START]]; -} - -- (unichar)getNextChar { - if (endReached) { - return '\0'; - } - - unichar c = [input characterAtIndex:_pos]; - if (_pos == _maxPos) { - endReached = true; - } else { - _pos++; - } - return c; -} - -- (BALValue *)parseList { - // ( has already been consumed - NSMutableArray *values = [NSMutableArray new]; - NSMutableString *tokenAccumulator; - - while (!endReached) { - unichar c = [self getNextChar]; - - if (c == ')' || c == ' ') { - // Both can mark the end of a symbol - if (tokenAccumulator != nil) { - // Unprefixed values can either be values or operators - BALValue *tmpVal = [self parseSpecial:tokenAccumulator]; - - if (tmpVal == nil) { - tmpVal = [self parseOperator:tokenAccumulator]; - } - - if (tmpVal == nil) { - tmpVal = [self parseNumber:tokenAccumulator]; - } - - if (tmpVal == nil) { - tmpVal = [self - errorWithMessage:[NSString stringWithFormat:@"Unknown symbol '%@': It is not an operator, and " - @"it could not be converted to a number", - tokenAccumulator]]; - } - - [values addObject:tmpVal]; - tokenAccumulator = nil; - } - - if (c == ')') { - for (BALValue *val in values) { - if ([val isKindOfClass:[BALErrorValue class]]) { - return val; - } - } - return [BALSExpression expressionWithValues:values]; - } - } else if (c == TOKEN_DELIMITER_STRING) { - [values addObject:[self parseString]]; - } else if (c == TOKEN_DELIMITER_VARIABLE) { - [values addObject:[self parseVariable]]; - } else if (c == TOKEN_DELIMITER_LIST_START) { - [values addObject:[self parseList]]; - } else if (c == TOKEN_DELIMITER_STRING_ARRAY_START) { - [values addObject:[self parseStringArray]]; - } else { - if (tokenAccumulator == nil) { - tokenAccumulator = [NSMutableString new]; - } - [tokenAccumulator appendString:[NSString stringWithCharacters:&c length:1]]; - } - } - - return [self errorUnexpectedEOF:@")"]; -} - -- (BALValue *)parseStringArray { - NSMutableSet *values = [NSMutableSet new]; - - while (!endReached) { - unichar c = [self getNextChar]; - - if (c == ']') { - return [BALPrimitiveValue valueWithStringSet:values]; - } else if (c == TOKEN_DELIMITER_STRING) { - BALValue *stringValue = [self parseString]; - if ([stringValue isKindOfClass:[BALErrorValue class]]) { - return stringValue; - } else if ([stringValue isKindOfClass:[BALPrimitiveValue class]] && - [(BALPrimitiveValue *)stringValue type] == BALPrimitiveValueTypeString && - [[(BALPrimitiveValue *)stringValue value] isKindOfClass:[NSString class]]) { - [values addObject:(NSString *)[(BALPrimitiveValue *)stringValue value]]; - } else { - return - [self errorWithPositionAndMessage: - [NSString stringWithFormat:@"Internal parser error: value is not a string nor an error"]]; - } - } else if (c != ' ') { - return [self - errorWithPositionAndMessage: - [NSString stringWithFormat:@"Unexpected character '%c' in string arary, expected \" or ]", c]]; - } - } - - return [self errorUnexpectedEOF:@"]"]; -} - -- (BALValue *)parseString { - NSMutableString *accumulator = [NSMutableString new]; - BOOL isEscaping = false; - - while (!endReached) { - unichar c = [self getNextChar]; - - if (isEscaping) { - switch (c) { - case '\\': // Actually / - c = '\\'; - break; - case 'n': - c = '\n'; - break; - case 't': - c = '\t'; - break; - case 'r': - c = '\r'; - break; - case '"': - c = '"'; - break; - case '\'': // Actually ' - c = '\''; - break; - default: - return [self - errorWithPositionAndMessage:[NSString stringWithFormat:@"Invalid escaped character: \\%c", c]]; - } - - isEscaping = false; - } else if (c == '\\') { - isEscaping = true; - continue; - } else if (c == TOKEN_DELIMITER_STRING) { - return [BALPrimitiveValue valueWithString:accumulator]; - } - - [accumulator appendString:[NSString stringWithCharacters:&c length:1]]; - } - return [self errorUnexpectedEOF:[NSString stringWithFormat:@"%c", TOKEN_DELIMITER_STRING]]; -} - -- (nullable BALPrimitiveValue *)parseSpecial:(NSString *)token { - token = [token lowercaseString]; - - if ([token isEqualToString:@"true"]) { - return [BALPrimitiveValue valueWithBoolean:true]; - } else if ([token isEqualToString:@"false"]) { - return [BALPrimitiveValue valueWithBoolean:false]; - } else if ([token isEqualToString:@"nil"]) { - return [BALPrimitiveValue nilValue]; - } - - return nil; -} - -- (nullable BALPrimitiveValue *)parseNumber:(NSString *)numberString { - NSNumber *parsedNumber = [numberFormatter numberFromString:numberString]; - if (parsedNumber == nil) { - return nil; - } - return [BALPrimitiveValue valueWithDouble:[parsedNumber doubleValue]]; -} - -- (nullable BALOperatorValue *)parseOperator:(NSString *)symbol { - BALOperator *op = [operators operatorForSymbol:symbol.lowercaseString]; - if (op == nil) { - return nil; - } - return [BALOperatorValue operatorValueWithOperator:op]; -} - -- (BALValue *)parseVariable { - NSMutableString *accumulator = [NSMutableString new]; - - while (!endReached) { - unichar c = [self getNextChar]; - - if (c == TOKEN_DELIMITER_VARIABLE) { - if ([accumulator stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet].length == - 0) { - return [self errorWithMessage:@"Variables cannot have an empty name"]; - } - return [BALVariableValue variableWithName:accumulator]; - } - - [accumulator appendString:[NSString stringWithCharacters:&c length:1]]; - } - return [self errorUnexpectedEOF:[NSString stringWithFormat:@"%c", TOKEN_DELIMITER_VARIABLE]]; -} - -- (BALErrorValue *)errorWithMessage:(NSString *)message { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeParser message:message]; -} - -- (BALErrorValue *)errorUnexpectedEOF:(NSString *)expected { - return [BALErrorValue errorWithKind:BALErrorValueKindTypeParser - message:[NSString stringWithFormat:@"Unexpected EOF. Expected: %@", expected]]; -} - -- (BALErrorValue *)errorWithPositionAndMessage:(NSString *)message { - return - [BALErrorValue errorWithKind:BALErrorValueKindTypeParser - message:[NSString stringWithFormat:@"At position %lu: %@", (unsigned long)_pos, message]]; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.h b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.h deleted file mode 100644 index 65bc115..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// BALCachingContext.h -// BatchTests -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - Wrapper context that adds a caching layer - - This is NOT thread safe - */ -@interface BALCachingContext : NSObject - -+ (instancetype)cachingContextWithContext:(id)context; - -- (instancetype)initWithContext:(id)context; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.m b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.m deleted file mode 100644 index 15eb7ac..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALCachingContext.m +++ /dev/null @@ -1,48 +0,0 @@ -// -// BALCachingContext.m -// BatchTests -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -@implementation BALCachingContext { - NSMutableDictionary *_cache; - id _context; -} - -+ (instancetype)cachingContextWithContext:(id)context { - return [[BALCachingContext alloc] initWithContext:context]; -} - -- (instancetype)initWithContext:(id)context { - self = [super init]; - if (self) { - _cache = [NSMutableDictionary new]; - _context = context; - } - return self; -} - -- (nullable BALValue *)resolveVariableNamed:(NSString *)name { - id cachedValue = _cache[name]; - if (cachedValue == [NSNull null]) { - // Cache hit, but it was nil - return nil; - } else if (cachedValue != nil) { - return cachedValue; - } - - BALValue *resolved = [_context resolveVariableNamed:name]; - - if (resolved != nil) { - _cache[name] = resolved; - } else { - _cache[name] = [NSNull null]; - } - - return resolved; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.h b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.h deleted file mode 100644 index 4cbb3b2..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// BALEventContext.h -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class BatchEventData; - -@interface BALEventContext : NSObject - -+ (instancetype)contextWithPrivateEvent:(NSString*)name; - -+ (instancetype)contextWithPublicEvent:(NSString*)name label:(nullable NSString*)label data:(nullable BatchEventData*)data; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.m b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.m deleted file mode 100644 index 04ed080..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALEventContext.m +++ /dev/null @@ -1,157 +0,0 @@ -// -// BALEventContext.m -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -#import -#import - -@implementation BALEventContext { - NSString *_eventName; - NSString *_eventLabel; - BatchEventData *_data; - BOOL _publicEvent; -} - -+ (instancetype)contextWithPrivateEvent:(NSString *)name { - return [[BALEventContext alloc] initWithEvent:name label:nil data:nil]; -} - -+ (instancetype)contextWithPublicEvent:(NSString *)name - label:(nullable NSString *)label - data:(nullable BatchEventData *)data { - return [[BALEventContext alloc] initWithEvent:name label:label data:data]; -} - -- (instancetype)initWithEvent:(NSString *)name label:(nullable NSString *)label data:(nullable BatchEventData *)data { - self = [super init]; - if (self) { - _eventName = [name copy]; - _eventLabel = [label copy]; - _data = [data copy]; - _publicEvent = [_eventName hasPrefix:@"E."]; - } - return self; -} - -- (nullable BALValue *)resolveVariableNamed:(nonnull NSString *)variableName { - if (![variableName hasPrefix:@"e."]) { - return nil; - } - - if ([variableName isEqualToString:@"e.name"]) { - return [BALPrimitiveValue valueWithString:_eventName]; - } else if ([variableName isEqualToString:@"e.label"]) { - return [self label]; - } else if ([variableName isEqualToString:@"e.tags"]) { - return [self tags]; - } else if ([variableName isEqualToString:@"e.converted"]) { - return [self converted]; - } else if ([variableName hasPrefix:@"e.attr['"]) { - return [self dataForRawVariableName:variableName]; - } - - return nil; -} - -- (nonnull BALValue *)label { - if (_publicEvent && _eventLabel != nil) { - return [BALPrimitiveValue valueWithString:_eventLabel]; - } - - return [BALPrimitiveValue nilValue]; -} - -- (nonnull BALValue *)tags { - if (_publicEvent && _data != nil) { - NSSet *tags = _data->_tags; - - if ([tags isKindOfClass:[NSSet class]]) { - return [BALPrimitiveValue valueWithStringSet:tags]; - } - } - - return [BALPrimitiveValue nilValue]; -} - -- (nonnull BALValue *)converted { - if (_publicEvent && _data != nil) { - return [BALPrimitiveValue valueWithBoolean:_data->_convertedFromLegacy]; - } - - return [BALPrimitiveValue valueWithBoolean:false]; -} - -- (nonnull BALValue *)dataForRawVariableName:(NSString *)variableName { - if (_publicEvent && _data != nil) { - NSDictionary *attributes = _data->_attributes; - - if (![attributes isKindOfClass:[NSDictionary class]] || [attributes count] == 0) { - return [BALPrimitiveValue nilValue]; - } - - NSString *wantedAttributeName = [self extractAttributeFromVariableName:variableName]; - - if (wantedAttributeName == nil) { - return [BALPrimitiveValue nilValue]; - } - - BATTypedEventAttribute *typedAttribute = attributes[wantedAttributeName]; - if (typedAttribute != nil) { - NSObject *value = typedAttribute.value; - switch (typedAttribute.type) { - case BAEventAttributeTypeBool: - if ([value isKindOfClass:[NSNumber class]]) { - return [BALPrimitiveValue valueWithBoolean:[(NSNumber *)value boolValue]]; - } - break; - case BAEventAttributeTypeDouble: - if ([value isKindOfClass:[NSNumber class]]) { - return [BALPrimitiveValue valueWithDouble:[(NSNumber *)value doubleValue]]; - } - break; - case BAEventAttributeTypeInteger: - if ([value isKindOfClass:[NSNumber class]]) { - return [BALPrimitiveValue valueWithDouble:[(NSNumber *)value integerValue]]; - } - break; - case BAEventAttributeTypeString: - if ([value isKindOfClass:[NSString class]]) { - return [BALPrimitiveValue valueWithString:(NSString *)value]; - } - break; - case BAEventAttributeTypeDate: - if ([value isKindOfClass:[NSDate class]]) { - // Multiply by 1000 to get milliseconds, in order to conform to its Java counterpart. - return [BALPrimitiveValue - valueWithDouble:floor(((NSDate *)value).timeIntervalSince1970 * (double)1000)]; - } - case BAEventAttributeTypeURL: - if ([value isKindOfClass:[NSURL class]]) { - return [BALPrimitiveValue valueWithURL:(NSURL *)value]; - } - break; - } - } - } - - return [BALPrimitiveValue nilValue]; -} - -- (nullable NSString *)extractAttributeFromVariableName:(NSString *)variableName { - // Assume that we already checked that the string is prefixed by e.attr[" - if ([variableName hasSuffix:@"']"] && variableName.length > 10) { - NSString *extractedName = [variableName substringWithRange:NSMakeRange(8, variableName.length - 10)]; - if ([extractedName length] > 0) { - return extractedName; - } - } - - return nil; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.h b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.h deleted file mode 100644 index 56cb0f1..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// BALMetaContext.h -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN -/** - Context wrapper that's an union of multiple contexts - - It should be initialized with the contextes in order of priority: first one to give a non "nil" - (not to be confused with a BALPrimitiveValue with a nil type, which is considered a result) - will "win". - */ -@interface BALMetaContext : NSObject - -+ (instancetype)metaContextWithContexts:(NSArray>*)contexts; - -- (instancetype)initWithContexts:(NSArray>*)contexts; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.m b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.m deleted file mode 100644 index 05f4c87..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALMetaContext.m +++ /dev/null @@ -1,37 +0,0 @@ -// -// BALMetaContext.m -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -@implementation BALMetaContext { - NSArray> *_contexts; -} - -+ (instancetype)metaContextWithContexts:(NSArray> *)contexts { - return [[BALMetaContext alloc] initWithContexts:contexts]; -} - -- (instancetype)initWithContexts:(NSArray> *)contexts { - self = [super init]; - if (self) { - _contexts = [contexts copy]; - } - return self; -} - -- (nullable BALValue *)resolveVariableNamed:(nonnull NSString *)name { - BALValue *val = nil; - for (id ctx in _contexts) { - val = [ctx resolveVariableNamed:name]; - if (val != nil) { - return val; - } - } - return nil; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALNativeAttributeContext.m b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALNativeAttributeContext.m deleted file mode 100644 index b705b59..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALNativeAttributeContext.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// BALNativeAttributeContext.m -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -#import - -@implementation BALNativeAttributeContext - -- (nullable BALValue *)resolveVariableNamed:(nonnull NSString *)name { - if ([name hasPrefix:@"b."] && [name length] > 2) { - NSString *parameter = [BAPropertiesCenter valueForShortName:[name substringFromIndex:2]]; - - if (parameter != nil && [parameter length] > 0) { - return [BALPrimitiveValue valueWithString:parameter]; - } else { - return [BALPrimitiveValue nilValue]; - } - } - return nil; -} - -@end diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.h b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.h deleted file mode 100644 index 0bf8345..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// BALUserAttributeContext.h -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface BALUserAttributeContext : NSObject - -+ (instancetype)contextWithDatasource:(id)datasource; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.m b/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.m deleted file mode 100644 index cfa16a8..0000000 --- a/Sources/Batch/Modules/Lisp/Evaluation Contexts/BALUserAttributeContext.m +++ /dev/null @@ -1,120 +0,0 @@ -// -// BALUserAttributeContext.m -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -@implementation BALUserAttributeContext { - id _datasource; - NSDictionary *_attributes; - NSDictionary *> *_tagCollections; -} - -+ (instancetype)contextWithDatasource:(id)datasource { - return [[BALUserAttributeContext alloc] initWithDatasource:datasource]; -} - -- (instancetype)initWithDatasource:(id)datasource; -{ - self = [super init]; - if (self) { - _datasource = datasource; - - // Attributes and tags are lazily fetched - // The code could be optimized further by tweaking the datasources to be able - // to only fetch a specific attribute - } - return self; -} - -- (nullable BALValue *)resolveVariableNamed:(nonnull NSString *)name { - if ([name length] > 2) { - if ([name hasPrefix:@"c."]) { - [self fetchAttributes]; - - for (NSString *key in _attributes.allKeys) { - BAUserAttribute *attr = _attributes[key]; - // Attributes are stored with "c." - if ([name caseInsensitiveCompare:key] == NSOrderedSame) { - return [self attributeToValue:attr]; - } - } - return [BALPrimitiveValue nilValue]; - - } else if ([name hasPrefix:@"t."]) { - NSString *wantedCollection = [name substringFromIndex:2]; - if (wantedCollection != nil && [wantedCollection length] > 0) { - [self fetchTags]; - NSSet *collection = _tagCollections[wantedCollection]; - if (collection != nil) { - return [BALPrimitiveValue valueWithStringSet:collection]; - } - } - return [BALPrimitiveValue nilValue]; - } - } - return nil; -} - -- (void)fetchAttributes { - if (_attributes == nil) { - _attributes = [_datasource attributes]; - } -} - -- (void)fetchTags { - if (_tagCollections == nil) { - _tagCollections = [_datasource tagCollections]; - } -} - -- (BALValue *)attributeToValue:(BAUserAttribute *)attribute { - if (attribute == nil) { - return [BALPrimitiveValue nilValue]; - } - - switch (attribute.type) { - case BAUserAttributeTypeDate: { - NSDate *date = attribute.value; - if ([date isKindOfClass:[NSDate class]]) { - // Multiply by 1000 to get milliseconds, in order to conform to its Java counterpart. - return [BALPrimitiveValue valueWithDouble:floor(date.timeIntervalSince1970 * (double)1000)]; - } - } - case BAUserAttributeTypeBool: { - NSNumber *nbr = attribute.value; - if ([nbr isKindOfClass:[NSNumber class]]) { - return [BALPrimitiveValue valueWithBoolean:[nbr boolValue]]; - } - } - case BAUserAttributeTypeDouble: - case BAUserAttributeTypeLongLong: { - NSNumber *nbr = attribute.value; - if ([nbr isKindOfClass:[NSNumber class]]) { - return [BALPrimitiveValue valueWithDouble:[nbr doubleValue]]; - } - } - case BAUserAttributeTypeString: { - NSString *str = attribute.value; - if ([str isKindOfClass:[NSString class]]) { - return [BALPrimitiveValue valueWithString:str]; - } - } - case BAUserAttributeTypeURL: { - NSURL *url = attribute.value; - if ([url isKindOfClass:[NSURL class]]) { - return [BALPrimitiveValue valueWithURL:url]; - } - } - case BAUserAttributeTypeDeleted: - default: - return [BALPrimitiveValue nilValue]; - } - - return [BALPrimitiveValue nilValue]; -} - -@end diff --git a/Sources/Batch/Modules/Local Campaigns/BALocalCampaign.h b/Sources/Batch/Modules/Local Campaigns/BALocalCampaign.h index 6784db4..63ec7c7 100644 --- a/Sources/Batch/Modules/Local Campaigns/BALocalCampaign.h +++ b/Sources/Batch/Modules/Local Campaigns/BALocalCampaign.h @@ -5,18 +5,17 @@ // Copyright © 2016 Batch. All rights reserved. // -#import +#import #import #import -#import #import +#import /** Represents an local campaign */ @interface BALocalCampaign : NSObject - /** Campaign ID, used to track views and capping */ @@ -41,7 +40,7 @@ /** Minimum messaging API level Optional (0 = ignored) - + The minimum messaging API level required to display this campaign (shouldn't be confused with the SDK API level) */ @property (assign) NSInteger minimumAPILevel; @@ -49,15 +48,16 @@ /** Maximum messaging API level Optional (0 = ignored) - - The maximum messaging API level that shouldn't be exceeded to display this campaign (shouldn't be confused with the SDK API level) + + The maximum messaging API level that shouldn't be exceeded to display this campaign (shouldn't be confused with the SDK + API level) */ @property (assign) NSInteger maximumAPILevel; /** Priority Optional - + Priority score: the higher, the more likely it is to be shown to the user Used as a "last resort" method to pick the most appropriate In-App campaign */ @@ -65,7 +65,7 @@ /** Campaign start date - + If the device date is earlier than this date, the campaign should not be displayed */ @property (nonnull, strong) BATZAwareDate *startDate; @@ -73,7 +73,7 @@ /** Campaign end date Optional - + If it is defined and the device date is later than this date, the campaign should not be displayed */ @property (nullable, strong) BATZAwareDate *endDate; @@ -81,7 +81,7 @@ /** "Hard" capping Optional (0 = ignored) - + Number of times a user can view this campaign before being uneligible */ @property (assign) NSInteger capping; @@ -94,15 +94,15 @@ /** Triggers - + Triggers that will trigger the display of the campaign. For example: event-based trigger. */ -@property (nonnull, strong) NSArray>* triggers; +@property (nonnull, strong) NSArray> *triggers; /** Persist Optional (default = yes) - + Whether this campaign should be persisted on disk or not. */ @property (assign) BOOL persist; @@ -120,7 +120,7 @@ /** Requires Just In Time Sync Optional (default = false) - + Whether this campaign should be verified by the server before being displayed. */ @property (assign) BOOL requiresJustInTimeSync; diff --git a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsCenter.h b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsCenter.h index 39f88ae..70131d2 100644 --- a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsCenter.h +++ b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsCenter.h @@ -9,9 +9,9 @@ #import +#import #import #import -#import @class BatchEventData; @@ -43,24 +43,26 @@ /** Called when an internal event is tracked - Will perform a quick check using a cache, and if there's a potentially wanted event, will submit the task to an queue so that - the checks required do not block the thread + Will perform a quick check using a cache, and if there's a potentially wanted event, will submit the task to an queue + so that the checks required do not block the thread */ -- (void)processTrackerPrivateEventNamed:(nonnull NSString*)name; +- (void)processTrackerPrivateEventNamed:(nonnull NSString *)name; /** Called when a public event is tracked - Will perform a quick check using a cache, and if there's a potentially wanted event, will submit the task to an queue so that - the checks required do not block the thread + Will perform a quick check using a cache, and if there's a potentially wanted event, will submit the task to an queue + so that the checks required do not block the thread */ -- (void)processTrackerPublicEventNamed:(nonnull NSString*)name label:(nullable NSString*)label data:(nullable BatchEventData*)data; +- (void)processTrackerPublicEventNamed:(nonnull NSString *)name + label:(nullable NSString *)label + data:(nullable BatchEventData *)data; /** Notify this module of the display of an In-App Campaign. Used for example for increasing the view count of a campaign, in order to be able to make the capping work. */ -- (void)didPerformCampaignOutputWithIdentifier:(nonnull NSString*)identifier eventData:(nullable NSObject*)eventData; +- (void)didPerformCampaignOutputWithIdentifier:(nonnull NSString *)identifier eventData:(nullable NSObject *)eventData; /** Handle the WS response payload: @@ -68,14 +70,14 @@ - Write it on disk if valid - Emit the campaigns loaded signal */ -- (void)handleWebserviceResponsePayload:(nonnull NSDictionary*)payload; +- (void)handleWebserviceResponsePayload:(nonnull NSDictionary *)payload; /** Notify this module that the local campaigns webservice has finished with success or not. - + Used to release the signal queue. */ --(void)localCampaignsWebserviceDidFinish; +- (void)localCampaignsWebserviceDidFinish; /** Trigger a WS call to refresh the campaigns diff --git a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsGlobalCappings.h b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsGlobalCappings.h index cf49441..6fd76d1 100644 --- a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsGlobalCappings.h +++ b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsGlobalCappings.h @@ -15,7 +15,7 @@ @property (nullable) NSNumber *session; /// List of time-based cappings -@property (nullable) NSArray* timeBasedCappings; +@property (nullable) NSArray *timeBasedCappings; @end @@ -31,6 +31,4 @@ /// Capping duration ( in seconds ) @property (nullable) NSNumber *duration; - @end - diff --git a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsManager.h b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsManager.h index 5f9b25a..fb79d78 100644 --- a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsManager.h +++ b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsManager.h @@ -7,8 +7,8 @@ #import -#import #import +#import #import #import @@ -29,20 +29,22 @@ typedef NS_ENUM(NSInteger, BATSyncedJITCampaignState) { */ @interface BALocalCampaignsManager : NSObject -- (instancetype)initWithViewTracker:(id )viewTracker; +- (instancetype)initWithViewTracker:(id)viewTracker; -- (instancetype)initWithDateProvider:(id )dateProvider viewTracker:(id )viewTracker; +- (instancetype)initWithDateProvider:(id)dateProvider + viewTracker:(id)viewTracker; -@property (readonly, nonnull) NSArray *campaignList; +@property (readonly, nonnull) NSArray *campaignList; @property (nullable) BALocalCampaignsGlobalCappings *cappings; /** - Update the currently stored campaign list. This should usually be done when a WS succeeds or when campaigns are loaded from the disk. - + Update the currently stored campaign list. This should usually be done when a WS succeeds or when campaigns are loaded + from the disk. + Also triggers the campaign loaded signal */ -- (void)loadCampaigns:(NSArray*)updatedCampaignList; +- (void)loadCampaigns:(NSArray *)updatedCampaignList; /** Checks if an event name will trigger at least one campaign, allowing for a fast pre-filter to check if it is worth @@ -54,22 +56,25 @@ typedef NS_ENUM(NSInteger, BATSyncedJITCampaignState) { Get all campaign between all of those that are satisfied by the latest application event and sort them by priority This is the campaign that you'll want to display */ -- (nonnull NSArray*)eligibleCampaignsSortedByPriority:(id)signal; +- (nonnull NSArray *)eligibleCampaignsSortedByPriority:(id)signal; /** Get the first eligible campaigns requiring a JIT sync (Meaning it stop at the first campaign not requiring JIT) */ -- (nonnull NSArray*)firstEligibleCampaignsRequiringSync:(NSArray*)eligibleCampaigns; +- (nonnull NSArray *)firstEligibleCampaignsRequiringSync: + (NSArray *)eligibleCampaigns; /** Get the first eligible campaign not requiring a JIT sync */ -- (nullable BALocalCampaign*)firstCampaignNotRequiringJITSync:(NSArray*)eligibleCampaigns; +- (nullable BALocalCampaign *)firstCampaignNotRequiringJITSync:(NSArray *)eligibleCampaigns; /** Checking with server if campaigns are still eligible */ -- (void)verifyCampaignsEligibilityFromServer:(NSArray*)eligibleCampaigns withCompletion:(void (^ _Nonnull)(BALocalCampaign* _Nullable electedCampaign))completionHandler; +- (void)verifyCampaignsEligibilityFromServer:(NSArray *)eligibleCampaigns + withCompletion: + (void (^_Nonnull)(BALocalCampaign *_Nullable electedCampaign))completionHandler; /** Check if JIT webservice is available. @@ -79,14 +84,14 @@ typedef NS_ENUM(NSInteger, BATSyncedJITCampaignState) { /** Check if the given campaign has been already synced recently */ -- (BATSyncedJITCampaignState)syncedJITCampaignState:(BALocalCampaign*)campaign; +- (BATSyncedJITCampaignState)syncedJITCampaignState:(BALocalCampaign *)campaign; /** Get the view counts for the loaded campaigns - + Can be nil if no campaigns are loaded */ -- (nullable NSDictionary*)viewCountsForLoadedCampaigns; +- (nullable NSDictionary *)viewCountsForLoadedCampaigns; /** Check if the global in-apps cappings have been reached. diff --git a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsParser.h b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsParser.h index 67326a8..ce4e0b2 100644 --- a/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsParser.h +++ b/Sources/Batch/Modules/Local Campaigns/BALocalCampaignsParser.h @@ -7,21 +7,24 @@ #import -#import #import +#import #import NS_ASSUME_NONNULL_BEGIN @interface BALocalCampaignsParser : NSObject -+ (nullable NSArray*)parseCampaigns:(nonnull NSDictionary*)rawJson outPersistable:(NSDictionary * _Nullable * _Nullable)persist error:(NSError**)error; ++ (nullable NSArray *)parseCampaigns:(nonnull NSDictionary *)rawJson + outPersistable:(NSDictionary *_Nullable *_Nullable)persist + error:(NSError **)error; -+ (nullable BALocalCampaign*)parseCampaign:(nonnull NSDictionary*)rawJson error:(NSError**)error; ++ (nullable BALocalCampaign *)parseCampaign:(nonnull NSDictionary *)rawJson error:(NSError **)error; -+ (nullable id)parseTrigger:(nonnull NSDictionary*)rawJson error:(NSError**)error; ++ (nullable id)parseTrigger:(nonnull NSDictionary *)rawJson error:(NSError **)error; -+ (nullable BALocalCampaignsGlobalCappings*)parseCappings:(nonnull NSDictionary*)rawJson outPersistable:(NSDictionary * _Nullable * _Nullable)persist; ++ (nullable BALocalCampaignsGlobalCappings *)parseCappings:(nonnull NSDictionary *)rawJson + outPersistable:(NSDictionary *_Nullable *_Nullable)persist; @end diff --git a/Sources/Batch/Modules/Local Campaigns/Outputs/BALocalCampaignOutputProtocol.h b/Sources/Batch/Modules/Local Campaigns/Outputs/BALocalCampaignOutputProtocol.h index 3511526..5a64e3c 100644 --- a/Sources/Batch/Modules/Local Campaigns/Outputs/BALocalCampaignOutputProtocol.h +++ b/Sources/Batch/Modules/Local Campaigns/Outputs/BALocalCampaignOutputProtocol.h @@ -15,16 +15,16 @@ NS_ASSUME_NONNULL_BEGIN /** Represents a local campaign output - + An output is the action executed by a triggered local campaign */ @protocol BALocalCampaignOutputProtocol @required -- (nullable instancetype)initWithPayload:(nonnull NSDictionary*)payload error:(NSError**)error; +- (nullable instancetype)initWithPayload:(nonnull NSDictionary *)payload error:(NSError **)error; -- (void)performForCampaign:(nonnull BALocalCampaign*)campaign; +- (void)performForCampaign:(nonnull BALocalCampaign *)campaign; @end diff --git a/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsFilePersistence.h b/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsFilePersistence.h index 7efbd44..fbe76f5 100644 --- a/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsFilePersistence.h +++ b/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsFilePersistence.h @@ -5,8 +5,8 @@ // Copyright © 2017 Batch. All rights reserved. // -#import #import +#import @interface BALocalCampaignsFilePersistence : NSObject diff --git a/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsPersisting.h b/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsPersisting.h index 01ab952..69b5853 100644 --- a/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsPersisting.h +++ b/Sources/Batch/Modules/Local Campaigns/Persistence/BALocalCampaignsPersisting.h @@ -11,9 +11,9 @@ NS_ASSUME_NONNULL_BEGIN @required -- (void)persistCampaigns:(nonnull NSDictionary*)rawCampaignsData; +- (void)persistCampaigns:(nonnull NSDictionary *)rawCampaignsData; -- (nullable NSDictionary*)loadCampaignsWithError:(NSError**)error; +- (nullable NSDictionary *)loadCampaignsWithError:(NSError **)error; - (void)deleteCampaigns; diff --git a/Sources/Batch/Modules/Local Campaigns/Signals/BALocalCampaignSignalProtocol.h b/Sources/Batch/Modules/Local Campaigns/Signals/BALocalCampaignSignalProtocol.h index d925f56..75c59ad 100644 --- a/Sources/Batch/Modules/Local Campaigns/Signals/BALocalCampaignSignalProtocol.h +++ b/Sources/Batch/Modules/Local Campaigns/Signals/BALocalCampaignSignalProtocol.h @@ -11,7 +11,7 @@ /** Represents an signal - + A signal is anything that happens during the lifecycle of an app that can trigger a local campaign */ diff --git a/Sources/Batch/Modules/Local Campaigns/Signals/BAPublicEventTrackedSignal.h b/Sources/Batch/Modules/Local Campaigns/Signals/BAPublicEventTrackedSignal.h index c089067..e3afe3a 100644 --- a/Sources/Batch/Modules/Local Campaigns/Signals/BAPublicEventTrackedSignal.h +++ b/Sources/Batch/Modules/Local Campaigns/Signals/BAPublicEventTrackedSignal.h @@ -19,6 +19,8 @@ @property (nullable, assign) BatchEventData *data; -- (nonnull instancetype)initWithName:(nonnull NSString *)name label:(nullable NSString *)label data:(nullable BatchEventData *)data; +- (nonnull instancetype)initWithName:(nonnull NSString *)name + label:(nullable NSString *)label + data:(nullable BatchEventData *)data; @end diff --git a/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignTrackerProtocol.h b/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignTrackerProtocol.h index 2b3add6..ded976b 100644 --- a/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignTrackerProtocol.h +++ b/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignTrackerProtocol.h @@ -17,21 +17,23 @@ NS_ASSUME_NONNULL_BEGIN Returns the updated counted event if successful, nil otherwise */ -- (nullable BALocalCampaignCountedEvent*)trackEventForCampaignID:(NSString*)campaignID kind:(BALocalCampaignTrackerEventKind)kind; +- (nullable BALocalCampaignCountedEvent *)trackEventForCampaignID:(NSString *)campaignID + kind:(BALocalCampaignTrackerEventKind)kind; /** Get aggregated event information for a given campaign ID and event kind. This method never returns nil, even if no event of that kind was ever tracked for this campaign ID. */ -- (BALocalCampaignCountedEvent*)eventInformationForCampaignID:(NSString*)campaignID kind:(BALocalCampaignTrackerEventKind)kind; +- (BALocalCampaignCountedEvent *)eventInformationForCampaignID:(NSString *)campaignID + kind:(BALocalCampaignTrackerEventKind)kind; /** Get the number of view events tracked since a given timestamp Return the number of view events (). */ - - (nullable NSNumber*)numberOfViewEventsSince:(double)timestamp; +- (nullable NSNumber *)numberOfViewEventsSince:(double)timestamp; @end diff --git a/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignsTracker.h b/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignsTracker.h index 6e588ce..4a2ea6d 100644 --- a/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignsTracker.h +++ b/Sources/Batch/Modules/Local Campaigns/Tracker/BALocalCampaignsTracker.h @@ -4,8 +4,8 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import @interface BALocalCampaignsTracker : BALocalCampaignsSQLTracker @@ -14,4 +14,3 @@ - (void)resetSessionViewsCount; @end - diff --git a/Sources/Batch/Modules/Local Campaigns/Triggers/BAEventTrigger.h b/Sources/Batch/Modules/Local Campaigns/Triggers/BAEventTrigger.h index 34af585..98fafb1 100644 --- a/Sources/Batch/Modules/Local Campaigns/Triggers/BAEventTrigger.h +++ b/Sources/Batch/Modules/Local Campaigns/Triggers/BAEventTrigger.h @@ -5,8 +5,8 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import +#import @interface BAEventTrigger : NSObject diff --git a/Sources/Batch/Modules/Local Campaigns/Triggers/BANextSessionTrigger.h b/Sources/Batch/Modules/Local Campaigns/Triggers/BANextSessionTrigger.h index 3950bfb..9c5faef 100644 --- a/Sources/Batch/Modules/Local Campaigns/Triggers/BANextSessionTrigger.h +++ b/Sources/Batch/Modules/Local Campaigns/Triggers/BANextSessionTrigger.h @@ -5,8 +5,8 @@ // Copyright © 2017 Batch. All rights reserved. // -#import #import +#import @interface BANextSessionTrigger : NSObject diff --git a/Sources/Batch/Modules/Messaging/BABatchMessagingDelegateWrapper.h b/Sources/Batch/Modules/Messaging/BABatchMessagingDelegateWrapper.h index 16f3801..7164b3f 100644 --- a/Sources/Batch/Modules/Messaging/BABatchMessagingDelegateWrapper.h +++ b/Sources/Batch/Modules/Messaging/BABatchMessagingDelegateWrapper.h @@ -5,15 +5,16 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import - +#import /** Delegate wrapping the dev's supplied messaging delegate. - Calls to these methods are safe, no matter whether there is a delegate or not, and if it implements the required methods or not. - - Methods usually returning void will return BOOL, indicating if the delegate implemented them and the invocations were forwared to it. + Calls to these methods are safe, no matter whether there is a delegate or not, and if it implements the required + methods or not. + + Methods usually returning void will return BOOL, indicating if the delegate implemented them and the invocations were + forwared to it. */ @interface BABatchMessagingDelegateWrapper : NSObject @@ -33,23 +34,26 @@ */ - (BOOL)hasWrappedDelegate; -- (BOOL)batchMessageDidAppear:(nullable NSString*)messageIdentifier; +- (BOOL)batchMessageDidAppear:(nullable NSString *)messageIdentifier; - (BOOL)batchMessageWasCancelledByUserAction:(nullable NSString *)messageIdentifier; - (BOOL)batchMessageWasCancelledByAutoclose:(nullable NSString *)messageIdentifier; -- (BOOL)batchMessageDidTriggerAction:(nonnull BatchMessageAction *)action messageIdentifier:(nullable NSString *)identifier actionIndex:(NSInteger)index; +- (BOOL)batchMessageDidTriggerAction:(nonnull BatchMessageAction *)action + messageIdentifier:(nullable NSString *)identifier + actionIndex:(NSInteger)index; - (BOOL)batchMessageDidDisappear:(nullable NSString *)messageIdentifier; - (BOOL)batchInAppMessageReady:(nonnull BatchInAppMessage *)message; -- (BOOL)batchMessageWasCancelledByError:(NSString* _Nullable)messageIdentifier NS_SWIFT_NAME(batchMessageWasCancelledByError(_:)); +- (BOOL)batchMessageWasCancelledByError:(NSString *_Nullable)messageIdentifier + NS_SWIFT_NAME(batchMessageWasCancelledByError(_:)); -- (BOOL)batchWebViewMessageDidTriggerAction:(BatchMessageAction * _Nullable)action - messageIdentifier:(NSString * _Nullable)messageIdentifier - analyticsIdentifier:(NSString * _Nullable)analyticsIdentifier; +- (BOOL)batchWebViewMessageDidTriggerAction:(BatchMessageAction *_Nullable)action + messageIdentifier:(NSString *_Nullable)messageIdentifier + analyticsIdentifier:(NSString *_Nullable)analyticsIdentifier; - (nullable UIViewController *)presentingViewControllerForBatchUI; diff --git a/Sources/Batch/Modules/Messaging/BADelegatedUIAlertController.h b/Sources/Batch/Modules/Messaging/BADelegatedUIAlertController.h index 0a074f4..cd51f75 100644 --- a/Sources/Batch/Modules/Messaging/BADelegatedUIAlertController.h +++ b/Sources/Batch/Modules/Messaging/BADelegatedUIAlertController.h @@ -5,17 +5,17 @@ // Copyright © 2016 Batch. All rights reserved. // -#import -#import #import +#import #import +#import @interface BADelegatedUIAlertController : UIAlertController @property (nonnull) BAMSGMessageAlert *messageDescription; -+ (instancetype _Nonnull)alertControllerWithMessage:(BAMSGMessageAlert* _Nonnull)message; ++ (instancetype _Nonnull)alertControllerWithMessage:(BAMSGMessageAlert *_Nonnull)message; -- (instancetype _Nonnull)initWithMessage:(BAMSGMessageAlert* _Nonnull)message; +- (instancetype _Nonnull)initWithMessage:(BAMSGMessageAlert *_Nonnull)message; @end diff --git a/Sources/Batch/Modules/Messaging/BAMSGAction.h b/Sources/Batch/Modules/Messaging/BAMSGAction.h index 0f9611d..d5e8571 100644 --- a/Sources/Batch/Modules/Messaging/BAMSGAction.h +++ b/Sources/Batch/Modules/Messaging/BAMSGAction.h @@ -10,7 +10,7 @@ @interface BAMSGAction : NSObject @property (nullable) NSString *actionIdentifier; -@property (nonnull) NSDictionary *actionArguments; +@property (nonnull) NSDictionary *actionArguments; - (BOOL)isDismissAction; diff --git a/Sources/Batch/Modules/Messaging/BAMSGCTA.h b/Sources/Batch/Modules/Messaging/BAMSGCTA.h index 8dc0d9d..68aa519 100644 --- a/Sources/Batch/Modules/Messaging/BAMSGCTA.h +++ b/Sources/Batch/Modules/Messaging/BAMSGCTA.h @@ -5,8 +5,8 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import +#import @interface BAMSGCTA : BAMSGAction diff --git a/Sources/Batch/Modules/Messaging/BAMSGImageDownloader.h b/Sources/Batch/Modules/Messaging/BAMSGImageDownloader.h index a65e249..6614671 100644 --- a/Sources/Batch/Modules/Messaging/BAMSGImageDownloader.h +++ b/Sources/Batch/Modules/Messaging/BAMSGImageDownloader.h @@ -9,8 +9,11 @@ @interface BAMSGImageDownloader : NSObject -+ (void)downloadImageForURL:(NSURL* _Nonnull)url ++ (void)downloadImageForURL:(NSURL *_Nonnull)url downloadTimeout:(NSTimeInterval)timeout - completionHandler:(void (^ __nonnull)(NSData* _Nullable rawData, BOOL isGif, UIImage* _Nullable image, NSError* _Nullable error))completionHandler; + completionHandler:(void (^__nonnull)(NSData *_Nullable rawData, + BOOL isGif, + UIImage *_Nullable image, + NSError *_Nullable error))completionHandler; @end diff --git a/Sources/Batch/Modules/Messaging/BAMSGMessage.h b/Sources/Batch/Modules/Messaging/BAMSGMessage.h index a685901..a76b92a 100644 --- a/Sources/Batch/Modules/Messaging/BAMSGMessage.h +++ b/Sources/Batch/Modules/Messaging/BAMSGMessage.h @@ -5,23 +5,22 @@ // Copyright © 2016 Batch. All rights reserved. // -#import -#import #import -#import #import +#import +#import +#import /** Represents a parsed html text */ @interface BAMSGHTMLText : NSObject -@property (nullable) NSArray* transforms; -@property (nonnull) NSString* text; +@property (nullable) NSArray *transforms; +@property (nonnull) NSString *text; @end - // Minimal message representation @interface BAMSGMessage : NSObject @@ -41,23 +40,23 @@ @interface BAMSGMessageInterstitial : BAMSGMessage -@property (nonnull) NSString *css; +@property (nonnull) NSString *css; @property (nullable) NSString *headingText; @property (nullable) NSString *titleText; @property (nullable) NSString *subtitleText; -@property (nonnull) NSArray *ctas; +@property (nonnull) NSArray *ctas; @property (nullable) NSString *videoURL; @property (nullable) NSString *heroImageURL; @property (nullable) UIImage *heroImage; @property (nullable) NSString *heroDescription; -@property BOOL showCloseButton; -@property BOOL attachCTAsBottom; -@property BOOL stackCTAsHorizontally; -@property BOOL stretchCTAsHorizontally; -@property BOOL flipHeroVertical; -@property BOOL flipHeroHorizontal; +@property BOOL showCloseButton; +@property BOOL attachCTAsBottom; +@property BOOL stackCTAsHorizontally; +@property BOOL stretchCTAsHorizontally; +@property BOOL flipHeroVertical; +@property BOOL flipHeroHorizontal; @property (nullable) NSNumber *heroSplitRatio; -@property NSTimeInterval autoClose; +@property NSTimeInterval autoClose; @end @@ -68,21 +67,20 @@ typedef NS_ENUM(NSUInteger, BAMSGBannerCTADirection) { @interface BAMSGMessageBaseBanner : BAMSGMessage -@property (nonnull) NSString *css; +@property (nonnull) NSString *css; @property (nullable) NSString *titleText; @property (nullable) BAMSGAction *globalTapAction; -@property NSTimeInterval globalTapDelay; -@property BOOL allowSwipeToDismiss; +@property NSTimeInterval globalTapDelay; +@property BOOL allowSwipeToDismiss; @property (nullable) NSString *imageURL; @property (nullable) NSString *imageDescription; -@property (nonnull) NSArray *ctas; -@property BOOL showCloseButton; -@property NSTimeInterval autoClose; +@property (nonnull) NSArray *ctas; +@property BOOL showCloseButton; +@property NSTimeInterval autoClose; @property BAMSGBannerCTADirection ctaDirection; @end - @interface BAMSGMessageBanner : BAMSGMessageBaseBanner @end @@ -90,36 +88,37 @@ typedef NS_ENUM(NSUInteger, BAMSGBannerCTADirection) { @end @interface BAMSGMessageImage : BAMSGMessage -@property CGSize imageSize; +@property CGSize imageSize; @property (nullable) NSString *imageURL; -@property NSTimeInterval globalTapDelay; -@property (nonnull) BAMSGAction *globalTapAction; -@property BOOL isFullscreen; +@property NSTimeInterval globalTapDelay; +@property (nonnull) BAMSGAction *globalTapAction; +@property BOOL isFullscreen; @property (nullable) NSString *imageDescription; -@property (nonnull) NSString *css; -@property NSTimeInterval autoClose; -@property BOOL allowSwipeToDismiss; +@property (nonnull) NSString *css; +@property NSTimeInterval autoClose; +@property BOOL allowSwipeToDismiss; @end /// Controls which kind of viewport-fit=cover bug workaround is applied typedef NS_ENUM(NSUInteger, BAMSGWebViewLayoutWorkaround) { BAMSGWebViewLayoutWorkaroundDoNothing = 0, - + /// Call setNeedsLayout at some point in the future, after displaying the web content BAMSGWebViewLayoutWorkaroundRelayoutPeriodically = 1, - + /// Read viewport and apply it natively to the scrollview - /// Note: only supported on iOS 11+. On iOS 10, this will fallback on BAMSGWebViewLayoutWorkaroundRelayoutPeriodically. + /// Note: only supported on iOS 11+. On iOS 10, this will fallback on + /// BAMSGWebViewLayoutWorkaroundRelayoutPeriodically. BAMSGWebViewLayoutWorkaroundApplyInsetsNatively = 2, }; @interface BAMSGMessageWebView : BAMSGMessage -@property (nonnull) NSString *css; -@property (nonnull) NSURL *url; -@property BOOL developmentMode; -@property BOOL openDeeplinksInApp; -@property NSTimeInterval timeout; -@property BAMSGWebViewLayoutWorkaround layoutWorkaround; +@property (nonnull) NSString *css; +@property (nonnull) NSURL *url; +@property BOOL developmentMode; +@property BOOL openDeeplinksInApp; +@property NSTimeInterval timeout; +@property BAMSGWebViewLayoutWorkaround layoutWorkaround; @end diff --git a/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.h b/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.h index 8e66339..b0599dd 100644 --- a/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.h +++ b/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.h @@ -9,6 +9,6 @@ - (void)presentAnimated; -- (BAPromise*)dismissAnimated; +- (BAPromise *)dismissAnimated; @end diff --git a/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.m b/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.m index e195cc6..2e05ffd 100644 --- a/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.m +++ b/Sources/Batch/Modules/Messaging/BAMSGOverlayWindow.m @@ -1,4 +1,6 @@ #import +#import +#import @implementation BAMSGOverlayWindow @@ -13,6 +15,12 @@ - (instancetype)init { - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { // Do not call [super hitTest] as Apple may slip some UIViews between our view controller's view // and the window that don't return nil when hit tested, which beaks touch passthrough + + // Workaround to dimiss the presented banner when a safari view controller is presenting. + UIViewController *frontmostViewController = [BAWindowHelper frontmostViewController]; + if ([frontmostViewController isKindOfClass:SFSafariViewController.class]) { + [self dismissAnimated]; + } UIView *hitView = [self.rootViewController.view hitTest:point withEvent:event]; if (hitView == nil) { return nil; diff --git a/Sources/Batch/Modules/Messaging/BAMSGPayloadParser.h b/Sources/Batch/Modules/Messaging/BAMSGPayloadParser.h index 23ded22..d99878c 100644 --- a/Sources/Batch/Modules/Messaging/BAMSGPayloadParser.h +++ b/Sources/Batch/Modules/Messaging/BAMSGPayloadParser.h @@ -5,12 +5,11 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import +#import @interface BAMSGPayloadParser : NSObject -+ (BAMSGMessage* _Nullable)messageForRawMessage:(BatchMessage* _Nonnull)rawMessage - bailIfNotAlert:(BOOL)bailNotAlert; ++ (BAMSGMessage *_Nullable)messageForRawMessage:(BatchMessage *_Nonnull)rawMessage bailIfNotAlert:(BOOL)bailNotAlert; @end diff --git a/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDeduplicatingDelegate.h b/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDeduplicatingDelegate.h index dd9eab0..827f0a3 100644 --- a/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDeduplicatingDelegate.h +++ b/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDeduplicatingDelegate.h @@ -5,8 +5,8 @@ #import -#import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -19,7 +19,8 @@ NS_ASSUME_NONNULL_BEGIN /// This class is the one that gets injected for the BAMessagingAnalyticsDelegate protocol @interface BAMessagingAnalyticsDeduplicatingDelegate : NSObject -- (instancetype)initWithWrappedDelegate:(nonnull id)delegate BATCH_USE_INJECTION_OUTSIDE_TESTS; +- (instancetype)initWithWrappedDelegate:(nonnull id)delegate + BATCH_USE_INJECTION_OUTSIDE_TESTS; @end diff --git a/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDelegate.h b/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDelegate.h index 9be756b..97f33d5 100644 --- a/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDelegate.h +++ b/Sources/Batch/Modules/Messaging/BAMessagingAnalyticsDelegate.h @@ -15,23 +15,24 @@ NS_ASSUME_NONNULL_BEGIN @protocol BAMessagingAnalyticsDelegate -- (void)messageShown:(BAMSGMessage* _Nonnull)message; +- (void)messageShown:(BAMSGMessage *_Nonnull)message; -- (void)messageClosed:(BAMSGMessage* _Nonnull)message; +- (void)messageClosed:(BAMSGMessage *_Nonnull)message; -- (void)message:(BAMSGMessage* _Nonnull)message closedByError:(BATMessagingCloseErrorCause)cause NS_SWIFT_NAME(messageClosed(_:byError:)); +- (void)message:(BAMSGMessage *_Nonnull)message + closedByError:(BATMessagingCloseErrorCause)cause NS_SWIFT_NAME(messageClosed(_:byError:)); -- (void)messageDismissed:(BAMSGMessage* _Nonnull)message; +- (void)messageDismissed:(BAMSGMessage *_Nonnull)message; - (void)messageButtonClicked:(BAMSGMessage *_Nonnull)message ctaIndex:(NSInteger)ctaIndex action:(BAMSGCTA *)action; -- (void)messageAutomaticallyClosed:(BAMSGMessage* _Nonnull)message; +- (void)messageAutomaticallyClosed:(BAMSGMessage *_Nonnull)message; - (void)messageGlobalTapActionTriggered:(BAMSGMessage *_Nonnull)message action:(BAMSGAction *)action; - (void)messageWebViewClickTracked:(BAMSGMessage *_Nonnull)message - action:(BAMSGAction*)action - analyticsIdentifier:(NSString*)analyticsID; + action:(BAMSGAction *)action + analyticsIdentifier:(NSString *)analyticsID; @end diff --git a/Sources/Batch/Modules/Messaging/BAMessagingCenter.h b/Sources/Batch/Modules/Messaging/BAMessagingCenter.h index 7922a10..a5eb2ad 100644 --- a/Sources/Batch/Modules/Messaging/BAMessagingCenter.h +++ b/Sources/Batch/Modules/Messaging/BAMessagingCenter.h @@ -8,19 +8,19 @@ #import #import -#import -#import #import #import -#import #import +#import #import +#import #import +#import #import -extern NSString * _Nonnull const kBATMessagingMessageDidAppear; -extern NSString * _Nonnull const kBATMessagingMessageDidDisappear; +extern NSString *_Nonnull const kBATMessagingMessageDidAppear; +extern NSString *_Nonnull const kBATMessagingMessageDidDisappear; NS_ASSUME_NONNULL_BEGIN @@ -36,6 +36,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable) BAMSGOverlayWindow *shownWindow; +@property (readonly) BOOL enableDynamicType; + + (instancetype _Nonnull)instance BATCH_USE_INJECTION_OUTSIDE_TESTS; - (void)setDelegate:(id _Nullable)delegate; @@ -48,14 +50,18 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)hasPendingMessage; -- (BatchMessage* _Nullable)popPendingMessage; +- (BatchMessage *_Nullable)popPendingMessage; - (BOOL)showPendingMessage; -- (void)setFontOverride:(nullable UIFont*)font boldFont:(nullable UIFont*)boldFont; +- (void)setFontOverride:(nullable UIFont *)font boldFont:(nullable UIFont *)boldFont; -- (void)setFontOverride:(nullable UIFont*)font boldFont:(nullable UIFont*)boldFont italicFont:(nullable UIFont*)italicFont boldItalicFont:(nullable UIFont*)boldItalicFont; +- (void)setFontOverride:(nullable UIFont *)font + boldFont:(nullable UIFont *)boldFont + italicFont:(nullable UIFont *)italicFont + boldItalicFont:(nullable UIFont *)boldItalicFont; +- (void)setEnableDynamicType:(BOOL)enableDynamicType; /** Process an in-app message (which is the marketing name for landing output of a local campaign) @@ -64,30 +70,32 @@ NS_ASSUME_NONNULL_BEGIN @param message In-App message to display */ -- (void)handleInAppMessage:(nonnull BatchInAppMessage*)message; +- (void)handleInAppMessage:(nonnull BatchInAppMessage *)message; -- (UIViewController* _Nullable)loadViewControllerForMessage:(BatchMessage* _Nonnull)message - error:(NSError * _Nullable * _Nullable)error; +- (UIViewController *_Nullable)loadViewControllerForMessage:(BatchMessage *_Nonnull)message + error:(NSError *_Nullable *_Nullable)error; -- (BOOL)presentMessagingViewController:(nonnull UIViewController*)vc error:(NSError**)error; +- (BOOL)presentMessagingViewController:(nonnull UIViewController *)vc error:(NSError **)error; /* Same as the non internal method, but removes automatic mode checks and does the actual work */ -- (UIViewController* _Nullable)internalLoadViewControllerForMessage:(BatchMessage* _Nonnull)message - error:(NSError * _Nullable * _Nullable)error; +- (UIViewController *_Nullable)internalLoadViewControllerForMessage:(BatchMessage *_Nonnull)message + error:(NSError *_Nullable *_Nullable)error; -- (void)performAction:(nonnull BAMSGAction*)action +- (void)performAction:(nonnull BAMSGAction *)action source:(nullable id)source actionIndex:(NSInteger)index messageIdentifier:(nullable NSString *)identifier; -- (void)performAction:(nonnull BAMSGAction*)action - source:(nullable id)source - webViewAnalyticsID:(nullable NSString *)analyticsID - messageIdentifier:(nullable NSString *)identifier; +- (void)performAction:(nonnull BAMSGAction *)action + source:(nullable id)source + webViewAnalyticsID:(nullable NSString *)analyticsID + messageIdentifier:(nullable NSString *)identifier; + +- (BAPromise *)dismissWindow:(nullable BAMSGOverlayWindow *)window; -- (BAPromise*)dismissWindow:(nullable BAMSGOverlayWindow*)window; +- (void)presentLandingMessage:(BatchMessage *_Nonnull)message bypassDnD:(BOOL)bypassDnD; @end diff --git a/Sources/Batch/Modules/Messaging/BAMessagingCenter.m b/Sources/Batch/Modules/Messaging/BAMessagingCenter.m index bc3cd5a..902a6e6 100644 --- a/Sources/Batch/Modules/Messaging/BAMessagingCenter.m +++ b/Sources/Batch/Modules/Messaging/BAMessagingCenter.m @@ -38,6 +38,7 @@ #import +#import #import #define LOGGER_DOMAIN @"Messaging" @@ -78,6 +79,8 @@ @interface BAMessagingCenter () { @implementation BAMessagingCenter +@synthesize enableDynamicType = _enableDynamicType; + + (void)load { [[NSNotificationCenter defaultCenter] addObserver:[BAMessagingCenter class] selector:@selector(pushOpenedNotification:) @@ -104,6 +107,7 @@ - (instancetype)init { _imageDownloadTimeout = BAMESSAGING_DEFAULT_TIMEOUT; _pendingMessage = nil; self.doNotDisturb = NO; + _enableDynamicType = YES; } return self; } @@ -125,7 +129,7 @@ + (void)pushOpenedNotification:(NSNotification *)notification { if ([BAMessagingCenter instance].automaticMode) { [BAThreading performBlockOnMainThreadAsync:^{ [BALogger debugForDomain:LOGGER_DOMAIN message:@"automatic mode is enabled: trying to display it"]; - [[BAMessagingCenter instance] displayMessage:message error:nil]; + [[BAMessagingCenter instance] displayMessage:message bypassDnD:false error:nil]; }]; } else { [BALogger debugForDomain:LOGGER_DOMAIN message:@"but BatchMessaging is in manual mode: ignoring."]; @@ -177,7 +181,7 @@ - (BatchMessage *_Nullable)popPendingMessage { - (BOOL)showPendingMessage { BatchMessage *msg = [self popPendingMessage]; if (msg) { - [self displayMessage:msg error:nil]; + [self displayMessage:msg bypassDnD:false error:nil]; return true; } return false; @@ -200,6 +204,17 @@ - (void)setFontOverride:(nullable UIFont *)font } } +- (void)setEnableDynamicType:(BOOL)enableDynamicType { + _enableDynamicType = enableDynamicType; +} + +- (BOOL)enableDynamicType { + if (@available(iOS 15.0, *)) { + return _enableDynamicType; + } + return false; +} + - (void)handleInAppMessage:(nonnull BatchInAppMessage *)message { [BAThreading performBlockOnMainThreadAsync:^{ if ([self->_wrappedDelegate batchInAppMessageReady:message]) { @@ -208,7 +223,7 @@ - (void)handleInAppMessage:(nonnull BatchInAppMessage *)message { } else { if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) { NSError *err; - if ([self displayMessage:message error:&err]) { + if ([self displayMessage:message bypassDnD:false error:&err]) { [BALogger debugForDomain:LOGGER_DOMAIN message:@"Displayed the In-App message %@", message]; } else { [BALogger publicForDomain:LOGGER_DOMAIN @@ -268,8 +283,7 @@ - (BOOL)presentMessagingViewController:(nonnull UIViewController *)vc error:(NSE } if ([(id)vc shouldDisplayInSeparateWindow]) { - [self showViewControllerInOwnWindow:vc]; - return true; + return [self showViewControllerInOwnWindow:vc error:error]; } else { BOOL hasDeveloperOverridenVC = true; __block UIViewController *targetVC = [_wrappedDelegate presentingViewControllerForBatchUI]; @@ -280,6 +294,9 @@ - (BOOL)presentMessagingViewController:(nonnull UIViewController *)vc error:(NSE if (targetVC) { UIViewController *presentedVC = targetVC.presentedViewController; + while (presentedVC.presentedViewController) { + presentedVC = presentedVC.presentedViewController; + } void (^presentationBlock)(void) = ^{ [targetVC presentViewController:vc animated:YES completion:nil]; }; @@ -521,7 +538,11 @@ - (NSMutableDictionary *)baseEventParametersForMessage:(BAMSGMessage *_Nonnull)m if ([message.sourceMessage isKindOfClass:[BatchInAppMessage class]]) { messageSource = @"local"; } else if ([message.sourceMessage isKindOfClass:[BatchPushMessage class]]) { - messageSource = @"landing"; + if (((BatchPushMessage *)message.sourceMessage).isDisplayedFromInbox) { + messageSource = @"inbox-landing"; + } else { + messageSource = @"landing"; + } } else { messageSource = @"unknown"; } @@ -720,8 +741,10 @@ - (BAEventDispatcherCenter *)eventDispatcher { @param outErr Error output pointer @return YES on success, NO on failure */ -- (BOOL)displayMessage:(BatchMessage *_Nonnull)message error:(NSError *_Nullable *_Nullable)outErr { - if (self.doNotDisturb) { +- (BOOL)displayMessage:(BatchMessage *_Nonnull)message + bypassDnD:(BOOL)bypassDnD + error:(NSError *_Nullable *_Nullable)outErr { + if (self.doNotDisturb && !bypassDnD) { [BALogger publicForDomain:LOGGER_DOMAIN message:@"A BatchMessage was attempted to be displayed, but Do Not Disturb is enabled. Enqueing."]; @@ -934,12 +957,30 @@ - (BAMSGWebviewViewController *)webviewViewControllerForMessage:(BAMSGMessageWeb return vc; } -- (void)showViewControllerInOwnWindow:(UIViewController *)vc { +- (BOOL)showViewControllerInOwnWindow:(UIViewController *)vc error:(NSError **)error { if (vc == nil) { - return; + if (error) { + *error = [NSError errorWithDomain:MESSAGING_ERROR_DOMAIN + code:BatchMessagingErrorInternal + userInfo:@{NSLocalizedDescriptionKey : @"Invalid view controller."}]; + } + return false; } UIWindow *overlayedWindow = [BAWindowHelper keyWindow]; + UIViewController *frontmostViewController = [BAWindowHelper frontmostViewController]; + if ([frontmostViewController isKindOfClass:SFSafariViewController.class]) { + if (error) { + *error = [NSError + errorWithDomain:MESSAGING_ERROR_DOMAIN + code:BatchMessagingErrorInternal + userInfo:@{ + NSLocalizedDescriptionKey : + @"An SFSafariViewController is already presenting and may not be hidden or obscured." + }]; + } + return false; + } BAMSGOverlayWindow *shownWindow = self.shownWindow; if (shownWindow) { UIViewController *shownVC = [shownWindow rootViewController]; @@ -980,6 +1021,7 @@ - (void)showViewControllerInOwnWindow:(UIViewController *)vc { [window presentAnimated]; self.shownWindow = window; + return true; } - (BAPromise *)dismissWindow:(nullable BAMSGOverlayWindow *)window { @@ -1002,6 +1044,16 @@ - (BAPromise *)dismissWindow:(nullable BAMSGOverlayWindow *)window { return dismissPromise; } +- (void)presentLandingMessage:(BatchMessage *_Nonnull)message bypassDnD:(BOOL)bypassDnD { + if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) { + [BALogger debugForDomain:LOGGER_DOMAIN + message:@"Trying to present landing message while application is in background"]; + } + [BAThreading performBlockOnMainThreadAsync:^{ + [self displayMessage:message bypassDnD:bypassDnD error:nil]; + }]; +} + #pragma mark UIAlertView delegate methods #pragma clang diagnostic push diff --git a/Sources/Batch/Modules/Messaging/BATHtmlParser.h b/Sources/Batch/Modules/Messaging/BATHtmlParser.h index 79231cf..0aaebd0 100644 --- a/Sources/Batch/Modules/Messaging/BATHtmlParser.h +++ b/Sources/Batch/Modules/Messaging/BATHtmlParser.h @@ -9,8 +9,8 @@ NS_ASSUME_NONNULL_BEGIN -typedef NSDictionary BATTextTransformAttributes; -typedef NSMutableDictionary BATMutableTextTransformAttributes; +typedef NSDictionary BATTextTransformAttributes; +typedef NSMutableDictionary BATMutableTextTransformAttributes; typedef NS_OPTIONS(NSUInteger, BATTextModifiers) { BATTextModifierNone = 0, @@ -25,7 +25,9 @@ typedef NS_OPTIONS(NSUInteger, BATTextModifiers) { @interface BATTextTransform : NSObject -- (instancetype)initWithLocation:(NSUInteger)location modifiers:(BATTextModifiers)modifiers attributes:(BATTextTransformAttributes*)attributes; +- (instancetype)initWithLocation:(NSUInteger)location + modifiers:(BATTextModifiers)modifiers + attributes:(BATTextTransformAttributes *)attributes; - (void)setEndLocation:(NSUInteger)endLocation; @@ -33,7 +35,7 @@ typedef NS_OPTIONS(NSUInteger, BATTextModifiers) { @property BATTextModifiers modifiers; -@property (nullable) BATTextTransformAttributes* attributes; +@property (nullable) BATTextTransformAttributes *attributes; @end @@ -42,16 +44,16 @@ typedef NS_OPTIONS(NSUInteger, BATTextModifiers) { /** Unstyled text */ -@property (readonly) NSString* text; +@property (readonly) NSString *text; /** Transformation list */ -@property (readonly) NSArray* transforms; +@property (readonly) NSArray *transforms; -- (instancetype)initWithString:(NSString*)string; +- (instancetype)initWithString:(NSString *)string; -- (nullable NSError*)parse; +- (nullable NSError *)parse; @end diff --git a/Sources/Batch/Modules/Messaging/BATMessagingCloseErrorCause.h b/Sources/Batch/Modules/Messaging/BATMessagingCloseErrorCause.h index 8dfd7c1..a48f54f 100644 --- a/Sources/Batch/Modules/Messaging/BATMessagingCloseErrorCause.h +++ b/Sources/Batch/Modules/Messaging/BATMessagingCloseErrorCause.h @@ -9,22 +9,22 @@ typedef NS_ENUM(NSUInteger, BATMessagingCloseErrorCause) { // Unknown error cause BATMessagingCloseErrorCauseUnknown = 0, - + // A server failure: bad SSL configuration, non 2xx HTTP status code BATMessagingCloseErrorCauseServerFailure = 1, - + // Unprocessable response (for example: a server served an image that could not be decoded) BATMessagingCloseErrorCauseInvalidResponse = 2, - + // Temporary network error, which may be the client's fault: DNS failure, Timeout, etc... BATMessagingCloseErrorCauseClientNetwork = 3 }; // Key for adding a messaging error cause in a NSError's userInfo dict -extern NSString * _Nonnull const kBATMessagingCloseErrorCauseKey; +extern NSString *_Nonnull const kBATMessagingCloseErrorCauseKey; @interface BATMessagingCloseErrorHelper : NSObject -+ (BATMessagingCloseErrorCause)guessErrorCauseForError:(nullable NSError*)error; ++ (BATMessagingCloseErrorCause)guessErrorCauseForError:(nullable NSError *)error; @end diff --git a/Sources/Batch/Modules/Messaging/CSS/BACSS.h b/Sources/Batch/Modules/Messaging/CSS/BACSS.h index c70866b..d7d1667 100644 --- a/Sources/Batch/Modules/Messaging/CSS/BACSS.h +++ b/Sources/Batch/Modules/Messaging/CSS/BACSS.h @@ -15,19 +15,18 @@ @property (assign) CGSize viewSize; @property (assign) BOOL darkMode; -- (BOOL)environmentMatchesQuery:(NSString*)query; +- (BOOL)environmentMatchesQuery:(NSString *)query; @end - @interface BACSSDOMNode : NSObject @property NSString *type; @property NSString *identifier; -@property NSArray *classes; +@property NSArray *classes; @property BACSSDOMNode *parentNode; -- (BOOL)matchesSelector:(NSString*)selector; +- (BOOL)matchesSelector:(NSString *)selector; @end @@ -43,7 +42,7 @@ @property rulesets @abstract All rulesets contained in the document */ -@property NSMutableArray *rulesets; +@property NSMutableArray *rulesets; @end @@ -63,7 +62,7 @@ @property NSString *selector; -@property NSMutableArray *declarations; +@property NSMutableArray *declarations; @end @@ -73,20 +72,20 @@ @property rulesets @abstract All rulesets contained in the document */ -@property NSMutableArray *rulesets; +@property NSMutableArray *rulesets; /*! @property mediaQueries @abstract All media queries contained in the document */ -@property NSMutableArray *mediaQueries; +@property NSMutableArray *mediaQueries; -typedef NSDictionary BACSSRules; +typedef NSDictionary BACSSRules; -- (BACSSRules*)flatRulesForNode:(BACSSDOMNode*)node withEnvironment:(BACSSEnvironment*)environment; +- (BACSSRules *)flatRulesForNode:(BACSSDOMNode *)node withEnvironment:(BACSSEnvironment *)environment; -- (NSArray*)rulesForNode:(BACSSDOMNode*)node withEnvironment:(BACSSEnvironment*)environment; +- (NSArray *)rulesForNode:(BACSSDOMNode *)node withEnvironment:(BACSSEnvironment *)environment; -- (BACSSRules*)flatRulesFromCSSDeclarations:(NSArray*)declarations; +- (BACSSRules *)flatRulesFromCSSDeclarations:(NSArray *)declarations; @end diff --git a/Sources/Batch/Modules/Messaging/CSS/BACSSImportProvider.h b/Sources/Batch/Modules/Messaging/CSS/BACSSImportProvider.h index 5a058d8..cbb8896 100644 --- a/Sources/Batch/Modules/Messaging/CSS/BACSSImportProvider.h +++ b/Sources/Batch/Modules/Messaging/CSS/BACSSImportProvider.h @@ -10,6 +10,6 @@ @protocol BACSSImportProvider @required -- (NSString* _Nullable)contentForImportNamed:(NSString* _Nonnull)importName; +- (NSString *_Nullable)contentForImportNamed:(NSString *_Nonnull)importName; @end diff --git a/Sources/Batch/Modules/Messaging/CSS/BACSSParser.h b/Sources/Batch/Modules/Messaging/CSS/BACSSParser.h index c512295..91534b2 100644 --- a/Sources/Batch/Modules/Messaging/CSS/BACSSParser.h +++ b/Sources/Batch/Modules/Messaging/CSS/BACSSParser.h @@ -5,15 +5,15 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import #import +#import @interface BACSSParser : NSObject -+ (instancetype)parserWithString:(NSString*)cssString andImportProvider:(id)importProvider; -- (instancetype)initWithString:(NSString*)cssString andImportProvider:(id)importProvider; ++ (instancetype)parserWithString:(NSString *)cssString andImportProvider:(id)importProvider; +- (instancetype)initWithString:(NSString *)cssString andImportProvider:(id)importProvider; -- (BACSSDocument*)parseWithError:(NSError**)error; +- (BACSSDocument *)parseWithError:(NSError **)error; @end diff --git a/Sources/Batch/Modules/Messaging/CSS/BACSSToken.h b/Sources/Batch/Modules/Messaging/CSS/BACSSToken.h index 38fa152..9480c89 100644 --- a/Sources/Batch/Modules/Messaging/CSS/BACSSToken.h +++ b/Sources/Batch/Modules/Messaging/CSS/BACSSToken.h @@ -9,11 +9,11 @@ typedef NS_ENUM(NSUInteger, BACSSSpecialTokenKind) { BACSSSpecialTokenKindUnknown = 0, - BACSSSpecialTokenKindBlockStart = 1, // { - BACSSSpecialTokenKindBlockEnd = 2, // } - BACSSSpecialTokenKindPropertyEnd = 3, // ; + BACSSSpecialTokenKindBlockStart = 1, // { + BACSSSpecialTokenKindBlockEnd = 2, // } + BACSSSpecialTokenKindPropertyEnd = 3, // ; BACSSSpecialTokenKindPropertySeparator = 4, // : - BACSSSpecialTokenKindNewline = 5 // \n + BACSSSpecialTokenKindNewline = 5 // \n }; @interface BACSSSpecialToken : NSObject diff --git a/Sources/Batch/Modules/Messaging/GIF/BATGIFAnimator.h b/Sources/Batch/Modules/Messaging/GIF/BATGIFAnimator.h index 5678714..838a2df 100644 --- a/Sources/Batch/Modules/Messaging/GIF/BATGIFAnimator.h +++ b/Sources/Batch/Modules/Messaging/GIF/BATGIFAnimator.h @@ -1,5 +1,5 @@ -#import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol BATGIFAnimatorDelegate @required -- (void)animator:(BATGIFAnimator*)animator needsToDisplayImage:(UIImage*)image; +- (void)animator:(BATGIFAnimator *)animator needsToDisplayImage:(UIImage *)image; @end @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @property NSUInteger framerate; -- (instancetype)initWithFile:(BATGIFFile*)file; +- (instancetype)initWithFile:(BATGIFFile *)file; - (void)startAnimating; diff --git a/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h b/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h index da4bf5b..67b6c75 100644 --- a/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h +++ b/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h @@ -4,8 +4,8 @@ NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger, BATGIFError) { BATGIFErrorCouldNotCreateImageSource, // CoreGraphics failed to create the source - BATGIFErrorNotAGif, // Source is not a GIF - BATGIFErrorAnimationNotNeeded, // Animation is not needed (not more than 1 frame) + BATGIFErrorNotAGif, // Source is not a GIF + BATGIFErrorAnimationNotNeeded, // Animation is not needed (not more than 1 frame) }; /** @@ -47,27 +47,28 @@ typedef NS_ENUM(NSUInteger, BATGIFCacheSize) { /** Checks if the given NSData might be a gif - + Note: this is a quick check. -initWithData:error: might still fail. */ -+ (BOOL)isPotentiallyAGif:(NSData*)data; ++ (BOOL)isPotentiallyAGif:(NSData *)data; -@property (readonly) NSUInteger frameCount; // Number of frames available. This reflects the number of frames we were able to decode from the GIF, not the number it told it had +@property (readonly) NSUInteger frameCount; // Number of frames available. This reflects the number of frames we were + // able to decode from the GIF, not the number it told it had /** Make a new BATGIFFile from the given data. This is an expensive operation that should not be done on the main thread */ -- (nullable instancetype)initWithData:(NSData*)data error:(NSError**)error; +- (nullable instancetype)initWithData:(NSData *)data error:(NSError **)error; /** Get the frame at an index. */ -- (BATGIFFrame*)frameAtIndex:(NSUInteger)index; +- (BATGIFFrame *)frameAtIndex:(NSUInteger)index; /** Consume the frame at an index. - + The cache will consider this frame and all the ones before it consumed (if all frames don't fit in memory). It is also going to start caching next ones in the background. */ @@ -76,7 +77,7 @@ typedef NS_ENUM(NSUInteger, BATGIFCacheSize) { /** Warn that a frame will be displayed (but not yet consumed). The difference between this method and "consumeFrameAtIndex" is that the frame will NOT be attempted to be freed. - + Call this method when you're about to display the frame at the specified index, so that this class may take this opportunity to add more in the cache. */ diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGBannerViewController.h b/Sources/Batch/Modules/Messaging/UI/BAMSGBannerViewController.h index e38c0e0..948ff0e 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGBannerViewController.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGBannerViewController.h @@ -11,7 +11,7 @@ /** Floating banner - + Format meant to be displayed in its own window, rather than modally. Usually vertically attached to a side of the screen */ diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.h b/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.h index f4b92bc..14c7c3c 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.h @@ -1,35 +1,35 @@ -#import -#import #import #import -#import -#import #import +#import +#import #import -#import +#import #import +#import +#import #import -#import +#import /** Handles banner display - + This is also the view controller used for Modal view, as they're basically a centered banner. Sadly, we don't have a better name for it, so we'll call it banner. Sorry. */ -@interface BAMSGBaseBannerViewController: BAMSGViewController +@interface BAMSGBaseBannerViewController : BAMSGViewController @property (nullable) NSString *titleText; @property (nullable) NSString *bodyText; @property (nullable) BAMSGHTMLText *bodyHtml; -@property BAMSGBannerCTADirection ctaStackDirection; +@property BAMSGBannerCTADirection ctaStackDirection; @property (nullable) BAMSGAction *globalTapAction; -@property NSTimeInterval globalTapDelay; -@property BOOL allowSwipeToDismiss; +@property NSTimeInterval globalTapDelay; +@property BOOL allowSwipeToDismiss; @property (nullable) NSString *imageURL; @property (nullable) NSString *imageDescription; @@ -38,10 +38,10 @@ UIGestureRecognizerDelegate> @property (nullable) BAMSGMessageBaseBanner *messageDescription; -- (nonnull instancetype)initWithStyleRules:(nonnull BACSSDocument*)style; +- (nonnull instancetype)initWithStyleRules:(nonnull BACSSDocument *)style; - (BOOL)canBeClosed; -- (void)didDetectGlobalTap:(nullable UIGestureRecognizer*)gestureRecognizer; +- (void)didDetectGlobalTap:(nullable UIGestureRecognizer *)gestureRecognizer; @end diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.h b/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.h index 642a6b3..a16680b 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.h @@ -5,16 +5,16 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import @class BAMSGMessageImage; @class BACSSDocument; -@interface BAMSGImageViewController: BAMSGViewController +@interface BAMSGImageViewController : BAMSGViewController -- (instancetype _Nonnull )initWithMessage:(BAMSGMessageImage *_Nonnull)message andStyle:(BACSSDocument*_Nonnull)style; +- (instancetype _Nonnull)initWithMessage:(BAMSGMessageImage *_Nonnull)message andStyle:(BACSSDocument *_Nonnull)style; -@property (nonatomic, readonly) BAMSGMessageImage * _Nonnull message; +@property (nonatomic, readonly) BAMSGMessageImage *_Nonnull message; @end diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGInterstitialViewController.h b/Sources/Batch/Modules/Messaging/UI/BAMSGInterstitialViewController.h index 42f4066..c91dff0 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGInterstitialViewController.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGInterstitialViewController.h @@ -5,16 +5,18 @@ // Copyright © 2016 Batch. All rights reserved. // -#import -#import #import #import -#import #import +#import #import +#import #import +#import -@interface BAMSGInterstitialViewController : BAMSGViewController +@interface BAMSGInterstitialViewController : BAMSGViewController @property (nullable) NSString *headingText; @property (nullable) NSString *titleText; @@ -23,26 +25,27 @@ @property (nullable) BAMSGHTMLText *bodyHtml; @property (nullable) UIImage *heroImage; @property (nullable) NSURL *videoURL; -@property BOOL attachCTAsBottom; -@property BOOL stackCTAsHorizontally; -@property BOOL stretchCTAsHorizontally; -@property BOOL flipHeroVertical; -@property BOOL flipHeroHorizontal; -@property float heroSplitRatio; +@property BOOL attachCTAsBottom; +@property BOOL stackCTAsHorizontally; +@property BOOL stretchCTAsHorizontally; +@property BOOL flipHeroVertical; +@property BOOL flipHeroHorizontal; +@property float heroSplitRatio; @property (nullable) BAMSGMessageInterstitial *messageDescription; /// Init an intersitial message VS /// @param style Style /// @param hasHeroContent If the message should configure itself to display a hero image/gif/video -/// @param waitForImage Should the message wait for an image to be downloaded. Should be false if you're injecting the heroImage or videoURL -- (nonnull instancetype)initWithStyleRules:(nonnull BACSSDocument*)style +/// @param waitForImage Should the message wait for an image to be downloaded. Should be false if you're injecting the +/// heroImage or videoURL +- (nonnull instancetype)initWithStyleRules:(nonnull BACSSDocument *)style hasHeroContent:(BOOL)hasHeroContent shouldWaitForImage:(BOOL)waitForImage; - (BOOL)canBeClosed; -- (void)didFinishLoadingHero:(nullable UIImage*)heroImage; -- (void)didFinishLoadingGIFHero:(nullable NSData*)gifData; +- (void)didFinishLoadingHero:(nullable UIImage *)heroImage; +- (void)didFinishLoadingGIFHero:(nullable NSData *)gifData; @end diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGModalViewController.h b/Sources/Batch/Modules/Messaging/UI/BAMSGModalViewController.h index 6eb8ac9..bb8b80f 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGModalViewController.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGModalViewController.h @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN /** Modal format - + Uses the banner as a base to render the alert, but draws a background and is presented modally. Like a more advanced system alert, based on the banner look & implementation. */ diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGStackView.h b/Sources/Batch/Modules/Messaging/UI/BAMSGStackView.h index 892055f..5d32ba4 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGStackView.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGStackView.h @@ -5,31 +5,32 @@ // Copyright © 2016 Batch. All rights reserved. // -#import -#import +#import #import +#import #import -#import +#import @class BAMSGStackView; @protocol BAMSGStackViewDelegate -- (nonnull NSString*)separatorPrefixForStackView:(nonnull BAMSGStackView*)stackView; +- (nonnull NSString *)separatorPrefixForStackView:(nonnull BAMSGStackView *)stackView; -- (nonnull BACSSRules*)stackView:(nonnull BAMSGStackView*)stackView rulesForSeparatorID:(nonnull NSString*)separatorID; +- (nonnull BACSSRules *)stackView:(nonnull BAMSGStackView *)stackView + rulesForSeparatorID:(nonnull NSString *)separatorID; @end @interface BAMSGStackView : BAMSGBaseContainerView -@property (readonly, nonnull) NSArray* items; +@property (readonly, nonnull) NSArray *items; @property (weak, nullable) id delegate; @property bool horizontal; -- (void)addItem:(nonnull BAMSGStackViewItem*)item; +- (void)addItem:(nonnull BAMSGStackViewItem *)item; // Size all items equally depending on the orientation // Mostly used for the CTA horizontal stack view diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h b/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h index 1a5d4b2..25e111e 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h @@ -5,23 +5,23 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import +#import @import UIKit; @interface BAMSGStackViewItem : NSObject -@property (nonnull) BACSSRules* rules; -@property (nullable) UIView* view; +@property (nonnull) BACSSRules *rules; +@property (nullable) UIView *view; @property BOOL attachToParentBottom; -- (nonnull NSArray*)computeConstraints; +- (nonnull NSArray *)computeConstraints; // "Private" properties, that will be set by the stack view -@property (nullable, weak) UIView* previousView; -@property (nullable, weak) UIView* nextView; -@property (nullable, weak) UIView* parentView; +@property (nullable, weak) UIView *previousView; +@property (nullable, weak) UIView *nextView; +@property (nullable, weak) UIView *parentView; @end diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h b/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h index 51c383a..84911e8 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h @@ -18,5 +18,4 @@ - (void)viewDidDisappear; - @end diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.h b/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.h index 8894a1c..3ac84b4 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.h @@ -5,54 +5,53 @@ // Copyright © Batch.com. All rights reserved. // -#import #import -#import #import +#import +#import @class BACSSDocument, BACSSDOMNode, BAMSGMessage, BAMSGCTA; @interface BAMSGViewController : UIViewController -@property (nonnull, readonly) BACSSDocument* style; +@property (nonnull, readonly) BACSSDocument *style; @property (nonatomic, nullable) BAMSGCloseButton *closeButton; @property (nonatomic, readonly) UIStatusBarStyle overridenStatusBarStyle; @property (nonatomic, nonnull, readonly) id messagingAnalyticsDelegate; - -- (nonnull instancetype)initWithStyleRules:(nonnull BACSSDocument*)style NS_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithStyleRules:(nonnull BACSSDocument *)style NS_DESIGNATED_INITIALIZER; #pragma mark - Parent - (BAMSGMessage *_Nonnull)message; #pragma mark - Styling -- (BACSSRules*_Nullable)rulesForNode:(BACSSDOMNode*_Nullable)node; +- (BACSSRules *_Nullable)rulesForNode:(BACSSDOMNode *_Nullable)node; - (void)setupRootStyle; -- (nonnull BACSSEnvironment*)computeCSSEnvironment; +- (nonnull BACSSEnvironment *)computeCSSEnvironment; - (CGSize)computeViewSize; #pragma mark - Dismissal @property (nonatomic, assign, readonly) BOOL isDismissed; /** Call to dismiss the controller.*/ -- (nonnull BAPromise*)dismiss; +- (nonnull BAPromise *)dismiss; /** The default implementation of this method does nothing. Must be overriden to do the actual dismiss action. */ -- (nonnull BAPromise*)doDismiss; +- (nonnull BAPromise *)doDismiss; /** Dismiss only if we're a modal AND not under another one. For subclass use only.*/ -- (nonnull BAPromise*)_doDismissSelfModal; +- (nonnull BAPromise *)_doDismissSelfModal; - (void)closeButtonAction; /** Call this method to track when the user asked to close the message isDismissed will be set to true Actually triggering the dismissal, if not already done, is your responsibility - + This is useful for iOS 13's swipe to dismiss. */ - (void)userDidCloseMessage; #pragma mark - CTA -@property (nullable) NSArray* ctas; +@property (nullable) NSArray *ctas; /// Perform CTA at the specified index. This will also dismiss the message. - (void)performCtaAtIndex:(NSInteger)index; @@ -62,20 +61,23 @@ @property (nonatomic, assign, readonly) BOOL showCloseButton; /** Setup the closing behaviour of the view (close button y/n, and whether the message should auto close after a delay) - + These settings might be overriden for accessibility purposes - + Set autoclosingDuration to 0 to disable autoclose */ - (void)setCloseButtonEnabled:(BOOL)showCloseButton autoclosingDuration:(NSTimeInterval)autoclosingDuration; -/** Override to set up autoclosing UI elements before animation takes place. Default implementation strokes the close button. */ +/** Override to set up autoclosing UI elements before animation takes place. Default implementation strokes the close + * button. */ - (void)setupAutoclosing; -/** Default to true. Override and return NO if countdown should wait for a condition, e.g. some initial loading to finish. */ +/** Default to true. Override and return NO if countdown should wait for a condition, e.g. some initial loading to + * finish. */ - (BOOL)automaticAutoclosingCountdown; /** Manually start the autoclosing coundown. */ - (void)startAutoclosingCountdown; -/** Override to handle the animation your way. Default implementation configures the close button (if not nil) for animation. */ +/** Override to handle the animation your way. Default implementation configures the close button (if not nil) for + * animation. */ - (void)doAnimateAutoclosing; - (NSTimeInterval)autoclosingRemainingTime; diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.m b/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.m index b5aa488..aa3144f 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.m +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGViewController.m @@ -194,6 +194,9 @@ - (void)setupRootStyle { break; // We've only got one rule to check, no need to continue } } + if (@available(iOS 15.0, *)) { + self.view.maximumContentSizeCategory = UIContentSizeCategoryExtraExtraExtraLarge; + } } #pragma mark - Dismissal diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.h b/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.h index 9a9b6c8..5f14789 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.h @@ -5,16 +5,16 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import @class BAMSGMessageWebView; @class BACSSDocument; -@interface BAMSGWebviewViewController: BAMSGViewController +@interface BAMSGWebviewViewController : BAMSGViewController -- (instancetype _Nonnull )initWithMessage:(BAMSGMessageWebView *_Nonnull)message andStyle:(BACSSDocument*_Nonnull)style; +- (instancetype _Nonnull)initWithMessage:(BAMSGMessageWebView *_Nonnull)message andStyle:(BACSSDocument *_Nonnull)style; -@property (nonatomic, readonly) BAMSGMessageWebView * _Nonnull message; +@property (nonatomic, readonly) BAMSGMessageWebView *_Nonnull message; @end diff --git a/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeLegacyWKHandler.h b/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeLegacyWKHandler.h index 5b44c43..6f7212d 100644 --- a/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeLegacyWKHandler.h +++ b/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeLegacyWKHandler.h @@ -8,8 +8,8 @@ #import #import -#import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -18,15 +18,15 @@ NS_ASSUME_NONNULL_BEGIN @protocol BATWebviewBridgeLegacyWKHandlerWebViewSource @required -- (nullable WKWebView*)backingWebViewForLegacyHandler:(BATWebviewBridgeLegacyWKHandler*)handler; +- (nullable WKWebView *)backingWebViewForLegacyHandler:(BATWebviewBridgeLegacyWKHandler *)handler; @end @interface BATWebviewBridgeLegacyWKHandler : BATWebviewBridgeWKHandler -- (instancetype)initWithBridge:(nonnull BATWebviewJavascriptBridge*)bridge NS_UNAVAILABLE; +- (instancetype)initWithBridge:(nonnull BATWebviewJavascriptBridge *)bridge NS_UNAVAILABLE; -- (instancetype)initWithBridge:(nonnull BATWebviewJavascriptBridge*)bridge +- (instancetype)initWithBridge:(nonnull BATWebviewJavascriptBridge *)bridge webViewProvider:(nonnull id)webViewProvider; @property (weak, nonatomic, readonly) WKWebView *webView; diff --git a/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeWKHandler.h b/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeWKHandler.h index 2591835..d734c7f 100644 --- a/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeWKHandler.h +++ b/Sources/Batch/Modules/Messaging/Webview/BATWebviewBridgeWKHandler.h @@ -14,11 +14,11 @@ NS_ASSUME_NONNULL_BEGIN @interface BATWebviewBridgeWKHandler : NSObject -- (instancetype)initWithBridge:(nonnull BATWebviewJavascriptBridge*)bridge; +- (instancetype)initWithBridge:(nonnull BATWebviewJavascriptBridge *)bridge; - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message - replyHandler:(void (^)(id _Nullable, NSString * _Nullable))replyHandler; + replyHandler:(void (^)(id _Nullable, NSString *_Nullable))replyHandler; @end diff --git a/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.h b/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.h index ab8aedc..5ad7852 100644 --- a/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.h +++ b/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.h @@ -5,28 +5,28 @@ // Copyright © Batch.com. All rights reserved. // -#import -#import #import +#import +#import NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSUInteger, BATWebviewJavascriptBridgeErrorCode) { - + /** Internal bridge error. Should not be exposed to the JS SDK, but should be logged. NSLocalizedFailureReasonErrorKey will contain the internal error, while NSLocalizedDescriptionKey will be the error code */ BATWebviewJavascriptBridgeErrorCodeInternalError, - + /** Public bridge error. Can be an unavailable value (advertising id), or malformed parameters Not exactly a cause, as it has a real underlying one, but good enough for our use. NSLocalizedDescriptionKey's value should be forwarded to the bridge in the "error" parameter, as is. */ BATWebviewJavascriptBridgeErrorCodePublicError, - + /** The requested method does not exist */ @@ -39,43 +39,45 @@ typedef NS_ENUM(NSUInteger, BATWebviewJavascriptBridgeErrorCode) { @required -- (void)bridge:(BATWebviewJavascriptBridge*)bridge shouldDismissMessageWithAnalyticsID:(nullable NSString*)analyticsIdentifier; +- (void)bridge:(BATWebviewJavascriptBridge *)bridge + shouldDismissMessageWithAnalyticsID:(nullable NSString *)analyticsIdentifier; -- (void)bridge:(BATWebviewJavascriptBridge*)bridge -shouldOpenDeeplink:(nonnull NSString*)url -openInAppOverride:(nullable NSNumber*)openInAppOverride - analyticsID:(nullable NSString*)analyticsIdentifier; +- (void)bridge:(BATWebviewJavascriptBridge *)bridge + shouldOpenDeeplink:(nonnull NSString *)url + openInAppOverride:(nullable NSNumber *)openInAppOverride + analyticsID:(nullable NSString *)analyticsIdentifier; -- (void)bridge:(BATWebviewJavascriptBridge*)bridge -shouldPerformAction:(NSString*)action - arguments:(NSDictionary*)arguments - analyticsID:(nullable NSString*)analyticsIdentifier; +- (void)bridge:(BATWebviewJavascriptBridge *)bridge + shouldPerformAction:(NSString *)action + arguments:(NSDictionary *)arguments + analyticsID:(nullable NSString *)analyticsIdentifier; @end @interface BATWebviewJavascriptBridge : NSObject -- (instancetype)initWithMessage:(nonnull BAMSGMessageWebView*)message +- (instancetype)initWithMessage:(nonnull BAMSGMessageWebView *)message delegate:(nullable id)delegate; -- (nonnull BAPromise*)executeBridgeMethod:(nullable NSString*)method arguments:(nullable NSDictionary*)rawJSONArguments; +- (nonnull BAPromise *)executeBridgeMethod:(nullable NSString *)method + arguments:(nullable NSDictionary *)rawJSONArguments; #pragma mark Methods visible for testing -- (BAPromise*)installationID; +- (BAPromise *)installationID; // Method that facilitates testing the attribution ID handling -- (nullable NSString*)readAttributionIDFromSDK; +- (nullable NSString *)readAttributionIDFromSDK; -- (BAPromise*)customRegion; +- (BAPromise *)customRegion; -- (BAPromise*)customLanguage; +- (BAPromise *)customLanguage; -- (BAPromise*)customUserID; +- (BAPromise *)customUserID; -- (BAPromise*)customPayload; +- (BAPromise *)customPayload; -- (BAPromise*)trackingID; +- (BAPromise *)trackingID; @end diff --git a/Sources/Batch/Modules/Messaging/Webview/BATWebviewUtils.h b/Sources/Batch/Modules/Messaging/Webview/BATWebviewUtils.h index 1817c11..2896484 100644 --- a/Sources/Batch/Modules/Messaging/Webview/BATWebviewUtils.h +++ b/Sources/Batch/Modules/Messaging/Webview/BATWebviewUtils.h @@ -12,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @interface BATWebviewUtils : NSObject // Returns the value of the "batchAnalyticsID" get parameter in an URL if available -+ (nullable NSString*)analyticsIdForURL:(nonnull NSString*)url; ++ (nullable NSString *)analyticsIdForURL:(nonnull NSString *)url; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGActivityIndicatorView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGActivityIndicatorView.h index 39100ac..9689016 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGActivityIndicatorView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGActivityIndicatorView.h @@ -5,8 +5,8 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -23,7 +23,8 @@ typedef NS_ENUM(NSUInteger, BAMSGActivityIndicatorViewColor) { @interface BAMSGActivityIndicatorView : UIActivityIndicatorView - (instancetype)initWithPreferredSize:(BAMSGActivityIndicatorViewSize)size NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyle)style __attribute__((deprecated("Use initWithPreferredSize:"))) NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyle)style + __attribute__((deprecated("Use initWithPreferredSize:")))NS_DESIGNATED_INITIALIZER; - (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER; - (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGBaseContainerView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGBaseContainerView.h index ef5f8ad..f2de2ee 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGBaseContainerView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGBaseContainerView.h @@ -1,7 +1,7 @@ #import -#import #import +#import @protocol BAMSGContainerViewProtocol @required @@ -10,7 +10,8 @@ @end -@interface BAMSGBaseContainerView : UIView +@interface BAMSGBaseContainerView + : UIView @property float cornerRadius; diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.h index b4c282b..b075265 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.h @@ -11,6 +11,9 @@ @interface BAMSGButton : UIButton -+ (void)setFontOverride:(nullable UIFont*)font boldFont:(nullable UIFont*)boldFont italicFont:(nullable UIFont*)italicFont boldItalicFont:(nullable UIFont*)boldItalicFont; ++ (void)setFontOverride:(nullable UIFont *)font + boldFont:(nullable UIFont *)boldFont + italicFont:(nullable UIFont *)italicFont + boldItalicFont:(nullable UIFont *)boldItalicFont; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.m b/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.m index 97135e1..583a235 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.m +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGButton.m @@ -6,6 +6,7 @@ // #import +#import static void *BAMSGButtonCornerRadiusContext = &BAMSGButtonCornerRadiusContext; @@ -53,6 +54,11 @@ - (void)setup { _savedCornerRadius = nil; _updatingCornerRadius = false; + self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; + self.titleLabel.adjustsFontForContentSizeCategory = [BAMessagingCenter instance].enableDynamicType; + if (@available(iOS 15.0, *)) { + self.maximumContentSizeCategory = UIContentSizeCategoryExtraExtraExtraLarge; + } // a corner radius change from outside the class needs to trigger a corner radius update [self.layer addObserver:self forKeyPath:@"cornerRadius" options:0 context:BAMSGButtonCornerRadiusContext]; diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGCloseButton.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGCloseButton.h index 0f0a2a2..29b722e 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGCloseButton.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGCloseButton.h @@ -5,8 +5,8 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import +#import @interface BAMSGCloseButton : UIButton @@ -17,6 +17,7 @@ @property (nonatomic) BOOL showBorder; - (void)prepareCountdown; -- (void)animateCountdownForDuration:(CFTimeInterval)duration completionHandler:(nullable void (^)(void))completionHandler; +- (void)animateCountdownForDuration:(CFTimeInterval)duration + completionHandler:(nullable void (^)(void))completionHandler; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGCountdownView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGCountdownView.h index c853c4b..35a8faa 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGCountdownView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGCountdownView.h @@ -9,7 +9,6 @@ */ - (void)setPercentage:(float)percentage; -- (void)setColor:(nonnull UIColor*)color; +- (void)setColor:(nonnull UIColor *)color; @end - diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGGradientView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGGradientView.h index c987045..e80809b 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGGradientView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGGradientView.h @@ -11,13 +11,16 @@ @protocol BAMSGGradientBackgroundProtocol -- (void)setBackgroundGradient:(float)angle colors:(NSArray*)colors locations:(NSArray*)locations; +- (void)setBackgroundGradient:(float)angle colors:(NSArray *)colors locations:(NSArray *)locations; @end @interface BAMSGGradientView : UIView -+ (void)setupGradientLayer:(CAGradientLayer*)layer withAngle:(float)angle colors:(NSArray*)colors locations:(NSArray*)locations; ++ (void)setupGradientLayer:(CAGradientLayer *)layer + withAngle:(float)angle + colors:(NSArray *)colors + locations:(NSArray *)locations; @property BOOL touchPassthrough; diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.h index 91dc14c..94ce7f0 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.h @@ -8,8 +8,8 @@ #import #import -#import #import +#import @interface BAMSGImageView : BAMSGGradientImageView diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.h index 33d4522..71cbff3 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.h @@ -5,17 +5,20 @@ // Copyright © 2016 Batch. All rights reserved. // -#import -#import #import +#import #import +#import @interface BAMSGLabel : UILabel @property UIEdgeInsets padding; -+ (void)setFontOverride:(nullable UIFont*)font boldFont:(nullable UIFont*)boldFont italicFont:(nullable UIFont*)italicFont boldItalicFont:(nullable UIFont*)boldItalicFont; ++ (void)setFontOverride:(nullable UIFont *)font + boldFont:(nullable UIFont *)boldFont + italicFont:(nullable UIFont *)italicFont + boldItalicFont:(nullable UIFont *)boldItalicFont; -- (void)setText:(NSString *_Nullable)text transforms:(NSArray*_Nullable)transforms; +- (void)setText:(NSString *_Nullable)text transforms:(NSArray *_Nullable)transforms; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.m b/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.m index 1bda95c..33078d5 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.m +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGLabel.m @@ -7,6 +7,7 @@ #import #import +#import @interface BAMSGLabel () { float lineHeightMultiply; @@ -41,7 +42,10 @@ - (instancetype)init { _padding = UIEdgeInsetsZero; self.lineBreakMode = NSLineBreakByWordWrapping; - + self.adjustsFontForContentSizeCategory = [BAMessagingCenter instance].enableDynamicType; + if (@available(iOS 15.0, *)) { + self.maximumContentSizeCategory = UIContentSizeCategoryExtraExtraExtraLarge; + } lineHeightMultiply = 0; lineHeightAdd = 0; letterSpacing = 0; @@ -114,7 +118,6 @@ - (void)applyRules:(nonnull BACSSRules *)rules { lineHeightAdd = [value floatValue]; } } - UIFont *customFont = [BAMSGStylableViewHelper fontFromRules:rules baseFont:sBAMSGLabelFontOverride baseBoldFont:sBAMSGLabelBoldFontOverride]; diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.h index ae39b03..7d26b88 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.h @@ -5,9 +5,9 @@ // Copyright © Batch.com. All rights reserved. // -#import #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -21,14 +21,13 @@ NS_ASSUME_NONNULL_BEGIN /** If true, snap the view back in default position when dismissing. Default to YES. */ @property (nonatomic, assign) BOOL resetPositionOnDismiss; - /** Link a view to this one Linked views will be applied the same transform and alpha changes when this view is dragged - + This only supports one linked view for now, as we only have one to deal with as of writing */ -- (void)setLinkedView:(nonnull UIView*)linkedView; +- (void)setLinkedView:(nonnull UIView *)linkedView; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAnchoredContainerView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAnchoredContainerView.h index 8848081..2fe806f 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAnchoredContainerView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAnchoredContainerView.h @@ -22,7 +22,7 @@ typedef NS_ENUM(NSUInteger, BAMSGPannableAnchoredContainerVerticalAnchor) { The biggest visible view displayed. This is used for automatic dismissal based on hiding a percentage of the visible view's height. Overriding this is useful when the container view is mostly transparent - + If not set, dismissal will only be based on velocity */ @property (weak, nullable) UIView *biggestUserVisibleView; diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableContainerView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableContainerView.h index fdcc535..210ed95 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableContainerView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableContainerView.h @@ -9,7 +9,7 @@ @protocol BAMSGPannableContainerViewDelegate -- (void)pannableContainerWasDismissed:(BAMSGBaseContainerView* _Nonnull)container; +- (void)pannableContainerWasDismissed:(BAMSGBaseContainerView *_Nonnull)container; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGRemoteImageView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGRemoteImageView.h index 1f44b01..ce836f0 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGRemoteImageView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGRemoteImageView.h @@ -1,18 +1,18 @@ -#import #import +#import @interface BAMSGRemoteImageView : BAMSGImageView /** Same as calling -setImageURL:completion: with a nil completion block. */ -- (void)setImageURL:(NSURL*)url; +- (void)setImageURL:(NSURL *)url; /** Ask the image view to load the image at `url` and display it. @param url The url pointing to the remote or local (file url) image. Local and remote gif images are also supported. @param completion Can be nil. If image couldn't be downloaded, completion is called with a non-null error. */ -- (void)setImageURL:(NSURL*)url completion:(void (^)(UIImage *, NSError *))completion; +- (void)setImageURL:(NSURL *)url completion:(void (^)(UIImage *, NSError *))completion; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h index f778329..91d1147 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h @@ -5,23 +5,25 @@ // Copyright © 2016 Batch. All rights reserved. // -#import #import +#import @import UIKit; @protocol BAMSGStylableView -- (void)applyRules:(nonnull BACSSRules*)rules; +- (void)applyRules:(nonnull BACSSRules *)rules; @end @interface BAMSGStylableViewHelper : NSObject -+ (void)applyCommonRules:(nonnull BACSSRules*)rules toView:(nonnull UIView*)view; ++ (void)applyCommonRules:(nonnull BACSSRules *)rules toView:(nonnull UIView *)view; -+ (nullable UIColor*)colorFromValue:(nonnull NSString*)value; ++ (nullable UIColor *)colorFromValue:(nonnull NSString *)value; -+ (nullable UIFont*)fontFromRules:(nonnull BACSSRules*)rules baseFont:(nullable UIFont*)baseFont baseBoldFont:(nullable UIFont*)baseBoldFont; ++ (nullable UIFont *)fontFromRules:(nonnull BACSSRules *)rules + baseFont:(nullable UIFont *)baseFont + baseBoldFont:(nullable UIFont *)baseBoldFont; @end diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.m b/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.m index 37288b2..8aad880 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.m +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.m @@ -8,6 +8,7 @@ #import #import #import +#import @implementation BAMSGStylableViewHelper @@ -267,7 +268,10 @@ + (nullable UIFont *)fontFromRules:(nonnull BACSSRules *)rules labelFont = guessedFont; } } - + if ([BAMessagingCenter instance].enableDynamicType) { + // Scales font if dynamic type is enabled + labelFont = [[UIFontMetrics defaultMetrics] scaledFontForFont:labelFont]; + } return labelFont; } diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.h index e1608e4..20628d1 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.h @@ -12,11 +12,12 @@ /// Set a view to be the same size than it's parent /// @param view view to constraint /// @param superview parent view -/// @param useSafeArea Use the safe area as inset, or constraint the view to it. true: constraint the child view to the safeAreaLayoutGuide, applying insets outside of the view -/// false: the view will be exactly the same size as the parent is and should handle the safe area using insets +/// @param useSafeArea Use the safe area as inset, or constraint the view to it. true: constraint the child view to the +/// safeAreaLayoutGuide, applying insets outside of the view +/// false: the view will be exactly the same size as the parent is and should handle the safe +/// area using insets + (void)setView:(nonnull UIView *)view fullframeToSuperview:(nonnull UIView *)superview useSafeArea:(BOOL)useSafeArea; - /// Returns the current scene size /// Prior to iOS 13, this returns the screen size, or the size of the split the app /// is running it on a multitasking iPad @@ -25,6 +26,6 @@ /// Get a string localized by UIKit's builtin localizations /// Useful for common stuff -+ (nonnull NSString*)localizedStringUsingUIKit:(nonnull NSString*)string; ++ (nonnull NSString *)localizedStringUsingUIKit:(nonnull NSString *)string; @end diff --git a/Sources/Batch/Modules/Metrics/BACounter.h b/Sources/Batch/Modules/Metrics/BACounter.h index cc6d77e..e76f7b7 100644 --- a/Sources/Batch/Modules/Metrics/BACounter.h +++ b/Sources/Batch/Modules/Metrics/BACounter.h @@ -3,8 +3,8 @@ // // Copyright © Batch.com. All rights reserved. // -#import #import +#import @interface BACounter : BAMetric diff --git a/Sources/Batch/Modules/Metrics/BAMetric.h b/Sources/Batch/Modules/Metrics/BAMetric.h index 1a4fc73..64f9467 100644 --- a/Sources/Batch/Modules/Metrics/BAMetric.h +++ b/Sources/Batch/Modules/Metrics/BAMetric.h @@ -3,38 +3,40 @@ // // Copyright © Batch.com. All rights reserved. // -#import #import #import +#import -@interface BAMetric : NSObject +@interface BAMetric : NSObject /// Metric name -@property (atomic, assign, readonly, nonnull) NSString* name; +@property (atomic, assign, readonly, nonnull) NSString *name; /// Metric type (observation | counter ) -@property (atomic, assign, readonly, nonnull) NSString* type; +@property (atomic, assign, readonly, nonnull) NSString *type; /// Metric values -@property (atomic, strong, readonly, nullable) NSMutableArray *values; +@property (atomic, strong, readonly, nullable) NSMutableArray *values; /// Metric label names (eg: method / code) -@property (atomic, strong, readwrite, nullable) NSMutableArray *labelNames; +@property (atomic, strong, readwrite, nullable) NSMutableArray *labelNames; /// Metric label values (eg: post / 200) -@property (atomic, strong, readwrite, nullable) NSMutableArray *labelValues; +@property (atomic, strong, readwrite, nullable) NSMutableArray *labelValues; /// Metric children (meaning every label values association is a child) @property (atomic, strong, readonly, nullable) NSMutableDictionary *children; -- (nonnull instancetype)initWithName:(nonnull NSString*)name; +- (nonnull instancetype)initWithName:(nonnull NSString *)name; -- (nonnull instancetype)initWithName:(nonnull NSString*)name andLabelNames:(nonnull NSString*)firstLabel, ... NS_REQUIRES_NIL_TERMINATION; +- (nonnull instancetype)initWithName:(nonnull NSString *)name + andLabelNames:(nonnull NSString *)firstLabel, ... NS_REQUIRES_NIL_TERMINATION; -- (nonnull instancetype)initWithName:(nonnull NSString*)name andLabelNamesList:(nonnull NSArray*) labelNames; +- (nonnull instancetype)initWithName:(nonnull NSString *)name + andLabelNamesList:(nonnull NSArray *)labelNames; /// Get or create a child from labels values -- (nonnull id)labels:(nonnull NSString*)firstLabel, ... NS_REQUIRES_NIL_TERMINATION; +- (nonnull id)labels:(nonnull NSString *)firstLabel, ... NS_REQUIRES_NIL_TERMINATION; /// Register this metric to the BAMetricManager instance - (nonnull id)registerMetric; @@ -46,9 +48,9 @@ - (BOOL)hasChanged; /// MsgPack method -- (BOOL)packToWriter:(nonnull BATMessagePackWriter *)writer error:(NSError * _Nullable * _Nullable)error; +- (BOOL)packToWriter:(nonnull BATMessagePackWriter *)writer error:(NSError *_Nullable *_Nullable)error; /// MsgPack method -- (nullable NSData *)pack:(NSError * _Nullable * _Nullable)error; +- (nullable NSData *)pack:(NSError *_Nullable *_Nullable)error; @end diff --git a/Sources/Batch/Modules/Metrics/BAMetricManager.h b/Sources/Batch/Modules/Metrics/BAMetricManager.h index 47da542..ba08d28 100644 --- a/Sources/Batch/Modules/Metrics/BAMetricManager.h +++ b/Sources/Batch/Modules/Metrics/BAMetricManager.h @@ -4,8 +4,8 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)sharedInstance; /// Add a metric to the registered metric list -- (void)addMetric:(BAMetric*)metric; +- (void)addMetric:(BAMetric *)metric; /// Send metrics that have changed - (void)sendMetrics; diff --git a/Sources/Batch/Modules/Metrics/BAMetricProtocol.h b/Sources/Batch/Modules/Metrics/BAMetricProtocol.h index 573adb0..fe583f2 100644 --- a/Sources/Batch/Modules/Metrics/BAMetricProtocol.h +++ b/Sources/Batch/Modules/Metrics/BAMetricProtocol.h @@ -9,10 +9,10 @@ @required /// Initialize a new metric child --(id)newChild:(NSMutableArray *)labels; +- (id)newChild:(NSMutableArray *)labels; @required /// Reset metric values --(void)reset; +- (void)reset; @end diff --git a/Sources/Batch/Modules/Metrics/BAMetricRegistry.h b/Sources/Batch/Modules/Metrics/BAMetricRegistry.h index 64c9a31..81febea 100644 --- a/Sources/Batch/Modules/Metrics/BAMetricRegistry.h +++ b/Sources/Batch/Modules/Metrics/BAMetricRegistry.h @@ -4,10 +4,9 @@ // Copyright © Batch.com. All rights reserved. // -#import -#import #import - +#import +#import NS_ASSUME_NONNULL_BEGIN @@ -16,14 +15,13 @@ NS_ASSUME_NONNULL_BEGIN @property (nonnull, readonly, class) BAMetricRegistry *instance; /// Observe local campaigns JIT response time -- (BAObservation*)localCampaignsJITResponseTime; +- (BAObservation *)localCampaignsJITResponseTime; /// Count local campaign ws calls by status ("OK", "KO") -- (BACounter*)localCampaignsJITCount; +- (BACounter *)localCampaignsJITCount; /// Observe local campaigns sync response time -- (BAObservation*)localCampaignsSyncResponseTime; - +- (BAObservation *)localCampaignsSyncResponseTime; @end diff --git a/Sources/Batch/Modules/Metrics/BAMetricWebserviceClient.h b/Sources/Batch/Modules/Metrics/BAMetricWebserviceClient.h index dad942b..911f81c 100644 --- a/Sources/Batch/Modules/Metrics/BAMetricWebserviceClient.h +++ b/Sources/Batch/Modules/Metrics/BAMetricWebserviceClient.h @@ -10,7 +10,7 @@ @interface BAMetricWebserviceClient : BAWebserviceMsgPackClient - (nullable instancetype)initWithMetrics:(nonnull NSArray *)metrics - success:(void (^ _Nullable)(void))successHandler - error:(void (^ _Nullable)(NSError* _Nonnull error))errorHandler; + success:(void (^_Nullable)(void))successHandler + error:(void (^_Nullable)(NSError *_Nonnull error))errorHandler; @end diff --git a/Sources/Batch/Modules/Metrics/BAObservation.h b/Sources/Batch/Modules/Metrics/BAObservation.h index 422b30f..2d1da02 100644 --- a/Sources/Batch/Modules/Metrics/BAObservation.h +++ b/Sources/Batch/Modules/Metrics/BAObservation.h @@ -4,8 +4,8 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import @interface BAObservation : BAMetric /// Increment the observation value diff --git a/Sources/Batch/Modules/Opt Out/BAOptOut.h b/Sources/Batch/Modules/Opt Out/BAOptOut.h index a43dade..ab9d55d 100644 --- a/Sources/Batch/Modules/Opt Out/BAOptOut.h +++ b/Sources/Batch/Modules/Opt Out/BAOptOut.h @@ -6,9 +6,9 @@ #define OptOutDefaultKey @"opted_out" #define ShouldFireOptinEventDefaultKey @"should_fire_optin_event" -extern NSString * _Nonnull const kBATOptOutChangedNotification; -extern NSString * _Nonnull const kBATOptOutValueKey; -extern NSString * _Nonnull const kBATOptOutWipeDataKey; +extern NSString *_Nonnull const kBATOptOutChangedNotification; +extern NSString *_Nonnull const kBATOptOutValueKey; +extern NSString *_Nonnull const kBATOptOutWipeDataKey; @class BAOptOutEventTracker; @@ -16,7 +16,9 @@ extern NSString * _Nonnull const kBATOptOutWipeDataKey; + (nonnull BAOptOut *)instance; -- (void)setOptedOut:(BOOL)newVal wipeData:(BOOL)wipeData completionHandler:(BatchOptOutNetworkErrorPolicy(^ _Nonnull)(BOOL success))handler; +- (void)setOptedOut:(BOOL)newVal + wipeData:(BOOL)wipeData + completionHandler:(BatchOptOutNetworkErrorPolicy (^_Nonnull)(BOOL success))handler; - (BOOL)isOptedOut; @@ -28,8 +30,10 @@ extern NSString * _Nonnull const kBATOptOutWipeDataKey; - (void)initEventTrackerIfNeeded; -- (void)setEventTracker:(nullable BAOptOutEventTracker*)eventTracker; +- (void)setEventTracker:(nullable BAOptOutEventTracker *)eventTracker; - (void)applyOptOut:(BOOL)shouldOptOut wipeData:(BOOL)wipeData; +- (void)wipeData; + @end diff --git a/Sources/Batch/Modules/Opt Out/BAOptOutEventTracker.h b/Sources/Batch/Modules/Opt Out/BAOptOutEventTracker.h index fe20e99..e041909 100644 --- a/Sources/Batch/Modules/Opt Out/BAOptOutEventTracker.h +++ b/Sources/Batch/Modules/Opt Out/BAOptOutEventTracker.h @@ -19,6 +19,6 @@ */ @interface BAOptOutEventTracker : NSObject -- (BAPromise*)track:(BAEvent*)event; +- (BAPromise *)track:(BAEvent *)event; @end diff --git a/Sources/Batch/Modules/Opt Out/BAOptOutWebserviceClient.h b/Sources/Batch/Modules/Opt Out/BAOptOutWebserviceClient.h index b83e609..252a9a2 100644 --- a/Sources/Batch/Modules/Opt Out/BAOptOutWebserviceClient.h +++ b/Sources/Batch/Modules/Opt Out/BAOptOutWebserviceClient.h @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN */ @interface BAOptOutWebserviceClient : BAQueryWebserviceClient -- (instancetype)initWithEvents:(NSArray*)events promises:(NSArray *)promises; +- (instancetype)initWithEvents:(NSArray *)events promises:(NSArray *)promises; @end diff --git a/Sources/Batch/Modules/Push/BAPushCenter.h b/Sources/Batch/Modules/Push/BAPushCenter.h index 06ed3ab..18e69b8 100644 --- a/Sources/Batch/Modules/Push/BAPushCenter.h +++ b/Sources/Batch/Modules/Push/BAPushCenter.h @@ -9,15 +9,15 @@ #import #import -#import #import #import +#import // Is the push open coming from UNUserNotificationCenterDelegate's didResponse callback? -extern NSString * const kBATPushOpenedNotificationOriginatesFromUNResponseKey; +extern NSString *const kBATPushOpenedNotificationOriginatesFromUNResponseKey; // Is the push open coming from application:didFinishLaunchingWithOptions? -extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; +extern NSString *const kBATPushOpenedNotificationOriginatesFromAppDelegate; /*! @class BAPushCenter @@ -28,7 +28,8 @@ extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; /*! @property shouldAutomaticallyRetreivePushToken - @abstract YES registerForRemoteNotifications should be called after the notificaiton user popup. Only YES if user called "[BatchPush registerForRemoteNotifications]" + @abstract YES registerForRemoteNotifications should be called after the notificaiton user popup. Only YES if user + called "[BatchPush registerForRemoteNotifications]" */ @property (assign, nonatomic) BOOL shouldAutomaticallyRetreivePushToken; @@ -56,12 +57,11 @@ extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; */ @property BOOL shouldSwizzle; - /*! @property startPushUserInfo @abstract userInfo of the push the app was started with, if it was. */ -@property NSDictionary* startPushUserInfo; +@property NSDictionary *startPushUserInfo; /*! @method instance @@ -109,7 +109,10 @@ extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; @method setNotificationsCategories: @abstract Set the notification action categories to iOS. @discussion You should call this every time your app starts - @param categories : A set of UIUserNotificationCategory or UNNotificationCategory instances that define the groups of actions a notification may include. If you try to register UIUserNotificationCategory instances on iOS 10, Batch will automatically do a best effort conversion to UNNotificationCategory. If you don't want this behaviour, please use the standard UIApplication methods. + @param categories : A set of UIUserNotificationCategory or UNNotificationCategory instances that define the groups of + actions a notification may include. If you try to register UIUserNotificationCategory instances on iOS 10, Batch will + automatically do a best effort conversion to UNNotificationCategory. If you don't want this behaviour, please use the + standard UIApplication methods. */ + (void)setNotificationsCategories:(NSSet *)categories; @@ -123,14 +126,16 @@ extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; /*! @method dismissNotifications @abstract Clear the app's notifications in the notification center. Also clears your badge. - @discussion Call this when you want to remove the notifications. Your badge is removed afterwards, so if you want one, you need to set it up again. + @discussion Call this when you want to remove the notifications. Your badge is removed afterwards, so if you want one, + you need to set it up again. */ + (void)dismissNotifications; /*! @method enableAutomaticDeeplinkHandling: @abstract Set whether Batch Push should automatically try to handle deeplinks - @discussion By default, this is set to YES. You need to call everytime your app is restarted, this option is not persisted. + @discussion By default, this is set to YES. You need to call everytime your app is restarted, this option is not + persisted. */ + (void)enableAutomaticDeeplinkHandling:(BOOL)handleDeeplinks; @@ -143,18 +148,21 @@ extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; /*! @method disableAutomaticIntegration - @abstract Disable the push's automatic integration. If you call this, you are responsible of forwarding your application's delegate calls to Batch. If you don't, some parts of the SDK and Dashboard will break. + @abstract Disable the push's automatic integration. If you call this, you are responsible of forwarding your + application's delegate calls to Batch. If you don't, some parts of the SDK and Dashboard will break. @warning This must be called before you start Batch, or it will have no effect. */ + (void)disableAutomaticIntegration; /*! @method handleDeviceToken - @abstract Registers a device token to Batch. You should call this method in "application:didRegisterForRemoteNotificationsWithDeviceToken:". - @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. + @abstract Registers a device token to Batch. You should call this method in + "application:didRegisterForRemoteNotificationsWithDeviceToken:". + @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't + implement this method, Batch's push features will NOT work. @param token : The untouched "deviceToken" NSData argument given to you in the application delegate method. */ -+ (void)handleDeviceToken:(NSData*)token; ++ (void)handleDeviceToken:(NSData *)token; /*! @method isBatchPush @@ -163,30 +171,39 @@ extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; @param userInfo : The untouched "userInfo" NSDictionary argument given to you in the application delegate method. @return If it returns true, you should not handle the push. */ -+ (BOOL)isBatchPush:(NSDictionary*)userInfo; ++ (BOOL)isBatchPush:(NSDictionary *)userInfo; /*! @method handleNotification - @abstract Make Batch process a notification. You should call this method in "application:didReceiveRemoteNotification:" or "application:didReceiveRemoteNotification:fetchCompletionHandler:". - @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. + @abstract Make Batch process a notification. You should call this method in "application:didReceiveRemoteNotification:" + or "application:didReceiveRemoteNotification:fetchCompletionHandler:". + @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't + implement this method, Batch's push features will NOT work. @param userInfo : The untouched "userInfo" NSDictionary argument given to you in the application delegate method. */ -+ (void)handleNotification:(NSDictionary*)userInfo; ++ (void)handleNotification:(NSDictionary *)userInfo; /*! @method handleNotification - @abstract Make Batch process a notification action. You should call this method in "application:handleActionWithIdentifier:forRemoteNotification:completionHandler:" or "application:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:". - @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. + @abstract Make Batch process a notification action. You should call this method in + "application:handleActionWithIdentifier:forRemoteNotification:completionHandler:" or + "application:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:". + @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't + implement this method, Batch's push features will NOT work. @param userInfo : The untouched "userInfo" NSDictionary argument given to you in the application delegate method. - @param identifier : The action's identifier. Used for tracking purposes: it can match your raw action name, or be a more user-friendly string; + @param identifier : The action's identifier. Used for tracking purposes: it can match your raw action name, or be a + more user-friendly string; */ -+ (void)handleNotification:(NSDictionary*)userInfo actionIdentifier:(NSString*)identifier; ++ (void)handleNotification:(NSDictionary *)userInfo actionIdentifier:(NSString *)identifier; /*! @method handleNotification - @abstract Make Batch process the user notification settings change. You should call this method in "application:didRegisterUserNotificationSettings:". - @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't implement this method, Batch's push features will NOT work. - @param notificationSettings : The untouched "notificationSettings" UIUserNotificationSettings* argument given to you in the application delegate method. + @abstract Make Batch process the user notification settings change. You should call this method in + "application:didRegisterUserNotificationSettings:". + @warning If you didn't call "disableAutomaticIntegration", this method will have no effect. If you called it but don't + implement this method, Batch's push features will NOT work. + @param notificationSettings : The untouched "notificationSettings" UIUserNotificationSettings* argument given to you in + the application delegate method. */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -194,29 +211,36 @@ extern NSString * const kBATPushOpenedNotificationOriginatesFromAppDelegate; #pragma clang diagnostic pop /** - Make Batch process a foreground notification. You should call this method if you set your own UNUserNotificationCenterDelegate, in userNotificationCenter:willPresentNotification:withCompletionHandler: - + Make Batch process a foreground notification. You should call this method if you set your own + UNUserNotificationCenterDelegate, in userNotificationCenter:willPresentNotification:withCompletionHandler: + @param center Original center argument @param notification Original notification argument - @param willShowSystemForegroundAlert Whether you will tell the framework to show this notification, or. Batch uses this value to adjust its behaviour accordingly for a better user experience. + @param willShowSystemForegroundAlert Whether you will tell the framework to show this notification, or. Batch uses + this value to adjust its behaviour accordingly for a better user experience. */ -+ (void)handleUserNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert NS_AVAILABLE_IOS(10_0); ++ (void)handleUserNotificationCenter:(UNUserNotificationCenter *)center + willPresentNotification:(UNNotification *)notification + willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert NS_AVAILABLE_IOS(10_0); /** - Make Batch process a background notification open/action. You should call this method if you set your own UNUserNotificationCenterDelegate, in userNotificationCenter:didReceiveNotificationResponse: - + Make Batch process a background notification open/action. You should call this method if you set your own + UNUserNotificationCenterDelegate, in userNotificationCenter:didReceiveNotificationResponse: + @param center Original center argument @param response Original response argument */ -+ (void)handleUserNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response NS_AVAILABLE_IOS(10_0); ++ (void)handleUserNotificationCenter:(UNUserNotificationCenter *)center + didReceiveNotificationResponse:(UNNotificationResponse *)response NS_AVAILABLE_IOS(10_0); /** Make Batch process a notification payload - - Most code should use handleUserNotificationCenter:didReceiveNotificationResponse: but getting an instance of UNNotificationResponse isn't doable manually + + Most code should use handleUserNotificationCenter:didReceiveNotificationResponse: but getting an instance of + UNNotificationResponse isn't doable manually */ - (void)parseNotification:(NSDictionary *)userInfo - fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler -originatesFromUNDelegateResponse:(BOOL)originatesFromUNDelegateResponse; + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler + originatesFromUNDelegateResponse:(BOOL)originatesFromUNDelegateResponse; @end diff --git a/Sources/Batch/Modules/Push/BAPushSystemHelperProtocol.h b/Sources/Batch/Modules/Push/BAPushSystemHelperProtocol.h index 4b496db..80331d3 100644 --- a/Sources/Batch/Modules/Push/BAPushSystemHelperProtocol.h +++ b/Sources/Batch/Modules/Push/BAPushSystemHelperProtocol.h @@ -10,13 +10,18 @@ @protocol BAPushSystemHelperProtocol -// Register for remote notifications for the given types and whether the app should declare that it supports a settings deeplink or not -- (void)registerForRemoteNotificationsTypes:(BatchNotificationType)notifType providesNotificationSettings:(BOOL)providesSettings; +// Register for remote notifications for the given types and whether the app should declare that it supports a settings +// deeplink or not +- (void)registerForRemoteNotificationsTypes:(BatchNotificationType)notifType + providesNotificationSettings:(BOOL)providesSettings; -// Register for provisional notifications for the given types and whether the app should declare that it supports a settings deeplink or not -- (void)registerForProvisionalNotifications:(BatchNotificationType)notifType providesNotificationSettings:(BOOL)providesSettings; +// Register for provisional notifications for the given types and whether the app should declare that it supports a +// settings deeplink or not +- (void)registerForProvisionalNotifications:(BatchNotificationType)notifType + providesNotificationSettings:(BOOL)providesSettings; -// Register the given categories to iOS. The set is not typed so the user can give us either iOS 8+ or 10+ classes (or any class, you must check the input beforehand) -- (void)registerCategories:(NSSet*)categories; +// Register the given categories to iOS. The set is not typed so the user can give us either iOS 8+ or 10+ classes (or +// any class, you must check the input beforehand) +- (void)registerCategories:(NSSet *)categories; @end diff --git a/Sources/Batch/Modules/Tracker/BAEvent.h b/Sources/Batch/Modules/Tracker/BAEvent.h old mode 100755 new mode 100644 index bdb499b..d077927 --- a/Sources/Batch/Modules/Tracker/BAEvent.h +++ b/Sources/Batch/Modules/Tracker/BAEvent.h @@ -14,13 +14,12 @@ @enum BAEventState @abstract Event state */ -enum -{ - BAEventStateAll = -1, // Value not meant to be stored in SQLite - BAEventStateNew = 0, - BAEventStateSending = 1, - BAEventStateSent = 2, - BAEventStateOld = 3 +enum { + BAEventStateAll = -1, // Value not meant to be stored in SQLite + BAEventStateNew = 0, + BAEventStateSending = 1, + BAEventStateSent = 2, + BAEventStateOld = 3 }; /*! @@ -110,21 +109,35 @@ typedef NSInteger BAEventState; @param parameters : Event parameters @return Instance. */ -- (instancetype)initWithName:(NSString *)name andParameters:(NSDictionary *)parameters __attribute__((warn_unused_result)); +- (instancetype)initWithName:(NSString *)name + andParameters:(NSDictionary *)parameters __attribute__((warn_unused_result)); /*! @method initWithIdentifier:name:date:parameters:state:andTick: @abstract Constructor from the SQL representation. @return Instance. */ -- (instancetype)initWithIdentifier:(NSString *)identifier name:(NSString *)name date:(NSString *)date parameters:(NSString *)parameters state:(BAEventState)state session:(NSString*)session andTick:(long long)tick __attribute__((warn_unused_result)); +- (instancetype)initWithIdentifier:(NSString *)identifier + name:(NSString *)name + date:(NSString *)date + parameters:(NSString *)parameters + state:(BAEventState)state + session:(NSString *)session + andTick:(long long)tick __attribute__((warn_unused_result)); /*! @method initWithIdentifier:name:date:secureDate:parameters:state:andTick: @abstract Constructor from the SQL representation. @return Instance. */ -- (instancetype)initWithIdentifier:(NSString *)identifier name:(NSString *)name date:(NSString *)date secureDate:(NSString *)secureDate parameters:(NSString *)parameters state:(BAEventState)state session:(NSString*)session andTick:(long long)tick __attribute__((warn_unused_result)); +- (instancetype)initWithIdentifier:(NSString *)identifier + name:(NSString *)name + date:(NSString *)date + secureDate:(NSString *)secureDate + parameters:(NSString *)parameters + state:(BAEventState)state + session:(NSString *)session + andTick:(long long)tick __attribute__((warn_unused_result)); /*! @method eventWithName: @@ -141,21 +154,35 @@ typedef NSInteger BAEventState; @param parameters : Event parameters @return Instance. */ -+ (instancetype)eventWithName:(NSString *)name andParameters:(NSDictionary *)parameters __attribute__((warn_unused_result)); ++ (instancetype)eventWithName:(NSString *)name + andParameters:(NSDictionary *)parameters __attribute__((warn_unused_result)); /*! @method eventWithIdentifier:name:date:parameters:state:andTick: @abstract Constructor from the SQL representation. @return Instance. */ -+ (instancetype)eventWithIdentifier:(NSString *)identifier name:(NSString *)name date:(NSString *)date parameters:(NSString *)parameters state:(BAEventState)state session:(NSString*)session andTick:(long long)tick __attribute__((warn_unused_result)); ++ (instancetype)eventWithIdentifier:(NSString *)identifier + name:(NSString *)name + date:(NSString *)date + parameters:(NSString *)parameters + state:(BAEventState)state + session:(NSString *)session + andTick:(long long)tick __attribute__((warn_unused_result)); /*! @method eventWithIdentifier:name:date:secureDate:parameters:state:andTick: @abstract Constructor from the SQL representation. @return Instance. */ -+ (instancetype)eventWithIdentifier:(NSString *)identifier name:(NSString *)name date:(NSString *)date secureDate:(NSString *)secureDate parameters:(NSString *)parameters state:(BAEventState)state session:(NSString*)session andTick:(long long)tick __attribute__((warn_unused_result)); ++ (instancetype)eventWithIdentifier:(NSString *)identifier + name:(NSString *)name + date:(NSString *)date + secureDate:(NSString *)secureDate + parameters:(NSString *)parameters + state:(BAEventState)state + session:(NSString *)session + andTick:(long long)tick __attribute__((warn_unused_result)); /*! @method identifiersOfEvents: @@ -167,7 +194,6 @@ typedef NSInteger BAEventState; @end - /** A collapsable event is an event that only keeps the last occurrence in the database */ diff --git a/Sources/Batch/Modules/Tracker/BAEventDBHelperProtocol.h b/Sources/Batch/Modules/Tracker/BAEventDBHelperProtocol.h index e126ebc..da495ec 100644 --- a/Sources/Batch/Modules/Tracker/BAEventDBHelperProtocol.h +++ b/Sources/Batch/Modules/Tracker/BAEventDBHelperProtocol.h @@ -6,8 +6,9 @@ // Copyright (c) 2014 Batch SDK. All rights reserved. // -#import #import +#import +#import /*! @protocol BAEventDBHelperProtocol @@ -36,6 +37,6 @@ @param statement precompiled statement to bind the event to @return YES if insertion has been populated, NO otherwise. */ -- (BOOL)bindEvent:(BAEvent*)event withStatement:(sqlite3_stmt **)statement __attribute__((warn_unused_result)); +- (BOOL)bindEvent:(BAEvent *)event withStatement:(sqlite3_stmt **)statement __attribute__((warn_unused_result)); @end diff --git a/Sources/Batch/Modules/Tracker/BAEventDatasourceProtocol.h b/Sources/Batch/Modules/Tracker/BAEventDatasourceProtocol.h index fbf536a..9a874c3 100644 --- a/Sources/Batch/Modules/Tracker/BAEventDatasourceProtocol.h +++ b/Sources/Batch/Modules/Tracker/BAEventDatasourceProtocol.h @@ -6,8 +6,8 @@ // Copyright (c) 2014 Batch SDK. All rights reserved. // -#import #import +#import /*! @protocol BAEventDatasourceProtocol @@ -56,7 +56,7 @@ @param state : State to update to @param events : Event IDs to update (NSArray of NSString) */ -- (void)updateEventsStateTo:(BAEventState)state forEventsIdentifier:(NSArray*)events; +- (void)updateEventsStateTo:(BAEventState)state forEventsIdentifier:(NSArray *)events; /*! @method deleteEvents: diff --git a/Sources/Batch/Modules/Tracker/BAEventSQLiteDatasource.h b/Sources/Batch/Modules/Tracker/BAEventSQLiteDatasource.h index 9bb5e01..c074513 100644 --- a/Sources/Batch/Modules/Tracker/BAEventSQLiteDatasource.h +++ b/Sources/Batch/Modules/Tracker/BAEventSQLiteDatasource.h @@ -6,27 +6,27 @@ // Copyright (c) 2014 Batch SDK. All rights reserved. // +#import +#import #import #import -#import -#import /*! @class BAEventSQLiteDatasource @abstract Implementation of BAEventDatasourceProtocol using SQLLite */ -@interface BAEventSQLiteDatasource : NSObject -{ +@interface BAEventSQLiteDatasource : NSObject { sqlite3 *_database; - + sqlite3_stmt *_insertStatement; - + sqlite3_stmt *_collapseDeleteStatement; } - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithFilename:(NSString *)name forDBHelper:(id)eventDBHelper __attribute__((warn_unused_result)); +- (instancetype)initWithFilename:(NSString *)name + forDBHelper:(id)eventDBHelper __attribute__((warn_unused_result)); /*! @property templateEvent @@ -34,5 +34,4 @@ */ @property id eventDBHelper; - @end diff --git a/Sources/Batch/Modules/Tracker/BAEventSQLiteHelper.h b/Sources/Batch/Modules/Tracker/BAEventSQLiteHelper.h index d3281c0..f394263 100644 --- a/Sources/Batch/Modules/Tracker/BAEventSQLiteHelper.h +++ b/Sources/Batch/Modules/Tracker/BAEventSQLiteHelper.h @@ -6,9 +6,9 @@ // Copyright (c) 2014 Batch SDK. All rights reserved. // +#import #import #import -#import @interface BAEventSQLiteHelper : NSObject diff --git a/Sources/Batch/Modules/Tracker/BATrackerCenter.h b/Sources/Batch/Modules/Tracker/BATrackerCenter.h index 8ee9283..a0884a2 100644 --- a/Sources/Batch/Modules/Tracker/BATrackerCenter.h +++ b/Sources/Batch/Modules/Tracker/BATrackerCenter.h @@ -6,8 +6,8 @@ // Copyright (c) 2014 Batch SDK. All rights reserved. // -#import #import +#import #import #import @@ -24,29 +24,27 @@ @enum BATrackerMode @abstract Possible causes of webservice failure. */ -enum -{ +enum { /*! Value to completly switch off the event tracker. */ - BATrackerModeOFF = 0, - + BATrackerModeOFF = 0, + /*! Value to stop sending the event (event will continue to be registred in DB). */ - BATrackerModeDB_ONLY = 1, - + BATrackerModeDB_ONLY = 1, + /*! Value to completely activate the event tracker (default value). */ - BATrackerModeON = 2 + BATrackerModeON = 2 }; /*! @typedef BATrackerMode */ typedef NSInteger BATrackerMode; - /*! @class BATrackerCenter @abstract Central control point of Batch event tracking services. @@ -77,7 +75,7 @@ typedef NSInteger BATrackerMode; /*! Track an uncollapsable publicevent with label and data - + Do not prepend "E." to the event name: this method will do it */ + (void)trackPublicEvent:(nonnull NSString *)name label:(nullable NSString *)label data:(nullable BatchEventData *)data; @@ -88,9 +86,12 @@ typedef NSInteger BATrackerMode; + (void)trackPrivateEvent:(nonnull NSString *)name parameters:(nullable NSDictionary *)parameters; /*! - Track a private event with parameters, optionally collapsable (meaning that only one instance of the event will be stored) + Track a private event with parameters, optionally collapsable (meaning that only one instance of the event will be + stored) */ -+ (void)trackPrivateEvent:(nonnull NSString *)name parameters:(nullable NSDictionary *)parameters collapsable:(BOOL)collapsable; ++ (void)trackPrivateEvent:(nonnull NSString *)name + parameters:(nullable NSDictionary *)parameters + collapsable:(BOOL)collapsable; /*! Track an already existing private event. Use case: BAEvent is created from an old BAEventLight instance. @@ -101,7 +102,7 @@ typedef NSInteger BATrackerMode; @method trackLocation: @abstract Track an location event */ -+ (void)trackLocation:(nonnull CLLocation*)location; ++ (void)trackLocation:(nonnull CLLocation *)location; /*! @method datasource diff --git a/Sources/Batch/Modules/Tracker/BATrackerSender.h b/Sources/Batch/Modules/Tracker/BATrackerSender.h index 1d3f056..8cf6075 100644 --- a/Sources/Batch/Modules/Tracker/BATrackerSender.h +++ b/Sources/Batch/Modules/Tracker/BATrackerSender.h @@ -11,14 +11,16 @@ /*! @class BATrackerSender @abstract Treat the tracker webservice execution. - @discussion This object is responsible for finding the right events to send, send them when asked, and handle their state. + @discussion This object is responsible for finding the right events to send, send them when asked, and handle their + state. */ @interface BATrackerSender : NSObject /*! @method send @abstract Send the events to the server - @return YES if the webservice has been started by calling this method or the webservice was already running, NO if no events were available to send or sending is disabled. + @return YES if the webservice has been started by calling this method or the webservice was already running, NO if no + events were available to send or sending is disabled. */ - (BOOL)send __attribute__((warn_unused_result)); diff --git a/Sources/Batch/Modules/Tracker/BATrackerSignpostHelper.h b/Sources/Batch/Modules/Tracker/BATrackerSignpostHelper.h index 251661e..40c82cf 100644 --- a/Sources/Batch/Modules/Tracker/BATrackerSignpostHelper.h +++ b/Sources/Batch/Modules/Tracker/BATrackerSignpostHelper.h @@ -11,14 +11,14 @@ NS_ASSUME_NONNULL_BEGIN @protocol BATrackerSignpostHelperProtocol -- (void)trackEvent:(NSString*)event withParameters:(NSDictionary*)parameters collapsable:(BOOL)collapsable; +- (void)trackEvent:(NSString *)event withParameters:(NSDictionary *)parameters collapsable:(BOOL)collapsable; @end /** Signpost helper for Batch's event tracker Allows easier event debugging in instruments - + Do not instanciate on versions iOS < 12 */ API_AVAILABLE(ios(12.0)) diff --git a/Sources/Batch/Modules/User/BAUserAttribute.h b/Sources/Batch/Modules/User/BAUserAttribute.h index 36f2baa..ca532e4 100644 --- a/Sources/Batch/Modules/User/BAUserAttribute.h +++ b/Sources/Batch/Modules/User/BAUserAttribute.h @@ -14,7 +14,8 @@ + (nonnull instancetype)attributeWithValue:(nonnull id)value type:(BAUserAttributeType)type; -+ (nonnull NSDictionary*)serverJsonRepresentationForAttributes:(nullable NSDictionary*)attributes; ++ (nonnull NSDictionary *)serverJsonRepresentationForAttributes: + (nullable NSDictionary *)attributes; @property (nonatomic, nonnull) id value; @@ -22,5 +23,5 @@ @end -typedef NSDictionary BAUserAttributes; -typedef NSDictionary*> BAUserTagCollections; +typedef NSDictionary BAUserAttributes; +typedef NSDictionary *> BAUserTagCollections; diff --git a/Sources/Batch/Modules/User/BAUserCenter.h b/Sources/Batch/Modules/User/BAUserCenter.h index d7da2ba..c2ba5b5 100644 --- a/Sources/Batch/Modules/User/BAUserCenter.h +++ b/Sources/Batch/Modules/User/BAUserCenter.h @@ -6,8 +6,8 @@ // Copyright (c) 2015 Batch SDK. All rights reserved. // -#import #import +#import @interface BAUserCenter : NSObject diff --git a/Sources/Batch/Modules/User/BAUserDataDiff.h b/Sources/Batch/Modules/User/BAUserDataDiff.h index 6f49dc8..8ebb7b9 100644 --- a/Sources/Batch/Modules/User/BAUserDataDiff.h +++ b/Sources/Batch/Modules/User/BAUserDataDiff.h @@ -6,17 +6,17 @@ NS_ASSUME_NONNULL_BEGIN /** Represents the difference between two sets of attributes. - + A modified attribute will appear in both "added" and "removed" */ @interface BAUserAttributesDiff : NSObject -- (instancetype)initWithNewAttributes:(BAUserAttributes*)newAttributes previous:(BAUserAttributes*)previousAttributes; +- (instancetype)initWithNewAttributes:(BAUserAttributes *)newAttributes previous:(BAUserAttributes *)previousAttributes; - (BOOL)hasChanges; -@property (readonly) BAUserAttributes* added; -@property (readonly) BAUserAttributes* removed; +@property (readonly) BAUserAttributes *added; +@property (readonly) BAUserAttributes *removed; @end @@ -27,15 +27,16 @@ NS_ASSUME_NONNULL_BEGIN /** Diff two string sets - + Optimized for tag collections */ -- (instancetype)initWithNewTagCollections:(BAUserTagCollections*)newCollections previous:(BAUserTagCollections*)previousCollections; +- (instancetype)initWithNewTagCollections:(BAUserTagCollections *)newCollections + previous:(BAUserTagCollections *)previousCollections; - (BOOL)hasChanges; -@property (readonly) BAUserTagCollections* added; -@property (readonly) BAUserTagCollections* removed; +@property (readonly) BAUserTagCollections *added; +@property (readonly) BAUserTagCollections *removed; @end @@ -43,13 +44,12 @@ NS_ASSUME_NONNULL_BEGIN /** Convert attributes and tag collections diff to event parameters suitable for server consumption - + This includes writing the attributes in their "flat" form ("attr_name.type": value) */ -+ (NSDictionary*)eventParametersFromAttributes:(BAUserAttributesDiff*)attributesDiff - tagCollections:(BAUserTagCollectionsDiff*)tagCollectionsDiff - version:(NSNumber*)version; - ++ (NSDictionary *)eventParametersFromAttributes:(BAUserAttributesDiff *)attributesDiff + tagCollections:(BAUserTagCollectionsDiff *)tagCollectionsDiff + version:(NSNumber *)version; @end diff --git a/Sources/Batch/Modules/User/BAUserDataEditor.h b/Sources/Batch/Modules/User/BAUserDataEditor.h index 3888e3e..5230a34 100644 --- a/Sources/Batch/Modules/User/BAUserDataEditor.h +++ b/Sources/Batch/Modules/User/BAUserDataEditor.h @@ -6,47 +6,70 @@ // Copyright (c) 2015 Batch SDK. All rights reserved. // +#import #import @interface BAUserDataEditor : NSObject -- (void)setLanguage:(nullable NSString*)language; +- (void)setLanguage:(nullable NSString *)language; -- (void)setRegion:(nullable NSString*)region; +- (void)setRegion:(nullable NSString *)region; -- (void)setIdentifier:(nullable NSString*)identifier; +- (void)setIdentifier:(nullable NSString *)identifier; -- (void)setAttribute:(nullable NSObject*)attribute forKey:(nonnull NSString*)key; +- (BOOL)setEmail:(nullable NSString *)email error:(NSError *_Nullable *_Nullable)error; -- (BOOL)setBooleanAttribute:(BOOL)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (void)setEmailMarketingSubscriptionState:(BatchEmailSubscriptionState)state; -- (BOOL)setDateAttribute:(nonnull NSDate*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (void)setAttribute:(nullable NSObject *)attribute forKey:(nonnull NSString *)key; -- (BOOL)setStringAttribute:(nonnull NSString*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (BOOL)setBooleanAttribute:(BOOL)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); -- (BOOL)setNumberAttribute:(nonnull NSNumber*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (BOOL)setDateAttribute:(nonnull NSDate *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); -- (BOOL)setIntegerAttribute:(NSInteger)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (BOOL)setStringAttribute:(nonnull NSString *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); -- (BOOL)setLongLongAttribute:(long long)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (BOOL)setNumberAttribute:(nonnull NSNumber *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); -- (BOOL)setFloatAttribute:(float)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (BOOL)setIntegerAttribute:(NSInteger)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); -- (BOOL)setDoubleAttribute:(double)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (BOOL)setLongLongAttribute:(long long)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); -- (BOOL)setURLAttribute:(nonnull NSURL*)attribute forKey:(nonnull NSString*)key error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); +- (BOOL)setFloatAttribute:(float)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); -- (void)removeAttributeForKey:(nonnull NSString*)key; +- (BOOL)setDoubleAttribute:(double)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); + +- (BOOL)setURLAttribute:(nonnull NSURL *)attribute + forKey:(nonnull NSString *)key + error:(NSError *_Nullable *_Nullable)error NS_SWIFT_NAME(setAttribute(_:forKey:)); + +- (void)removeAttributeForKey:(nonnull NSString *)key; - (void)clearAttributes; -- (void)addTag:(nonnull NSString*)tag inCollection:(nonnull NSString*)collection; +- (void)addTag:(nonnull NSString *)tag inCollection:(nonnull NSString *)collection; -- (void)removeTag:(nonnull NSString*)tag fromCollection:(nonnull NSString*)collection; +- (void)removeTag:(nonnull NSString *)tag fromCollection:(nonnull NSString *)collection; - (void)clearTags; -- (void)clearTagCollection:(nonnull NSString*)collection; +- (void)clearTagCollection:(nonnull NSString *)collection; - (void)save; @@ -56,8 +79,6 @@ // Testing methods -- (BOOL)writeChangesToDatasource:(NSArray * _Nonnull)applyQueue changeset:(long long)changeset NS_SWIFT_NAME(writeToDatasource(changes:changeset:)); - -- (NSArray * _Nonnull)operationQueue; +- (NSArray *_Nonnull)operationQueue; @end diff --git a/Sources/Batch/Modules/User/BAUserDataEditor.m b/Sources/Batch/Modules/User/BAUserDataEditor.m index 63a23a9..f32ca48 100644 --- a/Sources/Batch/Modules/User/BAUserDataEditor.m +++ b/Sources/Batch/Modules/User/BAUserDataEditor.m @@ -7,6 +7,7 @@ // #import +#import #import #import #import @@ -15,22 +16,26 @@ #import #import #import +#import #import #import -#import #define PUBLIC_DOMAIN @"BatchUser - Editor" #define DEBUG_DOMAIN @"UserDataEditor" -#define LANGAGUE_INDEX 0 +#define LANGUAGE_INDEX 0 #define REGION_INDEX 1 #define IDENTIFIER_INDEX 2 #define ATTRIBUTE_NAME_RULE @"^[a-zA-Z0-9_]{1,30}$" -//#define TAG_VALUE_RULE @"^[a-zA-Z0-9_]{1,255}$" + +// #define TAG_VALUE_RULE @"^[a-zA-Z0-9_]{1,255}$" #define ATTR_STRING_MAX_LENGTH 64 #define ATTR_URL_MAX_LENGTH 2048 +/// Waiting time before editor apply the save operation (in ms) +#define DISPATCH_QUEUE_TIMER 500 + #define VALIDATE_ATTRIBUTE_KEY_OR_BAIL() \ key = [self validateAndNormalizeKey:key error:error]; \ if (key == nil) { \ @@ -64,6 +69,9 @@ @implementation BAUserDataEditor { NSRegularExpression *_attributeNameValidationRegexp; BOOL _updatedFields[3]; NSString *_userFields[3]; + + /// Email subscription + BAUserEmailSubscription *_emailSubscription; } - (instancetype)init { @@ -103,8 +111,8 @@ - (void)setLanguage:(nullable NSString *)language { } } - _updatedFields[LANGAGUE_INDEX] = YES; - _userFields[LANGAGUE_INDEX] = language; + _updatedFields[LANGUAGE_INDEX] = YES; + _userFields[LANGUAGE_INDEX] = language; } - (void)setRegion:(nullable NSString *)region { @@ -136,6 +144,64 @@ - (void)setIdentifier:(nullable NSString *)identifier { _userFields[IDENTIFIER_INDEX] = identifier; } +- (BOOL)setEmail:(nullable NSString *)email error:(NSError **)error { + INIT_AND_BLANK_ERROR_IF_NEEDED(error) + + // Ensure we already have a custom user identifier + // or setIdentifier has been previously called in this editor instance + if ([BatchUser identifier] == nil && + (_updatedFields[IDENTIFIER_INDEX] == NO || + (_updatedFields[IDENTIFIER_INDEX] == YES && _userFields[IDENTIFIER_INDEX] == nil))) { + *error = [self + logAndMakeSaveErrorWithCode:BatchUserDataEditorErrorInternal + reason:@"setEmail called even though no custom user id is set. Please ensure to call " + @"setIdentifier before using this method."]; + return false; + } + + // Deleting case + if (email == nil) { + if (_emailSubscription == nil) { + _emailSubscription = [[BAUserEmailSubscription alloc] initWithEmail:nil]; + } else { + [_emailSubscription setEmail:nil]; + } + return true; + } + + // Ensure email is not too long + if ([BAEmailUtils isEmailTooLong:email]) { + *error = + [self logAndMakeSaveErrorWithCode:BatchUserDataEditorErrorInvalidValue + reason:@"Email can't be longer than %d characters. Ignoring.", EMAIL_MAX_LENGTH]; + return false; + } + + // Ensure email is valid + if (![BAEmailUtils isValidEmail:email]) { + *error = [self logAndMakeSaveErrorWithCode:BatchUserDataEditorErrorInvalidValue + reason:@"setEmail called with invalid email format. Please ensure to " + @"respect the following regex: .@.\\..* "]; + return false; + } + + if (_emailSubscription == nil) { + _emailSubscription = [[BAUserEmailSubscription alloc] + initWithEmail:[email stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]]; + } else { + [_emailSubscription setEmail:[email stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]]; + } + + return true; +} + +- (void)setEmailMarketingSubscriptionState:(BatchEmailSubscriptionState)state { + if (_emailSubscription == nil) { + _emailSubscription = [[BAUserEmailSubscription alloc] init]; + } + [_emailSubscription setEmailSubscriptionState:state forKind:BAEmailKindMarketing]; +} + - (void)setAttribute:(nullable NSObject *)attribute forKey:(nonnull NSString *)key { if (attribute == nil) { [self removeAttributeForKey:key]; @@ -175,9 +241,9 @@ - (BOOL)setBooleanAttribute:(BOOL)attribute forKey:(nonnull NSString *)key error INIT_AND_BLANK_ERROR_IF_NEEDED(error) VALIDATE_ATTRIBUTE_KEY_OR_BAIL() - __unsafe_unretained typeof(self) weakSelf = self; [self addToQueueSynchronized:^BOOL() { - return [weakSelf->_datasource setBoolAttribute:attribute forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setBoolAttribute:attribute forKey:key]; }]; return true; @@ -188,9 +254,9 @@ - (BOOL)setDateAttribute:(nonnull NSDate *)attribute forKey:(nonnull NSString *) VALIDATE_ATTRIBUTE_KEY_OR_BAIL() ENSURE_ATTRIBUTE_VALUE_CLASS(attribute, [NSDate class]) - __unsafe_unretained typeof(self) weakSelf = self; [self addToQueueSynchronized:^BOOL() { - return [weakSelf->_datasource setDateAttribute:attribute forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setDateAttribute:attribute forKey:key]; }]; return true; @@ -212,9 +278,9 @@ - (BOOL)setStringAttribute:(nonnull NSString *)attribute return false; } - __unsafe_unretained typeof(self) weakSelf = self; [self addToQueueSynchronized:^BOOL() { - return [weakSelf->_datasource setStringAttribute:(NSString *)attribute forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setStringAttribute:(NSString *)attribute forKey:key]; }]; return true; @@ -244,9 +310,9 @@ - (BOOL)setURLAttribute:(nonnull NSURL *)attribute return false; } - __unsafe_unretained typeof(self) weakSelf = self; [self addToQueueSynchronized:^BOOL() { - return [weakSelf->_datasource setURLAttribute:(NSURL *)attribute forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setURLAttribute:(NSURL *)attribute forKey:key]; }]; return true; @@ -257,7 +323,6 @@ - (BOOL)setNumberAttribute:(nonnull NSNumber *)numberAttr forKey:(nonnull NSStri VALIDATE_ATTRIBUTE_KEY_OR_BAIL() ENSURE_ATTRIBUTE_VALUE_CLASS(numberAttr, [NSNumber class]) - __unsafe_unretained typeof(self) weakSelf = self; BOOL (^operationBlock)(void); const char *ctype = [numberAttr objCType]; @@ -269,36 +334,44 @@ - (BOOL)setNumberAttribute:(nonnull NSNumber *)numberAttr forKey:(nonnull NSStri [BALogger debugForDomain:DEBUG_DOMAIN message:@"Attribute for key '%@' is a NSNumber: %s", key, ctype]; if (numberAttr == (id)kCFBooleanTrue || numberAttr == (id)kCFBooleanFalse) { operationBlock = ^BOOL() { - return [weakSelf->_datasource setBoolAttribute:[numberAttr boolValue] forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setBoolAttribute:[numberAttr boolValue] forKey:key]; }; } else if (strcmp(ctype, @encode(short)) == 0 || strcmp(ctype, @encode(int)) == 0 || strcmp(ctype, @encode(long)) == 0 || strcmp(ctype, @encode(long long)) == 0) { operationBlock = ^BOOL() { - return [weakSelf->_datasource setLongLongAttribute:[numberAttr longLongValue] forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setLongLongAttribute:[numberAttr longLongValue] forKey:key]; }; } else if (strcmp(ctype, @encode(char)) == 0) { // Usually chars are booleans, even shorts are stored as ints. char val = [numberAttr charValue]; if (val == 0 || val == 1) { operationBlock = ^BOOL() { - return [weakSelf->_datasource setBoolAttribute:[numberAttr boolValue] forKey:key]; + id datasource = + [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setBoolAttribute:[numberAttr boolValue] forKey:key]; }; } else { operationBlock = ^BOOL() { - return [weakSelf->_datasource setLongLongAttribute:[numberAttr charValue] forKey:key]; + id datasource = + [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setLongLongAttribute:[numberAttr charValue] forKey:key]; }; } } // Decimal values else if (strcmp(ctype, @encode(float)) == 0 || strcmp(ctype, @encode(double)) == 0) { operationBlock = ^BOOL() { - return [weakSelf->_datasource setDoubleAttribute:[numberAttr doubleValue] forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setDoubleAttribute:[numberAttr doubleValue] forKey:key]; }; } // According to the documentation that's not supported, but give it a shot else if (strcmp(ctype, @encode(BOOL)) == 0) { operationBlock = ^BOOL() { - return [weakSelf->_datasource setBoolAttribute:[numberAttr boolValue] forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setBoolAttribute:[numberAttr boolValue] forKey:key]; }; } else { // Try to make it work in a long long @@ -306,7 +379,9 @@ - (BOOL)setNumberAttribute:(nonnull NSNumber *)numberAttr forKey:(nonnull NSStri if ([numberAttr isEqualToNumber:[NSNumber numberWithLongLong:val]]) { // Yay it worked, allow it. You're lucky we're in a good mood ;) operationBlock = ^BOOL() { - return [weakSelf->_datasource setLongLongAttribute:val forKey:key]; + id datasource = + [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setLongLongAttribute:val forKey:key]; }; } } @@ -330,9 +405,9 @@ - (BOOL)setLongLongAttribute:(long long)attribute forKey:(nonnull NSString *)key INIT_AND_BLANK_ERROR_IF_NEEDED(error) VALIDATE_ATTRIBUTE_KEY_OR_BAIL() - __unsafe_unretained typeof(self) weakSelf = self; [self addToQueueSynchronized:^BOOL() { - return [weakSelf->_datasource setLongLongAttribute:attribute forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setLongLongAttribute:attribute forKey:key]; }]; return true; @@ -346,9 +421,9 @@ - (BOOL)setDoubleAttribute:(double)attribute forKey:(nonnull NSString *)key erro INIT_AND_BLANK_ERROR_IF_NEEDED(error) VALIDATE_ATTRIBUTE_KEY_OR_BAIL() - __unsafe_unretained typeof(self) weakSelf = self; [self addToQueueSynchronized:^BOOL() { - return [weakSelf->_datasource setDoubleAttribute:attribute forKey:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource setDoubleAttribute:attribute forKey:key]; }]; return true; @@ -364,18 +439,16 @@ - (void)removeAttributeForKey:(nonnull NSString *)key { [BALogger debugForDomain:DEBUG_DOMAIN message:@"Removing attribute for key '%@'", key]; - __unsafe_unretained typeof(self) weakSelf = self; - [self addToQueueSynchronized:^BOOL { - return [weakSelf->_datasource removeAttributeNamed:key]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource removeAttributeNamed:key]; }]; } - (void)clearAttributes { - __unsafe_unretained typeof(self) weakSelf = self; - [self addToQueueSynchronized:^BOOL { - return [weakSelf->_datasource clearAttributes]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource clearAttributes]; }]; } @@ -401,10 +474,9 @@ - (void)addTag:(nonnull NSString *)tag inCollection:(nonnull NSString *)collecti tag = [self normalizeTag:tag]; - __unsafe_unretained typeof(self) weakSelf = self; - [self addToQueueSynchronized:^BOOL { - return [weakSelf->_datasource addTag:tag toCollection:collection]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource addTag:tag toCollection:collection]; }]; } @@ -430,18 +502,16 @@ - (void)removeTag:(nonnull NSString *)tag fromCollection:(nonnull NSString *)col tag = [self normalizeTag:tag]; - __unsafe_unretained typeof(self) weakSelf = self; - [self addToQueueSynchronized:^BOOL { - return [weakSelf->_datasource removeTag:tag fromCollection:collection]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource removeTag:tag fromCollection:collection]; }]; } - (void)clearTags { - __unsafe_unretained typeof(self) weakSelf = self; - [self addToQueueSynchronized:^BOOL { - return [weakSelf->_datasource clearTags]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource clearTags]; }]; } @@ -455,10 +525,9 @@ - (void)clearTagCollection:(nonnull NSString *)collection { return; } - __unsafe_unretained typeof(self) weakSelf = self; - [self addToQueueSynchronized:^BOOL { - return [weakSelf->_datasource clearTagsFromCollection:collection]; + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + return [datasource clearTagsFromCollection:collection]; }]; } @@ -466,65 +535,20 @@ - (void)clearTagCollection:(nonnull NSString *)collection { @param completion Used mainly for testing purposes. Called when saving operation completed or failed. */ - (void)save:(void (^)(void))completion { - @synchronized(_operationQueue) { - NSArray *applyQueue = [self popOperationQueue]; - - dispatch_async([BAUserDataManager sharedQueue], ^{ - if (![self canSave]) { - if (completion != nil) { - completion(); - } - return; - } - - NSNumber *changeset = [BAParameter objectForKey:kParametersUserProfileDataVersionKey fallback:@(0)]; - // Sanity - if (![changeset isKindOfClass:[NSNumber class]]) { - [BAParameter setValue:@(0) forKey:kParametersUserProfileDataVersionKey saved:YES]; - changeset = @(0); - } - - BAUserAttributes *oldAttributes = [self->_datasource attributes]; - BAUserTagCollections *oldTagCollections = [self->_datasource tagCollections]; - - long long newChangeset = [changeset longLongValue] + 1; - - if (![self writeChangesToDatasource:applyQueue changeset:newChangeset]) { - if (completion != nil) { - completion(); - } - return; - } - - BAUserAttributes *newAttributes = [self->_datasource attributes]; - BAUserTagCollections *newTagCollections = [self->_datasource tagCollections]; - - BAUserAttributesDiff *attributesDiff = [[BAUserAttributesDiff alloc] initWithNewAttributes:newAttributes - previous:oldAttributes]; - BAUserTagCollectionsDiff *tagCollectionsDiff = - [[BAUserTagCollectionsDiff alloc] initWithNewTagCollections:newTagCollections previous:oldTagCollections]; - - if ([attributesDiff hasChanges] || [tagCollectionsDiff hasChanges]) { - NSNumber *newChangesetNumber = @(newChangeset); - [BAParameter setValue:newChangesetNumber forKey:kParametersUserProfileDataVersionKey saved:YES]; - [BAParameter removeObjectForKey:kParametersUserProfileTransactionIDKey]; - [BAUserDataManager startAttributesSendWSWithDelay:0]; - - NSDictionary *eventParams = [BAUserDataDiffTransformer eventParametersFromAttributes:attributesDiff - tagCollections:tagCollectionsDiff - version:newChangesetNumber]; - [BATrackerCenter trackPrivateEvent:@"_INSTALL_DATA_CHANGED" parameters:eventParams]; - - [BALogger debugForDomain:DEBUG_DOMAIN message:@"Changes in install occurred: YES"]; - } else { - [BALogger debugForDomain:DEBUG_DOMAIN message:@"Changes in install occurred: NO"]; - } - - if (completion != nil) { - completion(); - } - }); - } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(DISPATCH_QUEUE_TIMER * NSEC_PER_MSEC)), + [BAUserDataManager sharedQueue], ^{ + NSArray *applyQueue; + @synchronized(self->_operationQueue) { + applyQueue = [self popOperationQueue]; + } + if (![self canSave]) { + if (completion != nil) { + completion(); + } + return; + } + [BAUserDataManager addOperationQueueAndSubmit:applyQueue withCompletion:completion]; + }); } - (void)save { @@ -548,32 +572,6 @@ - (BOOL)canSave { return true; } -- (BOOL)writeChangesToDatasource:(NSArray *)applyQueue changeset:(long long)changeset { - if (![self->_datasource acquireTransactionLockWithChangeset:changeset]) { - [BALogger publicForDomain:PUBLIC_DOMAIN - message:@"An internal error occurred while applying the changes. (Error code 35)"]; - return false; - } - - for (BOOL (^operation)(void) in applyQueue) { - if (!operation()) { - [self->_datasource rollbackTransaction]; - [BALogger errorForDomain:DEBUG_DOMAIN message:@"Operation returned false"]; - [BALogger publicForDomain:PUBLIC_DOMAIN - message:@"An internal error occurred while applying the changes. (Error code 36)"]; - return false; - } - } - - if (![self->_datasource commitTransaction]) { - [BALogger publicForDomain:PUBLIC_DOMAIN - message:@"An internal error occurred while applying the changes. (Error code 37)"]; - return false; - } - - return true; -} - - (NSArray *)operationQueue { return [_operationQueue copy]; } @@ -587,7 +585,7 @@ - (void)addToQueueSynchronized:(BOOL (^)(void))operationBlock { } - (BOOL (^)(void))userUpdateOperation { - if (!_updatedFields[LANGAGUE_INDEX] && !_updatedFields[REGION_INDEX] && !_updatedFields[IDENTIFIER_INDEX]) { + if (!_updatedFields[LANGUAGE_INDEX] && !_updatedFields[REGION_INDEX] && !_updatedFields[IDENTIFIER_INDEX]) { // Nothing to do return nil; } @@ -595,12 +593,12 @@ - (void)addToQueueSynchronized:(BOOL (^)(void))operationBlock { return ^{ NSString *previousUserFields[3]; BAUserProfile *userProfile = [BAUserProfile defaultUserProfile]; - previousUserFields[LANGAGUE_INDEX] = [userProfile language]; + previousUserFields[LANGUAGE_INDEX] = [userProfile language]; previousUserFields[REGION_INDEX] = [userProfile region]; previousUserFields[IDENTIFIER_INDEX] = [userProfile customIdentifier]; - if (self->_updatedFields[LANGAGUE_INDEX]) { - [userProfile setLanguage:self->_userFields[LANGAGUE_INDEX]]; + if (self->_updatedFields[LANGUAGE_INDEX]) { + [userProfile setLanguage:self->_userFields[LANGUAGE_INDEX]]; } if (self->_updatedFields[REGION_INDEX]) { @@ -629,6 +627,16 @@ - (void)addToQueueSynchronized:(BOOL (^)(void))operationBlock { }; } +- (BOOL (^)(void))emailUpdateOperation { + if (_emailSubscription == nil) { + return nil; + } + return ^{ + [self->_emailSubscription sendEmailSubscriptionEvent]; + return YES; + }; +} + - (void)clearUserFieldsStates { _updatedFields[0] = NO; _updatedFields[1] = NO; @@ -641,11 +649,17 @@ - (void)clearUserFieldsStates { - (NSArray *)popOperationQueue { NSMutableArray *applyQueue = [_operationQueue mutableCopy]; [_operationQueue removeAllObjects]; + BOOL (^userUpdateOperation)(void) = [self userUpdateOperation]; if (userUpdateOperation != nil) { [applyQueue insertObject:userUpdateOperation atIndex:0]; } + BOOL (^emailUpdateOperation)(void) = [self emailUpdateOperation]; + if (emailUpdateOperation != nil) { + [applyQueue addObject:emailUpdateOperation]; + } + return applyQueue; } diff --git a/Sources/Batch/Modules/User/BAUserDataManager.h b/Sources/Batch/Modules/User/BAUserDataManager.h index 84478d9..67172fb 100644 --- a/Sources/Batch/Modules/User/BAUserDataManager.h +++ b/Sources/Batch/Modules/User/BAUserDataManager.h @@ -15,7 +15,8 @@ @interface BAUserDataManager : NSObject /* - @abstract Shared operation queue that should synchronize all access to the db. ANY SQL ACCESS should happen in this queue. + @abstract Shared operation queue that should synchronize all access to the db. ANY SQL ACCESS should happen in this + queue. */ + (dispatch_queue_t)sharedQueue; @@ -24,7 +25,7 @@ + (void)startAttributesCheckWSWithDelay:(long long)delay; -+ (void)storeTransactionID:(NSString*)transaction forVersion:(NSNumber*)version; ++ (void)storeTransactionID:(NSString *)transaction forVersion:(NSNumber *)version; + (void)updateWithServerDataVersion:(long long)serverVersion; @@ -32,4 +33,10 @@ + (void)clearData; ++ (void)addOperationQueueAndSubmit:(NSArray *)queue withCompletion:(void (^_Nullable)(void))completion; + +// Testing methods + ++ (BOOL)writeChangesToDatasource:(NSArray *_Nonnull)applyQueue + changeset:(long long)changeset NS_SWIFT_NAME(writeToDatasource(changes:changeset:)); @end diff --git a/Sources/Batch/Modules/User/BAUserDataManager.m b/Sources/Batch/Modules/User/BAUserDataManager.m index f0835f9..8df9bb5 100644 --- a/Sources/Batch/Modules/User/BAUserDataManager.m +++ b/Sources/Batch/Modules/User/BAUserDataManager.m @@ -8,24 +8,35 @@ #import +#import #import #import +#import #import +#import +#import +#import #import +#import #import #import - -#import -#import #import +#define PUBLIC_DOMAIN @"BatchUser - Manager" +#define DEBUG_DOMAIN @"UserDataManager" + +/// Waiting time before operations are submitted (in ms) +#define DISPATCH_QUEUE_TIMER 500 + @implementation BAUserDataManager static NSLock *baUserDataManagerCheckScheduledLock; static BOOL baUserDataManagerCheckScheduled = NO; +static NSMutableArray *> *operationsQueues; + (void)load { baUserDataManagerCheckScheduledLock = [NSLock new]; + operationsQueues = [NSMutableArray new]; } + (dispatch_queue_t)sharedQueue { @@ -57,7 +68,6 @@ + (void)startAttributesSendWSWithDelay:(long long)delay { } NSDictionary *attributes = [BAUserAttribute serverJsonRepresentationForAttributes:[database attributes]]; - BAUserDataSendServiceDatasource *wsDatasource; wsDatasource = [[BAUserDataSendServiceDatasource alloc] initWithVersion:[changeset longLongValue] attributes:attributes @@ -189,4 +199,109 @@ + (void)clearData { }); } ++ (BOOL)writeChangesToDatasource:(NSArray *)applyQueue changeset:(long long)changeset { + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + + if (![datasource acquireTransactionLockWithChangeset:changeset]) { + [BALogger publicForDomain:PUBLIC_DOMAIN + message:@"An internal error occurred while applying the changes. (Error code 35)"]; + return false; + } + + for (BOOL (^operation)(void) in applyQueue) { + if (!operation()) { + [datasource rollbackTransaction]; + [BALogger errorForDomain:DEBUG_DOMAIN message:@"Operation returned false"]; + [BALogger publicForDomain:PUBLIC_DOMAIN + message:@"An internal error occurred while applying the changes. (Error code 36)"]; + return false; + } + } + + if (![datasource commitTransaction]) { + [BALogger publicForDomain:PUBLIC_DOMAIN + message:@"An internal error occurred while applying the changes. (Error code 37)"]; + return false; + } + + return true; +} + +/// Add an editor's operations queue to the queue +/// - Parameters: +/// - queue: editor's queue to add +/// - completion: completion triggered when operations are submited +/// - Warning: We are not synchronizing here because we are on the shared queue, so this method is NOT thread-safe. ++ (void)addOperationQueueAndSubmit:(NSArray *)queue withCompletion:(void (^_Nullable)(void))completion { + [operationsQueues addObject:queue]; + [BAUserDataManager submitWithCompletion:completion]; +} + ++ (void)submitWithCompletion:(void (^_Nullable)(void))completion { + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(DISPATCH_QUEUE_TIMER * NSEC_PER_MSEC)), + [BAUserDataManager sharedQueue], ^{ + if ([operationsQueues count] == 0) { + if (completion != nil) { + completion(); + } + return; + } + + NSMutableArray *applyQueue = [NSMutableArray array]; + for (NSArray *queue in operationsQueues) { + [applyQueue addObjectsFromArray:queue]; + } + [operationsQueues removeAllObjects]; + + id datasource = [BAInjection injectProtocol:@protocol(BAUserDatasourceProtocol)]; + NSNumber *changeset = [BAParameter objectForKey:kParametersUserProfileDataVersionKey fallback:@(0)]; + // Sanity + if (![changeset isKindOfClass:[NSNumber class]]) { + [BAParameter setValue:@(0) forKey:kParametersUserProfileDataVersionKey saved:YES]; + changeset = @(0); + } + + BAUserAttributes *oldAttributes = [datasource attributes]; + BAUserTagCollections *oldTagCollections = [datasource tagCollections]; + + long long newChangeset = [changeset longLongValue] + 1; + + if (![BAUserDataManager writeChangesToDatasource:applyQueue changeset:newChangeset]) { + if (completion != nil) { + completion(); + } + return; + } + + BAUserAttributes *newAttributes = [datasource attributes]; + BAUserTagCollections *newTagCollections = [datasource tagCollections]; + + BAUserAttributesDiff *attributesDiff = [[BAUserAttributesDiff alloc] initWithNewAttributes:newAttributes + previous:oldAttributes]; + BAUserTagCollectionsDiff *tagCollectionsDiff = + [[BAUserTagCollectionsDiff alloc] initWithNewTagCollections:newTagCollections previous:oldTagCollections]; + + if ([attributesDiff hasChanges] || [tagCollectionsDiff hasChanges]) { + NSNumber *newChangesetNumber = @(newChangeset); + [BAParameter setValue:newChangesetNumber forKey:kParametersUserProfileDataVersionKey saved:YES]; + [BAParameter removeObjectForKey:kParametersUserProfileTransactionIDKey]; + [BAUserDataManager startAttributesSendWSWithDelay:0]; + + NSDictionary *eventParams = [BAUserDataDiffTransformer eventParametersFromAttributes:attributesDiff + tagCollections:tagCollectionsDiff + version:newChangesetNumber]; + [BATrackerCenter trackPrivateEvent:@"_INSTALL_DATA_CHANGED" parameters:eventParams]; + + [BALogger debugForDomain:DEBUG_DOMAIN message:@"Changes in install occurred: YES"]; + } else { + [BALogger debugForDomain:DEBUG_DOMAIN message:@"Changes in install occurred: NO"]; + } + + if (completion != nil) { + completion(); + } + }); +} + @end diff --git a/Sources/Batch/Modules/User/BAUserDataOperation.h b/Sources/Batch/Modules/User/BAUserDataOperation.h index 494904d..446aa22 100644 --- a/Sources/Batch/Modules/User/BAUserDataOperation.h +++ b/Sources/Batch/Modules/User/BAUserDataOperation.h @@ -9,8 +9,7 @@ #import // Inspired by NSBlockOperation, but supports returning a value -@interface BAUserDataOperation : NSObject -{ +@interface BAUserDataOperation : NSObject { BOOL (^_operationBlock)(void); } diff --git a/Sources/Batch/Modules/User/BAUserDatasourceProtocol.h b/Sources/Batch/Modules/User/BAUserDatasourceProtocol.h index 4ad4b5e..d186139 100644 --- a/Sources/Batch/Modules/User/BAUserDatasourceProtocol.h +++ b/Sources/Batch/Modules/User/BAUserDatasourceProtocol.h @@ -6,8 +6,8 @@ // Copyright (c) 2015 Batch SDK. All rights reserved. // -#import #import +#import @class BAUserAttribute; @protocol BAUserDatasourceProtocol @@ -34,42 +34,42 @@ #pragma mark Attributes methods -- (BOOL)setLongLongAttribute:(long long)attribute forKey:(nonnull NSString*)key; +- (BOOL)setLongLongAttribute:(long long)attribute forKey:(nonnull NSString *)key; -- (BOOL)setDoubleAttribute:(double)attribute forKey:(nonnull NSString*)key; +- (BOOL)setDoubleAttribute:(double)attribute forKey:(nonnull NSString *)key; -- (BOOL)setBoolAttribute:(BOOL)attribute forKey:(nonnull NSString*)key; +- (BOOL)setBoolAttribute:(BOOL)attribute forKey:(nonnull NSString *)key; -- (BOOL)setStringAttribute:(nonnull NSString*)attribute forKey:(nonnull NSString*)key; +- (BOOL)setStringAttribute:(nonnull NSString *)attribute forKey:(nonnull NSString *)key; -- (BOOL)setDateAttribute:(nonnull NSDate*)attribute forKey:(nonnull NSString*)key; +- (BOOL)setDateAttribute:(nonnull NSDate *)attribute forKey:(nonnull NSString *)key; -- (BOOL)setURLAttribute:(nonnull NSURL*)attribute forKey:(nonnull NSString*)key; +- (BOOL)setURLAttribute:(nonnull NSURL *)attribute forKey:(nonnull NSString *)key; -- (BOOL)removeAttributeNamed:(nonnull NSString*)attribute; +- (BOOL)removeAttributeNamed:(nonnull NSString *)attribute; #pragma mark Tags methods -- (BOOL)addTag:(nonnull NSString*)tag toCollection:(nonnull NSString*)collection; +- (BOOL)addTag:(nonnull NSString *)tag toCollection:(nonnull NSString *)collection; -- (BOOL)removeTag:(nonnull NSString*)tag fromCollection:(nonnull NSString*)collection; +- (BOOL)removeTag:(nonnull NSString *)tag fromCollection:(nonnull NSString *)collection; #pragma mark Cleanup methods - (BOOL)clearTags; -- (BOOL)clearTagsFromCollection:(nonnull NSString*)collection; +- (BOOL)clearTagsFromCollection:(nonnull NSString *)collection; - (BOOL)clearAttributes; #pragma mark Reader methods -- (nonnull NSDictionary*)attributes; +- (nonnull NSDictionary *)attributes; -- (nonnull NSDictionary*>*)tagCollections; +- (nonnull NSDictionary *> *)tagCollections; #pragma mark Debug methods -- (nonnull NSString*)printDebugDump; +- (nonnull NSString *)printDebugDump; @end diff --git a/Sources/Batch/Modules/User/BAUserEmailSubscription.h b/Sources/Batch/Modules/User/BAUserEmailSubscription.h new file mode 100644 index 0000000..b4d62a2 --- /dev/null +++ b/Sources/Batch/Modules/User/BAUserEmailSubscription.h @@ -0,0 +1,29 @@ +// +// Batch +// +// Copyright © Batch.com. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Enum defining the email kinds for subscription management +typedef NS_ENUM(NSUInteger, BAEmailKind) { + BAEmailKindMarketing = 0, +}; + +@interface BAUserEmailSubscription : NSObject + +- (instancetype)initWithEmail:(nullable NSString *)email; + +- (void)setEmail:(nullable NSString *)email; + +- (void)setEmailSubscriptionState:(BatchEmailSubscriptionState)state forKind:(BAEmailKind)kind; + +- (void)sendEmailSubscriptionEvent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/User/BAUserEmailSubscription.m b/Sources/Batch/Modules/User/BAUserEmailSubscription.m new file mode 100644 index 0000000..ae06033 --- /dev/null +++ b/Sources/Batch/Modules/User/BAUserEmailSubscription.m @@ -0,0 +1,108 @@ +// +// Batch +// +// Copyright © Batch.com. All rights reserved. +// + +#import "BAUserEmailSubscription.h" +#import +#import + +#define DEBUG_DOMAIN @"BAUserEmailSubscription" + +@implementation BAUserEmailSubscription { + /// User email + NSString *_email; + + /// If we should delete the email + BOOL _deleteEmail; + + /// Subscriptions + NSMutableDictionary *_subscriptions; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _subscriptions = [NSMutableDictionary dictionary]; + } + return self; +} + +- (instancetype)initWithEmail:(nullable NSString *)email { + self = [super init]; + if (self) { + if (email == nil) { + _deleteEmail = true; + } + _email = email; + _subscriptions = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)setEmail:(nullable NSString *)email { + if (email == nil) { + _deleteEmail = true; + } + _email = email; +} + +- (void)setEmailSubscriptionState:(BatchEmailSubscriptionState)state forKind:(BAEmailKind)kind { + [_subscriptions setValue:[BAUserEmailSubscription subscriptionStateToString:state] + forKey:[BAUserEmailSubscription emailKindToString:kind]]; +} + +- (void)sendEmailSubscriptionEvent { + // Ensure we have a custom identifier + NSString *customID = [BatchUser identifier]; + if (customID == nil) { + [BALogger debugForDomain:DEBUG_DOMAIN message:@"Custom ID nill, not sending event"]; + return; + } + + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + params[@"custom_id"] = customID; + + if (_email != nil) { + params[@"email"] = _email; + } else if (_deleteEmail) { + params[@"email"] = [NSNull null]; + } + + if ([_subscriptions count] != 0) { + params[@"subscriptions"] = [_subscriptions copy]; + } + [BATrackerCenter trackPrivateEvent:@"_EMAIL_CHANGED" parameters:params]; +} + ++ (NSString *)subscriptionStateToString:(BatchEmailSubscriptionState)state { + NSString *result = nil; + switch (state) { + case BatchEmailSubscriptionStateSubscribed: + result = @"subscribed"; + break; + case BatchEmailSubscriptionStateUnsubscribed: + result = @"unsubscribed"; + break; + default: + [BALogger debugForDomain:DEBUG_DOMAIN message:@"Unknown subscriptions state"]; + break; + } + return result; +} + ++ (NSString *)emailKindToString:(BAEmailKind)kind { + NSString *result = nil; + switch (kind) { + case BAEmailKindMarketing: + result = @"marketing"; + break; + default: + [BALogger debugForDomain:DEBUG_DOMAIN message:@"Unknown email kind"]; + break; + } + return result; +} + +@end diff --git a/Sources/Batch/Modules/User/BAUserSQLiteDatasource.h b/Sources/Batch/Modules/User/BAUserSQLiteDatasource.h index f697494..5fb851a 100644 --- a/Sources/Batch/Modules/User/BAUserSQLiteDatasource.h +++ b/Sources/Batch/Modules/User/BAUserSQLiteDatasource.h @@ -6,11 +6,11 @@ // Copyright (c) 2015 Batch SDK. All rights reserved. // -#import -#import #import +#import +#import -@interface BAUserSQLiteDatasource : NSObject +@interface BAUserSQLiteDatasource : NSObject + (BAUserSQLiteDatasource *)instance BATCH_USE_INJECTION_OUTSIDE_TESTS; diff --git a/Sources/Batch/PrivateUmbrellaHeader.h b/Sources/Batch/PrivateUmbrellaHeader.h index 1d2df39..53b84d8 100644 --- a/Sources/Batch/PrivateUmbrellaHeader.h +++ b/Sources/Batch/PrivateUmbrellaHeader.h @@ -1,4 +1,5 @@ // PrivateUmbrellaHeader.h +// clang-format off // // This bridging header has been automatically generated by Bridgy // DO NOT EDIT MANUALLY. @@ -87,16 +88,6 @@ #import #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import #import #import #import @@ -106,6 +97,7 @@ #import #import #import +#import #import #import #import @@ -134,6 +126,7 @@ #import #import #import +#import #import #import #import @@ -251,6 +244,7 @@ #import #import #import +#import #import #import #import @@ -261,3 +255,5 @@ #import #import #import + +// clang-format on \ No newline at end of file diff --git a/Sources/Batch/Versions.h b/Sources/Batch/Versions.h index e18f593..8526d73 100644 --- a/Sources/Batch/Versions.h +++ b/Sources/Batch/Versions.h @@ -7,10 +7,10 @@ This header only contains the SDK versions It is included by defined.h the Info.plist preprocessor so that we can reference this in it - + Comments should not use the // form, as the plist preprocessor will include them */ -#define BASDKVersion 1.19.5 -#define BAAPILevel 51 +#define BASDKVersion 1.20.0 +#define BAAPILevel 61 #define BAMessagingAPILevel 12 diff --git a/Sources/Batch/Webservices/BAWebserviceMetrics.h b/Sources/Batch/Webservices/BAWebserviceMetrics.h index acbddad..279b3c3 100644 --- a/Sources/Batch/Webservices/BAWebserviceMetrics.h +++ b/Sources/Batch/Webservices/BAWebserviceMetrics.h @@ -31,7 +31,7 @@ @abstract Starts tracking a webservice duration @param shortName The webservice's short name */ -- (void)webserviceStarted:(NSString*)shortName; +- (void)webserviceStarted:(NSString *)shortName; /*! @method webserviceFinished:success: @@ -39,7 +39,7 @@ @param shortName The webservice's short name @param success Whether the WS succeeded or not */ -- (void)webserviceFinished:(NSString*)shortName success:(BOOL)success; +- (void)webserviceFinished:(NSString *)shortName success:(BOOL)success; @end @@ -49,7 +49,7 @@ */ @interface BAWebserviceMetric : NSObject -- (instancetype)initWithShortname:(NSString*)shortName; +- (instancetype)initWithShortname:(NSString *)shortName; @property (readonly, nonatomic) NSString *shortName; @@ -61,7 +61,7 @@ - (BOOL)isFinished; -- (NSDictionary*)dictionaryRepresentation; +- (NSDictionary *)dictionaryRepresentation; - (void)finishWithResult:(BOOL)success; diff --git a/Sources/Batch/Webservices/BAWebserviceURLBuilder.h b/Sources/Batch/Webservices/BAWebserviceURLBuilder.h index 5e90022..86eb6d4 100644 --- a/Sources/Batch/Webservices/BAWebserviceURLBuilder.h +++ b/Sources/Batch/Webservices/BAWebserviceURLBuilder.h @@ -13,11 +13,9 @@ NS_ASSUME_NONNULL_BEGIN + (nullable NSURL *)webserviceURLForShortname:(nonnull NSString *)shortname; -+ (nullable NSURL *)webserviceURLForShortname:(nonnull NSString *)shortname - apiKey:(nonnull NSString *)apiKey; ++ (nullable NSURL *)webserviceURLForShortname:(nonnull NSString *)shortname apiKey:(nonnull NSString *)apiKey; -+ (nullable NSURL *)webserviceURLForHost:(nonnull NSString *)host - shortname:(nonnull NSString *)shortname; ++ (nullable NSURL *)webserviceURLForHost:(nonnull NSString *)host shortname:(nonnull NSString *)shortname; + (nullable NSURL *)webserviceURLForHost:(nonnull NSString *)host; diff --git a/Sources/Batch/Webservices/Core/BAConnection.h b/Sources/Batch/Webservices/Core/BAConnection.h index 637b41d..7c04135 100644 --- a/Sources/Batch/Webservices/Core/BAConnection.h +++ b/Sources/Batch/Webservices/Core/BAConnection.h @@ -27,58 +27,56 @@ typedef NS_ENUM(NSUInteger, BAConnectionMethod) { @enum BAConnectionErrorCause @abstract Possible causes of webservice failure. */ -enum -{ +enum { /*! Value in BAConnectionErrorCauseNone when there is no error. */ - BAConnectionErrorCauseNone = 0, - - + BAConnectionErrorCauseNone = 0, + /*! Value in BAConnectionErrorCauseParsingError when there was a parsing error. */ - BAConnectionErrorCauseParsingError = 100, - + BAConnectionErrorCauseParsingError = 100, + /*! Value in BAConnectionErrorCauseNetworkUnavailable when the response is in [100;200[ or >= 400 . */ - BAConnectionErrorCauseServerError = 200, - + BAConnectionErrorCauseServerError = 200, + /*! Value in BAConnectionErrorCauseNetworkTimeout when the network timed out. */ - BAConnectionErrorCauseNetworkTimeout = 300, - + BAConnectionErrorCauseNetworkTimeout = 300, + /*! Value in BAConnectionErrorCauseSslHandshakeFailure when the SSL Handshake failed. */ BAConnectionErrorCauseSSLHandshakeFailure = 400, - + /*! Value in BAConnectionErrorCauseOther when the error is of another type than the specified ones. */ - BAConnectionErrorCauseOther = 500, - + BAConnectionErrorCauseOther = 500, + /*! Batch has been opted-out from: Webservice calls are not allowed */ - BAConnectionErrorCauseOptedOut = 600, - + BAConnectionErrorCauseOptedOut = 600, + /*! Could not serialize the request body */ - BAConnectionErrorCauseSerialization = 700, - + BAConnectionErrorCauseSerialization = 700, + /*! Could not create the URL Request */ - BAConnectionErrorCauseRequestCreation = 800, - + BAConnectionErrorCauseRequestCreation = 800, + /*! Server respond with http code 429 (overloaded) */ - BAConnectionErrorCauseServerTooManyRequest = 900, + BAConnectionErrorCauseServerTooManyRequest = 900, }; /*! @typedef BAConnectionErrorCause @@ -90,7 +88,8 @@ typedef NSInteger BAConnectionErrorCause; /*! @class BAConnection - @abstract This class provide implementation of NSURLSession and handle auto retring. NSURLConnection variant is available in BAConnectionCompat. + @abstract This class provide implementation of NSURLSession and handle auto retring. NSURLConnection variant is + available in BAConnectionCompat. @discussion This object use default value that you can override: timeout = 60 numberOfRetry = 0 @@ -110,7 +109,8 @@ typedef NSInteger BAConnectionErrorCause; /*! @property timeout - @abstract The number of second before the query is considerated as failed without response from the server. Default = 60. + @abstract The number of second before the query is considerated as failed without response from the server. Default + = 60. */ @property (nonatomic) NSTimeInterval timeout; @@ -130,7 +130,6 @@ typedef NSInteger BAConnectionErrorCause; */ @property (nonatomic) BOOL canBypassOptOut; - /*! @method errorCauseForError: @abstract Get the BAConnectionErrorCause associated to a NSError emitted from the connection @@ -143,8 +142,8 @@ typedef NSInteger BAConnectionErrorCause; delegate:(nullable id)delegate; - (void)configureWithMethod:(BAConnectionMethod)method - url:(nonnull NSURL*)url - body:(nullable NSData*)body + url:(nonnull NSURL *)url + body:(nullable NSData *)body cryptorFactory:(nullable id)cryptorFactory; - (void)start; diff --git a/Sources/Batch/Webservices/Core/BAConnectionDelegate.h b/Sources/Batch/Webservices/Core/BAConnectionDelegate.h index ec33cd7..cdd4b03 100644 --- a/Sources/Batch/Webservices/Core/BAConnectionDelegate.h +++ b/Sources/Batch/Webservices/Core/BAConnectionDelegate.h @@ -39,8 +39,9 @@ /*! @method connectionDidFinishSuccessfully: - @abstract Called when the connection did finish, telling if it succeeded (success is when the SDK managed to decrypt the answer, before parsing it). - Note that this can be called before or after connectionDidFinishLoadingWithData: no guarantees about the order are made + @abstract Called when the connection did finish, telling if it succeeded (success is when the SDK managed to decrypt + the answer, before parsing it). Note that this can be called before or after connectionDidFinishLoadingWithData: no + guarantees about the order are made */ - (void)connectionDidFinishSuccessfully:(BOOL)success; diff --git a/Sources/Batch/Webservices/Core/BAURLSessionProtocol.h b/Sources/Batch/Webservices/Core/BAURLSessionProtocol.h index 9d89ce0..fcb257c 100644 --- a/Sources/Batch/Webservices/Core/BAURLSessionProtocol.h +++ b/Sources/Batch/Webservices/Core/BAURLSessionProtocol.h @@ -9,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN /** Protocol defining expected methods on a NSURLSession-like object to perform network requests - + Production implementations should forward the calls to a configured NSURLSession instance. Allows to easily mock NSURLSession */ @@ -17,7 +17,9 @@ NS_ASSUME_NONNULL_BEGIN @required - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler; + completionHandler:(void (^)(NSData *_Nullable data, + NSURLResponse *_Nullable response, + NSError *_Nullable error))completionHandler; @end diff --git a/Sources/Batch/Webservices/Core/BAWebserviceClient.h b/Sources/Batch/Webservices/Core/BAWebserviceClient.h index 6f07b08..8527fc5 100644 --- a/Sources/Batch/Webservices/Core/BAWebserviceClient.h +++ b/Sources/Batch/Webservices/Core/BAWebserviceClient.h @@ -22,9 +22,8 @@ typedef NS_ENUM(NSUInteger, BAWebserviceClientRequestMethod) { */ @interface BAWebserviceClient : NSOperation - - (nullable instancetype)initWithMethod:(BAWebserviceClientRequestMethod)method - URL:(nullable NSURL*)url + URL:(nullable NSURL *)url contentType:(BAConnectionContentType)contentType delegate:(nullable id)delegate; @@ -50,18 +49,18 @@ typedef NS_ENUM(NSUInteger, BAWebserviceClientRequestMethod) { /* Query parameters to add */ -- (nonnull NSMutableDictionary*)queryParameters; +- (nonnull NSMutableDictionary *)queryParameters; /* Body parameters to add Unused for GET requests */ -- (nullable NSData *)requestBody:(NSError * _Nullable * _Nullable)error; +- (nullable NSData *)requestBody:(NSError *_Nullable *_Nullable)error; /* Additional HTTP headers */ -- (nonnull NSMutableDictionary*)requestHeaders; +- (nonnull NSMutableDictionary *)requestHeaders; /* Cryptor factory to use when sending/receiving data diff --git a/Sources/Batch/Webservices/Core/BAWebserviceClientExecutor.h b/Sources/Batch/Webservices/Core/BAWebserviceClientExecutor.h index 55f8fa0..6d57565 100644 --- a/Sources/Batch/Webservices/Core/BAWebserviceClientExecutor.h +++ b/Sources/Batch/Webservices/Core/BAWebserviceClientExecutor.h @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)sharedInstance; -- (void)addClient:(BAWebserviceClient*)client; +- (void)addClient:(BAWebserviceClient *)client; @end diff --git a/Sources/Batch/Webservices/Core/BAWebserviceJsonClient.h b/Sources/Batch/Webservices/Core/BAWebserviceJsonClient.h index 6370616..a038a09 100644 --- a/Sources/Batch/Webservices/Core/BAWebserviceJsonClient.h +++ b/Sources/Batch/Webservices/Core/BAWebserviceJsonClient.h @@ -17,7 +17,7 @@ @interface BAWebserviceJsonClient : BAWebserviceClient - (nullable instancetype)initWithMethod:(BAWebserviceClientRequestMethod)method - URL:(nullable NSURL*)url + URL:(nullable NSURL *)url delegate:(nullable id)delegate; /* diff --git a/Sources/Batch/Webservices/Core/BAWebserviceMsgPackClient.h b/Sources/Batch/Webservices/Core/BAWebserviceMsgPackClient.h index 3dbf28f..fedd363 100644 --- a/Sources/Batch/Webservices/Core/BAWebserviceMsgPackClient.h +++ b/Sources/Batch/Webservices/Core/BAWebserviceMsgPackClient.h @@ -18,7 +18,7 @@ @interface BAWebserviceMsgPackClient : BAWebserviceClient - (nullable instancetype)initWithMethod:(BAWebserviceClientRequestMethod)method - URL:(nullable NSURL*)url + URL:(nullable NSURL *)url delegate:(nullable id)delegate; @end diff --git a/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMCryptor.h b/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMCryptor.h index 456a87c..4f1bea3 100644 --- a/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMCryptor.h +++ b/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMCryptor.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN - (nonnull instancetype)init NS_UNAVAILABLE; -- (nullable instancetype)initWithKey:(NSString*)key version:(NSString*)version NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithKey:(NSString *)key version:(NSString *)version NS_DESIGNATED_INITIALIZER; @end diff --git a/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMGzipCryptor.h b/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMGzipCryptor.h index 0524131..a572e7b 100644 --- a/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMGzipCryptor.h +++ b/Sources/Batch/Webservices/Crypto/BAWebserviceAESGCMGzipCryptor.h @@ -7,8 +7,8 @@ #import -#import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN - (nonnull instancetype)init NS_UNAVAILABLE; -- (nullable instancetype)initWithKey:(NSString*)key version:(NSString*)version NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithKey:(NSString *)key version:(NSString *)version NS_DESIGNATED_INITIALIZER; @end diff --git a/Sources/Batch/Webservices/Crypto/BAWebserviceCryptor.h b/Sources/Batch/Webservices/Crypto/BAWebserviceCryptor.h index f79d3d7..f6ab039 100644 --- a/Sources/Batch/Webservices/Crypto/BAWebserviceCryptor.h +++ b/Sources/Batch/Webservices/Crypto/BAWebserviceCryptor.h @@ -9,12 +9,12 @@ NS_ASSUME_NONNULL_BEGIN @protocol BAWebserviceCryptor -- (nullable instancetype)initWithKey:(NSString*)key version:(NSString*)version; +- (nullable instancetype)initWithKey:(NSString *)key version:(NSString *)version; // On error, the result will be null. No error message is supported for now -- (nullable NSData*)encrypt:(NSData*)data; +- (nullable NSData *)encrypt:(NSData *)data; -- (nullable NSData*)decrypt:(NSData*)data; +- (nullable NSData *)decrypt:(NSData *)data; @end diff --git a/Sources/Batch/Webservices/Crypto/BAWebserviceCryptorFactory.h b/Sources/Batch/Webservices/Crypto/BAWebserviceCryptorFactory.h index 5b4af96..90c9386 100644 --- a/Sources/Batch/Webservices/Crypto/BAWebserviceCryptorFactory.h +++ b/Sources/Batch/Webservices/Crypto/BAWebserviceCryptorFactory.h @@ -5,10 +5,10 @@ // Copyright © Batch.com. All rights reserved. // -#import -#import #import #import +#import +#import NS_ASSUME_NONNULL_BEGIN @@ -21,13 +21,15 @@ NS_ASSUME_NONNULL_BEGIN (usually post data for webservices) */ //+ (nullable id)outboundCryptorForContentType:(BAConnectionContentType)contentType; -+ (nullable id)outboundCryptorForConnection:(BAConnection*)connection; ++ (nullable id)outboundCryptorForConnection:(BAConnection *)connection; /** Cipher for inbound data (usually data from server replies) */ -+ (nullable id)inboundCryptorForData:(NSData*)data connection:(BAConnection*)connection response:(NSHTTPURLResponse*)response; ++ (nullable id)inboundCryptorForData:(NSData *)data + connection:(BAConnection *)connection + response:(NSHTTPURLResponse *)response; /** HMAC Provider for specified content-type diff --git a/Sources/Batch/Webservices/Crypto/BAWebserviceStubCryptor.h b/Sources/Batch/Webservices/Crypto/BAWebserviceStubCryptor.h index b618253..b7238d9 100644 --- a/Sources/Batch/Webservices/Crypto/BAWebserviceStubCryptor.h +++ b/Sources/Batch/Webservices/Crypto/BAWebserviceStubCryptor.h @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithKey:(NSString*)key version:(NSString*)version NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithKey:(NSString *)key version:(NSString *)version NS_DESIGNATED_INITIALIZER; @end diff --git a/Sources/Batch/Webservices/Crypto/HMAC/BATWebserviceHMAC.h b/Sources/Batch/Webservices/Crypto/HMAC/BATWebserviceHMAC.h index 11bfafb..c72ec5a 100644 --- a/Sources/Batch/Webservices/Crypto/HMAC/BATWebserviceHMAC.h +++ b/Sources/Batch/Webservices/Crypto/HMAC/BATWebserviceHMAC.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN /** Automatically appends the Content hash and HMAC headers */ -- (void)appendToMutableRequest:(nonnull NSMutableURLRequest*)request; +- (void)appendToMutableRequest:(nonnull NSMutableURLRequest *)request; /** Get the header name of the content hash @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN Returns "Content-" Example: "Content-SHA1" */ -- (nonnull NSString*)contentHashHeaderKey; +- (nonnull NSString *)contentHashHeaderKey; /** Get the body's hashed value that should be put in the headers @@ -32,55 +32,60 @@ NS_ASSUME_NONNULL_BEGIN nil if an error occured */ -- (nullable NSString*)hashedContent:(nonnull NSData*)content; +- (nullable NSString *)hashedContent:(nonnull NSData *)content; /** Get the header name for the HMAC */ -- (nonnull NSString*)hmacHeaderKey; +- (nonnull NSString *)hmacHeaderKey; /** Get the HMAC - This doesn't add the content hash. If you wish to sign your content, use -contentHashHeaderKey and -hashedContent: to append the hash to the headers. - This method should be called once your headers are final. + This doesn't add the content hash. If you wish to sign your content, use -contentHashHeaderKey and -hashedContent: to + append the hash to the headers. This method should be called once your headers are final. */ -- (nullable NSString*)hmacForMethod:(nonnull NSString*)method relativeURL:(nonnull NSString*)url headers:(nonnull NSDictionary*)headers; +- (nullable NSString *)hmacForMethod:(nonnull NSString *)method + relativeURL:(nonnull NSString *)url + headers:(nonnull NSDictionary *)headers; /** Returns the summary string that is signed using hmac For testing only */ -- (nonnull NSString*)_requestSummaryForMethod:(nonnull NSString*)method relativeURL:(nonnull NSString*)url headers:(nonnull NSDictionary*)headers; +- (nonnull NSString *)_requestSummaryForMethod:(nonnull NSString *)method + relativeURL:(nonnull NSString *)url + headers:(nonnull NSDictionary *)headers; /** Returns the filtered headers according to the allowlist For testing only */ -- (nonnull NSDictionary*)_filteredHeaders:(nonnull NSDictionary*)headers; +- (nonnull NSDictionary *)_filteredHeaders: + (nonnull NSDictionary *)headers; /** Computes the SHA-256 hmac of the given data For testing only */ -- (nonnull NSData*)_sha256HmacOf:(nonnull NSData*)data; +- (nonnull NSData *)_sha256HmacOf:(nonnull NSData *)data; /** Extracts the relative URL string from a URL - + Example: https://batch.com/foo/bar?query=param returns /foo/bar?query=param For testing only */ -- (nonnull NSString*)_extractRelativeURL:(nonnull NSURL*)url; +- (nonnull NSString *)_extractRelativeURL:(nonnull NSURL *)url; /** Extracts the header keys and sorts them We need to do that since we enumerate the keys in two different methods, and the order needs to be predictable so that we don't have a desync - + For testing only */ -- (nonnull NSArray*)_sortedHeaderKeys:(nonnull NSDictionary*)headers; +- (nonnull NSArray *)_sortedHeaderKeys:(nonnull NSDictionary *)headers; @end @@ -90,7 +95,7 @@ Uses SHA 256 for the signature SHA 1 for content checksum Outputs them as Base64 - + Note: while this class exposes all methods needed to manually add HMAC in your NSURLRequest, you probably want to use -appendToMutableRequest: that handles everything. */ @@ -98,7 +103,7 @@ Note: while this class exposes all methods needed to manually add HMAC in your N - (nonnull instancetype)init NS_UNAVAILABLE; -- (nullable instancetype)initWithKey:(nonnull NSString*)key NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithKey:(nonnull NSString *)key NS_DESIGNATED_INITIALIZER; @end diff --git a/Sources/Batch/Webservices/MsgPack Services implementations/BALocalCampaignsJITService.h b/Sources/Batch/Webservices/MsgPack Services implementations/BALocalCampaignsJITService.h index 83b2454..b8ab224 100644 --- a/Sources/Batch/Webservices/MsgPack Services implementations/BALocalCampaignsJITService.h +++ b/Sources/Batch/Webservices/MsgPack Services implementations/BALocalCampaignsJITService.h @@ -4,18 +4,19 @@ // Copyright © Batch.com. All rights reserved. // -#import -#import #import +#import +#import NS_ASSUME_NONNULL_BEGIN @interface BALocalCampaignsJITService : BAWebserviceMsgPackClient - (nullable instancetype)initWithLocalCampaigns:(nonnull NSArray *)campaigns - viewTracker:(id )viewTracker - success:(void (^ _Nullable)(NSArray* eligibleCampaignIds))successHandler - error:(void (^ _Nullable)(NSError* _Nonnull error, NSNumber* _Nullable retryAfter))errorHandler; + viewTracker:(id)viewTracker + success:(void (^_Nullable)(NSArray *eligibleCampaignIds))successHandler + error:(void (^_Nullable)(NSError *_Nonnull error, + NSNumber *_Nullable retryAfter))errorHandler; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/BAEventTrackerService.h b/Sources/Batch/Webservices/Query Services Implementations/BAEventTrackerService.h index b9e1923..03a2c7f 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/BAEventTrackerService.h +++ b/Sources/Batch/Webservices/Query Services Implementations/BAEventTrackerService.h @@ -18,12 +18,12 @@ NS_ASSUME_NONNULL_BEGIN */ @interface BAEventTrackerService : NSObject -- (instancetype)initWithEvents:(NSArray*)events; +- (instancetype)initWithEvents:(NSArray *)events; /** Note that a promise-enabled service will NOT notify the scheduler of success */ -- (instancetype)initWithEvents:(NSArray*)events promises:(nullable NSArray *)promises; +- (instancetype)initWithEvents:(NSArray *)events promises:(nullable NSArray *)promises; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/BALocalCampaignsService.h b/Sources/Batch/Webservices/Query Services Implementations/BALocalCampaignsService.h index f3465f8..2230bdd 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/BALocalCampaignsService.h +++ b/Sources/Batch/Webservices/Query Services Implementations/BALocalCampaignsService.h @@ -18,13 +18,13 @@ NS_ASSUME_NONNULL_BEGIN @interface BALocalCampaignsServiceDatasource : NSObject -- (instancetype)initWithViewEvents:(nullable NSDictionary*)viewEvents; +- (instancetype)initWithViewEvents:(nullable NSDictionary *)viewEvents; @end @interface BALocalCampaignsServiceDelegate : NSObject -- (instancetype)initWithLocalCampaignsCenter:(BALocalCampaignsCenter*)center; +- (instancetype)initWithLocalCampaignsCenter:(BALocalCampaignsCenter *)center; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/BAPushTokenService.h b/Sources/Batch/Webservices/Query Services Implementations/BAPushTokenService.h index 3e5789c..087793a 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/BAPushTokenService.h +++ b/Sources/Batch/Webservices/Query Services Implementations/BAPushTokenService.h @@ -16,8 +16,7 @@ NS_ASSUME_NONNULL_BEGIN */ @interface BAPushTokenServiceDatasource : NSObject -- (instancetype)initWithToken:(NSString *)token - usesProductionEnvironment:(BOOL)usesProductionEnvironment; +- (instancetype)initWithToken:(NSString *)token usesProductionEnvironment:(BOOL)usesProductionEnvironment; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/BAUserDataServices.h b/Sources/Batch/Webservices/Query Services Implementations/BAUserDataServices.h index fc04080..6d118e6 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/BAUserDataServices.h +++ b/Sources/Batch/Webservices/Query Services Implementations/BAUserDataServices.h @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithVersion:(long long)version attributes:(nonnull NSDictionary *)attributes - andTags:(nonnull NSDictionary< NSString*, NSSet< NSString* >* >*)tags; + andTags:(nonnull NSDictionary *> *)tags; @end @@ -27,8 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @interface BAUserDataCheckServiceDatasource : NSObject -- (instancetype)initWithVersion:(long long)version - transactionID:(nonnull NSString*)transactionID; +- (instancetype)initWithVersion:(long long)version transactionID:(nonnull NSString *)transactionID; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQuery.h b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQuery.h index 23fc1e7..80a5e87 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQuery.h +++ b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQuery.h @@ -30,7 +30,6 @@ @end - /*! @class BAWebserviceQuery @abstract Common queries implementation. @@ -57,6 +56,6 @@ */ - (nonnull NSMutableDictionary *)objectToSend; -- (nonnull instancetype)initWithType:(nonnull NSString*)string; +- (nonnull instancetype)initWithType:(nonnull NSString *)string; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributes.h b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributes.h index e65315c..c485552 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributes.h +++ b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributes.h @@ -31,6 +31,6 @@ */ - (nonnull instancetype)initWithVersion:(long long)version attributes:(nonnull NSDictionary *)attributes - andTags:(nonnull NSDictionary< NSString*, NSSet< NSString* >* >*)tags; + andTags:(nonnull NSDictionary *> *)tags; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributesCheck.h b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributesCheck.h index e760f9b..de089af 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributesCheck.h +++ b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryAttributesCheck.h @@ -28,7 +28,6 @@ @param version : Database version @return Instance or nil. */ -- (nonnull instancetype)initWithTransactionID:(nonnull NSString *)transaction - andVersion:(long long)version; +- (nonnull instancetype)initWithTransactionID:(nonnull NSString *)transaction andVersion:(long long)version; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryLocalCampaigns.h b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryLocalCampaigns.h index 0a79ec7..6399d6e 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryLocalCampaigns.h +++ b/Sources/Batch/Webservices/Query Services Implementations/Query Models/BAWSQueryLocalCampaigns.h @@ -8,8 +8,8 @@ #import -#import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @param viewEvents : Array of viewEvents to forward to the server @return Instance or nil. */ -- (instancetype)initWithViewEvents:(nullable NSDictionary*)viewEvents; +- (instancetype)initWithViewEvents:(nullable NSDictionary *)viewEvents; @end diff --git a/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponse.h b/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponse.h index 039086b..51e2d01 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponse.h +++ b/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponse.h @@ -26,7 +26,6 @@ @end - /*! @class BAWSResponse @abstract Basic response implementation. diff --git a/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseAttributesCheck.h b/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseAttributesCheck.h index 90aabd0..aca1c0a 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseAttributesCheck.h +++ b/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseAttributesCheck.h @@ -49,7 +49,8 @@ typedef NS_ENUM(NSUInteger, BAWSResponseAttrCheckAction) { /*! @property time - @abstract Returned time to wait in ms. Only when action = RECHECK or RESEND. Default value is 15000 for RECHECK, 0 for RESEND + @abstract Returned time to wait in ms. Only when action = RECHECK or RESEND. Default value is 15000 for RECHECK, 0 for + RESEND */ @property (readonly) NSNumber *time; diff --git a/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseLocalCampaigns.h b/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseLocalCampaigns.h index 64534a5..8217daf 100644 --- a/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseLocalCampaigns.h +++ b/Sources/Batch/Webservices/Query Services Implementations/Response Models/BAWSResponseLocalCampaigns.h @@ -6,8 +6,8 @@ // Copyright (c) 2014 Batch SDK. All rights reserved. // -#import #import +#import /*! @class BAWSResponseLocalCampaigns diff --git a/Sources/Batch/Webservices/Query/BAQueryWebserviceClient.h b/Sources/Batch/Webservices/Query/BAQueryWebserviceClient.h index bbc30bf..c58cc3d 100644 --- a/Sources/Batch/Webservices/Query/BAQueryWebserviceClient.h +++ b/Sources/Batch/Webservices/Query/BAQueryWebserviceClient.h @@ -8,10 +8,10 @@ #import -#import #import -#import #import +#import +#import #import #import diff --git a/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDatasource.h b/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDatasource.h index f7d3fa3..befdc71 100644 --- a/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDatasource.h +++ b/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDatasource.h @@ -20,33 +20,32 @@ NS_ASSUME_NONNULL_BEGIN /** URL to send the request to */ -@property (nullable, readonly) NSURL* requestURL; +@property (nullable, readonly) NSURL *requestURL; /** Long identifier for this kind of request. Used for logging & deubgging Ex: start, attributesSend, localCampaigns */ -@property (readonly) NSString* requestIdentifier; +@property (readonly) NSString *requestIdentifier; /** Short identifier for this kind of request. Often matches the url fragment that designated this ws Ex: start, ats, ev - + Will be used for metrics too */ -@property (readonly) NSString* requestShortIdentifier; +@property (readonly) NSString *requestShortIdentifier; /** Queries to send to the webservice */ -@property (readonly) NSArray>* queriesToSend; +@property (readonly) NSArray> *queriesToSend; /** Should return the query response for the given source query and response data Returning nil makes the complete request fail */ -- (nullable BAWSResponse *)responseForQuery:(BAWSQuery *)query - content:(NSDictionary *)content; +- (nullable BAWSResponse *)responseForQuery:(BAWSQuery *)query content:(NSDictionary *)content; @end diff --git a/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h b/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h index 0795b7f..43839fc 100644 --- a/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h +++ b/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h @@ -15,11 +15,12 @@ NS_ASSUME_NONNULL_BEGIN @required -- (void)webserviceClientWillStart:(BAQueryWebserviceClient*)client; +- (void)webserviceClientWillStart:(BAQueryWebserviceClient *)client; -- (void)webserviceClient:(BAQueryWebserviceClient*)client didFailWithError:(NSError *)error; +- (void)webserviceClient:(BAQueryWebserviceClient *)client didFailWithError:(NSError *)error; -- (void)webserviceClient:(BAQueryWebserviceClient*)client didSucceedWithResponses:(NSArray> *)responses; +- (void)webserviceClient:(BAQueryWebserviceClient *)client + didSucceedWithResponses:(NSArray> *)responses; @end diff --git a/Sources/Batch/Webservices/Query/BAQueryWebserviceIdentifiersProviding.h b/Sources/Batch/Webservices/Query/BAQueryWebserviceIdentifiersProviding.h index c5e204a..fb23e36 100644 --- a/Sources/Batch/Webservices/Query/BAQueryWebserviceIdentifiersProviding.h +++ b/Sources/Batch/Webservices/Query/BAQueryWebserviceIdentifiersProviding.h @@ -9,6 +9,6 @@ */ @protocol BAQueryWebserviceIdentifiersProviding -- (NSDictionary*)identifiers; +- (NSDictionary *)identifiers; @end diff --git a/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.h b/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.h index 23fc25e..a37cbee 100644 --- a/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.h +++ b/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.h @@ -5,8 +5,8 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/batchTests/DataUtils.swift b/Sources/batchTests/DataUtils.swift index 33e1197..ff19d54 100644 --- a/Sources/batchTests/DataUtils.swift +++ b/Sources/batchTests/DataUtils.swift @@ -10,12 +10,12 @@ extension Data { while startIndex < hexString.endIndex { let endIndex = hexString.index(startIndex, offsetBy: 2, limitedBy: hexString.endIndex) ?? hexString.endIndex - var substr = hexString[startIndex..* proxy_invokedSelectors; +@property (readonly) NSSet *proxy_invokedSelectors; @end @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN // Methods must be recorded manually @interface InvocationRecordingObject : NSObject -@property (readonly) NSSet* invokedSelectors; +@property (readonly) NSSet *invokedSelectors; - (void)recordSelector:(SEL)selector; diff --git a/Sources/batchTests/Kernel/Concurrent/batchTaskDebouncerTest.swift b/Sources/batchTests/Kernel/Concurrent/batchTaskDebouncerTest.swift index 151b935..b92088c 100644 --- a/Sources/batchTests/Kernel/Concurrent/batchTaskDebouncerTest.swift +++ b/Sources/batchTests/Kernel/Concurrent/batchTaskDebouncerTest.swift @@ -9,7 +9,6 @@ import Batch.Batch_Private import XCTest class batchTaskDebouncerTest: XCTestCase { - override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. @@ -39,7 +38,7 @@ class batchTaskDebouncerTest: XCTestCase { // Maybe we also could measure the elapsed time? var callCounter = 0 let expectation = self.expectation(description: "Debounced task executed") - var debouncer: BATaskDebouncer? = nil + var debouncer: BATaskDebouncer? debouncer = BATaskDebouncer(delay: 0.2, queue: DispatchQueue.global(qos: .default)) { callCounter = callCounter + 1 if callCounter >= 3 { @@ -47,7 +46,6 @@ class batchTaskDebouncerTest: XCTestCase { } else { debouncer?.schedule() } - } debouncer?.schedule() debouncer?.schedule() diff --git a/Sources/batchTests/Kernel/Crypto/batchAESTests.m b/Sources/batchTests/Kernel/Crypto/batchAESTests.m index e32faff..b18ba12 100644 --- a/Sources/batchTests/Kernel/Crypto/batchAESTests.m +++ b/Sources/batchTests/Kernel/Crypto/batchAESTests.m @@ -76,7 +76,8 @@ - (void)testDataCryption { // Test with a long and complex data. NSString *start = @"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" - @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]唄ック金型илджفيحةحديد"; + @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]" + @"唄ック金型илджفيحةحديد"; uncrypted = [start dataUsingEncoding:NSUTF8StringEncoding]; crypted = [aes encryptData:uncrypted]; XCTAssert([uncrypted isEqualToData:crypted] == NO, @"Failed to crypt data from complex string."); @@ -111,7 +112,8 @@ - (void)testStringCryption { // Test with a long and complex data. uncrypted = @"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" - @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]唄ック金型илджفيحةحديد"; + @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]" + @"唄ック金型илджفيحةحديد"; crypted = [aes encrypt:uncrypted]; XCTAssert([uncrypted isEqualToString:crypted] == NO, @"Failed to crypt string from complex string."); XCTAssertEqualObjects( diff --git a/Sources/batchTests/Kernel/Crypto/shaTests.swift b/Sources/batchTests/Kernel/Crypto/shaTests.swift index c8959f2..92e8138 100644 --- a/Sources/batchTests/Kernel/Crypto/shaTests.swift +++ b/Sources/batchTests/Kernel/Crypto/shaTests.swift @@ -12,7 +12,7 @@ import XCTest class shaTests: XCTestCase { static let testData = "!&é\"'(§è!çà)-12567890°_%^$mù`=*/.,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]唄ック金型илджفيحةحديد" - .data(using: .utf8)! + .data(using: .utf8)! func testSHA1() { let expected = "pG+tIWKFrPjoZ4RHGLE4/mQllCE=" diff --git a/Sources/batchTests/Kernel/Dependency Injection/dependencyInjectionTests.swift b/Sources/batchTests/Kernel/Dependency Injection/dependencyInjectionTests.swift index 91d282e..2c2dab2 100644 --- a/Sources/batchTests/Kernel/Dependency Injection/dependencyInjectionTests.swift +++ b/Sources/batchTests/Kernel/Dependency Injection/dependencyInjectionTests.swift @@ -10,7 +10,6 @@ import Foundation import XCTest class dependencyInjectionTests: XCTestCase { - func testInstanceInjection() throws { let registry = BAInjectionRegistry() @@ -120,9 +119,9 @@ class dependencyInjectionTests: XCTestCase { // Also register another class to make sure we don't fuck with it registry.register(injectable: BAInjectable(instance: injectionTestClass()), forClass: injectionTestClass.self) - var injectedClass: injectionOffsetableTestClass = injectionOffsetableTestClass(offset: 10) + var injectedClass = injectionOffsetableTestClass(offset: 10) var injectedProtocol: injectionTestProtocol = injectionTestClass() - var injectedUntouchedClass: injectionTestClass = injectionTestClass() + var injectedUntouchedClass = injectionTestClass() func refreshInjections() throws { injectedClass = try XCTUnwrap( @@ -145,7 +144,7 @@ class dependencyInjectionTests: XCTestCase { // You can also manually release it. autoreleasepool { - overlay = registry.overlayClass(injectionOffsetableTestClass.self) { (original: Any?) -> Any? in + overlay = registry.overlayClass(injectionOffsetableTestClass.self) { (_: Any?) -> Any? in return injectionOffsetableTestClassMock(offset: 0) } @@ -157,7 +156,7 @@ class dependencyInjectionTests: XCTestCase { } // Manual releasing - overlay = registry.overlayProtocol(injectionTestProtocol.self) { (original: Any?) -> Any? in + overlay = registry.overlayProtocol(injectionTestProtocol.self) { (_: Any?) -> Any? in return injectionTestClassMock() } @@ -178,7 +177,7 @@ class dependencyInjectionTests: XCTestCase { XCTAssertEqual(1, injectedUntouchedClass.echo(1)) // Test that nil values work - overlay = registry.overlayClass(injectionOffsetableTestClass.self) { (original: Any?) -> Any? in + overlay = registry.overlayClass(injectionOffsetableTestClass.self) { (_: Any?) -> Any? in return nil } @@ -193,7 +192,6 @@ protocol injectionTestProtocol { } class injectionTestClass: NSObject, injectionTestProtocol { - @objc func echo(_ i: Int) -> Int { return i @@ -201,7 +199,6 @@ class injectionTestClass: NSObject, injectionTestProtocol { } class injectionOffsetableTestClass: NSObject, injectionTestProtocol { - let offset: Int init(offset: Int) { @@ -216,17 +213,15 @@ class injectionOffsetableTestClass: NSObject, injectionTestProtocol { } class injectionTestClassMock: NSObject, injectionTestProtocol { - @objc - func echo(_ i: Int) -> Int { + func echo(_: Int) -> Int { return 80 } } class injectionOffsetableTestClassMock: injectionOffsetableTestClass { - @objc - override func echo(_ i: Int) -> Int { + override func echo(_: Int) -> Int { return 90 } } diff --git a/Sources/batchTests/Kernel/GZip/gzipTests.m b/Sources/batchTests/Kernel/GZip/gzipTests.m index 38db110..8f17dd0 100644 --- a/Sources/batchTests/Kernel/GZip/gzipTests.m +++ b/Sources/batchTests/Kernel/GZip/gzipTests.m @@ -227,10 +227,19 @@ - (void)testZeroLengthInput { XCTAssertEqual(data.length, 0); } +- (void)testRandomData { + NSData *inputData = createRandomNSData(); + NSData *compressedData = [BATGZIP dataByGzipping:inputData]; + XCTAssertNotEqualObjects(inputData, compressedData); + NSData *outputData = [BATGZIP dataByGunzipping:compressedData]; + XCTAssertEqualObjects(inputData, outputData); +} + - (void)testCompressionPerformance { NSData *inputData = createRandomNSData(); [self measureBlock:^{ - __unused NSData *compressedData = [BATGZIP dataByGzipping:inputData]; + NSData *compressedData = [BATGZIP dataByGzipping:inputData]; + XCTAssertNotNil(compressedData); }]; } @@ -238,7 +247,8 @@ - (void)testDecompressionPerformance { NSData *inputData = createRandomNSData(); NSData *compressedData = [BATGZIP dataByGzipping:inputData]; [self measureBlock:^{ - __unused NSData *outputData = [BATGZIP dataByGunzipping:compressedData]; + NSData *outputData = [BATGZIP dataByGunzipping:compressedData]; + XCTAssertNotNil(outputData); }]; } diff --git a/Sources/batchTests/Kernel/Helpers/emailTests.swift b/Sources/batchTests/Kernel/Helpers/emailTests.swift new file mode 100644 index 0000000..3ff309e --- /dev/null +++ b/Sources/batchTests/Kernel/Helpers/emailTests.swift @@ -0,0 +1,28 @@ +// +// BatchTests +// +// Copyright © Batch.com. All rights reserved. +// + +import Batch.Batch_Private +import XCTest + +final class emailTests: XCTestCase { + func testEmailPatterns() { + XCTAssertTrue(BAEmailUtils.isValidEmail("foo@batch.com")) + XCTAssertTrue(BAEmailUtils.isValidEmail("bar@foo.batch.com")) + XCTAssertTrue(BAEmailUtils.isValidEmail("bar+foo@batch.com")) + XCTAssertTrue(BAEmailUtils.isValidEmail("FOObar@Test.Batch.COM")) + + XCTAssertFalse(BAEmailUtils.isValidEmail("@gmail.com")) + XCTAssertFalse(BAEmailUtils.isValidEmail("invalid@gmail")) + XCTAssertFalse(BAEmailUtils.isValidEmail("inva lid@gmail.com")) + XCTAssertFalse(BAEmailUtils.isValidEmail("invalid@gmail .com")) + XCTAssertFalse(BAEmailUtils.isValidEmail("invalid@inva lid.gmail.com")) + } + + func testEmailIsTooLong() { + XCTAssertTrue(BAEmailUtils.isEmailTooLong("testastringtoolongtobeanemailtestastringtoolongtobeanemailtestastringtoolongtobeanemailtestastringtoolongtobeanemailtestastringtoo@batch.com")) + XCTAssertFalse(BAEmailUtils.isEmailTooLong("bar@foo.batch.com")) + } +} diff --git a/Sources/batchTests/Kernel/Helpers/osHelperTests.swift b/Sources/batchTests/Kernel/Helpers/osHelperTests.swift index 079c1fb..2f76497 100644 --- a/Sources/batchTests/Kernel/Helpers/osHelperTests.swift +++ b/Sources/batchTests/Kernel/Helpers/osHelperTests.swift @@ -8,7 +8,6 @@ import Batch.Batch_Private import XCTest class osHelperTests: XCTestCase { - func testIntegerOSVersion() { func parse(version: Int) throws -> OperatingSystemVersion { var parsedVersion = OperatingSystemVersion(majorVersion: 0, minorVersion: 0, patchVersion: 0) @@ -22,25 +21,30 @@ class osHelperTests: XCTestCase { XCTAssertThrowsError(try parse(version: -014_000_000)) XCTAssertThrowsError(try parse(version: 0)) XCTAssertThrowsError(try parse(version: 10)) - XCTAssertThrowsError(try parse(version: 999999)) + XCTAssertThrowsError(try parse(version: 999_999)) XCTAssertEqual( - OperatingSystemVersion(majorVersion: 1, minorVersion: 0, patchVersion: 0), try parse(version: 001_000_000)) + OperatingSystemVersion(majorVersion: 1, minorVersion: 0, patchVersion: 0), try parse(version: 001_000_000) + ) XCTAssertEqual( - OperatingSystemVersion(majorVersion: 14, minorVersion: 0, patchVersion: 0), try parse(version: 014_000_000)) + OperatingSystemVersion(majorVersion: 14, minorVersion: 0, patchVersion: 0), try parse(version: 014_000_000) + ) XCTAssertEqual( - OperatingSystemVersion(majorVersion: 13, minorVersion: 2, patchVersion: 0), try parse(version: 013_002_000)) + OperatingSystemVersion(majorVersion: 13, minorVersion: 2, patchVersion: 0), try parse(version: 013_002_000) + ) XCTAssertEqual( OperatingSystemVersion(majorVersion: 10, minorVersion: 12, patchVersion: 04), - try parse(version: 010_012_004)) + try parse(version: 010_012_004) + ) XCTAssertEqual( OperatingSystemVersion(majorVersion: 999, minorVersion: 999, patchVersion: 999), - try parse(version: 999_999_999)) + try parse(version: 999_999_999) + ) XCTAssertEqual( OperatingSystemVersion(majorVersion: 147, minorVersion: 483, patchVersion: 647), - try parse(version: Int(Int32.max))) + try parse(version: Int(Int32.max)) + ) } - } fileprivate enum osHelperTestsError: Error { diff --git a/Sources/batchTests/Kernel/Helpers/swiftSwizzling.swift b/Sources/batchTests/Kernel/Helpers/swiftSwizzling.swift index 658be64..b5e1359 100644 --- a/Sources/batchTests/Kernel/Helpers/swiftSwizzling.swift +++ b/Sources/batchTests/Kernel/Helpers/swiftSwizzling.swift @@ -14,7 +14,7 @@ class SwiftStubApplicationDelegate: NSObject, UIApplicationDelegate { @objc public var didFailToRegisterRecorded = false @objc - func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { + func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError _: Error) { didFailToRegisterRecorded = true } } diff --git a/Sources/batchTests/Kernel/Logger/internalLoggerTests.swift b/Sources/batchTests/Kernel/Logger/internalLoggerTests.swift index 3bc59bb..b58034a 100644 --- a/Sources/batchTests/Kernel/Logger/internalLoggerTests.swift +++ b/Sources/batchTests/Kernel/Logger/internalLoggerTests.swift @@ -8,13 +8,12 @@ import Batch.Batch_Private import XCTest class internalLoggerTests: XCTestCase { - static let expectedPublicLog = "[Batch] - sample log" static let expectedInternalLog = "[Batch-Internal] - sample internal log" fileprivate let loggerDelegate = MockLoggerDelegate() - var previousLoggerDelegateSource: BALoggerDelegateSource? = nil + var previousLoggerDelegateSource: BALoggerDelegateSource? override func setUp() { loggerDelegate.reset() diff --git a/Sources/batchTests/Kernel/MessagePack/messagePackReaderTests.swift b/Sources/batchTests/Kernel/MessagePack/messagePackReaderTests.swift index d92c900..9416a67 100644 --- a/Sources/batchTests/Kernel/MessagePack/messagePackReaderTests.swift +++ b/Sources/batchTests/Kernel/MessagePack/messagePackReaderTests.swift @@ -33,14 +33,16 @@ final class MessagePackReaderTests: XCTestCase { assertUnpack("CE80000000", 2_147_483_648) { try $0.readIntegerAllowingNil(false) } - assertUnpack("CF7FFFFFFFFFFFFFFF", 9_223_372_036_854_775_807) { try $0.readIntegerAllowingNil(false) } // Max Int + // Max Int + assertUnpack("CF7FFFFFFFFFFFFFFF", 9_223_372_036_854_775_807) { try $0.readIntegerAllowingNil(false) } assertUnpack("CF8000000000000000", UInt(9_223_372_036_854_775_808)) { UInt(truncating: try $0.readIntegerAllowingNil(false)) } + // Max UInt assertUnpack("CFFFFFFFFFFFFFFFFF", UInt64(18_446_744_073_709_551_615)) { UInt64(truncating: try $0.readIntegerAllowingNil(false)) - } // Max UInt + } } func testInt() { @@ -124,7 +126,8 @@ final class MessagePackReaderTests: XCTestCase { XCTAssertEqual( expected, value, "Expected \(expected), got \(value)", - file: file, line: line) + file: file, line: line + ) } catch let err { XCTFail("Unpacking \(hexData) threw error '\(err)'", file: file, line: line) } diff --git a/Sources/batchTests/Kernel/MessagePack/messagePackWriterTests.swift b/Sources/batchTests/Kernel/MessagePack/messagePackWriterTests.swift index 04c599b..25e49fe 100644 --- a/Sources/batchTests/Kernel/MessagePack/messagePackWriterTests.swift +++ b/Sources/batchTests/Kernel/MessagePack/messagePackWriterTests.swift @@ -5,7 +5,6 @@ import XCTest // swiftlint:disable force_cast final class MessagePackWriterTests: XCTestCase { - func testNil() { assertPack("C0") { $0.writeNil() } } @@ -37,10 +36,12 @@ final class MessagePackWriterTests: XCTestCase { try assertPack("CE80000000") { try $0.write(2_147_483_648 as NSNumber) } - try assertPack("CF7FFFFFFFFFFFFFFF") { try $0.write(9_223_372_036_854_775_807 as NSNumber) } // Max Int + // Max Int + try assertPack("CF7FFFFFFFFFFFFFFF") { try $0.write(9_223_372_036_854_775_807 as NSNumber) } try assertPack("CF8000000000000000") { try $0.write(UInt(9_223_372_036_854_775_808) as NSNumber) } - try assertPack("CFFFFFFFFFFFFFFFFF") { try $0.write(UInt(18_446_744_073_709_551_615) as NSNumber) } // Max UInt + // Max UInt + try assertPack("CFFFFFFFFFFFFFFFFF") { try $0.write(UInt(18_446_744_073_709_551_615) as NSNumber) } // Extra pack tests that use different codepaths assertPack("7F") { $0.writeUnsignedInt(127) } @@ -128,7 +129,8 @@ final class MessagePackWriterTests: XCTestCase { XCTAssertEqual( Data(hexString: expected), writer.data, "Expected \(expected.uppercased()) Packed \(writer.data.hexString.uppercased())", - file: file, line: line) + file: file, line: line + ) } func assertPack( @@ -141,6 +143,7 @@ final class MessagePackWriterTests: XCTestCase { XCTAssertEqual( Data(hexString: expected), data, "Expected \(expected.uppercased()) Packed \(data.hexString.uppercased())", - file: file, line: line) + file: file, line: line + ) } } diff --git a/Sources/batchTests/Modules/Actions/groupActionTest.swift b/Sources/batchTests/Modules/Actions/groupActionTest.swift index e349845..7e816fd 100644 --- a/Sources/batchTests/Modules/Actions/groupActionTest.swift +++ b/Sources/batchTests/Modules/Actions/groupActionTest.swift @@ -10,7 +10,6 @@ import Foundation import XCTest class groupActionTest: XCTestCase { - override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. } @@ -27,15 +26,17 @@ class groupActionTest: XCTestCase { actionsCenter.register( BatchUserAction( identifier: "first", - actionBlock: { (identifier: String, args: [String: Any], source: BatchUserActionSource?) in + actionBlock: { (_: String, _: [String: Any], _: BatchUserActionSource?) in first.run() - })) + } + )) actionsCenter.register( BatchUserAction( identifier: "second", - actionBlock: { (identifier: String, args: [String: Any], source: BatchUserActionSource?) in + actionBlock: { (_: String, _: [String: Any], _: BatchUserActionSource?) in second.run() - })) + } + )) let groupJSON = "{\"actions\":[[\"first\", {\"foo\": \"bar\"}],[],[\"invalid\"],[\"second\"]]}" @@ -50,16 +51,19 @@ class groupActionTest: XCTestCase { actionsCenter.performAction( "batch.group", withArgs: parseJSON("{\"actions\":\"bar\"}"), - andSource: nil) + andSource: nil + ) actionsCenter.performAction("batch.group", withArgs: parseJSON("{\"actions\":[]}"), andSource: nil) actionsCenter.performAction( "batch.group", withArgs: parseJSON("{\"actions\":{\"foo\":\"bar\"}}"), - andSource: nil) + andSource: nil + ) actionsCenter.performAction( "batch.group", withArgs: parseJSON("{\"actions\":[{\"foo\":\"bar\"}]}"), - andSource: nil) + andSource: nil + ) } func testGroupLimits() { @@ -69,9 +73,10 @@ class groupActionTest: XCTestCase { actionsCenter.register( BatchUserAction( identifier: "shouldNotRun", - actionBlock: { (identifier: String, args: [String: Any], source: BatchUserActionSource?) in + actionBlock: { (_: String, _: [String: Any], _: BatchUserActionSource?) in shouldNotRun.run() - })) + } + )) let nestedAction = "{\"actions\":[[\"batch.group\", {\"actions\": [\"shouldNotRun\"]}]]}" @@ -88,15 +93,17 @@ class groupActionTest: XCTestCase { actionsCenter.register( BatchUserAction( identifier: "shouldNotRun", - actionBlock: { (identifier: String, args: [String: Any], source: BatchUserActionSource?) in + actionBlock: { (_: String, _: [String: Any], _: BatchUserActionSource?) in shouldNotRun.run() - })) + } + )) actionsCenter.register( BatchUserAction( identifier: "dummy", - actionBlock: { (identifier: String, args: [String: Any], source: BatchUserActionSource?) in + actionBlock: { (_: String, _: [String: Any], _: BatchUserActionSource?) in dummy.run() - })) + } + )) // Make sure that 10 actions max can run // This should only count valid actions diff --git a/Sources/batchTests/Modules/Display Receipt/displayReceiptSwiftTests.swift b/Sources/batchTests/Modules/Display Receipt/displayReceiptSwiftTests.swift index 0aafd62..225da9c 100644 --- a/Sources/batchTests/Modules/Display Receipt/displayReceiptSwiftTests.swift +++ b/Sources/batchTests/Modules/Display Receipt/displayReceiptSwiftTests.swift @@ -10,43 +10,41 @@ import XCTest @testable import Batch -//@testable import BatchExtension +// @testable import BatchExtension class DisplayReceiptSwiftTests: XCTestCase { - /* - func testPackSwiftUnpackObjC() throws - { - let od: [AnyHashable: Any] = [ - "sef": "toto", "bool": true, "hip": "hop" - ] - - let ed: [AnyHashable: Any] = [ - "i": "test-i", "ex": "test-ex", "va": "test-va" - ] - - let validPayload: [AnyHashable: Any] = [ - "com.batch": ["r":["m":1], "od": od, "i": "test-i", "ex": "test-ex", "va": "test-va"] - ] - - // We create and pack a receipt using the Swift lib - let receipt = try! DisplayReceiptHelper().displayReceipt(fromPayload: validPayload) - XCTAssertFalse(receipt.replay) - XCTAssertEqual(receipt.sendAttempt, 0) - XCTAssert(NSDictionary(dictionary: od).isEqual(to: receipt.od!)); - XCTAssert(NSDictionary(dictionary: ed).isEqual(to: receipt.ed!)); - - let packedData = try receipt.pack() - XCTAssertNotNil(packedData); - - // We try to read and unpack it using the ObjC lib - let objcReceipt = try? BADisplayReceipt.unpack(packedData) - XCTAssertNotNil(objcReceipt!) - XCTAssertFalse(objcReceipt!.replay) - XCTAssertEqual(objcReceipt!.sendAttempt, 0) - XCTAssert(NSDictionary(dictionary: od).isEqual(to: objcReceipt!.od!)); - XCTAssert(NSDictionary(dictionary: ed).isEqual(to: objcReceipt!.ed!)); - } - */ - + func testPackSwiftUnpackObjC() throws + { + let od: [AnyHashable: Any] = [ + "sef": "toto", "bool": true, "hip": "hop" + ] + + let ed: [AnyHashable: Any] = [ + "i": "test-i", "ex": "test-ex", "va": "test-va" + ] + + let validPayload: [AnyHashable: Any] = [ + "com.batch": ["r":["m":1], "od": od, "i": "test-i", "ex": "test-ex", "va": "test-va"] + ] + + // We create and pack a receipt using the Swift lib + let receipt = try! DisplayReceiptHelper().displayReceipt(fromPayload: validPayload) + XCTAssertFalse(receipt.replay) + XCTAssertEqual(receipt.sendAttempt, 0) + XCTAssert(NSDictionary(dictionary: od).isEqual(to: receipt.od!)); + XCTAssert(NSDictionary(dictionary: ed).isEqual(to: receipt.ed!)); + + let packedData = try receipt.pack() + XCTAssertNotNil(packedData); + + // We try to read and unpack it using the ObjC lib + let objcReceipt = try? BADisplayReceipt.unpack(packedData) + XCTAssertNotNil(objcReceipt!) + XCTAssertFalse(objcReceipt!.replay) + XCTAssertEqual(objcReceipt!.sendAttempt, 0) + XCTAssert(NSDictionary(dictionary: od).isEqual(to: objcReceipt!.od!)); + XCTAssert(NSDictionary(dictionary: ed).isEqual(to: objcReceipt!.ed!)); + } + */ } diff --git a/Sources/batchTests/Modules/Lisp/batchContextTests.swift b/Sources/batchTests/Modules/Lisp/batchContextTests.swift deleted file mode 100644 index c636b7c..0000000 --- a/Sources/batchTests/Modules/Lisp/batchContextTests.swift +++ /dev/null @@ -1,224 +0,0 @@ -// -// batchContextTests.swift -// BatchTests -// -// Copyright © Batch.com. All rights reserved. -// - -import Batch.Batch_Private -import Foundation -import XCTest - -class batchContextTests: XCTestCase { - - func testMetaContext() { - let context = BALMetaContext(contexts: [ - SimpleVariableContext(name: "foo", value: BALPrimitiveValue(string: "bar")!), - SimpleVariableContext(name: "lorem", value: BALPrimitiveValue(string: "ipsum")!), - ]) - - XCTAssertEqual(context.resolveVariableNamed("foo"), BALPrimitiveValue(string: "bar")) - XCTAssertEqual(context.resolveVariableNamed("lorem"), BALPrimitiveValue(string: "ipsum")) - XCTAssertNil(context.resolveVariableNamed("missing")) - } - - func testCachingContext() { - // Context that only returns a valid value on the first call - @objc class AlternatingContext: NSObject, BALEvaluationContext { - let value: BALValue - var shouldReturnValue = true - - init(value: BALValue) { - self.value = value - } - - func resolveVariableNamed(_ name: String) -> BALValue? { - if shouldReturnValue { - shouldReturnValue = false - return self.value - } - return nil - } - } - - var alternatingContext = AlternatingContext(value: BALPrimitiveValue.init(string: "foo")!) - var cachingContext = BALCachingContext(context: alternatingContext) - XCTAssertEqual(cachingContext.resolveVariableNamed("foo"), BALPrimitiveValue.init(string: "foo")) - // Test that the alternating context works - XCTAssertNil(alternatingContext.resolveVariableNamed("foo")) - XCTAssertEqual(cachingContext.resolveVariableNamed("foo"), BALPrimitiveValue.init(string: "foo")) - - alternatingContext = AlternatingContext(value: BALPrimitiveValue.nil()) - cachingContext = BALCachingContext(context: alternatingContext) - XCTAssertEqual(cachingContext.resolveVariableNamed("foo"), BALPrimitiveValue.nil()) - // Test that the alternating context works - XCTAssertNil(alternatingContext.resolveVariableNamed("foo")) - XCTAssertEqual(cachingContext.resolveVariableNamed("foo"), BALPrimitiveValue.nil()) - } - - func testPrivateEventContext() { - let context = BALEventContext(privateEvent: "_START") - func resolve(_ name: String) -> BALValue? { - return context.resolveVariableNamed(name.lowercased()) - } - - XCTAssertEqual(resolve("e.name"), BALPrimitiveValue(string: "_START")) - XCTAssertEqual(resolve("e.label"), BALPrimitiveValue.nil()) - XCTAssertEqual(resolve("e.tags"), BALPrimitiveValue.nil()) - XCTAssertEqual(resolve("e.attr['foo']"), BALPrimitiveValue.nil()) - - // Check that the context fall through unknown variables - XCTAssertNil(resolve("test")) - } - - func testPublicEventContext() { - let eventData = BatchEventData() - eventData.add(tag: "foo") - eventData.add(tag: "bar") - eventData.put(true, forKey: "bool") - eventData.put(2 as Double, forKey: "double") - eventData.put(2 as Float, forKey: "float") - eventData.put(2 as Int, forKey: "int") - eventData.put("str", forKey: "string") - eventData.put("str", forKey: "CAPS") - - let context = BALEventContext(publicEvent: "E.TEST_EVENT", label: "test label", data: eventData) - func resolve(_ name: String) -> BALValue? { - return context.resolveVariableNamed(name.lowercased()) - } - - XCTAssertEqual(resolve("e.name"), BALPrimitiveValue(string: "E.TEST_EVENT")) - XCTAssertEqual(resolve("e.label"), BALPrimitiveValue(string: "test label")) - XCTAssertEqual(resolve("e.tags"), BALPrimitiveValue(stringSet: ["foo", "bar"])) - - XCTAssertEqual(resolve("e.attr['bool']"), BALPrimitiveValue(boolean: true)) - XCTAssertEqual(resolve("e.attr['double']"), BALPrimitiveValue(double: 2.0)) - XCTAssertEqual(resolve("e.attr['float']"), BALPrimitiveValue(double: 2.0)) - XCTAssertEqual(resolve("e.attr['int']"), BALPrimitiveValue(double: 2.0)) - XCTAssertEqual(resolve("e.attr['string']"), BALPrimitiveValue(string: "str")) - XCTAssertEqual(resolve("e.attr['missing']"), BALPrimitiveValue.nil()) - - XCTAssertEqual(resolve("e.attr['STRING']"), BALPrimitiveValue(string: "str")) - XCTAssertEqual(resolve("e.attr['caps']"), BALPrimitiveValue(string: "str")) - - // Check that the context fall through unknown variables - XCTAssertNil(resolve("test")) - } - - func testNativeAttributeContext() { - let context = BALNativeAttributeContext() - func resolve(_ name: String) -> BALValue? { - return context.resolveVariableNamed(name.lowercased()) - } - - XCTAssertEqual(resolve("b.lvl"), BALPrimitiveValue(string: String(BAAPILevel))) - XCTAssertEqual(resolve("b.foobar"), BALPrimitiveValue.nil()) - - // Check that the context fall through unknown variables - XCTAssertNil(resolve("test")) - } - - func testUserAttributeContext() { - @objc class MockCustomDataDatasource: BaseMockCustomDataDatasource { - override func attributes() -> [String: BAUserAttribute] { - return [ - "c.str": BAUserAttribute(value: "string" as NSString, type: .string), - "c.long": BAUserAttribute(value: NSNumber(value: 2), type: .longLong), - "c.double": BAUserAttribute(value: NSNumber(value: 234.567), type: .double), - "c.bool": BAUserAttribute(value: NSNumber(value: true), type: .bool), - "c.date": BAUserAttribute(value: NSDate(timeIntervalSince1970: 1536325808.2345678), type: .date), - "c.null": BAUserAttribute(value: NSNull(), type: .deleted), - "c.inconsistent": BAUserAttribute(value: NSNumber(value: 2), type: .string), - ] - } - - override func tagCollections() -> [String: Set] { - return ["collection1": ["foo", "bar", "foo"]] - } - } - - let context = BALUserAttributeContext(datasource: MockCustomDataDatasource()) - func resolve(_ name: String) -> BALValue? { - return context.resolveVariableNamed(name.lowercased()) - } - - XCTAssertEqual(resolve("c.missing"), BALPrimitiveValue.nil()) - XCTAssertEqual(resolve("c.str"), BALPrimitiveValue(string: "string")) - XCTAssertEqual(resolve("c.long"), BALPrimitiveValue(double: 2)) - XCTAssertEqual(resolve("c.double"), BALPrimitiveValue(double: 234.567)) - XCTAssertEqual(resolve("c.bool"), BALPrimitiveValue(boolean: true)) - XCTAssertEqual(resolve("c.date"), BALPrimitiveValue(double: 1_536_325_808_234)) - XCTAssertEqual(resolve("c.null"), BALPrimitiveValue.nil()) - XCTAssertEqual(resolve("c.inconsistent"), BALPrimitiveValue.nil()) - - XCTAssertEqual(resolve("t.missing"), BALPrimitiveValue.nil()) - XCTAssertEqual(resolve("t.collection1"), BALPrimitiveValue(stringSet: ["foo", "bar"])) - - // Check that the context fall through unknown variables - XCTAssertNil(resolve("test")) - } -} - -@objc class SimpleVariableContext: NSObject, BALEvaluationContext { - let name: String - let value: BALValue - - init(name: String, value: BALValue) { - self.name = name.lowercased() - self.value = value - } - - func resolveVariableNamed(_ name: String) -> BALValue? { - if name.lowercased() == self.name { - return self.value - } - return nil - } -} - -@objc fileprivate class BaseMockCustomDataDatasource: NSObject, BAUserDatasourceProtocol { - func attributes() -> [String: BAUserAttribute] { - return [:] - } - - func tagCollections() -> [String: Set] { - return [:] - } - - func close() {} - - func clear() {} - - func acquireTransactionLock(withChangeset changeset: Int64) -> Bool { return false } - - func commitTransaction() -> Bool { return false } - - func rollbackTransaction() -> Bool { return false } - - func setLongLongAttribute(_ attribute: Int64, forKey key: String) -> Bool { return false } - - func setDoubleAttribute(_ attribute: Double, forKey key: String) -> Bool { return false } - - func setBoolAttribute(_ attribute: Bool, forKey key: String) -> Bool { return false } - - func setStringAttribute(_ attribute: String, forKey key: String) -> Bool { return false } - - func setDateAttribute(_ attribute: Date, forKey key: String) -> Bool { return false } - - func setURLAttribute(_ attribute: URL, forKey key: String) -> Bool { return false } - - func removeAttributeNamed(_ attribute: String) -> Bool { return false } - - func addTag(_ tag: String, toCollection collection: String) -> Bool { return false } - - func removeTag(_ tag: String, fromCollection collection: String) -> Bool { return false } - - func clearTags() -> Bool { return false } - - func clearTags(fromCollection collection: String) -> Bool { return false } - - func clearAttributes() -> Bool { return false } - - func printDebugDump() -> String { return "not implemented" } - -} diff --git a/Sources/batchTests/Modules/Lisp/batchLispTests.swift b/Sources/batchTests/Modules/Lisp/batchLispTests.swift deleted file mode 100644 index 5672d47..0000000 --- a/Sources/batchTests/Modules/Lisp/batchLispTests.swift +++ /dev/null @@ -1,376 +0,0 @@ -// -// batchListpTests.swift -// BatchTests -// -// Copyright © Batch.com. All rights reserved. -// - -import Batch.Batch_Private -import XCTest - -typealias PrimitiveValue = BALPrimitiveValue -typealias VariableValue = BALVariableValue - -class batchLispTests: XCTestCase { - - let context = TestsEvaluationContext() - - override func setUp() { - } - - override func tearDown() { - } - - //MARK: AST Tests - - func testBasicAST() { - assert( - expression: "(= 1 2)", - parsesTo: [ - MockOperator("="), - PrimitiveValue(double: 1), - PrimitiveValue(double: 2), - ]) - - assert( - expression: "(= true (> 1 2))", - parsesTo: [ - MockOperator("="), - PrimitiveValue.init(boolean: true), - [ - MockOperator(">"), - PrimitiveValue(double: 1), - PrimitiveValue(double: 2), - ] as LiteralSExpression, - ]) - - assert( - expression: "(= `foo` \"bar\")", - parsesTo: [ - MockOperator("="), - VariableValue.variable(withName: "foo"), - PrimitiveValue(string: "bar")!, - ]) - - assert( - expression: "(= true \"bar\\n\\t\\r\\\"\\\'\\\\ \")", - parsesTo: [ - MockOperator("="), - PrimitiveValue.init(boolean: true), - PrimitiveValue(string: "bar\n\t\r\"\'\\ ")!, - ]) - - assert( - expression: "(= true [\"a\" \"b\"])", - parsesTo: [ - MockOperator("="), - PrimitiveValue.init(boolean: true), - PrimitiveValue.init(stringSet: ["a", "b"])!, - ]) - - // Test that a set is a set and not an array - assert( - expression: "(= true [\"b\" \"a\" \"b\"])", - parsesTo: [ - MockOperator("="), - PrimitiveValue.init(boolean: true), - PrimitiveValue.init(stringSet: ["a", "b"])!, - ]) - } - - func testMalformedExpressions() { - assertParsingError("(= 2 2") - assertParsingError("= 2 2") - assertEvaluationError("(2 2)") - assertEvaluationError("(2)") - } - - func testVariables() { - assertTrue("(= `foo` \"bar\")") - assertTrue("(= `unknown` nil)") - } - - func testSubexpressions() { - assertTrue("(= true (= true true))") - assertFalse("(= true (= true false))") - } - - //MARK: Operator tests - - func testEqualityOperator() { - assertTrue("(=)") - assertTrue("(= 2 2)") - assertTrue("(= true true)") - assertTrue("(= \"ok\" \"ok\")") - - assertFalse("(= 2 3)") - assertFalse("(= true false)") - assertFalse("(= \"ok\" \"not ok\")") - - // Can't compare values of different type - assertFalse("(= 2 true)") - } - - func testIfOperator() { - assertTrue("(if true true false)") - assertFalse("(if false true false)") - assertTrue("(if (= 2 2) true false)") - assertTrue("(= (if true 2 1) 2)") - assertTrue("(= (if true \"ok\") \"ok\")") - assertTrue("(= (if true [\"ok\"]) [\"ok\"])") - assertTrue("(= nil (if false true))") - assertTrue("(= nil (if true nil false))") - - assertEvaluationError("(if nil true false true)") - assertEvaluationError("(if nil)") - assertEvaluationError("(if)") - assertEvaluationError("(if 2 true)") - assertEvaluationError("(if \"ok\" true)") - assertEvaluationError("(if [\"ok\"] true)") - } - - func testNotOperator() { - // Not only works with one boolean - assertEvaluationError("(not)") - assertEvaluationError("(not true true)") - assertEvaluationError("(not 1)") - assertEvaluationError("(not \"ok\")") - - assertFalse("(not true)") - assertTrue("(not false)") - } - - func testAndOperator() { - assertFalse("(and true false)") - assertFalse("(and false true)") - assertTrue("(and true true)") - assertFalse("(and false false)") - - assertFalse("(and true nil)") - assertFalse("(and nil true)") - - assertEvaluationError("(and \"bar\" true)") - assertFalse("(and false \"bar\")") - assertEvaluationError("(and 2 true)") - assertFalse("(and false 2)") - } - - func testOrOperator() { - assertTrue("(or true false)") - assertTrue("(or false true)") - assertTrue("(or true true)") - assertFalse("(or false false)") - - assertTrue("(or true nil)") - assertTrue("(or nil true)") - assertFalse("(or false nil)") - assertFalse("(or nil false)") - - assertEvaluationError("(or \"bar\" true)") - assertTrue("(or true \"bar\")") - assertEvaluationError("(or 2 true)") - assertTrue("(or true 2)") - } - - func testNumberComparisonOperators() { - assertTrue("(> 3 2)") - assertTrue("(> 3 2 1 0 -1)") - assertFalse("(> 3 2 1 0 4)") - assertFalse("(> 2 2)") - assertFalse("(> 2 2 1)") - assertFalse("(>= 3 2 1 0 4)") - assertTrue("(>= 2 2)") - assertTrue("(>= 2 2 1)") - - assertTrue("(< 2 3)") - assertTrue("(< 2 3 4 5 6)") - assertFalse("(< 2 3 4 5 6 1)") - assertFalse("(< 2 2)") - assertFalse("(< 2 2 3)") - assertFalse("(<= 2 3 4 5 6 1)") - assertTrue("(<= 2 2)") - assertTrue("(<= 2 2 3)") - } - - func testSetContains() { - assertTrue("(contains \"foo\" [\"foo\" \"bar\"])") - assertTrue("(contains [\"foo\"] [\"foo\" \"bar\"])") - assertTrue("(contains [\"foo\" \"lorem\"] [\"foo\" \"bar\"])") - assertFalse("(contains [\"lorem\"] [\"foo\" \"bar\"])") - assertFalse("(contains [\"lorem\"] nil)") - - assertTrue("(containsAll \"foo\" [\"foo\" \"bar\"])") - assertTrue("(containsAll [\"foo\"] [\"foo\" \"bar\"])") - assertTrue("(containsAll [\"foo\" \"bar\"] [\"foo\" \"bar\" \"baz\"])") - assertFalse("(containsAll [\"foo\" \"lorem\"] [\"foo\" \"bar\"])") - assertFalse("(containsAll [\"lorem\"] [\"foo\" \"bar\"])") - assertFalse("(containsAll [\"lorem\"] nil)") - } - - func testStringCast() { - assertTrue("(= (write-to-string 2) \"2\")") - assertTrue("(= (write-to-string 2345678.123) \"2345678.123\")") - assertTrue("(= (write-to-string true) \"true\")") - assertTrue("(= (write-to-string false) \"false\")") - assertTrue("(= (write-to-string \"ok\") \"ok\")") - assertTrue("(= (write-to-string nil) nil)") - - assertEvaluationError("(write-to-string [\"test\"])") - } - - func testStringToInteger() { - assertTrue("(= (parse-string \"2345678.123\") 2345678.123)") - assertTrue("(= (parse-string \"2\") 2)") - assertTrue("(= (parse-string nil) nil)") - - assertEvaluationError("(parse-string [\"test\"])") - assertEvaluationError("(parse-string 2)") - assertEvaluationError("(parse-string true)") - } - - func testCaseOperators() { - //TODO make tests using turkish locale and i - assertTrue("(= (upper \"ilower\") \"ILOWER\")") - assertTrue("(= (upper [\"first\" \"second\"]) [\"FIRST\" \"SECOND\"])") - assertFalse("(= (upper [\"first\" \"second\"]) [\"first\" \"second\"])") - assertTrue("(= (upper nil) nil)") - - assertEvaluationError("(upper true)") - assertEvaluationError("(upper 2)") - - assertTrue("(= (lower \"ILOWER\") \"ilower\")") - assertTrue("(= (lower [\"FIRST\" \"SECOND\"]) [\"first\" \"second\"])") - assertFalse("(= (lower [\"FIRST\" \"SECOND\"]) [\"FIRST\" \"SECOND\"])") - assertTrue("(= (lower nil) nil)") - - assertEvaluationError("(lower true)") - assertEvaluationError("(lower 2)") - } - - /* Unfortunately testing performance is not possible, as it runs too fast on a computer - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure { - let program = BALispParser(expression: "(and (= 2 2) (contains [\"foo\" \"bar\"] [\"baz\" \"bar\" \"foo\"]) (= `foo` \"bar\"))").parse() - if let program = program as? BALReducable { - program.reduce(BALEmptyEvaluationContext()) - } else { - - } - } - }*/ - - func assertTrue(_ expression: String, file: StaticString = #filePath, line: UInt = #line) { - assertBoolean(expression, expectedResult: true, file: file, line: line) - } - - func assertFalse(_ expression: String, file: StaticString = #filePath, line: UInt = #line) { - assertBoolean(expression, expectedResult: false, file: file, line: line) - } - - func assertParsingError(_ expression: String, file: StaticString = #filePath, line: UInt = #line) { - let program = BALispParser(expression: expression).parse() - guard let error = program as? BALErrorValue, - error.kind == .typeParser - else { - XCTFail("Expression should result in a parsing error: \(expression)", file: file, line: line) - return - } - } - - func assertEvaluationError(_ expression: String, file: StaticString = #filePath, line: UInt = #line) { - let result = evaluate(expression: expression) - guard let error = result as? BALErrorValue, - error.kind == .typeError - else { - XCTFail("Expression should result in a runtime error: \(expression)", file: file, line: line) - return - } - } - - func assertBoolean(_ expression: String, expectedResult: Bool, file: StaticString = #filePath, line: UInt = #line) { - let result = evaluate(expression: expression) - switch result { - case let error as BALErrorValue: - if error.kind == .typeParser { - XCTFail( - "Expression should be \(expectedResult), but could not be parsed: \(expression) Error: \(error)", - file: file, line: line) - return - } - XCTFail( - "Expression should be \(expectedResult), but errorred: \(expression) Error: \(error)", file: file, - line: line) - case let result as BALPrimitiveValue: - if result.type != .bool { - XCTFail("Expression result should be boolean", file: file, line: line) - return - } - - if let boolValue = (result.value as? NSNumber)?.boolValue { - XCTAssert( - boolValue == expectedResult, "Expression result should be \(expectedResult): \(expression)", - file: file, line: line) - return - } - - XCTFail( - "Expression result is of type bool, but the actual value could not be extracted. Looks like an internal error", - file: file, line: line) - default: - XCTFail( - "Expression should be \(expectedResult), but executing it resulted in an unexpected value: \(expression)", - file: file, line: line) - } - } - - // Exact same as the assert(expression, parseTo) method, but allows - // Swift to transform the array literal into a S-Expression implicitly - func assert( - expression: String, parsesTo expectedAST: LiteralSExpression, file: StaticString = #file, line: UInt = #line - ) { - assert(expression: expression, parsesTo: expectedAST as BALValue, file: file, line: line) - } - - func assert(expression: String, parsesTo expectedAST: BALValue, file: StaticString = #filePath, line: UInt = #line) - { - let parsedExpression = parse(expression: expression) - XCTAssertTrue( - parsedExpression.isEqual(expectedAST), - "Expression \(expression) does not parses to expected AST: \(expectedAST)", file: file, line: line) - } - - func parse(expression: String) -> BALValue { - return BALispParser(expression: expression).parse() - } - - func evaluate(expression: String) -> BALValue { - let program = BALispParser(expression: expression).parse() - if let program = program as? BALReducable { - return program.reduce(context) - } - return program - } -} - -@objc class TestsEvaluationContext: NSObject, BALEvaluationContext { - func resolveVariableNamed(_ name: String) -> BALValue? { - if name.lowercased() == "foo" { - return BALPrimitiveValue.init(string: "bar") - } - return BALPrimitiveValue.nil() - } - -} - -class LiteralSExpression: BALSExpression, ExpressibleByArrayLiteral { - required convenience init(arrayLiteral elements: BALValue...) { - self.init(values: elements) - } -} - -class MockOperator: BALOperatorValue { - convenience init(_ symbol: String) { - self.init(with: BALOperator(symbol: symbol, handler: { _, _ in return BALPrimitiveValue.nil() })) - } -} diff --git a/Sources/batchTests/Modules/Local Campaigns/localCampaignsManagerTests.swift b/Sources/batchTests/Modules/Local Campaigns/localCampaignsManagerTests.swift index 169252c..1d1d0f3 100644 --- a/Sources/batchTests/Modules/Local Campaigns/localCampaignsManagerTests.swift +++ b/Sources/batchTests/Modules/Local Campaigns/localCampaignsManagerTests.swift @@ -8,11 +8,11 @@ import Batch import XCTest class localCampaignsManagerTests: XCTestCase { - private let dateProvider = BASecureDateProvider() private let manager = BALocalCampaignsManager( - dateProvider: BASystemDateProvider(), viewTracker: BALocalCampaignsSQLTracker()) + dateProvider: BASystemDateProvider(), viewTracker: BALocalCampaignsSQLTracker() + ) func testEligibleCampaignsSortedByPriority() { let campaigns: [BALocalCampaign] = [ @@ -53,12 +53,11 @@ class localCampaignsManagerTests: XCTestCase { func testIsJITServiceAvailable() { XCTAssertTrue(manager.isJITServiceAvailable()) - manager.setValue((dateProvider.currentDate().timeIntervalSince1970 + 30), forKey: "_nextAvailableJITTimestamp") + manager.setValue(dateProvider.currentDate().timeIntervalSince1970 + 30, forKey: "_nextAvailableJITTimestamp") XCTAssertFalse(manager.isJITServiceAvailable()) } func testSyncedJITCampaignState() { - let dateProvider = BAMutableDateProvider(timestamp: 0) let manager = BALocalCampaignsManager(dateProvider: dateProvider, viewTracker: BALocalCampaignsSQLTracker()) @@ -85,7 +84,6 @@ class localCampaignsManagerTests: XCTestCase { dateProvider.setTime(30) XCTAssertEqual(BATSyncedJITCampaignState.requiresSync, manager.syncedJITCampaignState(campaign)) - } private func createFakeCampaignWith(priority: Int, jit: Bool) -> BALocalCampaign { diff --git a/Sources/batchTests/Modules/Local Campaigns/localCampaignsParserTests.swift b/Sources/batchTests/Modules/Local Campaigns/localCampaignsParserTests.swift index 84440bb..ec538be 100644 --- a/Sources/batchTests/Modules/Local Campaigns/localCampaignsParserTests.swift +++ b/Sources/batchTests/Modules/Local Campaigns/localCampaignsParserTests.swift @@ -9,9 +9,9 @@ import Batch.Batch_Private import Foundation import XCTest -fileprivate struct TestResponses { +fileprivate enum TestResponses { static let empty: [AnyHashable: Any] = [ - "campaigns": [] + "campaigns": [], ] static let cappingPayload: [AnyHashable: Any] = [ @@ -22,7 +22,7 @@ fileprivate struct TestResponses { ["views": 0, "duration": 3600], ["views": 1, "duration": 0], ], - ] + ], ] } @@ -30,7 +30,7 @@ class localCampaignsParserTests: XCTestCase { func testParserPersistence() { // Test that the parser returns a non nil outPersist when no campaigns are to // be persisted - var outPersistable: NSDictionary? = nil + var outPersistable: NSDictionary? let campaigns = try! BALocalCampaignsParser.parseCampaigns(TestResponses.empty, outPersistable: &outPersistable) XCTAssertEqual(0, campaigns.count) XCTAssertNotNil(outPersistable) @@ -39,14 +39,14 @@ class localCampaignsParserTests: XCTestCase { } func testParseCappings() { - var outPersistable: NSDictionary? = nil + var outPersistable: NSDictionary? let cappings = BALocalCampaignsParser.parseCappings( - TestResponses.cappingPayload, outPersistable: &outPersistable) + TestResponses.cappingPayload, outPersistable: &outPersistable + ) XCTAssertNotNil(cappings) XCTAssertEqual(2, cappings?.session) XCTAssertEqual(1, cappings?.timeBasedCappings?.count) XCTAssertNotNil(outPersistable) XCTAssertNotNil(outPersistable?["cappings"]) - } } diff --git a/Sources/batchTests/Modules/Local Campaigns/localCampaignsTrackerTests.swift b/Sources/batchTests/Modules/Local Campaigns/localCampaignsTrackerTests.swift index 683510a..2684507 100644 --- a/Sources/batchTests/Modules/Local Campaigns/localCampaignsTrackerTests.swift +++ b/Sources/batchTests/Modules/Local Campaigns/localCampaignsTrackerTests.swift @@ -10,19 +10,18 @@ import XCTest @testable import Batch -fileprivate struct TestResponses { +fileprivate enum TestResponses { static let cappingPayload: [AnyHashable: Any] = [ "cappings": [ "session": 2, "time": [ - ["views": 1, "duration": 3600] + ["views": 1, "duration": 3600], ], - ] + ], ] } class localCampaignsTrackerTests: XCTestCase { - override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. } @@ -32,7 +31,6 @@ class localCampaignsTrackerTests: XCTestCase { } func testSessionTracker() { - let tracker = BALocalCampaignsTracker() XCTAssertEqual(0, tracker.sessionViewsCount) @@ -44,7 +42,7 @@ class localCampaignsTrackerTests: XCTestCase { } func testIsOverGlobalCappings() { - //Cappings: (2/session & 1/h) + // Cappings: (2/session & 1/h) let dateProvider = BAMutableDateProvider(timestamp: Date().timeIntervalSince1970) let viewTracker = BALocalCampaignsTracker() viewTracker.clear() @@ -79,5 +77,4 @@ class localCampaignsTrackerTests: XCTestCase { viewTracker.clear() viewTracker.close() } - } diff --git a/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeLegacyTests.swift b/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeLegacyTests.swift index 27ee5cb..11d6c9d 100644 --- a/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeLegacyTests.swift +++ b/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeLegacyTests.swift @@ -10,7 +10,6 @@ import WebKit import XCTest class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebViewSource { - fileprivate let webViewMock = MockWKWebView() let contentController = WKUserContentController() var bridge: MinimalWebviewJavascriptBridge! @@ -31,7 +30,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": "2", "method": "success", "args": [:], - ])) + ]) + ) handler.userContentController( contentController, @@ -39,7 +39,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": NSNull(), "method": "success", "args": [:], - ])) + ]) + ) handler.userContentController( contentController, @@ -47,7 +48,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": nil, "method": "success", "args": [:], - ])) + ]) + ) handler.userContentController( contentController, @@ -55,7 +57,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": [], "method": "success", "args": [:], - ])) + ]) + ) handler.userContentController( contentController, @@ -63,7 +66,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": true, "method": "success", "args": [:], - ])) + ]) + ) handler.userContentController( contentController, @@ -71,7 +75,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": 2, "method": "success", "args": [:], - ])) + ]) + ) handler.userContentController( contentController, @@ -79,7 +84,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": -2, "method": "success", "args": [:], - ])) + ]) + ) } func testJavascriptCallbackEvaluation() { @@ -88,7 +94,8 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi webViewMock.it.expect().call( webViewMock.evaluateJavaScript( Arg.eq(makeJSEvalExpectationForSuccess(expected: "ok", taskID: taskID)), - completionHandler: Arg.closure()) + completionHandler: Arg.closure() + ) ) handler.userContentController( @@ -97,14 +104,16 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": taskID, "method": "success", "args": [:], - ])) + ]) + ) taskID = 25 webViewMock.it.expect().call( webViewMock.evaluateJavaScript( Arg.eq(makeJSEvalExpectationForSuccess(expected: "test_value", taskID: taskID)), - completionHandler: Arg.closure()) + completionHandler: Arg.closure() + ) ) handler.userContentController( @@ -113,14 +122,16 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": taskID, "method": "echo", "args": ["value": "test_value"], - ])) + ]) + ) taskID = 26 webViewMock.it.expect().call( webViewMock.evaluateJavaScript( Arg.eq(makeJSEvalExpectationForSuccess(expected: nil, taskID: taskID)), - completionHandler: Arg.closure()) + completionHandler: Arg.closure() + ) ) handler.userContentController( @@ -129,14 +140,16 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": taskID, "method": "echo_nil", "args": [:], - ])) + ]) + ) taskID = 30 webViewMock.it.expect().call( webViewMock.evaluateJavaScript( Arg.eq(makeJSEvalExpectationForError(expected: bridge.expectedErrorMessage, taskID: taskID)), - completionHandler: Arg.closure()) + completionHandler: Arg.closure() + ) ) handler.userContentController( @@ -145,36 +158,36 @@ class webviewBridgeLegacyTests: XCTestCase, BATWebviewBridgeLegacyWKHandlerWebVi "taskID": taskID, "method": "failure", "args": [:], - ])) + ]) + ) webViewMock.it.verify() } func makeJSEvalExpectationForSuccess(expected result: String?, taskID: Int) -> String { var expectedResponse = "{}" - if let result = result { + if let result { expectedResponse = """ - {\"result\":\"\(result)\"} - """ + {\"result\":\"\(result)\"} + """ } return """ - window.batchInAppSDK.__onWebkitCallback(\(taskID), \(expectedResponse)); - """ + window.batchInAppSDK.__onWebkitCallback(\(taskID), \(expectedResponse)); + """ } func makeJSEvalExpectationForError(expected error: String, taskID: Int) -> String { return """ - window.batchInAppSDK.__onWebkitCallback(\(taskID), {\"error\":\"\(error)\"}); - """ + window.batchInAppSDK.__onWebkitCallback(\(taskID), {\"error\":\"\(error)\"}); + """ } - func backingWebView(forLegacyHandler handler: BATWebviewBridgeLegacyWKHandler) -> WKWebView? { + func backingWebView(forLegacyHandler _: BATWebviewBridgeLegacyWKHandler) -> WKWebView? { return webViewMock } } fileprivate class MockWKWebView: WKWebView, MockDelegate { - private let mock = Mock() var it: Mock { diff --git a/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeWKHandlerTests.swift b/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeWKHandlerTests.swift index 34d6182..d81f6e9 100644 --- a/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeWKHandlerTests.swift +++ b/Sources/batchTests/Modules/Messaging/Webview/webviewBridgeWKHandlerTests.swift @@ -9,7 +9,6 @@ import Batch.Batch_Private import XCTest class webviewBridgeWKHandlerTests: XCTestCase { - let controller = WKUserContentController() let handler = BATWebviewBridgeWKHandler(bridge: MinimalWebviewJavascriptBridge()) @@ -18,63 +17,72 @@ class webviewBridgeWKHandlerTests: XCTestCase { handler.userContentController( controller, didReceive: MockWKMessage(body: []), - replyHandler: makeExpectErrorReplyHandler()) + replyHandler: makeExpectErrorReplyHandler() + ) handler.userContentController( controller, didReceive: MockWKMessage(body: "test"), - replyHandler: makeExpectErrorReplyHandler()) + replyHandler: makeExpectErrorReplyHandler() + ) handler.userContentController( controller, didReceive: MockWKMessage(body: [:]), - replyHandler: makeExpectErrorReplyHandler()) + replyHandler: makeExpectErrorReplyHandler() + ) handler.userContentController( controller, didReceive: MockWKMessage(body: ["method": 2]), - replyHandler: makeExpectErrorReplyHandler()) + replyHandler: makeExpectErrorReplyHandler() + ) handler.userContentController( controller, didReceive: MockWKMessage(body: ["method": 2, "args": [:]]), - replyHandler: makeExpectErrorReplyHandler()) + replyHandler: makeExpectErrorReplyHandler() + ) handler.userContentController( controller, didReceive: MockWKMessage(body: ["method": "success", "args": []]), - replyHandler: makeExpectErrorReplyHandler()) + replyHandler: makeExpectErrorReplyHandler() + ) handler.userContentController( controller, didReceive: MockWKMessage(method: "success", args: [:]), - replyHandler: makeExpectValueReplyHandler(expected: "ok")) - + replyHandler: makeExpectValueReplyHandler(expected: "ok") + ) } func testSuccess() { handler.userContentController( controller, didReceive: MockWKMessage(method: "success", args: [:]), - replyHandler: makeExpectValueReplyHandler(expected: "ok")) + replyHandler: makeExpectValueReplyHandler(expected: "ok") + ) handler.userContentController( controller, didReceive: MockWKMessage(method: "echo", args: ["value": "echoed_value"]), - replyHandler: makeExpectValueReplyHandler(expected: "echoed_value")) + replyHandler: makeExpectValueReplyHandler(expected: "echoed_value") + ) } func testError() { handler.userContentController( controller, didReceive: MockWKMessage(method: "failure", args: [:]), - replyHandler: makeExpectErrorReplyHandler()) + replyHandler: makeExpectErrorReplyHandler() + ) } func makeExpectValueReplyHandler(expected: T?, file: StaticString = #filePath, line: UInt = #line) -> ( Any?, String? ) -> Void where T: Equatable { - return { (value, error) in + return { value, error in if let value = value as? T { XCTAssertEqual(expected, value, file: file, line: line) } @@ -83,7 +91,7 @@ class webviewBridgeWKHandlerTests: XCTestCase { } func makeExpectErrorReplyHandler(file: StaticString = #filePath, line: UInt = #line) -> (Any?, String?) -> Void { - return { (value, error) in + return { value, error in XCTAssertNil(value, file: file, line: line) XCTAssertNotNil(error, file: file, line: line) } diff --git a/Sources/batchTests/Modules/Messaging/Webview/webviewJavascriptBridgeTests.swift b/Sources/batchTests/Modules/Messaging/Webview/webviewJavascriptBridgeTests.swift index ba4cf56..9bd98bf 100644 --- a/Sources/batchTests/Modules/Messaging/Webview/webviewJavascriptBridgeTests.swift +++ b/Sources/batchTests/Modules/Messaging/Webview/webviewJavascriptBridgeTests.swift @@ -10,7 +10,6 @@ import InstantMock import XCTest class webviewJavascriptBridgeTests: XCTestCase { - var promises = [BAPromise]() override func setUp() { @@ -61,7 +60,8 @@ class webviewJavascriptBridgeTests: XCTestCase { XCTAssertResolves( BridgeExpectations.trackingID as NSString, - promises.push(bridge.executeMethod("getTrackingID", arguments: [:]))) + promises.push(bridge.executeMethod("getTrackingID", arguments: [:])) + ) bridge = MockBridge(trackingID: nil) XCTAssertResolves(nil, promises.push(bridge.executeMethod("getTrackingID", arguments: [:]))) @@ -78,18 +78,21 @@ class webviewJavascriptBridgeTests: XCTestCase { delegate.expect().call( delegate.bridge( Arg.eq(bridge), shouldOpenDeeplink: Arg.eq(batchURL), openInAppOverride: Arg.eq(nil), - analyticsID: Arg.eq(nil)) + analyticsID: Arg.eq(nil) + ) ) delegate.expect().call( delegate.bridge( Arg.eq(bridge), shouldOpenDeeplink: Arg.eq(batchURL), openInAppOverride: Arg.eq(NSNumber?(false)), - analyticsID: Arg.eq(nil)) + analyticsID: Arg.eq(nil) + ) ) // 2nd is the bad analyticsID type delegate.expect().call( delegate.bridge( Arg.eq(bridge), shouldOpenDeeplink: Arg.eq(batchURL), openInAppOverride: Arg.eq(NSNumber?(true)), - analyticsID: Arg.eq(nil)), + analyticsID: Arg.eq(nil) + ), count: 3 ) delegate.expect().call( @@ -97,7 +100,8 @@ class webviewJavascriptBridgeTests: XCTestCase { Arg.eq(bridge), shouldOpenDeeplink: Arg.eq(batchURL), openInAppOverride: Arg.eq(NSNumber?(true)), - analyticsID: Arg.eq(BridgeExpectations.analyticsID as String?)) + analyticsID: Arg.eq(BridgeExpectations.analyticsID as String?) + ) ) XCTAssertRejects(promises.push(bridge.executeMethod("openDeeplink", arguments: [:]))) @@ -106,7 +110,8 @@ class webviewJavascriptBridgeTests: XCTestCase { promises.push( bridge.executeMethod( "openDeeplink", arguments: ["url": batchURL] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -116,7 +121,8 @@ class webviewJavascriptBridgeTests: XCTestCase { "url": batchURL, "openInApp": false, ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -126,7 +132,8 @@ class webviewJavascriptBridgeTests: XCTestCase { "url": batchURL, "openInApp": true, ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -137,7 +144,8 @@ class webviewJavascriptBridgeTests: XCTestCase { "openInApp": true, "analyticsID": 2, ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -148,7 +156,8 @@ class webviewJavascriptBridgeTests: XCTestCase { "openInApp": true, "analyticsID": NSNull(), ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -159,7 +168,8 @@ class webviewJavascriptBridgeTests: XCTestCase { "openInApp": true, "analyticsID": BridgeExpectations.analyticsID, ] - ))) + )) + ) XCTAssertNoPendingPromise(promises) delegate.verify() @@ -176,7 +186,8 @@ class webviewJavascriptBridgeTests: XCTestCase { ) delegate.expect().call( delegate.bridge( - Arg.eq(bridge), shouldDismissMessageWithAnalyticsID: Arg.eq(BridgeExpectations.analyticsID as String?)) + Arg.eq(bridge), shouldDismissMessageWithAnalyticsID: Arg.eq(BridgeExpectations.analyticsID as String?) + ) ) XCTAssertResolves("ok", promises.push(bridge.executeMethod("dismiss", arguments: [:]))) @@ -186,18 +197,20 @@ class webviewJavascriptBridgeTests: XCTestCase { bridge.executeMethod( "dismiss", arguments: [ - "analyticsID": 2 + "analyticsID": 2, ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( bridge.executeMethod( "dismiss", arguments: [ - "analyticsID": BridgeExpectations.analyticsID + "analyticsID": BridgeExpectations.analyticsID, ] - ))) + )) + ) XCTAssertNoPendingPromise(promises) delegate.verify() @@ -212,7 +225,8 @@ class webviewJavascriptBridgeTests: XCTestCase { Arg.eq(bridge), shouldPerformAction: Arg.eq("batch.test"), arguments: Arg.eq([:]), - analyticsID: Arg.eq(nil)) + analyticsID: Arg.eq(nil) + ) ) delegate.expect().call( @@ -220,7 +234,8 @@ class webviewJavascriptBridgeTests: XCTestCase { Arg.eq(bridge), shouldPerformAction: Arg.eq("batch.test"), arguments: Arg.eq(["arg1": "value"]), - analyticsID: Arg.eq(nil)), + analyticsID: Arg.eq(nil) + ), count: 2 ) @@ -229,7 +244,8 @@ class webviewJavascriptBridgeTests: XCTestCase { Arg.eq(bridge), shouldPerformAction: Arg.eq("batch.test"), arguments: Arg.eq(["arg1": "value"]), - analyticsID: Arg.eq(" ")) + analyticsID: Arg.eq(" ") + ) ) delegate.expect().call( @@ -237,7 +253,8 @@ class webviewJavascriptBridgeTests: XCTestCase { Arg.eq(bridge), shouldPerformAction: Arg.eq("batch.test"), arguments: Arg.eq(["arg1": "value"]), - analyticsID: Arg.eq(BridgeExpectations.analyticsID as String?)) + analyticsID: Arg.eq(BridgeExpectations.analyticsID as String?) + ) ) XCTAssertRejects(promises.push(bridge.executeMethod("performAction", arguments: [:]))) @@ -262,7 +279,8 @@ class webviewJavascriptBridgeTests: XCTestCase { "name": "batch.test", "args": [:], ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -271,10 +289,11 @@ class webviewJavascriptBridgeTests: XCTestCase { arguments: [ "name": "batch.test", "args": [ - "arg1": "value" + "arg1": "value", ], ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -283,11 +302,12 @@ class webviewJavascriptBridgeTests: XCTestCase { arguments: [ "name": "batch.test", "args": [ - "arg1": "value" + "arg1": "value", ], "analyticsID": 2, ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -296,11 +316,12 @@ class webviewJavascriptBridgeTests: XCTestCase { arguments: [ "name": "batch.test", "args": [ - "arg1": "value" + "arg1": "value", ], "analyticsID": " ", ] - ))) + )) + ) XCTAssertResolves( "ok", promises.push( @@ -309,18 +330,19 @@ class webviewJavascriptBridgeTests: XCTestCase { arguments: [ "name": "batch.test", "args": [ - "arg1": "value" + "arg1": "value", ], "analyticsID": BridgeExpectations.analyticsID, ] - ))) + )) + ) XCTAssertNoPendingPromise(promises) delegate.verify() } } -fileprivate struct BridgeExpectations { +fileprivate enum BridgeExpectations { static let installationID: NSString = "install" static let customLanguage: NSString = "xx" static let customRegion: NSString = "XX" @@ -332,7 +354,6 @@ fileprivate struct BridgeExpectations { } fileprivate class MockBridgeDelegate: Mock, BATWebviewJavascriptBridgeDelegate { - func bridge(_ bridge: BATWebviewJavascriptBridge, shouldDismissMessageWithAnalyticsID analyticsIdentifier: String?) { super.call(bridge, analyticsIdentifier) @@ -351,11 +372,9 @@ fileprivate class MockBridgeDelegate: Mock, BATWebviewJavascriptBridgeDelegate { ) { super.call(bridge, action, arguments, analyticsIdentifier) } - } fileprivate class MockBridge: BATWebviewJavascriptBridge { - var shouldReturnCustomDatas = true var shouldReturnAttributionID = true @@ -396,7 +415,6 @@ fileprivate class MockBridge: BATWebviewJavascriptBridge { } return BAPromise.resolved(BridgeExpectations.customUserID) } - } fileprivate class MockBatchMessage: BatchMessage { diff --git a/Sources/batchTests/Modules/Messaging/Webview/webviewTestHelpers.swift b/Sources/batchTests/Modules/Messaging/Webview/webviewTestHelpers.swift index c7a77d2..82c19b7 100644 --- a/Sources/batchTests/Modules/Messaging/Webview/webviewTestHelpers.swift +++ b/Sources/batchTests/Modules/Messaging/Webview/webviewTestHelpers.swift @@ -8,7 +8,6 @@ import Batch.Batch_Private import WebKit class MinimalWebviewJavascriptBridge: BATWebviewJavascriptBridge { - public let expectedErrorMessage = "test_error_message" override init() { @@ -25,7 +24,7 @@ class MinimalWebviewJavascriptBridge: BATWebviewJavascriptBridge { return BAPromise.rejected( NSError(domain: "tests", code: 0, userInfo: [NSLocalizedDescriptionKey: expectedErrorMessage])) case "echo": - return BAPromise.resolved((rawJSONArguments!["value"] as! NSString)) + return BAPromise.resolved(rawJSONArguments!["value"] as! NSString) case "echo_nil": return BAPromise.resolved(nil) default: diff --git a/Sources/batchTests/Modules/Messaging/Webview/webviewUtilsTests.swift b/Sources/batchTests/Modules/Messaging/Webview/webviewUtilsTests.swift index 20b89f9..f96eb08 100644 --- a/Sources/batchTests/Modules/Messaging/Webview/webviewUtilsTests.swift +++ b/Sources/batchTests/Modules/Messaging/Webview/webviewUtilsTests.swift @@ -18,6 +18,7 @@ class webviewUtilsTests: XCTestCase { XCTAssertEqual("foo", BATWebviewUtils.analyticsId(forURL: "https://batch.com/index.html?batchAnalyticsID=foo")) XCTAssertEqual("foo", BATWebviewUtils.analyticsId(forURL: "https://batch.com/?test=test&batchAnalyticsID=foo")) XCTAssertEqual( - "space example", BATWebviewUtils.analyticsId(forURL: "https://batch.com/?batchAnalyticsID=space%20example")) + "space example", BATWebviewUtils.analyticsId(forURL: "https://batch.com/?batchAnalyticsID=space%20example") + ) } } diff --git a/Sources/batchTests/Modules/Messaging/cssTests.swift b/Sources/batchTests/Modules/Messaging/cssTests.swift index 690457e..d5f6c23 100644 --- a/Sources/batchTests/Modules/Messaging/cssTests.swift +++ b/Sources/batchTests/Modules/Messaging/cssTests.swift @@ -9,7 +9,6 @@ import Batch.Batch_Private import XCTest class cssTests: XCTestCase { - override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. } @@ -59,5 +58,4 @@ class cssTests: XCTestCase { XCTAssertFalse(env.environmentMatchesQuery("@media android and (max-height:600)")) XCTAssertFalse(env.environmentMatchesQuery("@media ios and (max-height:599)")) } - } diff --git a/Sources/batchTests/Modules/Messaging/messagingAnalyticsDeduplicatingDelegateTests.swift b/Sources/batchTests/Modules/Messaging/messagingAnalyticsDeduplicatingDelegateTests.swift index 49950c3..64b7cd1 100644 --- a/Sources/batchTests/Modules/Messaging/messagingAnalyticsDeduplicatingDelegateTests.swift +++ b/Sources/batchTests/Modules/Messaging/messagingAnalyticsDeduplicatingDelegateTests.swift @@ -18,7 +18,8 @@ class messagingAnalyticsDeduplicatingDelegateTests: XCTestCase { deduplicateDelegate.messageAutomaticallyClosed(message) deduplicateDelegate.messageGlobalTapActionTriggered(message, action: BAMSGAction()) deduplicateDelegate.messageWebViewClickTracked( - message, action: BAMSGAction(), analyticsIdentifier: "foobar") + message, action: BAMSGAction(), analyticsIdentifier: "foobar" + ) } trackMethods() @@ -32,7 +33,6 @@ class messagingAnalyticsDeduplicatingDelegateTests: XCTestCase { // Test analytics delegate that fails the test when any method is called twice class TestMessagingAnalyticsDelegate: BAMessagingAnalyticsDelegate { - var shownCalled = false var closedCalled = false var closedByErrorCalled = false @@ -41,23 +41,23 @@ class TestMessagingAnalyticsDelegate: BAMessagingAnalyticsDelegate { var autoCloseCalled = false var globalTapCalled = false var timesWebviewClickCalled = 0 - var lastErrorCause: BATMessagingCloseErrorCause? = nil + var lastErrorCause: BATMessagingCloseErrorCause? - func messageShown(_ message: BAMSGMessage) { + func messageShown(_: BAMSGMessage) { if shownCalled { fail() } shownCalled = true } - func messageClosed(_ message: BAMSGMessage) { + func messageClosed(_: BAMSGMessage) { if closedCalled { fail() } closedCalled = true } - func messageClosed(_ message: BAMSGMessage, byError: BATMessagingCloseErrorCause) { + func messageClosed(_: BAMSGMessage, byError: BATMessagingCloseErrorCause) { if closedByErrorCalled { fail() } @@ -65,28 +65,28 @@ class TestMessagingAnalyticsDelegate: BAMessagingAnalyticsDelegate { lastErrorCause = byError } - func messageDismissed(_ message: BAMSGMessage) { + func messageDismissed(_: BAMSGMessage) { if dismissedCalled { fail() } dismissedCalled = true } - func messageButtonClicked(_ message: BAMSGMessage, ctaIndex: Int, action: BAMSGCTA) { + func messageButtonClicked(_: BAMSGMessage, ctaIndex _: Int, action _: BAMSGCTA) { if buttonClickedCalled { fail() } buttonClickedCalled = true } - func messageAutomaticallyClosed(_ message: BAMSGMessage) { + func messageAutomaticallyClosed(_: BAMSGMessage) { if autoCloseCalled { fail() } autoCloseCalled = true } - func messageGlobalTapActionTriggered(_ message: BAMSGMessage, action: BAMSGAction) { + func messageGlobalTapActionTriggered(_: BAMSGMessage, action _: BAMSGAction) { if globalTapCalled { fail() } @@ -94,7 +94,7 @@ class TestMessagingAnalyticsDelegate: BAMessagingAnalyticsDelegate { } func messageWebViewClickTracked( - _ message: BAMSGMessage, action: BAMSGAction, analyticsIdentifier analyticsID: String + _: BAMSGMessage, action _: BAMSGAction, analyticsIdentifier _: String ) { timesWebviewClickCalled = timesWebviewClickCalled + 1 } diff --git a/Sources/batchTests/Modules/User/batchUserDiffTests.swift b/Sources/batchTests/Modules/User/batchUserDiffTests.swift index 8b8d8a8..2e6d9db 100644 --- a/Sources/batchTests/Modules/User/batchUserDiffTests.swift +++ b/Sources/batchTests/Modules/User/batchUserDiffTests.swift @@ -11,7 +11,7 @@ import XCTest class BatchUserDiffTests: XCTestCase { func testAttributesDiff() { - let date = Date(timeIntervalSince1970: 123456) + let date = Date(timeIntervalSince1970: 123_456) let newAttributes: [String: BAUserAttribute] = [ "c.integer": BAUserAttribute(value: 2, type: .longLong), "c.string": BAUserAttribute(value: "foo", type: .string), @@ -31,14 +31,16 @@ class BatchUserDiffTests: XCTestCase { [ "c.integer": BAUserAttribute(value: 2, type: .longLong), "c.string": BAUserAttribute(value: "foo", type: .string), - ]) + ] + ) XCTAssertEqual( diff.removed, [ "c.removed": BAUserAttribute(value: "removed", type: .string), "c.string": BAUserAttribute(value: "foobar", type: .string), - ]) + ] + ) XCTAssertTrue(diff.hasChanges()) @@ -72,7 +74,8 @@ class BatchUserDiffTests: XCTestCase { "updated_one": ["baz"], "added_one": ["bar"], "newtags": ["added", "collection"], - ]) + ] + ) XCTAssertEqual( diff.removed, @@ -80,7 +83,8 @@ class BatchUserDiffTests: XCTestCase { "removed": ["ved", "remo"], "removed_one": ["foo"], "updated_one": ["bar"], - ]) + ] + ) XCTAssertTrue(diff.hasChanges()) @@ -90,28 +94,28 @@ class BatchUserDiffTests: XCTestCase { } func testEventSerialization() { - let newCollections: [String: Set] = [ - "newtags": ["new"] + "newtags": ["new"], ] let oldCollections: [String: Set] = [ - "oldtags": ["old"] + "oldtags": ["old"], ] let newAttributes: [String: BAUserAttribute] = [ - "c.new": BAUserAttribute(value: "newvalue", type: .string) + "c.new": BAUserAttribute(value: "newvalue", type: .string), ] let attributeTimestamp = 12_345_678 let oldAttributes: [String: BAUserAttribute] = [ - "c.old": BAUserAttribute(value: Date(timeIntervalSince1970: 12_345_678), type: .date) + "c.old": BAUserAttribute(value: Date(timeIntervalSince1970: 12_345_678), type: .date), ] let serializedDiff = BAUserDataDiffTransformer.eventParameters( fromAttributes: BAUserAttributesDiff(newAttributes: newAttributes, previous: oldAttributes), tagCollections: BAUserTagCollectionsDiff(newTagCollections: newCollections, previous: oldCollections), - version: 2) + version: 2 + ) XCTAssertEqual(serializedDiff["version"] as? Int, 2) XCTAssertEqual( @@ -119,13 +123,14 @@ class BatchUserDiffTests: XCTestCase { [ "t.newtags": ["new"], "new.s": "newvalue", - ] as NSDictionary) + ] as NSDictionary + ) XCTAssertEqual( serializedDiff["removed"] as! NSDictionary, [ "t.oldtags": ["old"], "old.t": attributeTimestamp * 1000, - ] as NSDictionary) - + ] as NSDictionary + ) } } diff --git a/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m b/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m index ccd62bb..d77c90f 100644 --- a/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m +++ b/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m @@ -26,6 +26,8 @@ - (void)testPublicMethods { [editor setLanguage:@"fr"]; [editor setRegion:@"fr"]; [editor setIdentifier:@"foo"]; + [editor setEmail:@"test@batch.com" error:nil]; + [editor setEmailMarketingSubscriptionState:BatchEmailSubscriptionStateSubscribed]; [editor setAttribute:@"foo" forKey:@"bar"]; [editor setAttribute:nil forKey:@"bar"]; [editor setBooleanAttribute:true forKey:@"bar" error:&fakeErr]; @@ -47,6 +49,8 @@ - (void)testPublicMethods { OCMVerify([mockBackingEditor setLanguage:@"fr"]); OCMVerify([mockBackingEditor setRegion:@"fr"]); OCMVerify([mockBackingEditor setIdentifier:@"foo"]); + OCMVerify([mockBackingEditor setEmail:@"test@batch.com" error:nil]); + OCMVerify([mockBackingEditor setEmailMarketingSubscriptionState:BatchEmailSubscriptionStateSubscribed]); OCMVerify([mockBackingEditor setAttribute:@"foo" forKey:@"bar"]); OCMVerify([mockBackingEditor setAttribute:nil forKey:@"bar"]); OCMVerify([mockBackingEditor setBooleanAttribute:true forKey:@"bar" error:anyError]); diff --git a/Sources/batchTests/Modules/User/batchUserEmailSubscriptionTests.m b/Sources/batchTests/Modules/User/batchUserEmailSubscriptionTests.m new file mode 100644 index 0000000..ad82ea7 --- /dev/null +++ b/Sources/batchTests/Modules/User/batchUserEmailSubscriptionTests.m @@ -0,0 +1,92 @@ +// +// BatchTests +// +// Copyright © Batch.com. All rights reserved. +// + +#import +#import "BATrackerCenter.h" +#import "OCMock.h" + +@interface batchUserEmailSubscriptionTests : XCTestCase + +@end + +@implementation batchUserEmailSubscriptionTests { + id userMock; + id trackerCenterMock; +} + +- (void)setUp { + userMock = OCMClassMock([BatchUser class]); + trackerCenterMock = OCMClassMock([BATrackerCenter class]); + OCMStub([trackerCenterMock instance]).andReturn(trackerCenterMock); + OCMStub([userMock identifier]).andReturn(@"test_id"); +} + +- (void)tearDown { + [userMock stopMocking]; + [trackerCenterMock stopMocking]; +} + +- (void)testSendEmailOnly { + BAUserEmailSubscription *emailSubscription = [[BAUserEmailSubscription alloc] init]; + [emailSubscription setEmail:@"test@batch.com"]; + OCMExpect([trackerCenterMock trackPrivateEvent:@"_EMAIL_CHANGED" parameters:self.eventEmailOnly]); + [emailSubscription sendEmailSubscriptionEvent]; + OCMVerifyAll(trackerCenterMock); +} + +- (void)testSendEmailNullOnly { + BAUserEmailSubscription *emailSubscription = [[BAUserEmailSubscription alloc] init]; + [emailSubscription setEmail:nil]; + OCMExpect([trackerCenterMock trackPrivateEvent:@"_EMAIL_CHANGED" parameters:self.eventEmailNullOnly]); + [emailSubscription sendEmailSubscriptionEvent]; + OCMVerifyAll(trackerCenterMock); +} + +- (void)testSendEmailSubscriptionOnly { + BAUserEmailSubscription *emailSubscription = [[BAUserEmailSubscription alloc] init]; + [emailSubscription setEmailSubscriptionState:BatchEmailSubscriptionStateSubscribed forKind:BAEmailKindMarketing]; + OCMExpect([trackerCenterMock trackPrivateEvent:@"_EMAIL_CHANGED" parameters:self.eventEmailSubscriptionOnly]); + [emailSubscription sendEmailSubscriptionEvent]; + OCMVerifyAll(trackerCenterMock); +} + +- (void)testSendEmailSubscriptionFull { + BAUserEmailSubscription *emailSubscription = [[BAUserEmailSubscription alloc] init]; + [emailSubscription setEmail:@"test@batch.com"]; + [emailSubscription setEmailSubscriptionState:BatchEmailSubscriptionStateUnsubscribed forKind:BAEmailKindMarketing]; + OCMExpect([trackerCenterMock trackPrivateEvent:@"_EMAIL_CHANGED" parameters:self.eventEmailSubscriptionFull]); + [emailSubscription sendEmailSubscriptionEvent]; + OCMVerifyAll(trackerCenterMock); +} + +- (NSDictionary *)eventEmailOnly { + return @{@"custom_id" : @"test_id", @"email" : @"test@batch.com"}; +} + +- (NSDictionary *)eventEmailNullOnly { + return @{@"custom_id" : @"test_id", @"email" : [NSNull null]}; +} + +- (NSDictionary *)eventEmailSubscriptionOnly { + return @{ + @"custom_id" : @"test_id", + @"subscriptions" : @{ + @"marketing" : @"subscribed", + } + }; +} + +- (NSDictionary *)eventEmailSubscriptionFull { + return @{ + @"custom_id" : @"test_id", + @"email" : @"test@batch.com", + @"subscriptions" : @{ + @"marketing" : @"unsubscribed", + } + }; +} + +@end diff --git a/Sources/batchTests/Modules/User/batchUserTests.m b/Sources/batchTests/Modules/User/batchUserTests.m index 9f5c417..aaa7ea1 100644 --- a/Sources/batchTests/Modules/User/batchUserTests.m +++ b/Sources/batchTests/Modules/User/batchUserTests.m @@ -61,15 +61,26 @@ - (void)testAttributesRead { [_editor setAttribute:[NSDate new] forKey:@"today"]; [_editor setAttribute:@3.2 forKey:@"float_value"]; [_editor setAttribute:@5 forKey:@"int_value"]; - [_editor save]; XCTestExpectation *exp = [self expectationWithDescription:@"testing attributes read"]; + [_editor save:^{ + [exp fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2 + handler:^(NSError *_Nullable error) { + if (error != nil) { + XCTFail("Expectation Failed with error: %@", error); + } + }]; + + XCTestExpectation *exp1 = [self expectationWithDescription:@"testing attributes read"]; __block NSDictionary *fetchedAttributes = nil; [BatchUser fetchAttributes:^(NSDictionary *_Nullable attributes) { fetchedAttributes = attributes; - [exp fulfill]; + [exp1 fulfill]; }]; [self waitForExpectationsWithTimeout:1 @@ -94,15 +105,26 @@ - (void)testTagsRead { [_editor addTag:@"tag_2" inCollection:@"collection_1"]; [_editor addTag:@"tag_3" inCollection:@"collection_2"]; [_editor addTag:@"TAG_4" inCollection:@"collection_3"]; - [_editor save]; XCTestExpectation *exp = [self expectationWithDescription:@"testing tag read"]; + [_editor save:^{ + [exp fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2 + handler:^(NSError *_Nullable error) { + if (error != nil) { + XCTFail("Expectation Failed with error: %@", error); + } + }]; + + XCTestExpectation *exp1 = [self expectationWithDescription:@"testing tag read"]; __block NSDictionary *> *fetchedTags = nil; [BatchUser fetchTagCollections:^(NSDictionary *> *_Nullable tags) { fetchedTags = tags; - [exp fulfill]; + [exp1 fulfill]; }]; [self waitForExpectationsWithTimeout:1 @@ -143,7 +165,7 @@ - (void)testCustomDataRead { [exp1 fulfill]; }]; - [self waitForExpectationsWithTimeout:1 + [self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) { if (error != nil) { XCTFail("Expectation Failed with error: %@", error); @@ -167,7 +189,7 @@ - (void)testCustomDataRead { [exp2 fulfill]; }]; - [self waitForExpectationsWithTimeout:1 + [self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) { if (error != nil) { XCTFail("Expectation Failed with error: %@", error); @@ -219,7 +241,7 @@ - (void)testCustomDataLimits { [exp1 fulfill]; }]; - [self waitForExpectationsWithTimeout:1 + [self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) { if (error != nil) { XCTFail("Expectation Failed with error: %@", error); diff --git a/Sources/batchTests/Modules/batchUserDataEditorTests.swift b/Sources/batchTests/Modules/batchUserDataEditorTests.swift index 212b98b..a64811a 100644 --- a/Sources/batchTests/Modules/batchUserDataEditorTests.swift +++ b/Sources/batchTests/Modules/batchUserDataEditorTests.swift @@ -11,7 +11,6 @@ fileprivate let invalidKeys = [ ] class UserDataEditorTests: XCTestCase { - func testModernAttributeMethods() throws { let datasource = MockUserDatasource() let url = URL(string: "https://batch.com") @@ -53,7 +52,7 @@ class UserDataEditorTests: XCTestCase { try editor.setAttribute("foo", forKey: "stringattr") try editor.setAttribute(url!, forKey: "urlattr") - editor.writeToDatasource(changes: editor.operationQueue(), changeset: 1) + BAUserDataManager.writeToDatasource(changes: editor.operationQueue(), changeset: 1) datasource.verify() } @@ -84,7 +83,7 @@ class UserDataEditorTests: XCTestCase { try editor.setAttribute(NSNumber(value: true), forKey: "boolattr") try editor.setAttribute(NSNumber(value: 1.234), forKey: "doubleattr") try editor.setAttribute(NSNumber(value: 1.234 as Float), forKey: "floatattr") - editor.writeToDatasource(changes: editor.operationQueue(), changeset: 1) + BAUserDataManager.writeToDatasource(changes: editor.operationQueue(), changeset: 1) datasource.verify() } @@ -120,13 +119,12 @@ class UserDataEditorTests: XCTestCase { editor.removeTag("foo", fromCollection: key) } - editor.writeToDatasource(changes: editor.operationQueue(), changeset: 1) + BAUserDataManager.writeToDatasource(changes: editor.operationQueue(), changeset: 1) datasource.verify() } func testModernAttributeMethodErrors() { - let url = URL(string: "https://batch.com") let datasource = MockUserDatasource() @@ -171,20 +169,22 @@ class UserDataEditorTests: XCTestCase { assertThrowsError(code: .invalidKey, try editor.setAttribute(20 as Int, forKey: key)) assertThrowsError(code: .invalidKey, try editor.setAttribute(20 as Int64, forKey: key)) assertThrowsError( - code: .invalidKey, try editor.setAttribute(Date(timeIntervalSince1970: 12345), forKey: key)) + code: .invalidKey, try editor.setAttribute(Date(timeIntervalSince1970: 12345), forKey: key) + ) assertThrowsError(code: .invalidKey, try editor.setAttribute(1.234 as Double, forKey: key)) assertThrowsError(code: .invalidKey, try editor.setAttribute(1.234 as Float, forKey: key)) assertThrowsError(code: .invalidKey, try editor.setAttribute("foo", forKey: key)) assertThrowsError(code: .invalidKey, try editor.setAttribute(url!, forKey: key)) - } assertThrowsError( code: .invalidValue, try editor.setAttribute( "lorem ipsum dolor blalblablalbalblalbalbalb alblalbalbla lbal bla blablalbalblalbalbla balba", - forKey: "stringattr")) + forKey: "stringattr" + ) + ) - editor.writeToDatasource(changes: editor.operationQueue(), changeset: 1) + BAUserDataManager.writeToDatasource(changes: editor.operationQueue(), changeset: 1) datasource.verify() } @@ -209,7 +209,7 @@ class UserDataEditorTests: XCTestCase { } editor.addTag("lorem ipsum dolor this is a way too long string blabla qsdqdsqdsdqsdqsdqsd", inCollection: "bar") - editor.writeToDatasource(changes: editor.operationQueue(), changeset: 1) + BAUserDataManager.writeToDatasource(changes: editor.operationQueue(), changeset: 1) datasource.verify() } @@ -237,11 +237,31 @@ class UserDataEditorTests: XCTestCase { editor.clearTagCollection("foo") editor.removeAttribute(forKey: "foo") - editor.writeToDatasource(changes: editor.operationQueue(), changeset: 1) + BAUserDataManager.writeToDatasource(changes: editor.operationQueue(), changeset: 1) datasource.verify() } + func testUserOperationQueue() { + do { + let editor = BAUserDataEditor() + try editor.setAttribute("test", forKey: "test") + editor.save() + try editor.setAttribute("test2", forKey: "test2") + editor.save() + XCTAssertEqual(editor.operationQueue().count, 2) + } catch {} + } + + func testSetEmail() throws { + let editor = BAUserDataEditor() + assertThrowsError(code: .internal, try editor.setEmail("test@batch.com")) + editor.setIdentifier(nil) + assertThrowsError(code: .internal, try editor.setEmail("test@batch.com")) + editor.setIdentifier("testid") + assertThrowsError(code: .invalidValue, try editor.setEmail("test@batchcom")) + } + func assertThrowsError( code: BatchUserDataEditorError.Code, _ expression: @escaping @autoclosure () throws -> Void, file: StaticString = #filePath, line: UInt = #line diff --git a/Sources/batchTests/Stubs/DeeplinkDelegateStub.h b/Sources/batchTests/Stubs/DeeplinkDelegateStub.h index dd40e8e..6410f7f 100644 --- a/Sources/batchTests/Stubs/DeeplinkDelegateStub.h +++ b/Sources/batchTests/Stubs/DeeplinkDelegateStub.h @@ -5,10 +5,10 @@ // Copyright © Batch.com. All rights reserved. // -#import #import +#import -@interface DeeplinkDelegateStub: NSObject +@interface DeeplinkDelegateStub : NSObject @property (assign) BOOL hasOpenBeenCalled; diff --git a/Sources/batchTests/Webservices/Crypto/HMAC/webserviceHMACTests.swift b/Sources/batchTests/Webservices/Crypto/HMAC/webserviceHMACTests.swift index 1ed3a27..05517a1 100644 --- a/Sources/batchTests/Webservices/Crypto/HMAC/webserviceHMACTests.swift +++ b/Sources/batchTests/Webservices/Crypto/HMAC/webserviceHMACTests.swift @@ -34,7 +34,8 @@ class webserviceHMACTests: XCTestCase { XCTAssertEqual(nil, request.allHTTPHeaderFields?["Content-SHA1"]) XCTAssertEqual( "SHA256 content-type,foo,x-batch-cipher-version Gf8afLnF3TY/LqACciolOoALYeQSZ2dXy8Vxhfl7kI4=", - request.allHTTPHeaderFields?["X-Batch-Signature"] ?? "error") + request.allHTTPHeaderFields?["X-Batch-Signature"] ?? "error" + ) let body = "!&é\"'(§è!çà)-12567890°_%^$mù`=*/.,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]唄ック金型илджفيحةحديد" @@ -52,14 +53,16 @@ class webserviceHMACTests: XCTestCase { XCTAssertEqual("pG+tIWKFrPjoZ4RHGLE4/mQllCE=", request.allHTTPHeaderFields?["Content-SHA1"] ?? "error") XCTAssertEqual( "SHA256 content-sha1,content-type,foo,x-batch-cipher-version +FZLG5QtIKKrW1zxwzboezVNAb5VJ5RZI0319Wrzal0=", - request.allHTTPHeaderFields?["X-Batch-Signature"] ?? "error") + request.allHTTPHeaderFields?["X-Batch-Signature"] ?? "error" + ) } func testHmac() { + // key: 12345 let precomputedHmacWithHeaders = - "SHA256 content-type,foo,x-batch-cipher-version 8Qc8LvpoiakXejOZ9HzkxJOhLulKUdU3fzIL8dk720M=" // key: 12345 - let precomputedHmacWithoutHeaders = "SHA256 GuWkDmJXZa5LJCRCDw5DZEWMm+BWUFL3b8ZjV1oEOcU=" // key: 12345 - let precomputedHmacWithNoPath = "SHA256 jqvGLeh81CwCwjJxbTDWtmbk9F+kKnfpWqtI4+RbTkY=" // key: 12345 + "SHA256 content-type,foo,x-batch-cipher-version 8Qc8LvpoiakXejOZ9HzkxJOhLulKUdU3fzIL8dk720M=" + let precomputedHmacWithoutHeaders = "SHA256 GuWkDmJXZa5LJCRCDw5DZEWMm+BWUFL3b8ZjV1oEOcU=" // key: 12345 + let precomputedHmacWithNoPath = "SHA256 jqvGLeh81CwCwjJxbTDWtmbk9F+kKnfpWqtI4+RbTkY=" // key: 12345 XCTAssertEqual( precomputedHmacWithHeaders, hmac.hmac( @@ -69,20 +72,26 @@ class webserviceHMACTests: XCTestCase { "foo": "bar", "x-batch-CIPHER-version": "2", "Content-Type": "application/JSON", - ])) + ] + ) + ) XCTAssertEqual( precomputedHmacWithoutHeaders, hmac.hmac( forMethod: "post", relativeURL: "/foo/BAR?param=value", - headers: [:])) + headers: [:] + ) + ) XCTAssertEqual( precomputedHmacWithNoPath, hmac.hmac( forMethod: "post", relativeURL: "", - headers: [:])) + headers: [:] + ) + ) } func testRequestSummary() { @@ -100,7 +109,8 @@ class webserviceHMACTests: XCTestCase { "foo": "bar", "x-batch-CIPHER-version": "2", "Content-Type": "application/JSON", - ]) + ] + ) ) XCTAssertEqual( @@ -108,13 +118,14 @@ class webserviceHMACTests: XCTestCase { hmac._requestSummary( forMethod: "post", relativeURL: "/foo/BAR?param=value", - headers: [:]) + headers: [:] + ) ) } func testShaHMAC() { var testString = "Lorem Ipsum Dolor 😂" - var b64PrecomputedHmac256 = "mih9WNLUTSrPTUOpoviX/PWCHaD2ie0ju716raNCv3Y=" // key: 12345 + var b64PrecomputedHmac256 = "mih9WNLUTSrPTUOpoviX/PWCHaD2ie0ju716raNCv3Y=" // key: 12345 var precomputedHmac256 = Data(base64Encoded: b64PrecomputedHmac256)! XCTAssertEqual(precomputedHmac256, hmac._sha256Hmac(of: testString.data(using: .utf8)!)) @@ -164,7 +175,8 @@ class webserviceHMACTests: XCTestCase { "pro", "User-Agent", "X-Batch-Cipher-Version", - ], hmac._sortedHeaderKeys(headers)) + ], hmac._sortedHeaderKeys(headers) + ) } func testRelativeURLs() { @@ -175,10 +187,12 @@ class webserviceHMACTests: XCTestCase { { let path = "foo/b😂 a r".addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "error" return hmac._extractRelativeURL(URL(string: "https://batch.com/\(path)")!) - }()) + }() + ) XCTAssertEqual( "/foo/bar?param1=value1¶m2=value2", - hmac._extractRelativeURL(URL(string: "https://batch.com/foo/bar?param1=value1¶m2=value2")!)) + hmac._extractRelativeURL(URL(string: "https://batch.com/foo/bar?param1=value1¶m2=value2")!) + ) } func testURLPathFixup() { diff --git a/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m b/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m index fadab8f..adbb044 100644 --- a/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m +++ b/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m @@ -51,10 +51,9 @@ - (void)testEncryptDecryptV1 { BAWebserviceAESGCMCryptor *cryptor = [[BAWebserviceAESGCMCryptor alloc] initWithKey:[self key] version:@"1"]; XCTAssertNotNil(cryptor); - NSData *expectedData = - [@"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" - @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]唄ック金型илджفيحةحديد" - dataUsingEncoding:NSUTF8StringEncoding]; + NSData *expectedData = [@"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" + @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]" + @"唄ック金型илджفيحةحديد" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertNotNil(expectedData); XCTAssertEqualObjects(expectedData, [cryptor decrypt:[cryptor encrypt:expectedData]]); @@ -68,10 +67,9 @@ - (void)testEncryptDecryptV2 { version:@"2"]; XCTAssertNotNil(cryptor); - NSData *expectedData = - [@"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" - @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]唄ック金型илджفيحةحديد" - dataUsingEncoding:NSUTF8StringEncoding]; + NSData *expectedData = [@"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" + @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]" + @"唄ック金型илджفيحةحديد" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertNotNil(expectedData); XCTAssertEqualObjects(expectedData, [cryptor decrypt:[cryptor encrypt:expectedData]]); diff --git a/Sources/batchTests/Webservices/Query Services/eventTrackerServiceTests.swift b/Sources/batchTests/Webservices/Query Services/eventTrackerServiceTests.swift index b835695..58bbdbd 100644 --- a/Sources/batchTests/Webservices/Query Services/eventTrackerServiceTests.swift +++ b/Sources/batchTests/Webservices/Query Services/eventTrackerServiceTests.swift @@ -10,7 +10,6 @@ import Foundation import XCTest class eventTrackerServiceTests: XCTestCase { - let events: [BAEvent] = [ eventTrackerServiceTests.makeEvent(id: 1, state: BAEventStateNew), eventTrackerServiceTests.makeEvent(id: 2, state: BAEventStateOld), @@ -23,11 +22,12 @@ class eventTrackerServiceTests: XCTestCase { date: "\(id)234", secureDate: "\(id)2345", parameters: """ - {"foo": "bar\(id)"} - """, + {"foo": "bar\(id)"} + """, state: state, session: "s\(id)", - andTick: Int64(990 + id)) + andTick: Int64(990 + id) + ) } static func makeSerializedEvent(id: Int) -> [String: Any] { @@ -55,7 +55,7 @@ class eventTrackerServiceTests: XCTestCase { let url = makeService().requestURL XCTAssertNotNil(url) XCTAssertTrue(url!.absoluteString.contains("tr")) - //TODO: better tests with ocmock or DI + // TODO: better tests with ocmock or DI } func testQuery() throws { @@ -84,11 +84,12 @@ class eventTrackerServiceTests: XCTestCase { date: "234", secureDate: "2345", parameters: """ - {"foo": "bar"} - """, + {"foo": "bar"} + """, state: BAEventStateOld, session: nil, - andTick: Int64(990)) + andTick: Int64(990) + ), ] let service = BAEventTrackerService(events: events as [Any]) // The bug made "objectToSend" crash: simply calling it was enough to trigger it, no need to test any value @@ -109,10 +110,11 @@ class eventTrackerServiceTests: XCTestCase { let promises = [BAPromise(), BAPromise()] let service = makeServiceWithPromises(promises) service.webserviceClient( - makeQueryClient(service: service), didFailWithError: NSError(domain: "test", code: 1, userInfo: nil)) + makeQueryClient(service: service), didFailWithError: NSError(domain: "test", code: 1, userInfo: nil) + ) XCTAssertTrue(promises[0].status == BAPromiseStatus.rejected) XCTAssertTrue(promises[1].status == BAPromiseStatus.rejected) - //TODO: Test non promise failure + // TODO: Test non promise failure } func testWebserviceSuccess() { @@ -120,10 +122,11 @@ class eventTrackerServiceTests: XCTestCase { let service = makeServiceWithPromises(promises) service.webserviceClient( makeQueryClient(service: service), - didSucceedWith: [BAWSResponseTracking(response: makeBasicQueryResponseDictionary())]) + didSucceedWith: [BAWSResponseTracking(response: makeBasicQueryResponseDictionary())] + ) XCTAssertTrue(promises[0].status == BAPromiseStatus.resolved) XCTAssertTrue(promises[1].status == BAPromiseStatus.resolved) - //TODO: Test non promise success + // TODO: Test non promise success } func makeService() -> BAEventTrackerService { diff --git a/Sources/batchTests/Webservices/Query Services/pushTokenServiceTests.swift b/Sources/batchTests/Webservices/Query Services/pushTokenServiceTests.swift index da16d55..77788cd 100644 --- a/Sources/batchTests/Webservices/Query Services/pushTokenServiceTests.swift +++ b/Sources/batchTests/Webservices/Query Services/pushTokenServiceTests.swift @@ -12,7 +12,6 @@ import XCTest fileprivate let expectedToken = "test_token" class pushTokenServiceTests: XCTestCase { - func testIdentifier() { XCTAssertEqual(makeService().requestIdentifier, "push") } diff --git a/Sources/batchTests/XCTest+BAPromise.swift b/Sources/batchTests/XCTest+BAPromise.swift index d180023..8d40c4d 100644 --- a/Sources/batchTests/XCTest+BAPromise.swift +++ b/Sources/batchTests/XCTest+BAPromise.swift @@ -21,10 +21,11 @@ public func XCTAssertResolves( promise.then { (_ resolvedValue: T?) in XCTAssertEqual(expected, resolvedValue, message, file: file, line: line) } - promise.catch { (err) in + promise.catch { err in XCTFail( "Promise was expected to be resolved with '\(String(describing: expected))' but was rejected with '\(String(describing: err))'.", - file: file, line: line) + file: file, line: line + ) } } @@ -32,8 +33,8 @@ public func XCTAssertResolves( // Note: this doesn't wait for the promise to have been executed before completing the tests. // As there is no way to signal the test runner that we should wait for a value, please call XCTAssertNoPendingPromise at the end of your test public func XCTAssertRejects( - _ promise: @autoclosure () throws -> BAPromise, _ message: @autoclosure () -> String = "", - file: StaticString = #filePath, line: UInt = #line + _ promise: @autoclosure () throws -> BAPromise, _: @autoclosure () -> String = "", + file _: StaticString = #filePath, line _: UInt = #line ) { let promise = try! promise() promise.then { (_ resolvedValue: T?) in @@ -44,7 +45,7 @@ public func XCTAssertRejects( // Asserts that the promise isn't pending, but has been resolved or rejected // This should be ran at the end of your test public func XCTAssertNoPendingPromise( - _ promise: @autoclosure () throws -> BAPromise, file: StaticString = #filePath, line: UInt = #line + _ promise: @autoclosure () throws -> BAPromise, file _: StaticString = #filePath, line _: UInt = #line ) { let promise = try! promise() XCTAssertNotEqual(BAPromiseStatus.pending, promise.status) @@ -56,7 +57,7 @@ public func XCTAssertNoPendingPromise( _ promises: @autoclosure () throws -> [BAPromise], file: StaticString = #filePath, line: UInt = #line ) { let promises = try! promises() - promises.forEach { (promise) in + promises.forEach { promise in XCTAssertNotEqual(BAPromiseStatus.pending, promise.status, file: file, line: line) } } @@ -65,7 +66,7 @@ public func XCTAssertNoPendingPromise( // Useful for XCTAssertNoPendingPromise extension Array { mutating func push(_ promise: Element) -> Element where Element: BAPromise { - self.append(promise) + append(promise) return promise } } diff --git a/Sources/batchTests/batchEventDataTests.swift b/Sources/batchTests/batchEventDataTests.swift index 042ed07..e904476 100644 --- a/Sources/batchTests/batchEventDataTests.swift +++ b/Sources/batchTests/batchEventDataTests.swift @@ -16,7 +16,7 @@ class BatchEventDataTests: XCTestCase { data.add(tag: "BAR") data.add(tag: "baz") - let now = Date(timeIntervalSince1970: 1589466748.930) + let now = Date(timeIntervalSince1970: 1_589_466_748.930) let url = URL(string: "https://batch.com") data.put(1, forKey: "int") data.put(1.0 as Float, forKey: "float") @@ -50,7 +50,7 @@ class BatchEventDataTests: XCTestCase { func testSizeLimits() { let data = BatchEventData() - for i in 0...20 { + for i in 0 ... 20 { data.add(tag: String(i)) data.put(i, forKey: String(i)) } @@ -68,7 +68,7 @@ class BatchEventDataTests: XCTestCase { // Issue #57 let data = BatchEventData() - for i in 0...14 { + for i in 0 ... 14 { data.put(i, forKey: String(i)) } data.put("foobar", forKey: "2") @@ -90,7 +90,8 @@ class BatchEventDataTests: XCTestCase { data.put( "A way too long string that goes for quiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiite too long" - + "Lorem ipsum dolor and other various stuff.", forKey: "string") + + "Lorem ipsum dolor and other various stuff.", forKey: "string" + ) data.put("foobar", forKey: "invalid_key%%%") data.put("foobar", forKey: "key_that_is_too_long_really_it_should_be_more_than_thirty_chars") data.put(URL(string: "batch.com")!, forKey: "url_without_scheme") @@ -160,7 +161,7 @@ class BatchEventDataTests: XCTestCase { "FViUCTCzfE", ] - let legacyData: [String: String] = unorderedKeys.reduce(into: [:]) { (data, key) in + let legacyData: [String: String] = unorderedKeys.reduce(into: [:]) { data, key in data[key] = value } @@ -174,9 +175,9 @@ class BatchEventDataTests: XCTestCase { XCTAssertEqual(15, attributeKeys.count) - let expectedConvertedKeys = unorderedKeys.map({ "\($0.lowercased()).s" }).sorted().prefix(10) - expectedConvertedKeys.forEach({ + let expectedConvertedKeys = unorderedKeys.map { "\($0.lowercased()).s" }.sorted().prefix(10) + expectedConvertedKeys.forEach { XCTAssertTrue(attributeKeys.contains($0)) - }) + } } } diff --git a/Tools/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/Tools/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Tools/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Tools/Bridgy/Sources/Bridgy/Generator.swift b/Tools/Bridgy/Sources/Bridgy/Generator.swift index d5d979b..02f9e3d 100644 --- a/Tools/Bridgy/Sources/Bridgy/Generator.swift +++ b/Tools/Bridgy/Sources/Bridgy/Generator.swift @@ -31,6 +31,7 @@ public enum GeneratorError: Error { } let bridgingHeaderPrefix = """ +// clang-format off // // This bridging header has been automatically generated by Bridgy // DO NOT EDIT MANUALLY. @@ -40,6 +41,10 @@ let bridgingHeaderPrefix = """ """ +let bridgingHeaderSuffix = """ +// clang-format on +""" + public class Generator { var basePath: String var outputDir: String @@ -186,6 +191,8 @@ public class Generator { } } + content.append("\n" + bridgingHeaderSuffix) + return content } diff --git a/Tools/Dockerfile.format b/Tools/Dockerfile.format new file mode 100644 index 0000000..c8e67f3 --- /dev/null +++ b/Tools/Dockerfile.format @@ -0,0 +1,18 @@ +FROM swift:jammy + +ENV DEBIAN_FRONTEND noninteractive + +# Clang-format +RUN apt-get update -y && apt-get install -y clang-format-14 && \ + mv /usr/bin/clang-format-14 /usr/bin/clang-format + +COPY .clang-format /data/.clang-format +COPY .clang-format-version /data/.clang-format-version +COPY .swift-version /data/.swift-version +COPY .swiftformat /data/.swiftformat +COPY Tools /data/Tools + +RUN cd /data/Tools && swift run -c release swiftformat || true + +WORKDIR "/data/Tools/Scripts" +ENTRYPOINT ["/bin/bash"] \ No newline at end of file diff --git a/Tools/Package.resolved b/Tools/Package.resolved new file mode 100644 index 0000000..8d6a962 --- /dev/null +++ b/Tools/Package.resolved @@ -0,0 +1,14 @@ +{ + "pins" : [ + { + "identity" : "swiftformat", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nicklockwood/SwiftFormat", + "state" : { + "revision" : "fee7e1a1ac9518cfe3c4673382368641ccbdc62c", + "version" : "0.51.7" + } + } + ], + "version" : 2 +} diff --git a/Tools/Package.swift b/Tools/Package.swift new file mode 100644 index 0000000..0317499 --- /dev/null +++ b/Tools/Package.swift @@ -0,0 +1,19 @@ +// swift-tools-version:5.6 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Tools", + dependencies: [ + // Dependencies declare other packages that this package depends on. + .package(url: "https://github.com/nicklockwood/SwiftFormat", exact: "0.51.7"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "Tools", + dependencies: []), + ] +) diff --git a/Tools/Scripts/format-check.sh b/Tools/Scripts/format-check.sh new file mode 100644 index 0000000..b3810e1 --- /dev/null +++ b/Tools/Scripts/format-check.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +if [ `uname -s` == Linux ]; then + CLANGFORMAT=`which clang-format` +else + CLANGFORMAT=`xcrun -find clang-format` +fi + +if [ ! -x "${CLANGFORMAT}" ]; then + echo "clang-format is missing. On a mac, please install it using homebrew: brew install clang-format" + exit 1 +fi + +EXPECTED_CLANGFORMAT_VERSION=`cat ../../.clang-format-version` +CLANGFORMAT_VERSION=`${CLANGFORMAT} --version` + +if echo $CLANGFORMAT_VERSION | grep -q -v "${EXPECTED_CLANGFORMAT_VERSION}"; then + echo "clang-format version mismatch. expected ${EXPECTED_CLANGFORMAT_VERSION}, got ${CLANGFORMAT_VERSION}" +fi + +set -e +SDK_FOLDER="../../sdk" + +# Format Objective-C code +find "${SDK_FOLDER}/Batch" "${SDK_FOLDER}/batchTests" -type f -name "*.[mh]" -not \( -path "${SDK_FOLDER}/Batch/Versions.h" \) -print0 | xargs -0 ${CLANGFORMAT} --dry-run --Werror -i + +# Format Swift code +swift run -c release swiftformat --lint "${SDK_FOLDER}/Batch" "${SDK_FOLDER}/batchTests" diff --git a/Tools/Scripts/format.sh b/Tools/Scripts/format.sh new file mode 100755 index 0000000..19d7462 --- /dev/null +++ b/Tools/Scripts/format.sh @@ -0,0 +1,26 @@ +#!/bin/bash +if [ `uname -s` == Linux ]; then + CLANGFORMAT=`which clang-format` +else + CLANGFORMAT=`xcrun -find clang-format` +fi + +if [ ! -x "${CLANGFORMAT}" ]; then + echo "clang-format is missing. On a mac, please install it using homebrew: brew install clang-format" + exit 1 +fi + +EXPECTED_CLANGFORMAT_VERSION=`cat ../../.clang-format-version` +CLANGFORMAT_VERSION=`${CLANGFORMAT} --version` + +if echo $CLANGFORMAT_VERSION | grep -q -v "${EXPECTED_CLANGFORMAT_VERSION}"; then + echo "clang-format version mismatch. expected ${EXPECTED_CLANGFORMAT_VERSION}, got ${CLANGFORMAT_VERSION}" +fi + +SDK_FOLDER="../../sdk" + +# Format Objective-C code +find "${SDK_FOLDER}/Batch" "${SDK_FOLDER}/batchTests" -type f -name "*.[mh]" -not \( -path "${SDK_FOLDER}/Batch/Versions.h" \) -print0 | xargs -0 ${CLANGFORMAT} -i + +# Format Swift code +swift run -c release swiftformat "${SDK_FOLDER}/Batch" "${SDK_FOLDER}/batchTests" diff --git a/Sources/generate_private_umbrella_header.sh b/Tools/Scripts/generate_private_umbrella_header.sh similarity index 100% rename from Sources/generate_private_umbrella_header.sh rename to Tools/Scripts/generate_private_umbrella_header.sh diff --git a/Tools/Scripts/generate_sdk_report_size.sh b/Tools/Scripts/generate_sdk_report_size.sh new file mode 100644 index 0000000..f8a2cbc --- /dev/null +++ b/Tools/Scripts/generate_sdk_report_size.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# fail if any commands fails +set -e +# debug log +set -x + +# Building archive without Batch SDK +xcodebuild clean archive -workspace $BITRISE_PROJECT_PATH -scheme $BITRISE_SIZE_REPORT_SCHEME -configuration Release -sdk iphoneos -archivePath "SizeReport.xcarchive" SKIP_INSTALL=NO CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED="NO" + +# Extracting archive and size report +xcodebuild -exportArchive -archivePath SizeReport.xcarchive -exportPath "Generated" -exportOptionsPlist OptionsPlist.plist + +# Reading size report +cat Generated/App\ Thinning\ Size\ Report.txt +initial_size=$(sed -n 14p Generated/App\ Thinning\ Size\ Report.txt) + +# Installing Batch SDK +cd SizeReport +sed -i '' '9i\ +pod "Batch", "~> 1.17"' Podfile +pod install +cd SizeReport +sed -i '' '8i\ +@import Batch;' AppDelegate.m +sed -i '' '18i\ +[Batch startWithAPIKey:@"YOUR_API_KEY"];' AppDelegate.m + +cd .. + +# Building archive with Batch SDK +xcodebuild clean archive -workspace SizeReport.xcworkspace -scheme $BITRISE_SIZE_REPORT_SCHEME -configuration Release -sdk iphoneos -archivePath "../SizeReport.xcarchive" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED="NO" + +cd .. + +# Extracting archive and size report +xcodebuild -exportArchive -archivePath SizeReport.xcarchive -exportPath "Generated" -exportOptionsPlist OptionsPlist.plist + +# Reading size report +cat Generated/App\ Thinning\ Size\ Report.txt +final_size=$(sed -n 14p Generated/App\ Thinning\ Size\ Report.txt) + +# Writting report file +echo $initial_size >> report.txt +echo $final_size >> report.txt \ No newline at end of file diff --git a/Sources/make_doc.sh b/Tools/Scripts/make_doc.sh similarity index 100% rename from Sources/make_doc.sh rename to Tools/Scripts/make_doc.sh diff --git a/Tools/strip_public_swift_framework.sh b/Tools/Scripts/strip_public_swift_framework.sh similarity index 100% rename from Tools/strip_public_swift_framework.sh rename to Tools/Scripts/strip_public_swift_framework.sh diff --git a/Tools/Sources/Tools/.gitkeep b/Tools/Sources/Tools/.gitkeep new file mode 100644 index 0000000..e69de29