diff --git a/Package.swift b/Package.swift index 23cd05a..95f5c78 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.20.0.zip", - checksum: "90c5ed03fab1c1708f54eb6eaa8180962e14659cc76fe0bd7f561273818eec94" + url: "https://download.batch.com/sdk/ios/spm/BatchSDK-ios_spm-xcframework-1.21.0.zip", + checksum: "0e1edfbf2df8952552ae62bcfd1262347554af3c993a38c2d0e4eccbcac28c7b" ) ] ) \ No newline at end of file diff --git a/Sources/Batch.xcodeproj/project.pbxproj b/Sources/Batch.xcodeproj/project.pbxproj index 0a5e281..58b25d2 100644 --- a/Sources/Batch.xcodeproj/project.pbxproj +++ b/Sources/Batch.xcodeproj/project.pbxproj @@ -104,6 +104,7 @@ 510BD5DC22E0B4D500D8CBA1 /* BAWSQueryStart.m in Sources */ = {isa = PBXBuildFile; fileRef = 510BD5D422E0B4D500D8CBA1 /* BAWSQueryStart.m */; }; 510D906F24C83A81005981AC /* shaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510D906E24C83A81005981AC /* shaTests.swift */; }; 510FFEE822FD800700BBF277 /* dependencyInjectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510FFEE622FD7FE500BBF277 /* dependencyInjectionTests.swift */; }; + 51103A792A7405B50082987C /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 51103A782A7405B40082987C /* PrivacyInfo.xcprivacy */; }; 511B91FE22CE32A3002BC4A8 /* Batch.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 517D701822BBC34A00E374FB /* Batch.framework */; }; 511B920322CE416D002BC4A8 /* BAWebserviceCryptorFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 511B920122CE416D002BC4A8 /* BAWebserviceCryptorFactory.h */; settings = {ATTRIBUTES = (Private, ); }; }; 511B920422CE416D002BC4A8 /* BAWebserviceCryptorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 511B920222CE416D002BC4A8 /* BAWebserviceCryptorFactory.m */; }; @@ -117,8 +118,6 @@ 5127299E23FD720E00999505 /* BATMessagePackWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5127299C23FD720E00999505 /* BATMessagePackWriter.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5127299F23FD720E00999505 /* BATMessagePackWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5127299D23FD720E00999505 /* BATMessagePackWriter.m */; }; 512EA4E523BE37F300B7DBB1 /* pushTokenServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512EA4E423BE37F300B7DBB1 /* pushTokenServiceTests.swift */; }; - 513175DC2524BC30001D0033 /* BATrackingAuthorization.h in Headers */ = {isa = PBXBuildFile; fileRef = 513175DA2524BC30001D0033 /* BATrackingAuthorization.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 513175DD2524BC30001D0033 /* BATrackingAuthorization.m in Sources */ = {isa = PBXBuildFile; fileRef = 513175DB2524BC30001D0033 /* BATrackingAuthorization.m */; }; 513347902507D7DB005A89AB /* jsonTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5133478F2507D7DB005A89AB /* jsonTests.m */; }; 51379B7F22FC5C0200AB7B82 /* BAInjectableImplementations.h in Headers */ = {isa = PBXBuildFile; fileRef = 51379B7D22FC5C0200AB7B82 /* BAInjectableImplementations.h */; settings = {ATTRIBUTES = (Private, ); }; }; 51379B8022FC5C0200AB7B82 /* BAInjectableImplementations.m in Sources */ = {isa = PBXBuildFile; fileRef = 51379B7E22FC5C0200AB7B82 /* BAInjectableImplementations.m */; }; @@ -853,6 +852,7 @@ 510BD5D422E0B4D500D8CBA1 /* BAWSQueryStart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAWSQueryStart.m; sourceTree = ""; }; 510D906E24C83A81005981AC /* shaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = shaTests.swift; sourceTree = ""; }; 510FFEE622FD7FE500BBF277 /* dependencyInjectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dependencyInjectionTests.swift; sourceTree = ""; }; + 51103A782A7405B40082987C /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 511074631C208B7800BFC215 /* BAUserDataServices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BAUserDataServices.h; sourceTree = ""; }; 511074641C208B7800BFC215 /* BAUserDataServices.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BAUserDataServices.m; sourceTree = ""; }; 511074691C208F6300BFC215 /* BAUserDataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BAUserDataManager.h; path = Batch/Modules/User/BAUserDataManager.h; sourceTree = SOURCE_ROOT; }; @@ -905,8 +905,6 @@ 5130B5EA1DBA6F5300874EFF /* BACSSImportProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BACSSImportProvider.h; path = Batch/Modules/Messaging/CSS/BACSSImportProvider.h; sourceTree = SOURCE_ROOT; }; 5130B5EC1DBA6FA600874EFF /* BACSSBuiltinImportProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BACSSBuiltinImportProvider.h; path = Batch/Modules/Messaging/CSS/BACSSBuiltinImportProvider.h; sourceTree = SOURCE_ROOT; }; 5130B5ED1DBA6FA600874EFF /* BACSSBuiltinImportProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BACSSBuiltinImportProvider.m; path = Batch/Modules/Messaging/CSS/BACSSBuiltinImportProvider.m; sourceTree = SOURCE_ROOT; }; - 513175DA2524BC30001D0033 /* BATrackingAuthorization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BATrackingAuthorization.h; sourceTree = ""; }; - 513175DB2524BC30001D0033 /* BATrackingAuthorization.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BATrackingAuthorization.m; sourceTree = ""; }; 5133478F2507D7DB005A89AB /* jsonTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = jsonTests.m; sourceTree = ""; }; 51379B7D22FC5C0200AB7B82 /* BAInjectableImplementations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAInjectableImplementations.h; sourceTree = ""; }; 51379B7E22FC5C0200AB7B82 /* BAInjectableImplementations.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAInjectableImplementations.m; sourceTree = ""; }; @@ -1416,8 +1414,6 @@ 028499FB19B9EFBA0013408B /* BAStatus.m */, 51A21AFD20ED0167007917E0 /* BANotificationAuthorization.h */, 51A21AFC20ED0167007917E0 /* BANotificationAuthorization.m */, - 513175DA2524BC30001D0033 /* BATrackingAuthorization.h */, - 513175DB2524BC30001D0033 /* BATrackingAuthorization.m */, 51B5E4871C849D8900047F6E /* BABundleInfo.h */, 51B5E4881C849D8900047F6E /* BABundleInfo.m */, 51AE746620850217005186D7 /* BAInstallationID.h */, @@ -1806,6 +1802,7 @@ 5190F1CA253491530014E5BA /* Versions.h */, 51BB37AB1E918D3600D9A142 /* Batch.modulemap */, 02F7846419B9EF5A0006FF07 /* Info.plist */, + 51103A782A7405B40082987C /* PrivacyInfo.xcprivacy */, ); name = "Supporting Files"; sourceTree = ""; @@ -2936,7 +2933,6 @@ 5127299E23FD720E00999505 /* BATMessagePackWriter.h in Headers */, 51696F7A25263BFC00951CA4 /* BAApplicationLifecycle.h in Headers */, 5145C78224C1F0BE004A89FE /* BAConnectionContentType.h in Headers */, - 513175DC2524BC30001D0033 /* BATrackingAuthorization.h in Headers */, 5190F1E8253495B30014E5BA /* Versions.h in Headers */, 5162B2F42571561900607780 /* BAMSGWebviewViewController.h in Headers */, 51FCC9332577EF9C00FA76C6 /* BAMSGActivityIndicatorView.h in Headers */, @@ -3034,7 +3030,7 @@ 02F7845719B9EF5A0006FF07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1200; + LastUpgradeCheck = 1500; ORGANIZATIONNAME = Batch.com; TargetAttributes = { 02849C3219BA00350013408B = { @@ -3093,6 +3089,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 51103A792A7405B50082987C /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3119,13 +3116,15 @@ buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( ); outputPaths = ( ); 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=\"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"; + 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\npushd .\ncd \"${PROJECT_DIR}/universal\"\nxcodebuild -create-xcframework \\\n -framework \"Archives/Batch-iphoneos.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -framework \"Archives/Batch-iphonesimulator.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -framework \"Archives/Batch-macos.xcarchive/Products/Library/Frameworks/Batch.framework\" \\\n -output \"Batch.xcframework\"\n\n# Sign it for distribution\n# (Apple Enterprise Account)\n\nif [ \"$BATCHSDK_SIGN_XCFRAMEWORK\" == \"1\" ]\nthen\n echo \"Signing Batch.xcframework\"\n codesign --timestamp -v --sign \"iPhone Distribution: IMEDIAPP\" \"${XCFRAMEWORK_OUTPUT}\"\nfi\n"; }; 516C406723D9FD63000C11CF /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -3450,7 +3449,6 @@ 517D708722BBC45900E374FB /* BAUserAttribute.m in Sources */, 517D708822BBC45900E374FB /* BAUserDataServices.m in Sources */, 1E45578627CE1B510048D3A8 /* BALocalCampaignsJITService.m in Sources */, - 513175DD2524BC30001D0033 /* BATrackingAuthorization.m in Sources */, 517D708922BBC45900E374FB /* BAActionsCenter.m in Sources */, 629B42A52490D8FA0025411E /* BATGZIP.m in Sources */, 629B42A12490C9120025411E /* BAWebserviceAESGCMGzipCryptor.m in Sources */, @@ -3563,6 +3561,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -3608,7 +3607,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -3622,6 +3621,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -3660,7 +3660,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -3684,7 +3684,7 @@ ); HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/Batch/**"; INFOPLIST_FILE = batchTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3716,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 = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3809,12 +3809,14 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = U5K2ETC2Y6; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREFIX_HEADER = "$(SOURCE_ROOT)/Batch/batch-Prefix.pch"; INFOPLIST_FILE = Batch/Info.plist; @@ -3822,7 +3824,7 @@ INFOPLIST_PREFIX_HEADER = Batch/Versions.h; INFOPLIST_PREPROCESS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3830,6 +3832,8 @@ ); MACH_O_TYPE = staticlib; MODULEMAP_FILE = Batch/Batch.modulemap; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.batch.Batch; @@ -3856,6 +3860,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = YES; DEFINES_MODULE = YES; @@ -3864,6 +3869,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_OPTIMIZATION_LEVEL = s; GCC_PREFIX_HEADER = "$(SOURCE_ROOT)/Batch/batch-Prefix.pch"; @@ -3873,7 +3879,7 @@ INFOPLIST_PREFIX_HEADER = Batch/Versions.h; INFOPLIST_PREPROCESS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -3881,11 +3887,12 @@ ); MACH_O_TYPE = staticlib; MODULEMAP_FILE = Batch/Batch.modulemap; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.batch.Batch; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; - STRIP_STYLE = debugging; SWIFT_VERSION = 5.7; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/Sources/Batch.xcodeproj/xcshareddata/xcschemes/Batch.xcscheme b/Sources/Batch.xcodeproj/xcshareddata/xcschemes/Batch.xcscheme index de838bb..36a487e 100644 --- a/Sources/Batch.xcodeproj/xcshareddata/xcschemes/Batch.xcscheme +++ b/Sources/Batch.xcodeproj/xcshareddata/xcschemes/Batch.xcscheme @@ -1,6 +1,6 @@ _Nullable)loggerDelegate NS_AVAILABLE_IOS(8_0); ++ (void)setLoggerDelegate:(id _Nullable)loggerDelegate; /// Get the debug view controller. /// @@ -208,7 +208,7 @@ typedef NS_ENUM(NSUInteger, BatchOptOutNetworkErrorPolicy) { /// - 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); ++ (void)setAssociatedDomains:(NSArray *_Nonnull)domains; @end diff --git a/Sources/Batch/BatchCore.m b/Sources/Batch/BatchCore.m index 69e914a..ee3513b 100644 --- a/Sources/Batch/BatchCore.m +++ b/Sources/Batch/BatchCore.m @@ -43,12 +43,12 @@ + (BatchUserProfile *)defaultUserProfile { return sharedInstance; } -// Set if Batch can try to use IDFA (default = YES) +// Set if Batch can try to use IDFA. Deprecated. + (void)setUseIDFA:(BOOL)use { - [BACenterMulticastDelegate setUseIDFA:use]; + [BALogger publicForDomain:nil message:@"Ignoring 'setUseIDFA' API call: Batch has removed support for IDFA."]; } -+ (void)setLoggerDelegate:(id)loggerDelegate NS_AVAILABLE_IOS(8_0) { ++ (void)setLoggerDelegate:(id)loggerDelegate { [[[BACoreCenter instance] configuration] setLoggerDelegate:loggerDelegate]; } diff --git a/Sources/Batch/BatchPush.h b/Sources/Batch/BatchPush.h index b3454da..75d739d 100644 --- a/Sources/Batch/BatchPush.h +++ b/Sources/Batch/BatchPush.h @@ -85,7 +85,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// 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) ++ (void)setupPush __attribute__((deprecated("setupPush is deprecated. You don't need to do anything else besides removing this call, " "Batch Push will still work as expected."))); @@ -95,7 +95,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// 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); ++ (void)setRemoteNotificationTypes:(BatchNotificationType)type; /// Method to trigger the iOS popup that asks the user if they wants to allow notifications to be displayed, then /// get a Push token. @@ -105,7 +105,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// 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); ++ (void)requestNotificationAuthorization; /// Method to ask iOS for a provisional notification authorization. /// @@ -116,15 +116,15 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// from the statusbar when unlocked. /// /// This method does nothing on iOS 11 or lower. -+ (void)requestProvisionalNotificationAuthorization NS_AVAILABLE_IOS(8_0); ++ (void)requestProvisionalNotificationAuthorization; /// 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); ++ (void)refreshToken; /// Open the system settings on your applications' notification settings. -+ (void)openSystemNotificationSettings NS_AVAILABLE_IOS(8_0); ++ (void)openSystemNotificationSettings; /// Method to trigger the iOS popup that asks the user if they wants to allow Push Notifications, then get a Push token. /// (Deprecated) @@ -135,7 +135,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// 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__(( ++ (void)registerForRemoteNotifications __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. @@ -152,8 +152,8 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// - 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."))); + + __attribute__((deprecated("Use setNotificationCategories and registerForRemoteNotifications separately."))); /// Set the notification action categories to iOS. /// @@ -164,19 +164,19 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// 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); ++ (void)setNotificationsCategories:(nullable NSSet *)categories; /// 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); ++ (void)clearBadge; /// 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); ++ (void)dismissNotifications; /// Set whether Batch Push should automatically try to handle deeplinks. /// @@ -190,13 +190,13 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// - 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); ++ (void)enableAutomaticDeeplinkHandling:(BOOL)handleDeeplinks; /// 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); ++ (nullable NSString *)deeplinkFromUserInfo:(nonnull NSDictionary *)userData; /// Get the last known push token. /// @@ -204,7 +204,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// - 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); ++ (nullable NSString *)lastKnownPushToken; /// Disable the push's automatic integration. /// @@ -212,7 +212,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// `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); ++ (void)disableAutomaticIntegration; /// Registers a device token to Batch. /// @@ -220,7 +220,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// - 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); ++ (void)handleDeviceToken:(nonnull NSData *)token; /// Check if the received push is a Batch one. /// @@ -229,7 +229,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// - 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); ++ (BOOL)isBatchPush:(nonnull NSDictionary *)userInfo; /// Make Batch process a notification. (Deprecated) /// @@ -255,8 +255,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// - 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); ++ (void)handleNotification:(nonnull NSDictionary *)userInfo actionIdentifier:(nullable NSString *)identifier; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -289,7 +288,7 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { + (void)handleUserNotificationCenter:(nonnull UNUserNotificationCenter *)center willPresentNotification:(nonnull UNNotification *)notification willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert - NS_AVAILABLE_IOS(10_0)NS_SWIFT_NAME(handle(userNotificationCenter:willPresent:willShowSystemForegroundAlert:)); + NS_SWIFT_NAME(handle(userNotificationCenter:willPresent:willShowSystemForegroundAlert:)); /// Make Batch process a background notification open/action. /// @@ -299,8 +298,8 @@ typedef NS_ENUM(NSUInteger, BatchNotificationSource) { /// - 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:)); + didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response + NS_SWIFT_NAME(handle(userNotificationCenter:didReceive:)); @end diff --git a/Sources/Batch/BatchPush.m b/Sources/Batch/BatchPush.m index af22804..53a85e3 100644 --- a/Sources/Batch/BatchPush.m +++ b/Sources/Batch/BatchPush.m @@ -199,16 +199,11 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center if (self.showForegroundNotifications) { options = UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound; - // TODO: Remove ifdef once we Xcode 12 supports macOS 11 Big Sur -#ifdef __IPHONE_14_0 if (@available(iOS 14.0, *)) { options = options | UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner; } else { options = options | UNNotificationPresentationOptionAlert; } -#else - options = options | UNNotificationPresentationOptionAlert; -#endif } if (completionHandler) { diff --git a/Sources/Batch/BatchUser.h b/Sources/Batch/BatchUser.h index 9e37e46..c85c2c7 100644 --- a/Sources/Batch/BatchUser.h +++ b/Sources/Batch/BatchUser.h @@ -236,6 +236,11 @@ typedef NS_ENUM(NSUInteger, BatchEmailSubscriptionState) { /// - Parameter identifier: User identifier. - (void)setIdentifier:(nullable NSString *)identifier; +/// Set the user attribution identifier. +/// +/// - Parameter attributionID: A valid UUID string or null to reset. +- (void)setAttributionIdentifier:(nullable NSString *)attributionID; + /// Set the user email. /// /// - Important: This method requires to already have a registered identifier for the user diff --git a/Sources/Batch/BatchUser.m b/Sources/Batch/BatchUser.m index b55f1cc..84c8ec0 100644 --- a/Sources/Batch/BatchUser.m +++ b/Sources/Batch/BatchUser.m @@ -233,6 +233,10 @@ - (void)setIdentifier:(nullable NSString *)identifier { [_backingImpl setIdentifier:identifier]; } +- (void)setAttributionIdentifier:(nullable NSString *)attributionID { + [_backingImpl setAttributionIdentifier:attributionID]; +} + - (BOOL)setEmail:(nullable NSString *)email error:(NSError **)error { return [_backingImpl setEmail:email error:error]; } diff --git a/Sources/Batch/Defined.h b/Sources/Batch/Defined.h index a663b6a..d3f7195 100644 --- a/Sources/Batch/Defined.h +++ b/Sources/Batch/Defined.h @@ -23,15 +23,6 @@ } \ *error = nil; -// Enable IDFA related code -// Even though IDFA collection is based on AdSupport being linked to the app, -// some users might want to remove all IDFA references from the code. -// This is a quick hack until we properly move towards IDFA collection into a plugin. -// Note: this does NOT remove AppTrackingTransparency related code -#ifndef BATCH_ENABLE_IDFA -#define BATCH_ENABLE_IDFA 1 -#endif - // BAVersion, BALevel and BAMessagingLevel have moved into Version.h and have been renamed // Their values are not documented there because the Info.plist header parser is pretty dumb and will include comments // If you need to get the user facing BAVersion, use BACoreCenter.sdkVersion @@ -67,8 +58,7 @@ #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 kParametersIDsPatternValue @"s,da,did,cus,idfa,dla,dre,dtz,osv,de,apv,apc,bid,pl,lvl,mlvl,pid,plv,brv" #define kParametersAdvancedIDsPatternKey @"app.ids.pattern_advanced" #define kParametersAdvancedIDsPatternValue @"dty,sop" @@ -76,6 +66,8 @@ #define kParametersCustomUserIDKey @"app.id.custom" #define kParametersAppLanguageKey @"app.language" #define kParametersAppRegionKey @"app.region" +#define kParametersAttributionIDKey @"app.id.attribution" + #define kParametersAppProfileVersionKey @"app.profile.version" #define kParametersDateFormat @"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'" diff --git a/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h b/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h index 32859ce..2f81d13 100644 --- a/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h +++ b/Sources/Batch/Kernel/Helpers/BAPartialApplicationDelegate.h @@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)application:(UIApplication *)application - didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_AVAILABLE_IOS(8_0); + didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings; #pragma clang diagnostic pop diff --git a/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h b/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h index 13192de..6e72708 100644 --- a/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h +++ b/Sources/Batch/Kernel/Helpers/BATJsonDictionary.h @@ -24,14 +24,14 @@ NS_ASSUME_NONNULL_BEGIN 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)clazz 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)clazz fallback:(nullable id)fallback; /** Writes the specified error in the error pointer, and return nil. diff --git a/Sources/Batch/Kernel/Logger/BALogger.m b/Sources/Batch/Kernel/Logger/BALogger.m index 8d8c621..98af601 100644 --- a/Sources/Batch/Kernel/Logger/BALogger.m +++ b/Sources/Batch/Kernel/Logger/BALogger.m @@ -32,7 +32,7 @@ + (void)publicForDomain:(NSString *)name message:(NSString *)formatstring, ... { NSString *statement = [[NSString alloc] initWithFormat:formatstring arguments:arglist]; va_end(arglist); - [BALogger logMessage:statement domain:name internal:false]; + [BALogger logMessage:statement domain:name internal:false level:OS_LOG_TYPE_INFO]; } // Log the message using an error tag. @@ -43,7 +43,7 @@ + (void)errorForDomain:(NSString *)name message:(NSString *)formatstring, ... { NSString *statement = [[NSString alloc] initWithFormat:formatstring arguments:arglist]; va_end(arglist); - [BALogger logMessage:statement domain:name internal:true]; + [BALogger logMessage:statement domain:name internal:true level:OS_LOG_TYPE_FAULT]; } } @@ -55,7 +55,7 @@ + (void)warningForDomain:(NSString *)name message:(NSString *)formatstring, ... NSString *statement = [[NSString alloc] initWithFormat:formatstring arguments:arglist]; va_end(arglist); - [BALogger logMessage:statement domain:name internal:true]; + [BALogger logMessage:statement domain:name internal:true level:OS_LOG_TYPE_ERROR]; } } @@ -67,7 +67,7 @@ + (void)debugForDomain:(NSString *)name message:(NSString *)formatstring, ... { NSString *statement = [[NSString alloc] initWithFormat:formatstring arguments:arglist]; va_end(arglist); - [BALogger logMessage:statement domain:name internal:true]; + [BALogger logMessage:statement domain:name internal:true level:OS_LOG_TYPE_DEBUG]; } } @@ -139,7 +139,7 @@ + (void)setEnableInternalLogs:(BOOL)enableInternalLogs { } // Private method that do the NSLog(). -+ (void)logMessage:(NSString *)message domain:(NSString *)domain internal:(BOOL)internal { ++ (void)logMessage:(NSString *)message domain:(NSString *)domain internal:(BOOL)internal level:(os_log_type_t)level { if ([BANullHelper isNull:message] == YES) { return; } @@ -150,7 +150,7 @@ + (void)logMessage:(NSString *)message domain:(NSString *)domain internal:(BOOL) domain = [NSString stringWithFormat:@"%@ - ", domain]; } - [[BALogger sharedLogger] logMessage:message subsystem:domain internal:internal]; + [[BALogger sharedLogger] logMessage:message subsystem:domain internal:internal level:level]; [BALoggerDelegateSource.loggerDelegate logWithMessage:[NSString diff --git a/Sources/Batch/Kernel/Logger/BALoggerProtocol.h b/Sources/Batch/Kernel/Logger/BALoggerProtocol.h index 470342b..5e0eb8a 100644 --- a/Sources/Batch/Kernel/Logger/BALoggerProtocol.h +++ b/Sources/Batch/Kernel/Logger/BALoggerProtocol.h @@ -1,9 +1,13 @@ #import #import +#import @protocol BALoggerProtocol -- (void)logMessage:(NSString *)message subsystem:(NSString *)subsystem internal:(BOOL)internal; +- (void)logMessage:(NSString *)message + subsystem:(NSString *)subsystem + internal:(BOOL)internal + level:(os_log_type_t)level; @end diff --git a/Sources/Batch/Kernel/Logger/BALoggerUnified.m b/Sources/Batch/Kernel/Logger/BALoggerUnified.m index e12542c..2f05bea 100644 --- a/Sources/Batch/Kernel/Logger/BALoggerUnified.m +++ b/Sources/Batch/Kernel/Logger/BALoggerUnified.m @@ -19,7 +19,10 @@ - (instancetype)init { return self; } -- (void)logMessage:(NSString *)message subsystem:(NSString *)subsystem internal:(BOOL)internal { +- (void)logMessage:(NSString *)message + subsystem:(NSString *)subsystem + internal:(BOOL)internal + level:(os_log_type_t)level { if ((!internal && _coreLogObject == nil) || (internal && _internalLogObject == nil)) { NSLog(@"[%@] - %@%@", internal ? @"Batch-Internal" : @"Batch", subsystem, message); return; @@ -33,8 +36,16 @@ - (void)logMessage:(NSString *)message subsystem:(NSString *)subsystem internal: return; } - os_log(internal ? _internalLogObject : _coreLogObject, "%{public}s%{public}s", - [subsystem cStringUsingEncoding:NSUTF8StringEncoding], [message cStringUsingEncoding:NSUTF8StringEncoding]); + if (@available(iOS 17.0, *)) { + os_log_with_type(internal ? _internalLogObject : _coreLogObject, level, "%{public}s %{public}s%{public}s", + [internal ? @"[Batch-Internal]" : @"[Batch]" cStringUsingEncoding:NSUTF8StringEncoding], + [subsystem cStringUsingEncoding:NSUTF8StringEncoding], + [message cStringUsingEncoding:NSUTF8StringEncoding]); + } else { + os_log_with_type(internal ? _internalLogObject : _coreLogObject, level, "%{public}s%{public}s", + [subsystem cStringUsingEncoding:NSUTF8StringEncoding], + [message cStringUsingEncoding:NSUTF8StringEncoding]); + } } @end diff --git a/Sources/Batch/Kernel/Parameters/BAParameter.h b/Sources/Batch/Kernel/Parameters/BAParameter.h index 9f51a91..40f00e1 100644 --- a/Sources/Batch/Kernel/Parameters/BAParameter.h +++ b/Sources/Batch/Kernel/Parameters/BAParameter.h @@ -28,11 +28,11 @@ @method objectForKey:fallback: @abstract Return the value for the givent key, fallback otherwise. @param key : The key to get the value from. - @param class : The kind of class the result should be + @param clazz : The kind of class the result should be @param fallback : The fallback returned if anything goes wrong. @return the value if any and of the right class, fallback otherwise */ -+ (nullable id)objectForKey:(nonnull NSString *)key kindOfClass:(nonnull Class)class fallback:(nullable id)fallback; ++ (nullable id)objectForKey:(nonnull NSString *)key kindOfClass:(nonnull Class)clazz fallback:(nullable id)fallback; /*! @method setValue:forKey:saved: diff --git a/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.m b/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.m index c0c45e5..1966e2f 100644 --- a/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.m +++ b/Sources/Batch/Kernel/Parameters/BAPropertiesCenter.m @@ -17,7 +17,6 @@ #import #import #import -#import #import @@ -69,18 +68,13 @@ - (void)setupParameterMappings { @"di" : @"localInstallation", @"cus" : @"customIdentifier", @"tok" : @"pushToken", -#if BATCH_ENABLE_IDFA @"idfa" : @"attributionID", -#endif - @"attid_e" : @"isAttributionIdEnabled", - @"tath" : @"trackingAuthorizationStatus", @"dre" : @"deviceRegion", @"dla" : @"deviceLanguage", @"dtz" : @"deviceTimezone", @"are" : @"applicationRegion", @"ala" : @"applicationLanguage", @"da" : @"deviceDate", - @"ada" : @"appInstallDate", @"did" : @"sdkInstallDate", @"dty" : @"deviceType", @"osv" : @"deviceOSVersion", @@ -166,24 +160,8 @@ - (NSString *)pushToken { return nil; } -#if BATCH_ENABLE_IDFA - (NSString *)attributionID { - return [BACoreCenter instance].status.trackingAuthorization.attributionIdentifier.UUIDString; -} -#endif - -- (NSString *)isAttributionIdEnabled { -#if BATCH_ENABLE_IDFA - return @"1"; -#else - return @"0"; -#endif -} - -- (NSString *)trackingAuthorizationStatus { - BATrackingAuthorizationStatus status = - [BACoreCenter instance].status.trackingAuthorization.trackingAuthorizationStatus; - return [NSString stringWithFormat:@"%lu", (unsigned long)status]; + return [BAParameter objectForKey:kParametersAttributionIDKey fallback:nil]; } // MCC+MNC @@ -218,16 +196,6 @@ - (NSString *)deviceDate { return [self.dateFormatter stringFromDate:currentDate]; } -- (NSString *)appInstallDate { - NSDate *lastInstallDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:NSTemporaryDirectory() error:nil] - objectForKey:NSFileCreationDate]; - if (lastInstallDate == nil) { - return nil; - } - - return [self.dateFormatter stringFromDate:lastInstallDate]; -} - - (NSString *)sdkInstallDate { NSString *timestampString = [BAParameter objectForKey:kParametersLocalInstallDateIdentifierKey fallback:nil]; if (timestampString == nil) { diff --git a/Sources/Batch/Modules/Actions/BAActionsCenter.m b/Sources/Batch/Modules/Actions/BAActionsCenter.m index 503909f..085078b 100644 --- a/Sources/Batch/Modules/Actions/BAActionsCenter.m +++ b/Sources/Batch/Modules/Actions/BAActionsCenter.m @@ -296,9 +296,7 @@ - (BatchUserAction *)ratingAction { return; } } - if (@available(iOS 10.3, *)) { - [SKStoreReviewController requestReview]; - } + [SKStoreReviewController requestReview]; }]; } @@ -367,15 +365,11 @@ - (void)performGroupAction:(nonnull NSDictionary *)rawAr - (void)doSmartReoptin { [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) { - if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) { + if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined || + settings.authorizationStatus == UNAuthorizationStatusProvisional) { [BatchPush requestNotificationAuthorization]; } else if (settings.authorizationStatus == UNAuthorizationStatusDenied) { [[BAPushCenter instance] openSystemNotificationSettings]; - } else if (@available(iOS 12.0, *)) { - // Should be a || higher, but the @available macro does not allow that - if (settings.authorizationStatus == UNAuthorizationStatusProvisional) { - [BatchPush requestNotificationAuthorization]; - } } }]; } diff --git a/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h b/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h index dc7c725..b531652 100644 --- a/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h +++ b/Sources/Batch/Modules/Core/BACenterMulticastDelegate.h @@ -50,15 +50,6 @@ */ + (void)setCustomUserIdentifier:(NSString *)identifier; -/*! - @method setUseIDFA: - @abstract Set if Batch can try to use IDFA (default = YES) - @discussion Setting this to NO have a negative impact on offer delivery and restore. - @param use : YES if Batch can try to use the IDFA, NO if you don't want Batch to use the IDFA. - @warning You should only use it if you know what you are doing. - */ -+ (void)setUseIDFA:(BOOL)use; - /*! @method setUseAdvancedDeviceInformation: @abstract Set if Batch can try to use advanced device information (default = YES) diff --git a/Sources/Batch/Modules/Core/BACenterMulticastDelegate.m b/Sources/Batch/Modules/Core/BACenterMulticastDelegate.m index d8591ff..47af604 100644 --- a/Sources/Batch/Modules/Core/BACenterMulticastDelegate.m +++ b/Sources/Batch/Modules/Core/BACenterMulticastDelegate.m @@ -94,15 +94,6 @@ + (void)setCustomUserIdentifier:(NSString *)identifier { } } -// Set if Batch can try to use IDFA (default = YES) -+ (void)setUseIDFA:(BOOL)use { - for (id plugin in kPluginsList) { - if ([plugin respondsToSelector:@selector(setUseIDFA:)]) { - [plugin setUseIDFA:use]; - } - } -} - + (void)setUseAdvancedDeviceInformation:(BOOL)use { for (id plugin in kPluginsList) { if ([plugin respondsToSelector:@selector(setUseAdvancedDeviceInformation:)]) { diff --git a/Sources/Batch/Modules/Core/BAConfiguration.h b/Sources/Batch/Modules/Core/BAConfiguration.h index b35b287..7998d50 100644 --- a/Sources/Batch/Modules/Core/BAConfiguration.h +++ b/Sources/Batch/Modules/Core/BAConfiguration.h @@ -21,20 +21,6 @@ extern NSString *_Nonnull const kBATConfigurationChangedNotification; */ @interface BAConfiguration : NSObject -/*! - @method setUseIDFA: - @abstract Set the IDFA use condition. - @param useIDFA : YES to allow use of the IDFA, NO otherwise. - */ -- (void)setUseIDFA:(BOOL)useIDFA; - -/*! - @method useIDFA - @abstract Condition to use the IDFA. - @return YES if Batch can use the IDFA, NO otherwise. - */ -- (BOOL)useIDFA __attribute__((warn_unused_result)); - /*! @method setUseAdvancedDeviceInformation: @abstract Set the advanced device information use condition. diff --git a/Sources/Batch/Modules/Core/BAConfiguration.m b/Sources/Batch/Modules/Core/BAConfiguration.m index 9e1f842..6133957 100644 --- a/Sources/Batch/Modules/Core/BAConfiguration.m +++ b/Sources/Batch/Modules/Core/BAConfiguration.m @@ -22,9 +22,6 @@ @interface BAConfiguration () { // Application developper key. NSString *_developperKey; - // Use IDFA. - BOOL _idfa; - // Use advanced device information. BOOL _advancedDeviceInformation; @@ -45,9 +42,6 @@ - (instancetype)init { return nil; } - // Default use the IDFA. - _idfa = YES; - // We allow advanced device information (aka advenced identifiers) by default _advancedDeviceInformation = YES; @@ -57,17 +51,6 @@ - (instancetype)init { #pragma mark - #pragma mark Public methods -// Set the IDFA use condition. -- (void)setUseIDFA:(BOOL)useIDFA { - _idfa = useIDFA; - [[BANotificationCenter defaultCenter] postNotificationName:kBATConfigurationChangedNotification object:nil]; -} - -// Condition to use the IDFA. -- (BOOL)useIDFA { - return _idfa; -} - - (void)setUseAdvancedDeviceInformation:(BOOL)use { _advancedDeviceInformation = use; [[BANotificationCenter defaultCenter] postNotificationName:kBATConfigurationChangedNotification object:nil]; diff --git a/Sources/Batch/Modules/Core/BACoreCenter.h b/Sources/Batch/Modules/Core/BACoreCenter.h index f652570..e5c6f38 100644 --- a/Sources/Batch/Modules/Core/BACoreCenter.h +++ b/Sources/Batch/Modules/Core/BACoreCenter.h @@ -78,15 +78,6 @@ */ + (void)openURLWithUIApplication:(NSURL *)URL; -/*! - @method setUseIDFA: - @abstract Set if Batch can try to use IDFA (default = YES) - @discussion Setting this to NO have a negative impact on offer delivery and restore. - @param use : YES if Batch can try to use the IDFA, NO if you don't want Batch to use the IDFA. - @warning You should only use it if you know what you are doing. - */ -+ (void)setUseIDFA:(BOOL)use; - /*! @method setUseAdvancedDeviceInformation: @abstract Set if Batch can use advanced device identifiers (default = YES) @@ -99,9 +90,7 @@ 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. + @param use : YES if Batch can try to use advanced device information, NO if you don't want to */ + (void)setUseAdvancedDeviceInformation:(BOOL)use; diff --git a/Sources/Batch/Modules/Core/BACoreCenter.m b/Sources/Batch/Modules/Core/BACoreCenter.m index 3b28c3d..c01b2eb 100644 --- a/Sources/Batch/Modules/Core/BACoreCenter.m +++ b/Sources/Batch/Modules/Core/BACoreCenter.m @@ -96,10 +96,6 @@ + (BOOL)isRunningInDevelopmentMode { return [[BACoreCenter instance] executeIsDevelopmentMode]; } -+ (void)setUseIDFA:(BOOL)use { - [[BACoreCenter instance] setUseIDFA:use]; -} - + (void)setUseAdvancedDeviceInformation:(BOOL)use { [[BACoreCenter instance] setUseAdvancedDeviceInformation:use]; } @@ -356,11 +352,6 @@ - (BOOL)executeIsDevelopmentMode { return [self.configuration developmentMode]; } -// Set if Batch can try to use IDFA (default = YES) -- (void)setUseIDFA:(BOOL)use { - [self.configuration setUseIDFA:use]; -} - - (void)setUseAdvancedDeviceInformation:(BOOL)use { [self.configuration setUseAdvancedDeviceInformation:use]; } diff --git a/Sources/Batch/Modules/Core/BANotificationAuthorization.m b/Sources/Batch/Modules/Core/BANotificationAuthorization.m index 46bee5a..8ad8bd2 100644 --- a/Sources/Batch/Modules/Core/BANotificationAuthorization.m +++ b/Sources/Batch/Modules/Core/BANotificationAuthorization.m @@ -106,8 +106,7 @@ - (void)fetch:(void (^_Nullable)(BANotificationAuthorizationSettings *_Nonnull)) [self fetchUN:completionHandler]; } -- (void)fetchUN:(void (^_Nullable)(BANotificationAuthorizationSettings *_Nonnull))completionHandler - NS_AVAILABLE_IOS(10.0) { +- (void)fetchUN:(void (^_Nullable)(BANotificationAuthorizationSettings *_Nonnull))completionHandler { [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) { BANotificationAuthorizationSettings *baSettings = [BANotificationAuthorizationSettings new]; diff --git a/Sources/Batch/Modules/Core/BAStatus.m b/Sources/Batch/Modules/Core/BAStatus.m index 4e8814a..758dbdd 100644 --- a/Sources/Batch/Modules/Core/BAStatus.m +++ b/Sources/Batch/Modules/Core/BAStatus.m @@ -14,7 +14,6 @@ #import #import #import -#import @implementation BAStatus { // Initialization. @@ -48,8 +47,6 @@ - (NSError *)initialization { _notificationAuthorization = [BANotificationAuthorization new]; - _trackingAuthorization = [BATrackingAuthorization new]; - _installationIdHelper = [BADBGFindMyInstallationHelper new]; return nil; diff --git a/Sources/Batch/Modules/Core/BATrackingAuthorization.h b/Sources/Batch/Modules/Core/BATrackingAuthorization.h deleted file mode 100644 index 281a8e8..0000000 --- a/Sources/Batch/Modules/Core/BATrackingAuthorization.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// BATrackingAuthorization.h -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -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 - 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; - -- (void)settingsMayHaveChanged; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Batch/Modules/Core/BATrackingAuthorization.m b/Sources/Batch/Modules/Core/BATrackingAuthorization.m deleted file mode 100644 index e702ff4..0000000 --- a/Sources/Batch/Modules/Core/BATrackingAuthorization.m +++ /dev/null @@ -1,200 +0,0 @@ -// -// BATrackingAuthorization.m -// Batch -// -// Copyright © Batch.com. All rights reserved. -// - -#import "BATrackingAuthorization.h" - -#import -#import -#import -#import - -#if !TARGET_OS_MACCATALYST -#import -#endif - -@implementation BATrackingAuthorization { - NSUUID *_zeroUUID; - NSUUID *_previousTrackingId; - BATrackingAuthorizationStatus _previousAuthorizationStatus; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _zeroUUID = [[NSUUID alloc] initWithUUIDBytes:(uuid_t){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}]; - - _previousTrackingId = [self attributionIdentifier]; - _previousAuthorizationStatus = [self trackingAuthorizationStatus]; - - [[BANotificationCenter defaultCenter] addObserver:self - selector:@selector(settingsMayHaveChanged) - name:kBATConfigurationChangedNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationDidBecomeActive) - name:UIApplicationDidBecomeActiveNotification - object:nil]; - } - return self; -} - -- (void)applicationDidBecomeActive { - [self settingsMayHaveChanged]; -} - -- (void)settingsMayHaveChanged { - NSUUID *newTrackingId = [self attributionIdentifier]; - BATrackingAuthorizationStatus newAuthorizationStatus = [self trackingAuthorizationStatus]; - if (_previousAuthorizationStatus != newAuthorizationStatus || ![self uuidMatchesPrevious:newTrackingId]) { - _previousTrackingId = newTrackingId; - _previousAuthorizationStatus = newAuthorizationStatus; - [self trackingStatusChanged]; - } -} - -- (void)trackingStatusChanged { - [BATrackerCenter trackPrivateEvent:@"_TRACKING_STATUS_CHANGE" - parameters:[self statusDictionaryRepresentation] - collapsable:true]; -} - -- (BOOL)uuidMatchesPrevious:(NSUUID *)newUUID { - if (newUUID == _previousTrackingId) { - // Handles nil - return true; - } - return [_previousTrackingId isEqual:newUUID]; -} - -// This method returns the IDFA, except if: -// - It's disabled in the config -// - the UUID is zeroed out -// - We don't compile support for it -- (NSUUID *)attributionIdentifier { -#if BATCH_ENABLE_IDFA - - if (![[BACoreCenter instance].configuration useIDFA]) { - return nil; - } - -#if !TARGET_OS_MACCATALYST - if (@available(iOS 14.5, *)) { - if (ATTrackingManager.trackingAuthorizationStatus != ATTrackingManagerAuthorizationStatusAuthorized) { - [BALogger debugForDomain:@"TAth" message:@"Skipping attribution identifier, disallowed by ATT."]; - return nil; - } - } -#endif - - SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@Id%@", @"advertising", @"entifier"]); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - Class class = NSClassFromString([NSString stringWithFormat:@"%@Ma%@", @"ASIdentifier", @"nager"]); - if (class != nil) { - if ([class respondsToSelector:NSSelectorFromString(@"sharedManager")] == YES) { - id manager = [class performSelector:NSSelectorFromString(@"sharedManager")]; - if (manager != nil) { - if ([manager respondsToSelector:selector] == YES) { - NSUUID *uuid = [manager performSelector:selector]; - // Filter out iOS 10+'s zeroed uuid in case of limited ad tracking - if ([uuid isEqual:_zeroUUID]) { - return nil; - } - return uuid; - } - } - } - } -#pragma clang diagnostic pop - - return nil; - -#else - - return nil; - -#endif -} - -- (nonnull NSDictionary *)statusDictionaryRepresentation { - id attributionID = [[self attributionIdentifier] UUIDString]; - if (attributionID == nil) { - attributionID = [NSNull null]; - } - return @{@"attid" : attributionID, @"tath" : @([self trackingAuthorizationStatus])}; -} - -- (BATrackingAuthorizationStatus)trackingAuthorizationStatus { - // Even if Batch has no IDFA support compiled in, returning the tracking status - // has some use cases, so do not remove support for it - - if (![[BACoreCenter instance].configuration useIDFA]) { - return BATrackingAuthorizationStatusForbiddenByBatchConfig; - } - -#if !TARGET_OS_MACCATALYST - if (@available(iOS 14.0, *)) { - switch (ATTrackingManager.trackingAuthorizationStatus) { - case ATTrackingManagerAuthorizationStatusNotDetermined: - return BATrackingAuthorizationStatusNotDetermined; - case ATTrackingManagerAuthorizationStatusDenied: - return BATrackingAuthorizationStatusDenied; - case ATTrackingManagerAuthorizationStatusAuthorized: - return BATrackingAuthorizationStatusAuthorized; - case ATTrackingManagerAuthorizationStatusRestricted: - return BATrackingAuthorizationStatusRestricted; - default: - return BATrackingAuthorizationStatusUnknown; - } - } -#endif - - return [self legacyAuthorizationStatus]; -} - -- (BATrackingAuthorizationStatus)legacyAuthorizationStatus { -#if BATCH_ENABLE_IDFA - - // This always returns false on iOS 14+, don't use this method on this OS. - SEL selector = NSSelectorFromString(@"isAdvertisingTrackingEnabled"); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - Class class = NSClassFromString([NSString stringWithFormat:@"%@Ma%@", @"ASIdentifier", @"nager"]); - if (class != nil) { - if ([class respondsToSelector:NSSelectorFromString(@"sharedManager")] == YES) { - id manager = [class performSelector:NSSelectorFromString(@"sharedManager")]; - if (manager != nil) { - if ([manager respondsToSelector:selector] == YES) { - NSInvocation *invocation = [NSInvocation - invocationWithMethodSignature:[class instanceMethodSignatureForSelector:selector]]; - [invocation setSelector:selector]; - [invocation setTarget:manager]; - [invocation invoke]; - BOOL isTrackingEnabled = false; - [invocation getReturnValue:&isTrackingEnabled]; - return isTrackingEnabled ? BATrackingAuthorizationStatusAuthorized - : BATrackingAuthorizationStatusDenied; - } - } - } - } -#pragma clang diagnostic pop - - return BATrackingAuthorizationStatusAuthorized; - -#else - - // If we didn't compile IDFA support, return Unknown: we do not want to invoke ASIdentifierManager at all - // but we do not want to always return "denied" either - - return BATrackingAuthorizationStatusUnknown; -#endif -} - -@end diff --git a/Sources/Batch/Modules/Core/BAUserProfile.h b/Sources/Batch/Modules/Core/BAUserProfile.h index 7d3e29f..bcb30d9 100644 --- a/Sources/Batch/Modules/Core/BAUserProfile.h +++ b/Sources/Batch/Modules/Core/BAUserProfile.h @@ -43,6 +43,13 @@ */ @property (strong, nonatomic, nullable) NSString *region; +/*! + @property attributionID + @abstract The user attribution identifier. + @discussion Set to nil to reset the setting. + */ +@property (strong, nonatomic, nullable) NSString *attributionID; + /*! @method defaultUserProfile @abstract Access the default user profile object. @@ -64,4 +71,6 @@ */ - (void)incrementVersion; +- (void)sendAttributionIDChangedEvent; + @end diff --git a/Sources/Batch/Modules/Core/BAUserProfile.m b/Sources/Batch/Modules/Core/BAUserProfile.m index e9abe8e..52c7694 100644 --- a/Sources/Batch/Modules/Core/BAUserProfile.m +++ b/Sources/Batch/Modules/Core/BAUserProfile.m @@ -89,6 +89,12 @@ - (void)incrementVersion { } } +- (void)sendAttributionIDChangedEvent { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + params[@"attribution_id"] = self.attributionID != nil ? self.attributionID : [NSNull null]; + [BATrackerCenter trackPrivateEvent:@"_ATTRIBUTION_ID_CHANGED" parameters:params]; +} + #pragma mark - #pragma mark Properties override methods @@ -142,6 +148,21 @@ - (void)setRegion:(NSString *)region { } } +/*** Attribution Identifier ***/ + +- (NSString *)attributionID { + return [BAParameter objectForKey:kParametersAttributionIDKey fallback:nil]; +} + +- (void)setAttributionID:(NSString *)attributionID { + NSError *error = [self updateValue:attributionID forKey:kParametersAttributionIDKey]; + + if (error != nil) { + [BALogger errorForDomain:@"UserProfile" + message:@"Error changing the attribution identifier: %@", [error localizedDescription]]; + } +} + #pragma mark - #pragma mark NSCoding archive methods @@ -168,5 +189,4 @@ - (id)initWithCoder:(NSCoder *)decoder { return self; } - @end diff --git a/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h b/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h index 67b6c75..4f70e32 100644 --- a/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h +++ b/Sources/Batch/Modules/Messaging/GIF/BATGIFFile.h @@ -12,7 +12,7 @@ typedef NS_ENUM(NSInteger, BATGIFError) { Cache sizes. Note that an extra frame will be held at all times : the current frame. Meaning that if you have a cache size of 2, 3 frames will be held in memory at all times. */ -typedef NS_ENUM(NSUInteger, BATGIFCacheSize) { +typedef NS_ENUM(NSInteger, BATGIFCacheSize) { BATGIFCacheSizeUndefined = -1, BATGIFCacheSizeNoCache = 0, BATGIFCacheSizeNormal = 10, diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.m b/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.m index 339a612..da5fa50 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.m +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGBaseBannerViewController.m @@ -486,14 +486,7 @@ - (void)applyAbsolutePositionmentRulesForView:(id)view NSLayoutAttribute matchingAlignAttr = alignAttr; id alignView; if (marginUseSafeArea != 0) { - if (@available(iOS 11.0, *)) { - alignView = parentView.safeAreaLayoutGuide; - } else if (alignAttr == NSLayoutAttributeTop) { - alignView = self.topLayoutGuide; - matchingAlignAttr = NSLayoutAttributeBottom; - } else { - alignView = parentView; - } + alignView = parentView.safeAreaLayoutGuide; } else { alignView = parentView; } @@ -742,14 +735,7 @@ - (void)applyMainContainerViewRules { NSLayoutAttribute matchingAlignAttr = alignAttr; id edgeAlignView; if (alignAttrPadding != 0) { - if (@available(iOS 11.0, *)) { - edgeAlignView = parentView.safeAreaLayoutGuide; - } else if (alignAttr == NSLayoutAttributeTop) { - edgeAlignView = self.topLayoutGuide; - matchingAlignAttr = NSLayoutAttributeBottom; - } else { - edgeAlignView = parentView; - } + edgeAlignView = parentView.safeAreaLayoutGuide; } else { edgeAlignView = parentView; } @@ -790,23 +776,21 @@ - (void)applyMainContainerViewRules { // previous versions of the SDK that already applied the margin after the safe area if (hAlignAttr == NSLayoutAttributeCenterX) { if (margin.left != 0 && margin.right != 0) { - if (@available(iOS 11.0, *)) { - [constraints addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeLeft - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:parentView.safeAreaLayoutGuide - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:margin.left]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:innerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:parentView.safeAreaLayoutGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:margin.left]]; - [constraints addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeRight - relatedBy:NSLayoutRelationLessThanOrEqual - toItem:parentView.safeAreaLayoutGuide - attribute:NSLayoutAttributeRight - multiplier:1.0 - constant:-margin.right]]; - } + [constraints addObject:[NSLayoutConstraint constraintWithItem:innerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:parentView.safeAreaLayoutGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-margin.right]]; } [constraints addObject:[NSLayoutConstraint constraintWithItem:innerView @@ -827,11 +811,7 @@ - (void)applyMainContainerViewRules { id hEdgeAlignView; if (hAlignAttrPadding != 0) { - if (@available(iOS 11.0, *)) { - hEdgeAlignView = parentView.safeAreaLayoutGuide; - } else { - hEdgeAlignView = parentView; - } + hEdgeAlignView = parentView.safeAreaLayoutGuide; } else { hEdgeAlignView = parentView; } @@ -912,65 +892,44 @@ - (void)applyContainerViewRulesForNode:(BACSSDOMNode *)node views:NSDictionaryOfVariableBindings(innerView)]]; if (useSafeArea) { - if (@available(iOS 11.0, *)) { - UILayoutGuide *safeGuide = parentView.safeAreaLayoutGuide; - NSMutableArray *safeLayoutConstraints = [NSMutableArray new]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:usePaddingForSafeArea ? padding.top : 0]]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:usePaddingForSafeArea ? -padding.bottom : 0]]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeLeft - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:usePaddingForSafeArea ? padding.left : 0]]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeRight - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeRight - multiplier:1.0 - constant:usePaddingForSafeArea ? -padding.right : 0]]; - for (NSLayoutConstraint *c in safeLayoutConstraints) { - c.priority = 1000; - } - [NSLayoutConstraint activateConstraints:safeLayoutConstraints]; - } else if (shouldUseTopGuide) { - // topLayoutGuide is only allowed if: - // - shouldUseTopGuide is true - // - useSafeArea is true - // shouldUseTopGuide is a hint given by the caller, since only the view highest on the screen should use - // that as the topLayoutGuide depends on the view controller. The safe area guide is WAY better, as it works - // in every view no matter where they are on the screen, so the burden of figuring that out is not on us. - // It's complex and hardly maintainable, but this whole class is like that anyway, so enjoy changing that - // and be sure you test on iOS 8,9,10,11. Yes, all of them :) - NSLayoutConstraint *topGuideConstraint = - [NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:self.topLayoutGuide - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:usePaddingForSafeArea ? padding.top : 0]; - topGuideConstraint.priority = 1000; - [NSLayoutConstraint activateConstraints:@[ topGuideConstraint ]]; + UILayoutGuide *safeGuide = parentView.safeAreaLayoutGuide; + NSMutableArray *safeLayoutConstraints = [NSMutableArray new]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint constraintWithItem:innerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:usePaddingForSafeArea ? padding.top : 0]]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint constraintWithItem:innerView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:usePaddingForSafeArea ? -padding.bottom : 0]]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint constraintWithItem:innerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:usePaddingForSafeArea ? padding.left : 0]]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint constraintWithItem:innerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:usePaddingForSafeArea ? -padding.right : 0]]; + for (NSLayoutConstraint *c in safeLayoutConstraints) { + c.priority = 1000; } + [NSLayoutConstraint activateConstraints:safeLayoutConstraints]; } [NSLayoutConstraint activateConstraints:constraints]; diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.m b/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.m index f11e117..f020718 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.m +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGImageViewController.m @@ -36,7 +36,7 @@ @interface BAMSGImageViewController () *safeLayoutConstraints = [NSMutableArray new]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeTop - relatedBy:fitToSafeArea ? NSLayoutRelationEqual - : NSLayoutRelationGreaterThanOrEqual - toItem:safeGuide - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:usePaddingForSafeArea ? padding.top : 0]]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint - constraintWithItem:innerView - attribute:NSLayoutAttributeBottom - relatedBy:fitToSafeArea ? NSLayoutRelationEqual : NSLayoutRelationLessThanOrEqual - toItem:safeGuide - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:usePaddingForSafeArea ? -padding.bottom : 0]]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint constraintWithItem:innerView - attribute:NSLayoutAttributeLeft - relatedBy:fitToSafeArea ? NSLayoutRelationEqual - : NSLayoutRelationGreaterThanOrEqual - toItem:safeGuide - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:usePaddingForSafeArea ? padding.left : 0]]; - [safeLayoutConstraints - addObject:[NSLayoutConstraint - constraintWithItem:innerView - attribute:NSLayoutAttributeRight - relatedBy:fitToSafeArea ? NSLayoutRelationEqual : NSLayoutRelationLessThanOrEqual - toItem:safeGuide - attribute:NSLayoutAttributeRight - multiplier:1.0 - constant:usePaddingForSafeArea ? -padding.right : 0]]; - for (NSLayoutConstraint *c in safeLayoutConstraints) { - c.priority = safeAreaPriority; - } - [NSLayoutConstraint activateConstraints:safeLayoutConstraints]; - addedSafeAreaConstraints = YES; + UILayoutGuide *safeGuide = parentView.safeAreaLayoutGuide; + NSMutableArray *safeLayoutConstraints = [NSMutableArray new]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint + constraintWithItem:innerView + attribute:NSLayoutAttributeTop + relatedBy:fitToSafeArea ? NSLayoutRelationEqual : NSLayoutRelationGreaterThanOrEqual + toItem:safeGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:usePaddingForSafeArea ? padding.top : 0]]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint + constraintWithItem:innerView + attribute:NSLayoutAttributeBottom + relatedBy:fitToSafeArea ? NSLayoutRelationEqual : NSLayoutRelationLessThanOrEqual + toItem:safeGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:usePaddingForSafeArea ? -padding.bottom : 0]]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint + constraintWithItem:innerView + attribute:NSLayoutAttributeLeft + relatedBy:fitToSafeArea ? NSLayoutRelationEqual : NSLayoutRelationGreaterThanOrEqual + toItem:safeGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:usePaddingForSafeArea ? padding.left : 0]]; + [safeLayoutConstraints + addObject:[NSLayoutConstraint + constraintWithItem:innerView + attribute:NSLayoutAttributeRight + relatedBy:fitToSafeArea ? NSLayoutRelationEqual : NSLayoutRelationLessThanOrEqual + toItem:safeGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:usePaddingForSafeArea ? -padding.right : 0]]; + for (NSLayoutConstraint *c in safeLayoutConstraints) { + c.priority = safeAreaPriority; } + [NSLayoutConstraint activateConstraints:safeLayoutConstraints]; + addedSafeAreaConstraints = YES; } if (wantsHeightFilled) { @@ -733,9 +729,7 @@ - (void)applyContainerViewRulesForNode:(BACSSDOMNode *)node id hAlignView = parentView; if (useSafeArea) { - if (@available(iOS 11.0, *)) { - hAlignView = parentView.safeAreaLayoutGuide; - } + hAlignView = parentView.safeAreaLayoutGuide; } NSLayoutConstraint *c = [NSLayoutConstraint constraintWithItem:innerView diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h b/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h index 25e111e..9dc567a 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGStackViewItem.h @@ -7,8 +7,7 @@ #import #import - -@import UIKit; +#import @interface BAMSGStackViewItem : NSObject diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h b/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h index 84911e8..f60e726 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGVideoView.h @@ -5,8 +5,8 @@ // Copyright © 2016 Batch. All rights reserved. // -@import Foundation; -@import UIKit; +#import +#import #import diff --git a/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.m b/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.m index 8de5d3c..4d3a128 100644 --- a/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.m +++ b/Sources/Batch/Modules/Messaging/UI/BAMSGWebviewViewController.m @@ -79,10 +79,11 @@ - (void)viewDidLoad { CGRect windowFrame = [BAWindowHelper keyWindow].frame; _webView = [[WKWebView alloc] initWithFrame:windowFrame configuration:[self webViewConfiguration]]; - // Back up the original value in case Apple changes it in an iOS release - if (@available(iOS 11.0, *)) { - _originalWebViewScrollBehaviour = _webView.scrollView.contentInsetAdjustmentBehavior; + if (@available(iOS 16.4, *)) { + _webView.inspectable = true; } + // Back up the original value in case Apple changes it in an iOS release + _originalWebViewScrollBehaviour = _webView.scrollView.contentInsetAdjustmentBehavior; _webView.clipsToBounds = YES; [_webView setOpaque:NO]; _webView.backgroundColor = [UIColor clearColor]; @@ -305,42 +306,33 @@ - (void)nativelyApplyViewport { // - Parse viewport-fit // - Apply the viewport-fit value natively on the scrollview // (Note that at this point: maybe implement a way of toggling which workaround we want to try?) - // - // On iOS 10, we must revert to the older workaround - - if (@available(iOS 11.0, *)) { - __weak BAMSGWebviewViewController *weakSelf = self; - - NSString *viewportExtractionJavascript = - @"document.querySelector('meta[name=\"viewport\"]').getAttribute(\"content\")"; - [_webView - evaluateJavaScript:viewportExtractionJavascript - completionHandler:^(id _Nullable result, NSError *_Nullable error) { - BOOL isViewportCover = false; - if ([result isKindOfClass:NSString.class]) { - NSString *stringResult = (NSString *)result; - if ([stringResult rangeOfString:@"viewport-fit=cover" options:NSCaseInsensitiveSearch].location != - NSNotFound) { - isViewportCover = true; - } - } - - [BALogger debugForDomain:@"WebView" message:@"Viewport-fit is cover: %i", isViewportCover]; - - BAMSGWebviewViewController *strongSelf = weakSelf; - if (strongSelf != nil) { - strongSelf->_webView.scrollView.contentInsetAdjustmentBehavior = - isViewportCover ? UIScrollViewContentInsetAdjustmentNever - : strongSelf->_originalWebViewScrollBehaviour; - [strongSelf->_webView setAlpha:1]; - [strongSelf->_webView setNeedsLayout]; - } - }]; - } else { - [self scheduleWebViewRelayouts]; - [_webView setAlpha:1]; - [_webView setNeedsLayout]; - } + + __weak BAMSGWebviewViewController *weakSelf = self; + + NSString *viewportExtractionJavascript = + @"document.querySelector('meta[name=\"viewport\"]').getAttribute(\"content\")"; + [_webView evaluateJavaScript:viewportExtractionJavascript + completionHandler:^(id _Nullable result, NSError *_Nullable error) { + BOOL isViewportCover = false; + if ([result isKindOfClass:NSString.class]) { + NSString *stringResult = (NSString *)result; + if ([stringResult rangeOfString:@"viewport-fit=cover" options:NSCaseInsensitiveSearch].location != + NSNotFound) { + isViewportCover = true; + } + } + + [BALogger debugForDomain:@"WebView" message:@"Viewport-fit is cover: %i", isViewportCover]; + + BAMSGWebviewViewController *strongSelf = weakSelf; + if (strongSelf != nil) { + strongSelf->_webView.scrollView.contentInsetAdjustmentBehavior = + isViewportCover ? UIScrollViewContentInsetAdjustmentNever + : strongSelf->_originalWebViewScrollBehaviour; + [strongSelf->_webView setAlpha:1]; + [strongSelf->_webView setNeedsLayout]; + } + }]; } - (void)setupWebviewSettings { diff --git a/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.m b/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.m index deb3897..3963a8f 100644 --- a/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.m +++ b/Sources/Batch/Modules/Messaging/Webview/BATWebviewJavascriptBridge.m @@ -157,11 +157,7 @@ This method does all of the heavy lifting (argument checking, error handling): j // Method that facilitates testing the attribution ID handling - (nullable NSString *)readAttributionIDFromSDK { -#if BATCH_ENABLE_IDFA return [BAPropertiesCenter valueForShortName:@"idfa"]; -#else - return nil; -#endif } - (BAPromise *)attributionID { @@ -169,9 +165,7 @@ - (nullable NSString *)readAttributionIDFromSDK { // TODO: Wall this behind a compilation flag NSString *identifier = [self readAttributionIDFromSDK]; if ([BANullHelper isStringEmpty:identifier]) { - [promise - reject:[self makePublicError:@"Not available: User denied permission to use it, application cannot use it " - @"due to missing framework or it was disabled in Batch's configuration."]]; + [promise reject:[self makePublicError:@"No attribution identifier found."]]; } else { [promise resolve:identifier]; } diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.m b/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.m index e7db2af..fc4bede 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.m +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGImageView.m @@ -111,9 +111,7 @@ - (void)setup { borderRadius = 0; _roundedCorners = UIRectCornerAllCorners; - if (@available(iOS 11.0, *)) { - [self setAccessibilityIgnoresInvertColors:YES]; - } + [self setAccessibilityIgnoresInvertColors:YES]; } - (void)setImage:(UIImage *)image { diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.m b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.m index 9ee6143..cb76ede 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.m +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGPannableAlertContainerView.m @@ -24,7 +24,7 @@ @implementation BAMSGPannableAlertContainerView { // Gesture recognizer state dependent variable BOOL _shouldDismiss; - UIImpactFeedbackGenerator *_hapticFeedbackGenerator NS_AVAILABLE_IOS(10_0); + UIImpactFeedbackGenerator *_hapticFeedbackGenerator; CGPoint _linkedViewInitialOffset; CGFloat _initialAlpha; CGFloat _linkedViewInitialAlpha; diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h b/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h index 91d1147..7ea442c 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGStylableView.h @@ -7,8 +7,7 @@ #import #import - -@import UIKit; +#import @protocol BAMSGStylableView diff --git a/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.m b/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.m index e784392..c6da59e 100644 --- a/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.m +++ b/Sources/Batch/Modules/Messaging/Widgets/BAMSGViewToolbox.m @@ -21,44 +21,42 @@ + (void)setView:(UIView *)view fullframeToSuperview:(UIView *)superview useSafeA // as we can't only rely on useSafeArea BOOL addedSafeAreaConstraints = false; - if (@available(iOS 11, *)) { - if (useSafeArea) { - addedSafeAreaConstraints = true; - UILayoutGuide *safeGuide = superview.safeAreaLayoutGuide; - NSMutableArray *safeLayoutConstraints = [NSMutableArray new]; - [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:0]]; + if (useSafeArea) { + addedSafeAreaConstraints = true; + UILayoutGuide *safeGuide = superview.safeAreaLayoutGuide; + NSMutableArray *safeLayoutConstraints = [NSMutableArray new]; + [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0]]; - [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:0]]; + [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0]]; - [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view - attribute:NSLayoutAttributeLeft - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:0]]; + [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0]]; - [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view - attribute:NSLayoutAttributeRight - relatedBy:NSLayoutRelationEqual - toItem:safeGuide - attribute:NSLayoutAttributeRight - multiplier:1.0 - constant:0]]; - [NSLayoutConstraint activateConstraints:safeLayoutConstraints]; - } + [safeLayoutConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:safeGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0]]; + [NSLayoutConstraint activateConstraints:safeLayoutConstraints]; } if (!addedSafeAreaConstraints) { @@ -84,12 +82,10 @@ + (CGSize)sceneSize { } else { return [UIWindow new].bounds.size; } - } else if (@available(iOS 9, *)) { + } else { // On iOS 9, iPads support split screen, so init a UIWindow, which will have the split's size, and read it // iOS 8 would have a 0 sized UIWindow return [UIWindow new].bounds.size; - } else { - return [UIScreen mainScreen].bounds.size; } } diff --git a/Sources/Batch/Modules/Opt Out/BAOptOut.m b/Sources/Batch/Modules/Opt Out/BAOptOut.m index 505872f..044ae60 100644 --- a/Sources/Batch/Modules/Opt Out/BAOptOut.m +++ b/Sources/Batch/Modules/Opt Out/BAOptOut.m @@ -151,12 +151,9 @@ - (NSMutableDictionary *)makeBaseEventData { NSMutableDictionary *data = [NSMutableDictionary new]; data[@"di"] = [[BAPropertiesCenter valueForShortName:@"di"] uppercaseString]; -#if BATCH_ENABLE_IDFA data[@"idfa"] = [BAPropertiesCenter valueForShortName:@"idfa"]; -#endif data[@"cus"] = [BAPropertiesCenter valueForShortName:@"cus"]; data[@"tok"] = [BAPropertiesCenter valueForShortName:@"tok"]; - return data; } diff --git a/Sources/Batch/Modules/Push/BAPushCenter.h b/Sources/Batch/Modules/Push/BAPushCenter.h index 18e69b8..95a559d 100644 --- a/Sources/Batch/Modules/Push/BAPushCenter.h +++ b/Sources/Batch/Modules/Push/BAPushCenter.h @@ -144,7 +144,7 @@ extern NSString *const kBATPushOpenedNotificationOriginatesFromAppDelegate; @abstract Get Batch Push's deeplink from a notification's userInfo. @return Batch's Deeplink, or nil if not found. */ -+ (NSString *)deeplinkFromUserInfo:(NSDictionary *)userData NS_AVAILABLE_IOS(8_0); ++ (NSString *)deeplinkFromUserInfo:(NSDictionary *)userData; /*! @method disableAutomaticIntegration @@ -207,7 +207,7 @@ extern NSString *const kBATPushOpenedNotificationOriginatesFromAppDelegate; */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -+ (void)handleRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_AVAILABLE_IOS(8_0); ++ (void)handleRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings; #pragma clang diagnostic pop /** @@ -221,7 +221,7 @@ extern NSString *const kBATPushOpenedNotificationOriginatesFromAppDelegate; */ + (void)handleUserNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification - willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert NS_AVAILABLE_IOS(10_0); + willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert; /** Make Batch process a background notification open/action. You should call this method if you set your own @@ -231,7 +231,7 @@ extern NSString *const kBATPushOpenedNotificationOriginatesFromAppDelegate; @param response Original response argument */ + (void)handleUserNotificationCenter:(UNUserNotificationCenter *)center - didReceiveNotificationResponse:(UNNotificationResponse *)response NS_AVAILABLE_IOS(10_0); + didReceiveNotificationResponse:(UNNotificationResponse *)response; /** Make Batch process a notification payload diff --git a/Sources/Batch/Modules/Push/BAPushCenter.m b/Sources/Batch/Modules/Push/BAPushCenter.m index 0c6eec7..41a95d5 100644 --- a/Sources/Batch/Modules/Push/BAPushCenter.m +++ b/Sources/Batch/Modules/Push/BAPushCenter.m @@ -597,7 +597,7 @@ - (void)handleRegisterUserNotificationSettings:(UIUserNotificationSettings *)not + (void)handleUserNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification - willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert NS_AVAILABLE_IOS(10_0); + willShowSystemForegroundAlert:(BOOL)willShowSystemForegroundAlert; { if ([[BAOptOut instance] isOptedOut]) { [BALogger debugForDomain:@"Push" @@ -675,7 +675,7 @@ - (void)application:(UIApplication *)application #pragma clang diagnostic ignored "-Wdeprecated-implementations" #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)application:(UIApplication *)application - didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_AVAILABLE_IOS(8_0) + didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings #pragma clang diagnostic pop { [self internalHandleRegisterUserNotificationSettings:notificationSettings]; diff --git a/Sources/Batch/Modules/Push/BAPushSystemHelper.m b/Sources/Batch/Modules/Push/BAPushSystemHelper.m index 0734cc0..cf01402 100644 --- a/Sources/Batch/Modules/Push/BAPushSystemHelper.m +++ b/Sources/Batch/Modules/Push/BAPushSystemHelper.m @@ -22,9 +22,7 @@ - (void)registerForRemoteNotificationsTypes:(BatchNotificationType)notifType UNAuthorizationOptions options = [self systemOptionsForBatchTypes:notifType]; if (providesSettings) { - if (@available(iOS 12.0, *)) { - options |= UNAuthorizationOptionProvidesAppNotificationSettings; - } + options |= UNAuthorizationOptionProvidesAppNotificationSettings; } [self requestAuthorization:options]; @@ -32,17 +30,15 @@ - (void)registerForRemoteNotificationsTypes:(BatchNotificationType)notifType - (void)registerForProvisionalNotifications:(BatchNotificationType)notifType providesNotificationSettings:(BOOL)providesSettings { - if (@available(iOS 12.0, *)) { - UNAuthorizationOptions options = [self systemOptionsForBatchTypes:notifType]; - - options |= UNAuthorizationOptionProvisional; + UNAuthorizationOptions options = [self systemOptionsForBatchTypes:notifType]; - if (providesSettings) { - options |= UNAuthorizationOptionProvidesAppNotificationSettings; - } + options |= UNAuthorizationOptionProvisional; - [self requestAuthorization:options]; + if (providesSettings) { + options |= UNAuthorizationOptionProvidesAppNotificationSettings; } + + [self requestAuthorization:options]; } - (void)registerCategories:(NSSet *)categories { @@ -95,9 +91,7 @@ - (UNAuthorizationOptions)systemOptionsForBatchTypes:(BatchNotificationType)batc retOptions |= UNAuthorizationOptionCarPlay; } if (batchTypes & BatchNotificationTypeCritical) { - if (@available(iOS 12.0, *)) { - retOptions |= UNAuthorizationOptionCriticalAlert; - } + retOptions |= UNAuthorizationOptionCriticalAlert; } return retOptions; diff --git a/Sources/Batch/Modules/Tracker/BATrackerCenter.m b/Sources/Batch/Modules/Tracker/BATrackerCenter.m index 65c5a45..c162608 100644 --- a/Sources/Batch/Modules/Tracker/BATrackerCenter.m +++ b/Sources/Batch/Modules/Tracker/BATrackerCenter.m @@ -137,10 +137,7 @@ - (instancetype)init { _flushing = NO; _started = NO; _optOutModule = [BAOptOut instance]; - - if (@available(iOS 12.0, *)) { - _signpostHelper = [BATrackerSignpostHelper new]; - } + _signpostHelper = [BATrackerSignpostHelper new]; return self; } diff --git a/Sources/Batch/Modules/User/BAUserDataEditor.h b/Sources/Batch/Modules/User/BAUserDataEditor.h index 5230a34..186539b 100644 --- a/Sources/Batch/Modules/User/BAUserDataEditor.h +++ b/Sources/Batch/Modules/User/BAUserDataEditor.h @@ -17,6 +17,8 @@ - (void)setIdentifier:(nullable NSString *)identifier; +- (void)setAttributionIdentifier:(nullable NSString *)attributionID; + - (BOOL)setEmail:(nullable NSString *)email error:(NSError *_Nullable *_Nullable)error; - (void)setEmailMarketingSubscriptionState:(BatchEmailSubscriptionState)state; diff --git a/Sources/Batch/Modules/User/BAUserDataEditor.m b/Sources/Batch/Modules/User/BAUserDataEditor.m index f32ca48..da0b28e 100644 --- a/Sources/Batch/Modules/User/BAUserDataEditor.m +++ b/Sources/Batch/Modules/User/BAUserDataEditor.m @@ -136,7 +136,7 @@ - (void)setIdentifier:(nullable NSString *)identifier { if (![BANullHelper isNull:identifier] && [identifier isKindOfClass:[NSString class]] && [identifier length] > 1024) { [BALogger publicForDomain:PUBLIC_DOMAIN - message:@"setIdentifier called with identifier region (must be less 1024 chars)"]; + message:@"setIdentifier called with invalid identifier (must be less 1024 chars)"]; return; } @@ -144,6 +144,27 @@ - (void)setIdentifier:(nullable NSString *)identifier { _userFields[IDENTIFIER_INDEX] = identifier; } +- (void)setAttributionIdentifier:(nullable NSString *)attributionID { + if (![BANullHelper isNull:attributionID] && [attributionID isKindOfClass:[NSString class]] && + [[NSUUID alloc] initWithUUIDString:attributionID] == nil) { + [BALogger + publicForDomain:PUBLIC_DOMAIN + message: + @"setAttributionIdentifier called with invalid attribution identifier (must be a valid UUID)"]; + return; + } + + [self addfirstToQueueSynchronized:^BOOL { + BAUserProfile *userProfile = [BAUserProfile defaultUserProfile]; + NSString *oldAttributionID = userProfile.attributionID; + userProfile.attributionID = attributionID; + if (![oldAttributionID isEqualToString:attributionID]) { + [userProfile sendAttributionIDChangedEvent]; + } + return YES; + }]; +} + - (BOOL)setEmail:(nullable NSString *)email error:(NSError **)error { INIT_AND_BLANK_ERROR_IF_NEEDED(error) @@ -584,6 +605,12 @@ - (void)addToQueueSynchronized:(BOOL (^)(void))operationBlock { } } +- (void)addfirstToQueueSynchronized:(BOOL (^)(void))operationBlock { + @synchronized(_operationQueue) { + [_operationQueue insertObject:operationBlock atIndex:0]; + } +} + - (BOOL (^)(void))userUpdateOperation { if (!_updatedFields[LANGUAGE_INDEX] && !_updatedFields[REGION_INDEX] && !_updatedFields[IDENTIFIER_INDEX]) { // Nothing to do diff --git a/Sources/Batch/PrivacyInfo.xcprivacy b/Sources/Batch/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..0cbee57 --- /dev/null +++ b/Sources/Batch/PrivacyInfo.xcprivacy @@ -0,0 +1,82 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeUserID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeProductInteraction + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + NSPrivacyCollectedDataTypePurposeAppFunctionality + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + NSPrivacyCollectedDataTypePurposeProductPersonalization + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeOtherDataTypes + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + NSPrivacyCollectedDataTypePurposeProductPersonalization + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + 1C8F.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + + diff --git a/Sources/Batch/PrivateUmbrellaHeader.h b/Sources/Batch/PrivateUmbrellaHeader.h index 53b84d8..5d7f202 100644 --- a/Sources/Batch/PrivateUmbrellaHeader.h +++ b/Sources/Batch/PrivateUmbrellaHeader.h @@ -99,7 +99,6 @@ #import #import #import -#import #import #import #import diff --git a/Sources/Batch/Versions.h b/Sources/Batch/Versions.h index 8526d73..6dfa8c1 100644 --- a/Sources/Batch/Versions.h +++ b/Sources/Batch/Versions.h @@ -11,6 +11,6 @@ Comments should not use the // form, as the plist preprocessor will include them */ -#define BASDKVersion 1.20.0 -#define BAAPILevel 61 +#define BASDKVersion 1.21.0 +#define BAAPILevel 70 #define BAMessagingAPILevel 12 diff --git a/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h b/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h index 43839fc..a818d99 100644 --- a/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h +++ b/Sources/Batch/Webservices/Query/BAQueryWebserviceClientDelegate.h @@ -13,10 +13,10 @@ NS_ASSUME_NONNULL_BEGIN @protocol BAQueryWebserviceClientDelegate -@required - - (void)webserviceClientWillStart:(BAQueryWebserviceClient *)client; +@required + - (void)webserviceClient:(BAQueryWebserviceClient *)client didFailWithError:(NSError *)error; - (void)webserviceClient:(BAQueryWebserviceClient *)client diff --git a/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.m b/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.m index 9b76292..efc9274 100644 --- a/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.m +++ b/Sources/Batch/Webservices/Query/BAStandardQueryWebserviceIdentifiersProvider.m @@ -53,12 +53,6 @@ + (instancetype)sharedInstance { [idsToFetch addObjectsFromArray:advancedIds]; } - // As of 1.17, "idfa" isn't hardcoded in the pattern anymore - // Add it to the list of IDs to be fetched if we have compile-time support for it -#if BATCH_ENABLE_IDFA - [idsToFetch addObject:@"idfa"]; -#endif - // Add references. for (NSString *idName in idsToFetch) { if (![BANullHelper isStringEmpty:idName]) { diff --git a/Sources/batchTests/Kernel/Crypto/batchAESTests.m b/Sources/batchTests/Kernel/Crypto/batchAESTests.m index b18ba12..b61039d 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]; @@ -112,7 +113,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."); diff --git a/Sources/batchTests/Modules/Core/batchUserProfileTests.m b/Sources/batchTests/Modules/Core/batchUserProfileTests.m index dfce189..afa17f0 100644 --- a/Sources/batchTests/Modules/Core/batchUserProfileTests.m +++ b/Sources/batchTests/Modules/Core/batchUserProfileTests.m @@ -138,6 +138,18 @@ - (void)testBasics { [profile setRegion:nil]; region = [profile region]; XCTAssertNil(region, @"Region not nil."); + + NSString *attributionID = [profile attributionID]; + XCTAssertNil(attributionID, @"Attribution identifier not nil: %@.", attributionID); + + [profile setAttributionID:@"batch.attribution.id"]; + attributionID = [profile attributionID]; + XCTAssertNotNil(attributionID, @"Failed to get the attribution identifier."); + XCTAssertTrue([@"batch.attribution.id" isEqualToString:attributionID], @"Attribution identifier not stored."); + + [profile setAttributionID:nil]; + attributionID = [profile attributionID]; + XCTAssertNil(attributionID, @"Attribution identifier not nil."); } - (void)testVersion { diff --git a/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m b/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m index d77c90f..d1d33e4 100644 --- a/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m +++ b/Sources/batchTests/Modules/User/batchUserEditorPublicAPITests.m @@ -26,6 +26,7 @@ - (void)testPublicMethods { [editor setLanguage:@"fr"]; [editor setRegion:@"fr"]; [editor setIdentifier:@"foo"]; + [editor setAttributionIdentifier:@"EA7583CD-A667-48BC-B806-42ECB2B48606"]; [editor setEmail:@"test@batch.com" error:nil]; [editor setEmailMarketingSubscriptionState:BatchEmailSubscriptionStateSubscribed]; [editor setAttribute:@"foo" forKey:@"bar"]; @@ -49,6 +50,7 @@ - (void)testPublicMethods { OCMVerify([mockBackingEditor setLanguage:@"fr"]); OCMVerify([mockBackingEditor setRegion:@"fr"]); OCMVerify([mockBackingEditor setIdentifier:@"foo"]); + OCMVerify([mockBackingEditor setAttributionIdentifier:@"EA7583CD-A667-48BC-B806-42ECB2B48606"]); OCMVerify([mockBackingEditor setEmail:@"test@batch.com" error:nil]); OCMVerify([mockBackingEditor setEmailMarketingSubscriptionState:BatchEmailSubscriptionStateSubscribed]); OCMVerify([mockBackingEditor setAttribute:@"foo" forKey:@"bar"]); diff --git a/Sources/batchTests/Modules/User/batchUserTests.m b/Sources/batchTests/Modules/User/batchUserTests.m index aaa7ea1..34fa76f 100644 --- a/Sources/batchTests/Modules/User/batchUserTests.m +++ b/Sources/batchTests/Modules/User/batchUserTests.m @@ -26,11 +26,17 @@ @interface BAParameter () - (instancetype)initWithSuiteName:(NSString *_Nullable)suiteName; @end -@implementation batchUserTests +@implementation batchUserTests { + id trackerCenterMock; +} - (void)setUp { [super setUp]; + // Mock tracker center + trackerCenterMock = OCMClassMock([BATrackerCenter class]); + OCMStub([trackerCenterMock instance]).andReturn(trackerCenterMock); + // Mock data source to set a test specific database BAUserSQLiteDatasource *dataSourceToUse = [[BAUserSQLiteDatasource alloc] initWithDatabaseName:@"test-attribute-read"]; @@ -52,7 +58,7 @@ - (void)setUp { - (void)tearDown { [super tearDown]; - + [trackerCenterMock stopMocking]; self.datasourceOverlay = nil; } @@ -254,4 +260,47 @@ - (void)testCustomDataLimits { XCTAssertNil([BatchUser identifier]); } +- (void)testAttributionIDChangedEvent { + // Ensure event is not sent when attribution id is not a valid UUID + XCTestExpectation *exp1 = [self expectationWithDescription:@"Wait for editor stacking operations"]; + [_editor setAttributionIdentifier:@"WRONG-UUID"]; + OCMReject([trackerCenterMock trackPrivateEvent:@"_ATTRIBUTION_ID_CHANGED" + parameters:@{@"attribution_id" : @"WRONG-UUID"}]); + [_editor save:^{ + [exp1 fulfill]; + }]; + [self waitForExpectations:@[ exp1 ] timeout:3.0]; + + // Ensure event is sent when attribution id is a valid UUID + XCTestExpectation *exp2 = [self expectationWithDescription:@"Wait for editor stacking operations"]; + [_editor setAttributionIdentifier:@"EA7583CD-A667-48BC-B806-42ECB2B48606"]; + OCMExpect([trackerCenterMock trackPrivateEvent:@"_ATTRIBUTION_ID_CHANGED" + parameters:@{@"attribution_id" : @"EA7583CD-A667-48BC-B806-42ECB2B48606"}]); + [_editor save:^{ + [exp2 fulfill]; + }]; + [self waitForExpectations:@[ exp2 ] timeout:3.0]; + + // Ensure event is not sent when attribution id did not changed + [_editor setAttributionIdentifier:@"EA7583CD-A667-48BC-B806-42ECB2B48606"]; + OCMReject([trackerCenterMock trackPrivateEvent:@"_ATTRIBUTION_ID_CHANGED" + parameters:@{@"attribution_id" : @"EA7583CD-A667-48BC-B806-42ECB2B48606"}]); + XCTestExpectation *exp3 = [self expectationWithDescription:@"Wait for editor stacking operations"]; + [_editor save:^{ + [exp3 fulfill]; + }]; + [self waitForExpectations:@[ exp3 ] timeout:3.0]; + + // Ensure event is sent when attribution id is nil (reset) + XCTestExpectation *exp4 = [self expectationWithDescription:@"Wait for editor stacking operations"]; + [_editor setAttributionIdentifier:nil]; + OCMExpect([trackerCenterMock trackPrivateEvent:@"_ATTRIBUTION_ID_CHANGED" + parameters:@{@"attribution_id" : [NSNull null]}]); + [_editor save:^{ + [exp4 fulfill]; + }]; + [self waitForExpectations:@[ exp4 ] timeout:3.0]; + OCMVerifyAll(trackerCenterMock); +} + @end diff --git a/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m b/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m index adbb044..3816034 100644 --- a/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m +++ b/Sources/batchTests/Webservices/Crypto/webserviceAESGCMCryptorTests.m @@ -52,7 +52,8 @@ - (void)testEncryptDecryptV1 { XCTAssertNotNil(cryptor); NSData *expectedData = [@"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" - @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]" + @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[" + @"]" @"唄ック金型илджفيحةحديد" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertNotNil(expectedData); @@ -68,7 +69,8 @@ - (void)testEncryptDecryptV2 { XCTAssertNotNil(cryptor); NSData *expectedData = [@"!&é\"'(§è!çà)-12567890°_%^$mù`=*/" - @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[]" + @".,?,;:=‘{«ÇøÇø}—둶ǡ@#|¿¡ïŒ€£µ~©®†™≈<>≤≥êÊ•π‡∂ƒÌ¬◊ß∞÷≠+∫√¢‰∆∑Ω¥∏ªŸ[" + @"]" @"唄ック金型илджفيحةحديد" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertNotNil(expectedData); diff --git a/Tools/Scripts/gen_objc_api_from_objc_framework.sh b/Tools/Scripts/gen_objc_api_from_objc_framework.sh new file mode 100644 index 0000000..96ff3eb --- /dev/null +++ b/Tools/Scripts/gen_objc_api_from_objc_framework.sh @@ -0,0 +1,191 @@ +# +# https://github.com/ChrisMash/PublicAPIMonitoringExample +# +# Generates the ObjC API from the specified ObjCnframework and places it in the specified directory +# with the filename _objc_api.txt +# +# NOTE: Should be run with bash rather than sh due to usage of echo -e. +# +# Parameters: +# - The name of the framework file (with extension) +# - The path to the framework file +# - The directory/Users/arnaud.r/Sources/temps/PublicAPIMonitoringExample/Scripts/gen_objc_api_from_objc_framework.sh to output the file to +# +# Example: bash gen_objc_api_from_objc_framework.sh ObjC_Framework.framework ./ ./api +# + +# +# Will echo out the first subdirectory found that contains a .framework in it, +# under the specified search path +# Example: findFirstFrameworkSubDirectory "folder1/folder2" +# +findFirstFrameworkSubDirectory() { + SEARCH_PATH=$1 + for ENTRY in "${SEARCH_PATH}"/*; do + for SUB_ENTRY in "${ENTRY}"/*; do + if [[ $SUB_ENTRY == *.framework ]]; then + echo $SUB_ENTRY + return 0 + fi + done + done + + exit 1 +} + +# +# Will echo out the first subdirectory found that contains a .framework in it, +# with the specified subdirectory, under the specified search path +# Example: findFirstFrameworkFolder "Headers" "folder1/folder2" +# +findFirstFrameworkFolder() { + DESIRED_SUBDIR=$1 + SEARCH_DIR=$2 + + if [[ $SEARCH_DIR == *.xcframework* ]]; then + # .xcframeworks contain multiple .framework folders, each with a Headers folder + echo "$(findFirstFrameworkSubDirectory $SEARCH_DIR)/${DESIRED_SUBDIR}" + elif [[ $SEARCH_DIR == *.framework* ]]; then + # .frameworks have the Headers folder directly inside + echo "${SEARCH_DIR}/${DESIRED_SUBDIR}" + else + echo "Error: Expected to be looking in a .framework or .xcframework" + exit 1 + fi + + return 0 +} + +STARTTIME=$(date +%s) +FRAMEWORK_NAME_WEXT=$1 +FRAMEWORK_DIR=$2 +OUTPUT_DIR=$3 + +# Strip off the extension to get the framework name +FRAMEWORK_NAME="${FRAMEWORK_NAME_WEXT%.*}" +# Generate the path to the framework header +HEADERS_PATH=$(findFirstFrameworkFolder "Headers" "${FRAMEWORK_DIR}/${FRAMEWORK_NAME_WEXT}") +FW_HEADER_PATH="${HEADERS_PATH}/${FRAMEWORK_NAME}.h" + +API="" +IN_COMMENT_BLOCK=false +SCANNED_HEADERS=() + +scanHeader() { + HEADER_PATH=$1 + # If we've not scanned this header yet + if ! [[ " ${SCANNED_HEADERS[@]} " =~ " ${HEADER_PATH} " ]]; then + #echo "Scanning: ${HEADER_PATH}" + SCANNED_HEADERS+=($HEADER_PATH) + + addToAPI $HEADER_PATH + scanChildHeaders $HEADER_PATH +# else +# echo "Skipping (already scanned): ${HEADER_PATH}" + fi +} + +SL_COMMENT_PATTERN="//*" +ML_COMMENT_START_PATTERN="\/\**" +ML_COMMENT_END_PATTERN="\*\/*" + +isNotCommentLine() { + [[ $1 != $SL_COMMENT_PATTERN + && $1 != $ML_COMMENT_START_PATTERN + && $1 != $ML_COMMENT_END_PATTERN ]] + return +} + +addToAPI() { + HEADER_PATH=$1 + HEADER=$(cat ${HEADER_PATH}) + + # Add relevant lines to the API + while IFS= read -r line; do + # Trim any whitespace + TRIMMED_LINE=$(echo "${line}" | tr -d '[:space:]') + # If it's length is greater than 0 + if [ ${#TRIMMED_LINE} -gt 0 ]; then + # If it isn't a comment + if isNotCommentLine "${TRIMMED_LINE}"; then + # If we're not in a multi-line comment block + if ! $IN_COMMENT_BLOCK; then + # If it isn't a NS_ (don't care about these, e.g. NS_ASSUME_NONNULL_BEGIN) + if [[ $TRIMMED_LINE != NS_* ]]; then + # If it isn't a # (e.g. #import, #include etc.) + if [[ $TRIMMED_LINE != \#* ]]; then + # If it isn't a @; (e.g. forward declaration such as @class X; or @protocol Y;. Or a @import) + if [[ $TRIMMED_LINE != @class*\; + && $TRIMMED_LINE != @protocol*\; + && $TRIMMED_LINE != @import*\; ]]; then + # Add it to the API + API="${API}\n${line}" +# else +# echo "Skipped @;: ${line}" + fi +# else +# echo "Skipped #: ${line}" + fi +# else +# echo "Skipped NS_: ${line}" + fi +# else +# echo "Skipped comment: ${line}" + fi + else + #echo "Skipped comment: ${line}" + # Skipped a comment, check if we're in a multi-line comment block or not + if [[ $TRIMMED_LINE != $SL_COMMENT_PATTERN + && $TRIMMED_LINE == $ML_COMMENT_START_PATTERN ]]; then + IN_COMMENT_BLOCK=true + elif [[ $TRIMMED_LINE == $ML_COMMENT_END_PATTERN ]]; then + IN_COMMENT_BLOCK=false + fi + fi + fi + done <<< "$HEADER" +} + +scanChildHeaders() { + HEADER_PATH=$1 + # Find all the lines that import/include another header + IMPORTS=$(grep "^#\(import\|include\).*$" ${HEADER_PATH}) + #echo "Imports:\n${IMPORTS}" + # If we found any imports (length of string greater than 0) + if [ ${#IMPORTS} -gt 0 ]; then + # For each one + while IFS= read -r line; do + # Remove the '#import " prefix (or include) + LINE_WITHOUT_PREFIX=${line#"#import "} + LINE_WITHOUT_PREFIX=${LINE_WITHOUT_PREFIX#"#include "} + # Determine whether it's angle brackets or quotations around the header path + if [[ $LINE_WITHOUT_PREFIX == \<* ]]; then + # Skip over irrelevant imports that aren't for the framework in questions + if [[ $LINE_WITHOUT_PREFIX != "<${FRAMEWORK_NAME}"* ]]; then + continue + fi + # Remove the '' suffix + CHILD_HEADER=${CHILD_HEADER%>} + else + # Remove the '"' prefix + CHILD_HEADER=${LINE_WITHOUT_PREFIX#\"} + # Remove the '"' suffix + CHILD_HEADER=${CHILD_HEADER%\"} + fi + # Generate the path to the header + CHILD_HEADER_PATH="${HEADERS_PATH}/${CHILD_HEADER}" + # Scan it + scanHeader $CHILD_HEADER_PATH + done <<< "$IMPORTS" + fi +} + +# Scan the framework header and the headers it includes +scanHeader ${FW_HEADER_PATH} +# Output the public API to a file +echo -e "${API}" > "${OUTPUT_DIR}/${FRAMEWORK_NAME}_objc_api.txt" + +ENDTIME=$(date +%s) +echo "Executed in ~$(($ENDTIME - $STARTTIME))s" diff --git a/Tools/Scripts/strip_public_swift_framework.sh b/Tools/Scripts/strip_public_swift_framework.sh index dc5adb7..d2209f8 100755 --- a/Tools/Scripts/strip_public_swift_framework.sh +++ b/Tools/Scripts/strip_public_swift_framework.sh @@ -11,16 +11,16 @@ ## 6/ It removes the Batch.Swift module ## 1/ -rm Headers/Batch-Swift.h +rm Headers/Batch-Swift.h 2>/dev/null ## 2/ -rm -r PrivateHeaders +rm -r PrivateHeaders 2>/dev/null ## 3/ -rm -r _CodeSignature +rm -r _CodeSignature 2>/dev/null ## 4/ -rm -r Modules/Batch.swiftmodule +rm -r Modules/Batch.swiftmodule 2>/dev/null ## 5/ perl -pi -000 -e "s/\\/\\/#start-remove-prod.*#end-remove-prod//s" Modules/module.modulemap