From f9a63141e98010287dfbaf231198cfa79bd06381 Mon Sep 17 00:00:00 2001 From: Frank Schmitt Date: Tue, 15 Sep 2020 17:03:20 -0700 Subject: [PATCH] Apptentive IOS SDK 5.3.0 --- .../Apptentive.xcodeproj/project.pbxproj | 30 +- .../xcschemes/Apptentive.xcscheme | 11 +- .../xcschemes/ApptentiveDebugging.xcscheme | 6 +- Apptentive/Apptentive/Apptentive.h | 965 +----------------- Apptentive/Apptentive/Apptentive.m | 66 +- Apptentive/Apptentive/Apptentive.storyboard | 46 +- Apptentive/Apptentive/ApptentiveMain.h | 957 +++++++++++++++++ Apptentive/Apptentive/ApptentiveStyleSheet.m | 2 +- Apptentive/Apptentive/Apptentive_Private.h | 2 +- .../ApptentiveUnreadMessagesBadgeView.m | 2 +- ...veInteractionAppleRatingDialogController.m | 13 +- .../Engagement/Model/ApptentiveConversation.h | 2 +- .../Engagement/Model/ApptentiveSDK.m | 2 +- Apptentive/Apptentive/Info.plist | 2 +- .../ApptentiveMessageCenterViewModel.m | 2 +- Apptentive/Apptentive/Misc/ApptentiveLog.h | 2 +- .../Apptentive/Misc/ApptentiveLogMonitor.m | 22 +- .../Apptentive/Misc/ApptentiveURLOpener.m | 12 +- .../Requests & Payloads/ApptentiveRequest.m | 2 +- .../ApptentiveSurveyCollectionViewLayout.m | 16 +- .../ApptentiveSurveyViewController.m | 28 +- .../ApptentiveSurveyViewModel.m | 2 +- .../Views/ApptentiveSurveyCollectionView.h | 1 + .../Views/ApptentiveSurveyCollectionView.m | 28 - .../Views/ApptentiveSurveyGreetingView.m | 10 - .../ApptentiveTests/ApptentiveConnectTests.m | 2 +- .../ApptentiveTests/ApptentiveMetricsTests.m | 2 +- .../ApptentiveStyleSheetTests.m | 2 +- .../ApptentiveTests-Bridging-Header.h | 2 +- .../CodePointAndInteractionTests.m | 2 +- Apptentive/ApptentiveTests/CriteriaTests.m | 2 +- Apptentive/ApptentiveTests/Info.plist | 2 +- CHANGELOG.md | 12 + Example/Example.xcodeproj/project.pbxproj | 24 +- .../xcschemes/iOSExample.xcscheme | 15 +- Example/Podfile.lock | 8 +- Example/iOSExample/AppDelegate.swift | 4 +- Example/iOSExample/PictureManager.swift | 2 +- Example/podfile | 2 +- apptentive-ios.podspec | 6 +- 40 files changed, 1160 insertions(+), 1158 deletions(-) create mode 100644 Apptentive/Apptentive/ApptentiveMain.h diff --git a/Apptentive/Apptentive.xcodeproj/project.pbxproj b/Apptentive/Apptentive.xcodeproj/project.pbxproj index 0d6d967d8..607e0b45f 100644 --- a/Apptentive/Apptentive.xcodeproj/project.pbxproj +++ b/Apptentive/Apptentive.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 01201AD31FC637BE00EB3593 /* CodePointAndInteractionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 01201AD21FC637BD00EB3593 /* CodePointAndInteractionTests.m */; }; 01216C501EBBB53E0062BD0D /* RequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01216C4F1EBBB53E0062BD0D /* RequestTests.swift */; }; 0123005F20531698000EC3C3 /* ClauseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0123005E20531698000EC3C3 /* ClauseTests.m */; }; + 012B96C325118349008A56CC /* Apptentive.h in Headers */ = {isa = PBXBuildFile; fileRef = 012B96C22511832D008A56CC /* Apptentive.h */; }; 012ED9292072F33F003D87F3 /* ApptentiveRetryPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 012ED9272072F33F003D87F3 /* ApptentiveRetryPolicy.h */; }; 012ED92A2072F33F003D87F3 /* ApptentiveRetryPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012ED9282072F33F003D87F3 /* ApptentiveRetryPolicy.m */; }; 012ED92C2072FABE003D87F3 /* RetryPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012ED92B2072FABE003D87F3 /* RetryPolicyTests.swift */; }; @@ -97,7 +98,7 @@ 018FAFF01FC4B21A007C52FE /* ApptentiveComparisonClause.m in Sources */ = {isa = PBXBuildFile; fileRef = 018FAFEE1FC4B21A007C52FE /* ApptentiveComparisonClause.m */; }; 01917D451E5E0B7400B37D82 /* ConversationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01917D441E5E0B7400B37D82 /* ConversationManagerTests.swift */; }; 01A2CF9B1E49062800C2103A /* Apptentive.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01A2CF911E49062700C2103A /* Apptentive.framework */; }; - 01A2CFA21E49062800C2103A /* Apptentive.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A2CF941E49062700C2103A /* Apptentive.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 01A2CFA21E49062800C2103A /* ApptentiveMain.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A2CF941E49062700C2103A /* ApptentiveMain.h */; settings = {ATTRIBUTES = (Public, ); }; }; 01A2D0F81E490A9700C2103A /* Apptentive_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A2CFAB1E490A9600C2103A /* Apptentive_Private.h */; }; 01A2D0F91E490A9700C2103A /* Apptentive.m in Sources */ = {isa = PBXBuildFile; fileRef = 01A2CFAC1E490A9700C2103A /* Apptentive.m */; }; 01A2D0FA1E490A9700C2103A /* Apptentive.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 01A2CFAD1E490A9700C2103A /* Apptentive.storyboard */; }; @@ -462,6 +463,7 @@ 01201AD21FC637BD00EB3593 /* CodePointAndInteractionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePointAndInteractionTests.m; sourceTree = ""; }; 01216C4F1EBBB53E0062BD0D /* RequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestTests.swift; sourceTree = ""; }; 0123005E20531698000EC3C3 /* ClauseTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ClauseTests.m; sourceTree = ""; }; + 012B96C22511832D008A56CC /* Apptentive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Apptentive.h; sourceTree = ""; }; 012ED9272072F33F003D87F3 /* ApptentiveRetryPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApptentiveRetryPolicy.h; sourceTree = ""; }; 012ED9282072F33F003D87F3 /* ApptentiveRetryPolicy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ApptentiveRetryPolicy.m; sourceTree = ""; }; 012ED92B2072FABE003D87F3 /* RetryPolicyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetryPolicyTests.swift; sourceTree = ""; }; @@ -540,7 +542,7 @@ 01917D431E5E0B7400B37D82 /* ApptentiveTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ApptentiveTests-Bridging-Header.h"; sourceTree = ""; }; 01917D441E5E0B7400B37D82 /* ConversationManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConversationManagerTests.swift; sourceTree = ""; }; 01A2CF911E49062700C2103A /* Apptentive.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Apptentive.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 01A2CF941E49062700C2103A /* Apptentive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Apptentive.h; sourceTree = ""; }; + 01A2CF941E49062700C2103A /* ApptentiveMain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApptentiveMain.h; sourceTree = ""; }; 01A2CF951E49062700C2103A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 01A2CF9A1E49062800C2103A /* ApptentiveTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ApptentiveTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 01A2CFA11E49062800C2103A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -1002,6 +1004,7 @@ 01A2CF921E49062700C2103A /* Products */, ); sourceTree = ""; + usesTabs = 1; }; 01A2CF921E49062700C2103A /* Products */ = { isa = PBXGroup; @@ -1015,6 +1018,7 @@ 01A2CF931E49062700C2103A /* Apptentive */ = { isa = PBXGroup; children = ( + 012B96C22511832D008A56CC /* Apptentive.h */, 0168B1AC24AAAFD1006EEF65 /* DebugLogging.cer */, EF3FE88720A226EE00A3C9C5 /* Apptimize */, 01A2CFB01E490A9700C2103A /* Custom Views */, @@ -1028,7 +1032,7 @@ 01A2D0CD1E490A9700C2103A /* Reachability */, 01A2D0D01E490A9700C2103A /* Surveys */, 01A2D0441E490A9700C2103A /* localization */, - 01A2CF941E49062700C2103A /* Apptentive.h */, + 01A2CF941E49062700C2103A /* ApptentiveMain.h */, 01A2CFAC1E490A9700C2103A /* Apptentive.m */, 01A2CFAD1E490A9700C2103A /* Apptentive.storyboard */, 01A2CFAE1E490A9700C2103A /* ApptentiveStyleSheet.h */, @@ -1806,7 +1810,7 @@ EF3063A91F2A8353004B4EB9 /* ApptentivePayloadDebug.h in Headers */, 01F1DFFC1E5BBFCB009AB3D2 /* ApptentiveConversationMetadataItem.h in Headers */, 01A2D1FA1E490A9700C2103A /* ApptentiveSurveyQuestionView.h in Headers */, - 01A2CFA21E49062800C2103A /* Apptentive.h in Headers */, + 01A2CFA21E49062800C2103A /* ApptentiveMain.h in Headers */, 01A2D18E1E490A9700C2103A /* ApptentiveMessageCenterContextMessageCell.h in Headers */, 01A2D1B41E490A9700C2103A /* ApptentiveLegacySurveyResponse.h in Headers */, 4D4B36241F01892A005C7EC0 /* ApptentiveEngagementBackend.h in Headers */, @@ -1833,6 +1837,7 @@ 01A2D1D01E490A9700C2103A /* ApptentiveSerialRequest.h in Headers */, 01A2D1D61E490A9700C2103A /* ApptentiveBackend.h in Headers */, 01A2D1411E490A9700C2103A /* ApptentiveVersion.h in Headers */, + 012B96C325118349008A56CC /* Apptentive.h in Headers */, EF49AC941EF2C50B00E2187F /* NSMutableData+Types.h in Headers */, 01A2D1271E490A9700C2103A /* ApptentiveEngagement.h in Headers */, 014508B11EAE5F71003326E7 /* ApptentiveClient.h in Headers */, @@ -1973,7 +1978,8 @@ 01A2CF881E49062700C2103A /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0930; + LastSwiftUpdateCheck = 1200; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Apptentive, Inc."; TargetAttributes = { 01A2CF901E49062700C2103A = { @@ -2402,6 +2408,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -2409,7 +2416,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 43; + CURRENT_PROJECT_VERSION = 45; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -2423,7 +2430,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; @@ -2460,6 +2467,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -2467,7 +2475,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 43; + CURRENT_PROJECT_VERSION = 45; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -2479,7 +2487,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; SDKROOT = iphoneos; @@ -2499,7 +2507,7 @@ DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 86WML2UN43; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 43; + DYLIB_CURRENT_VERSION = 45; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Apptentive/Misc/ApptentiveConnect-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = "APPTENTIVE_DEBUG=1"; @@ -2519,7 +2527,7 @@ DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 86WML2UN43; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 43; + DYLIB_CURRENT_VERSION = 45; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Apptentive/Misc/ApptentiveConnect-Prefix.pch"; INFOPLIST_FILE = Apptentive/Info.plist; diff --git a/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/Apptentive.xcscheme b/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/Apptentive.xcscheme index 7b000bf5b..f1e85f8c5 100644 --- a/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/Apptentive.xcscheme +++ b/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/Apptentive.xcscheme @@ -1,6 +1,6 @@ - - - - diff --git a/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/ApptentiveDebugging.xcscheme b/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/ApptentiveDebugging.xcscheme index 7e5174d31..a9641d847 100644 --- a/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/ApptentiveDebugging.xcscheme +++ b/Apptentive/Apptentive.xcodeproj/xcshareddata/xcschemes/ApptentiveDebugging.xcscheme @@ -1,6 +1,6 @@ - - - - -#import +#ifndef Apptentive_h +#define Apptentive_h -NS_ASSUME_NONNULL_BEGIN - -//! Project version number for Apptentive. -/** The Apptentive version number */ -FOUNDATION_EXPORT double ApptentiveVersionNumber; - -//! Project version string for Apptentive. -/** The Apptentive version string */ -FOUNDATION_EXPORT const unsigned char ApptentiveVersionString[]; - -/** The version number of the Apptentive SDK. */ -#define kApptentiveVersionString @"5.2.14" - -/** The version number of the Apptentive API platform. */ -#define kApptentiveAPIVersionString @"9" - -/** The platform that the SDK is built for. */ -#define kApptentivePlatformString @"iOS" - -/** - A code corresponding to the reason that the Apptentive server authentication failed. - */ -typedef NS_ENUM(NSInteger, ApptentiveAuthenticationFailureReason) { - /** An unknown authentication failure. */ - ApptentiveAuthenticationFailureReasonUnknown, - /** An invalid JWT algorithm was used. */ - ApptentiveAuthenticationFailureReasonInvalidAlgorithm, - /** A malformed JWT was encountered. */ - ApptentiveAuthenticationFailureReasonMalformedToken, - /** An invalid JWT was encountered. */ - ApptentiveAuthenticationFailureReasonInvalidToken, - /** A required subclaim was missing. */ - ApptentiveAuthenticationFailureReasonMissingSubClaim, - /** A subclaim didn't match the logged-in session. */ - ApptentiveAuthenticationFailureReasonMismatchedSubClaim, - /** An invalid subclaim was encountered. */ - ApptentiveAuthenticationFailureReasonInvalidSubClaim, - /** The JWT expired. */ - ApptentiveAuthenticationFailureReasonExpiredToken, - /** The JWT was revoked. */ - ApptentiveAuthenticationFailureReasonRevokedToken, - /** The Apptentive App Key was missing. */ - ApptentiveAuthenticationFailureReasonMissingAppKey, - /** The Apptentive App Signature was missing */ - ApptentiveAuthenticationFailureReasonMissingAppSignature, - /** In invalid combination of an Apptentive App Key and an Apptentive App Signature was found. */ - ApptentiveAuthenticationFailureReasonInvalidKeySignaturePair -}; - -/** A block used to notify your app that an authenticated request failed to authenticate. */ -typedef void (^ApptentiveAuthenticationFailureCallback)(ApptentiveAuthenticationFailureReason reason, NSString *errorMessage); - -/** A block used to interact with the default engagement flow. */ -typedef BOOL (^ApptentiveInteractionCallback)(NSString *eventName, NSDictionary * _Nullable customData); - -@protocol ApptentiveDelegate -, ApptentiveStyle; - -/** Notification sent when Message Center unread messages count changes. */ -extern NSNotificationName const ApptentiveMessageCenterUnreadCountChangedNotification; - -/** Notification sent when the user has agreed to rate the application. */ -extern NSNotificationName const ApptentiveAppRatingFlowUserAgreedToRateAppNotification; - -/** Notification sent when a survey is shown. */ -extern NSNotificationName const ApptentiveSurveyShownNotification; - -/** Notification sent when a survey is submitted by the user. */ -extern NSNotificationName const ApptentiveSurveySentNotification; - -/** Notification sent when a survey is cancelled. */ -extern NSNotificationName const ApptentiveSurveyCancelledNotification; - -/** Notification sent when a message is sent, either by the user or using a sendAttachment method. - You can use this notification to ask the user to enable push notifications. */ -extern NSNotificationName const ApptentiveMessageSentNotification; - -/** Notification user info key whose value indicates whether the message was sent by the user or using a sendAttachment method. */ -extern NSString *const ApptentiveSentByUserKey; - -/** Error domain for the Apptentive SDK */ -extern NSString *const ApptentiveErrorDomain; - -/** - When a survey is shown or sent, notification's userInfo dictionary will contain the ApptentiveSurveyIDKey key. - Value is the ID of the survey that was shown or sent. - */ -extern NSString *const ApptentiveSurveyIDKey; - -/** Supported Push Providers for use in `setPushNotificationIntegration:withDeviceToken:` */ -typedef NS_ENUM(NSInteger, ApptentivePushProvider) { - /** Specifies the Apptentive push provider. */ - ApptentivePushProviderApptentive, - /** Specifies the Urban Airship push provider. */ - ApptentivePushProviderUrbanAirship, - /** Specifies the Amazon Simple Notification Service push provider. */ - ApptentivePushProviderAmazonSNS, - /** Specifies the Parse push provider. */ - ApptentivePushProviderParse, -}; - -/** - Log levels supported by the logging system. Each level includes those above it on the list. -*/ -typedef NS_ENUM(NSUInteger, ApptentiveLogLevel) { - /** Undefined. */ - ApptentiveLogLevelUndefined = 0, - /** Critical failure log messages. */ - ApptentiveLogLevelCrit = 1, - /** Error log messages. */ - ApptentiveLogLevelError = 2, - /** Warning log messages. */ - ApptentiveLogLevelWarn = 3, - /** Informational log messages. */ - ApptentiveLogLevelInfo = 4, - /** Log messages that are potentially useful for debugging. */ - ApptentiveLogLevelDebug = 5, - /** All possible log messages enabled. */ - ApptentiveLogLevelVerbose = 6 -}; - -@interface TermsAndConditions : NSObject - -@property (nullable, strong, nonatomic, readonly) NSString *bodyText; -@property (nullable, strong, nonatomic, readonly) NSString *linkText; -@property (nullable, strong, nonatomic, readonly) NSURL *linkURL; - -- (instancetype)initWithBodyText:(nullable NSString *)bodyText linkText:(nullable NSString *)linkText linkURL:(nullable NSURL *)linkURL; - -@end - -/** - An `ApptentiveConfiguration` instance is used to pass configuration - parameters into the `-registerWithConfiguration:` method. - - The `Apptentive` singleton instance makes a copy of the configuration - parameters, so changes made to the configuration later - will have no effect. - */ -@interface ApptentiveConfiguration : NSObject - -/** The Apptentive App Key, obtained from your Apptentive dashboard. */ -@property (copy, nonatomic, readonly) NSString *apptentiveKey; - -/** The Apptentive App Signature, obtained from your Apptentive dashboard. */ -@property (copy, nonatomic, readonly) NSString *apptentiveSignature; - -/** The granularity of log messages emitted from the SDK (defaults to `ApptentiveLogLevelInfo`). */ -@property (assign, nonatomic) ApptentiveLogLevel logLevel; - -/** If set, redacts potentially-sensitive information such as user data and credentials from logging. */ -@property (assign, nonatomic) BOOL shouldSanitizeLogMessages; - -/** The server URL to use for API calls. Should only be used for testing. */ -@property (copy, nonatomic) NSURL *baseURL; - -/** The name of the distribution that includes the Apptentive SDK. For example "Cordova". */ -@property (copy, nonatomic, nullable) NSString *distributionName; - -/** The version of the distribution that includes the Apptentive SDK. */ -@property (copy, nonatomic, nullable) NSString *distributionVersion; - -/** The iTunes store app ID of the app (used for Apptentive rating prompt). */ -@property (copy, nonatomic, nullable) NSString *appID; - -/** If set, shows a button in Surveys and Message Center that presents information about Apptentive including a link to our privacy policy. */ -@property (assign, nonatomic) BOOL showInfoButton; - -/** If set, shows a valid combination of terms & conditions and/or a link with an optional text mask, below the submit button in Surveys. */ -@property (copy, nonatomic, nullable) TermsAndConditions* surveyTermsAndConditions; - -/** - Returns an instance of the `ApptentiveConfiguration` class - initialized with the specified parameters. - - @param apptentiveKey The Apptentive App Key, obtained from your Apptentive dashboard. - @param apptentiveSignature The Apptentive App Signature, obtained from your Apptentive dashboard. - @return The newly-initiazlied configuration object. - */ -+ (nullable instancetype)configurationWithApptentiveKey:(NSString *)apptentiveKey apptentiveSignature:(NSString *)apptentiveSignature; - -@end - -/** - `Apptentive` is a singleton which is used as the main point of entry for the Apptentive service. - -## Configuration - - Before calling any other methods on the shared `Apptentive` instance, register you app key and signature: - - ApptentiveConfiguration *configuration = [ApptentiveConfiguration configurationWithApptentiveKey:@"your APP key here" apptentiveSignature:@"your APP signature here"]; - [Apptentive registerWithConfiguration:configuration]; - - -## Engaging Events - - The Ratings Prompt and other Apptentive interactions are targeted to certain Apptentive events. For example, - you could decide to show the Ratings Prompt after an event named "user_completed_level" has been engaged. - You can later reconfigure the Ratings Prompt interaction to instead show after engaging "user_logged_in". - - You would add calls at these points to optionally engage with the user: - - [[Apptentive sharedConnection] engage:@"completed_level" fromViewController:viewController]; - - See the readme for more information. - -## Notifications - - `ApptentiveMessageCenterUnreadCountChangedNotification` - - Sent when the number of unread messages changes. - The notification object is undefined. The `userInfo` dictionary contains a `count` key, the value of which - is the number of unread messages. - - `ApptentiveAppRatingFlowUserAgreedToRateAppNotification` - - Sent when the user has agreed to rate the application. - - `ApptentiveSurveySentNotification` - - Sent when a survey is submitted by the user. The userInfo dictionary will have a key named `ApptentiveSurveyIDKey`, - with a value of the id of the survey that was sent. - - */ -@interface Apptentive : NSObject - -///--------------------------------- -/// @name Basic Usage -///--------------------------------- -/** The shared singleton of `Apptentive`. */ -+ (instancetype)sharedConnection; - -/** Alias for `sharedConnection` */ -@property (class, readonly, nonatomic) Apptentive *shared; - -/** Initializes Apptentive instance with a given configuration */ -+ (void)registerWithConfiguration:(ApptentiveConfiguration *)configuration; - -/** The key copied from the configuration object. */ -@property (readonly, nonatomic) NSString *apptentiveKey; - -/** The signature copied from the configuration object. */ -@property (readonly, nonatomic) NSString *apptentiveSignature; - -/** - The app's iTunes App ID. - - You can find this in iTunes Connect, and is the numeric "Apple ID" shown on your app details page. - */ -@property (copy, nonatomic, nullable) NSString *appID; - -@property (readonly, nonatomic) BOOL showInfoButton; - -@property (copy, nonatomic, nullable, readonly) TermsAndConditions* surveyTermsAndConditions; - - -/** An object conforming to the `ApptentiveDelegate` protocol. - If a `nil` value is passed for the view controller into methods such as `-engage:fromViewController`, - the SDK will request a view controller from the delegate from which to present an interaction. - - Deprecation Note: when a suitable view controller is not available for presenting interactions, - the system will now use a new window to present Apptentive UI. */ -@property (weak, nonatomic) id delegate DEPRECATED_ATTRIBUTE; - -///-------------------- -/// @name Engage Events -///-------------------- - -/** - Shows interaction UI, if applicable, related to a given event. - - For example, if you have a survey to display on app launch, you might call with event label set to - `@"app.launch"` here, along with the view controller survey should be displayed from. - - @param event A string representing the name of the event. - @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. - */ -- (void)engage:(NSString *)event fromViewController:(UIViewController *_Nullable)viewController NS_SWIFT_NAME(engage(event:from:)); - -/** - Shows interaction UI, if applicable, related to a given event. - - For example, if you have a survey to display on app launch, you might call with event label set to - `@"app.launch"` here, along with the view controller survey should be displayed from. - - @param event A string representing the name of the event. - @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. - @param completion A completion callback - */ -- (void)engage:(NSString *)event fromViewController:(UIViewController *_Nullable)viewController completion:(void (^_Nullable)(BOOL engaged))completion NS_SWIFT_NAME(engage(event:from:completion:)); - -/** - Shows interaction UI, if applicable, related to a given event, and attaches the specified custom data to the event. - - @param event A string representing the name of the event. - @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. - @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. - */ -- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData fromViewController:(UIViewController *_Nullable)viewController NS_SWIFT_NAME(engage(event:withCustomData:from:)); - -/** - Shows interaction UI, if applicable, related to a given event, and attaches the specified custom data to the event. - - @param event A string representing the name of the event. - @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. - @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. - @param completion A completion callback - */ -- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData fromViewController:(UIViewController *_Nullable)viewController completion:(void (^_Nullable)(BOOL engaged))completion NS_SWIFT_NAME(engage(event:withCustomData:from:completion:)); - -/** - Shows interaction UI, if applicable, related to a given event. Attaches the specified custom data to the event along with the specified extended data. - - @param event A string representing the name of the event. - @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. - @param extendedData An array of dictionaries with specific Apptentive formatting. For example, [Apptentive extendedDataDate:[NSDate date]]. - @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. - */ -- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData withExtendedData:(nullable NSArray *)extendedData fromViewController:(UIViewController *_Nullable)viewController NS_SWIFT_NAME(engage(event:withCustomData:withExtendedData:from:)); - -/** - Shows interaction UI, if applicable, related to a given event. Attaches the specified custom data to the event along with the specified extended data. - - @param event A string representing the name of the event. - @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. - @param extendedData An array of dictionaries with specific Apptentive formatting. For example, [Apptentive extendedDataDate:[NSDate date]]. - @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. - */ -- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData withExtendedData:(nullable NSArray *)extendedData fromViewController:(UIViewController *_Nullable)viewController completion:(void (^_Nullable)(BOOL engaged))completion NS_SWIFT_NAME(engage(event:withCustomData:withExtendedData:from:completion:)); - -/** - Asynchronously checks whether the given event will cause an Interaction to be shown. - - For example, callback would be invoked with YES parameter if a survey is ready to be shown the next time you engage your survey-targeted event. You can use this method to hide a "Show Survey" button in your app if there is no survey to take. - - @param event A string representing the name of the event. - @param completion Completion callback - */ -- (void)queryCanShowInteractionForEvent:(NSString *)event completion:(void (^)(BOOL canShowInteraction))completion; - -///-------------------- -/// @name Extended Data for Events -///-------------------- - -/** - Used to specify a point in time in an event's extended data. - - @param date A date and time to be included in an event's extended data. - - @return An extended data dictionary representing a point in time, to be included in an event's extended data. - */ -+ (NSDictionary *)extendedDataDate:(NSDate *)date NS_SWIFT_NAME(extendedData(date:)); - -/** - Used to specify a geographic coordinate in an event's extended data. - - @param latitude A location's latitude coordinate. - @param longitude A location's longitude coordinate. - - @return An extended data dictionary representing a geographic coordinate, to be included in an event's extended data. - */ -+ (NSDictionary *)extendedDataLocationForLatitude:(double)latitude longitude:(double)longitude NS_SWIFT_NAME(extendedData(latitude:longitude:)); - -/** - Used to specify a commercial transaction (incorporating multiple items) in an event's extended data. - - @param transactionID The transaction's ID. - @param affiliation The store or affiliation from which this transaction occurred. - @param revenue The transaction's revenue. - @param shipping The transaction's shipping cost. - @param tax Tax on the transaction. - @param currency Currency for revenue/shipping/tax values. - @param commerceItems An array of commerce items contained in the transaction. Create commerce items with [Apptentive extendedDataCommerceItemWithItemID:name:category:price:quantity:currency:]. - - @return An extended data dictionary representing a commerce transaction, to be included in an event's extended data. - */ -+ (NSDictionary *)extendedDataCommerceWithTransactionID:(nullable NSString *)transactionID - affiliation:(nullable NSString *)affiliation - revenue:(nullable NSNumber *)revenue - shipping:(nullable NSNumber *)shipping - tax:(nullable NSNumber *)tax - currency:(nullable NSString *)currency - commerceItems:(nullable NSArray *)commerceItems - NS_SWIFT_NAME(extendedData(transactionID:affiliation:revenue:shipping:tax:currency:commerceItems:)); - -/** - Used to specify a commercial transaction (consisting of a single item) in an event's extended data. - - @param itemID The transaction item's ID. - @param name The transaction item's name. - @param category The transaction item's category. - @param price The individual item price. - @param quantity The number of units purchased. - @param currency Currency for price. - - @return An extended data dictionary representing a single item in a commerce transaction, to be included in an event's extended data. - */ -+ (NSDictionary *)extendedDataCommerceItemWithItemID:(nullable NSString *)itemID - name:(nullable NSString *)name - category:(nullable NSString *)category - price:(nullable NSNumber *)price - quantity:(nullable NSNumber *)quantity - currency:(nullable NSString *)currency - NS_SWIFT_NAME(extendedData(itemID:name:category:price:quantity:currency:)); - -///-------------------- -/// @name Presenting UI -///-------------------- - -/** - Asynchronously determines if Message Center will be displayed when `presentMessageCenterFromViewController:` is called. - - If app has not yet synced with Apptentive, you will be unable to display Message Center. Use `queryCanShowMessageCenterWithCompletion:` - to determine if Message Center is ready to be displayed. If Message Center is not ready you could, for example, - hide the "Message Center" button in your interface. - **/ - -- (void)queryCanShowMessageCenterWithCompletion:(void (^)(BOOL canShowMessageCenter))completion; - -/** - Presents Message Center modally from the specified view controller. - - If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a - "We're attempting to connect" view in place of Message Center. - - @param viewController The view controller from which to present Message Center. - */ -- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController; - -/** - Presents Message Center modally from the specified view controller. - - If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a - "We're attempting to connect" view in place of Message Center. - - @param viewController The view controller from which to present Message Center. - @param completion Completion callback. - */ -- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController completion:(void (^_Nullable)(BOOL presented))completion; - -/** - Presents Message Center from a given view controller with custom data. - - If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a - "We're attempting to connect" view in place of Message Center. - - @param viewController The view controller from which to present Message Center. - @param customData A dictionary of key/value pairs to be associated with any messages sent via Message Center. - */ -- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController withCustomData:(nullable NSDictionary *)customData; - -/** - Presents Message Center from a given view controller with custom data. - - If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a - "We're attempting to connect" view in place of Message Center. - - @param viewController The view controller from which to present Message Center. - @param customData A dictionary of key/value pairs to be associated with any messages sent via Message Center. - @param completion Completion callback. - */ -- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController withCustomData:(nullable NSDictionary *)customData completion:(void (^_Nullable)(BOOL presented))completion; - -/** - Dismisses Message Center. - - @param animated `YES` to animate the dismissal, otherwise `NO`. - @param completion A block called at the conclusion of the message center being dismissed. - - @note Under normal circumstances, Message Center will be dismissed by the user tapping the Close button, so it is not necessary to call this method. - */ -- (void)dismissMessageCenterAnimated:(BOOL)animated completion:(nullable void (^)(void))completion; - -///------------------------------------- -/// @name Displaying Unread Message Count -///------------------------------------- - -/** - Returns the current number of unread messages in Message Center. - - These are the messages sent via the Apptentive website to this user. - - @return The number of unread messages. - */ -@property (readonly, nonatomic) NSUInteger unreadMessageCount; - -/** - Returns a "badge" than can be used as a UITableViewCell accessoryView to indicate the current number of unread messages. - - To keep this value updated, your view controller will must register for `ApptentiveMessageCenterUnreadCountChangedNotification` - and reload the table view cell when a notification is received. - - @param apptentiveHeart A Boolean value indicating whether to include a heart logo adjacent to the number. - - @return A badge view suitable for use as a table view cell accessory view. - */ -- (UIView *)unreadMessageCountAccessoryView:(BOOL)apptentiveHeart NS_SWIFT_NAME(unreadMessageCountAccessoryView(apptentiveHeart:)); - -///--------------------------------------- -/// @name Open App Store -///--------------------------------------- - -/** - Open your app's page on the App Store or Mac App Store. - - This method can be used to power, for example, a "Rate this app" button in your settings screen. - `openAppStore` opens the app store directly, without the normal Apptentive Ratings Prompt. - */ -- (void)openAppStore; - -///------------------------------------ -/// @name Enable Push Notifications -///------------------------------------ - -/** - Register for Push Notifications with the given service provider. - - Uses the `deviceToken` from `application:didRegisterForRemoteNotificationsWithDeviceToken:` - - Only one Push Notification Integration can be added at a time. Setting a Push Notification - Integration removes all previously set Push Notification Integrations. - - To enable background fetching of Message Center messages upon receiving a remote notification, - add `remote-notification` as a `UIBackgroundModes` value in your app's Info.plist. - - @param pushProvider The Push Notification provider with which to register. - @param deviceToken The device token used to send Remote Notifications. - **/ - -- (void)setPushNotificationIntegration:(ApptentivePushProvider)pushProvider withDeviceToken:(NSData *)deviceToken NS_SWIFT_NAME(setPushProvider(_:deviceToken:)); - -/** - Forwards a push notification from your application delegate to Apptentive. - - Apptentive will attempt to fetch Messages Center messages in the background when the notification is received. - - To enable background fetching of Message Center messages upon receiving a remote notification, - add `remote-notification` as a `UIBackgroundModes` value in your app's Info.plist. - - The `completionHandler` block will be called when the message fetch is completed. To ensure that messages can be - retrieved, please do not call the `completionHandler` block yourself if the notification was sent by Apptentive. - - If the notification was not sent by Apptentive, the parent app is responsible for calling the `completionHandler` block. - - @param userInfo The `userInfo` dictionary of the notification. - @param completionHandler The block to execute when the message fetch operation is complete. - - @return `YES` if the notification was sent by Apptentive, `NO` otherwise. - */ -- (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler; - -/** - Forwards a push notification from your application delegate to Apptentive. - - Deprecated. The value passed to `fromViewController` is ignored. Use `-didReceveRemoteNotification:fetchCompletionHandler` instead. - - @param userInfo The `userInfo` dictionary of the notification. - @param viewController The view controller Message Center may be presented from. - @param completionHandler The block to execute when the message fetch operation is complete. - - @return `YES` if the notification was sent by Apptentive, `NO` otherwise. - */ -- (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo fromViewController:(UIViewController *)viewController fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler DEPRECATED_ATTRIBUTE; - -/** - Forwards a push notification from your application delegate to Apptentive Connect. - - Deprecated. The value passed to `fromViewController` is ignored. Use `-didReceiveRemoteNotification:fetchCompletionHandler:` instead. - - @param userInfo The `userInfo` dictionary of the notification. - @param viewController The view controller Message Center may be presented from. - - @return `YES` if the notification was sent by Apptentive, `NO` otherwise. - */ -- (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo fromViewController:(UIViewController *)viewController DEPRECATED_ATTRIBUTE; - -/** - Forwards a local notification from your application delegate to Apptentive. - - @param notification The `UILocalNotification` object received by the application delegate. - @param viewController The view controller Message Center may be presented from. - @return `YES` if the notification was sent by Apptentive, `NO` otherwise. - */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -- (BOOL)didReceiveLocalNotification:(UILocalNotification *)notification fromViewController:(UIViewController *)viewController NS_SWIFT_NAME(didReceiveLocalNotification(_:from:)); -#pragma clang diagnostic pop - -/** - Forwards a user notification from your user notification center delegate to Apptentive. - In the event that this method returns `NO`, your code must call the completion handler. - - @param response The notification response - @param viewController The view controller to present Message Center from. If absent, Message Center will be presented in a new window. - @param completionHandler The completion handler that will be called if the notification was sent by Apptentive. - @return `YES` if the notification was sent by Apptentive, `NO` otherwise. - - */ -- (BOOL)didReceveUserNotificationResponse:(UNNotificationResponse *)response fromViewController:(nullable UIViewController *)viewController withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10_0); - -/** - Forwards a user notification from your user notification center delegate to Apptentive. - In the event that this method returns `NO`, your code must call the completion handler. - - @param response The notification response - @param completionHandler The completion handler that will be called if the notification was sent by Apptentive - @return `YES` if the notification was sent by Apptentive, `NO` otherwise. - -*/ -- (BOOL)didReceveUserNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10_0); - -/** - Tells the system to display an alert, if appropriate, for a notification. - In the event that this method returns `NO`, your code must call the completion handler. - - @param notification The notification - @param completionHandler The completion handler that will be called if the notification was sent by Apptentive - @return `YES` if the notification was sent by Apptentive, `NO` otherwise. - */ -- (BOOL)willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler NS_AVAILABLE_IOS(10_0); - -///------------------------------------- -/// @name Attach Text, Images, and Files -///------------------------------------- - -/** - Attaches text to the user's feedback. This method should be called from the main thread only. - - This will appear in your online Apptentive dashboard, but will *not* appear in Message Center on the device. - - @param text The text to attach to the user's feedback as a file. - */ -- (void)sendAttachmentText:(NSString *)text NS_SWIFT_NAME(sendAttachment(_:)); - -/** - Attaches an image the user's feedback. This method should be called from the main thread only. - - This will appear in your online Apptentive dashboard, but will *not* appear in Message Center on the device. - - @param image The image to attach to the user's feedback as a file. - */ -- (void)sendAttachmentImage:(UIImage *)image NS_SWIFT_NAME(sendAttachment(_:)); - -/** - Attaches an arbitrary file to the user's feedback. This method should be called from the main thread only. - - This will appear in your online Apptentive dashboard, but will *not* appear in Message Center on the device. - - @param fileData The contents of the file as data. - @param mimeType The MIME type of the file data. - */ -- (void)sendAttachmentFile:(NSData *)fileData withMimeType:(NSString *)mimeType NS_SWIFT_NAME(sendAttachment(_:mimeType:)); - -///--------------------------------------- -/// @name Add Custom Device or Person Data -///--------------------------------------- - -/** The name of the app user when communicating with Apptentive. */ -@property (copy, nonatomic, nullable) NSString *personName; -/** The email address of the app user in form fields and communicating with Apptentive. */ -@property (copy, nonatomic, nullable) NSString *personEmailAddress; - -/** - Removes custom data associated with the current person. - - Will remove data, if any, associated with the current person with the key `key`. - - @param key The key of the data. - */ -- (void)removeCustomPersonDataWithKey:(NSString *)key; - -/** - Removes custom data associated with the current device. - - Will remove data, if any, associated with the current device with the key `key`. - - @param key The key of the data. - */ -- (void)removeCustomDeviceDataWithKey:(NSString *)key; - -/** - Adds custom text data associated with the current device. - - Adds an additional data field to any feedback sent. This will show up in the device data in the - conversation on your Apptentive dashboard. - - @param string Custom data of type `NSString`. - @param key A key to associate the data with. - */ -- (void)addCustomDeviceDataString:(NSString *)string withKey:(NSString *)key NS_SWIFT_NAME(addCustomDeviceData(_:withKey:)); - -/** - Adds custom numeric data associated with the current device. - - Adds an additional data field to any feedback sent. This will show up in the device data in the - conversation on your Apptentive dashboard. - - @param number Custom data of type `NSNumber`. - @param key A key to associate the data with. - */ -- (void)addCustomDeviceDataNumber:(NSNumber *)number withKey:(NSString *)key NS_SWIFT_NAME(addCustomDeviceData(_:withKey:)); - -/** - Adds custom Boolean data associated with the current device. - - Adds an additional data field to any feedback sent. This will show up in the device data in the - conversation on your Apptentive dashboard. - - @param boolValue Custom data of type `BOOL`. - @param key A key to associate the data with. - */ -- (void)addCustomDeviceDataBool:(BOOL)boolValue withKey:(NSString *)key NS_SWIFT_NAME(addCustomDeviceData(_:withKey:)); - -/** - Adds custom text data associated with the current person. - - Adds an additional data field to any feedback sent. This will show up in the person data in the - conversation on your Apptentive dashboard. - - @param string Custom data of type `NSString`. - @param key A key to associate the data with. - */ -- (void)addCustomPersonDataString:(NSString *)string withKey:(NSString *)key NS_SWIFT_NAME(addCustomPersonData(_:withKey:)); - -/** - Adds custom numeric data associated with the current person. - - Adds an additional data field to any feedback sent. This will show up in the person data in the - conversation on your Apptentive dashboard. - - @param number Custom data of type `NSNumber`. - @param key A key to associate the data with. - */ -- (void)addCustomPersonDataNumber:(NSNumber *)number withKey:(NSString *)key NS_SWIFT_NAME(addCustomPersonData(_:withKey:)); - - -/** - Adds custom Boolean data associated with the current person. - - Adds an additional data field to any feedback sent. This will show up in the person data in the - conversation on your Apptentive dashboard. - - @param boolValue Custom data of type `BOOL`. - @param key A key to associate the data with. - */ -- (void)addCustomPersonDataBool:(BOOL)boolValue withKey:(NSString *)key NS_SWIFT_NAME(addCustomPersonData(_:withKey:)); - -///------------------------------------ -/// @name Miscellaneous -///------------------------------------ - - -/** - Dismisses any currently-visible interactions. - - @note This method is for internal use and is subject to change. - - @param animated Whether to animate the dismissal. - */ -- (void)dismissAllInteractions:(BOOL)animated NS_SWIFT_NAME(dismissAllInteractions(animated:)); - -///--------------------------------- -/// @name Interface Customization -///--------------------------------- - -/** The style sheet used for styling Apptentive UI. - - @note See the [Apptentive Styling Guide for iOS](https://learn.apptentive.com/knowledge-base/interface-customization-ios/) for information on configuring this property. - */ -@property (strong, nonatomic) id styleSheet; - - -#if APPTENTIVE_DEBUG -- (void)checkSDKConfiguration; +#ifdef NO_USE_FRAMEWORKS +#import +#import +#else +#import +#import #endif -///--------------------------------- -/// @name Authentication -///--------------------------------- - -/** - Logs the specified user in, using the value of the proof parameter to - ensure that the login attempt is authorized. - - @param token An authorization token. - @param completion A block that is called when the login attempt succeeds or fails. - */ -- (void)logInWithToken:(NSString *)token completion:(void (^)(BOOL success, NSError *error))completion; - -/** - Ends the current user session. The user session will be persisted in a logged-out state - so that it can be resumed using the logIn: method. - */ -- (void)logOut; - -/** - A block that is called when a logged-in conversation's request fails due to a problem with the user's JWT. - */ -@property (copy, nonatomic) ApptentiveAuthenticationFailureCallback authenticationFailureCallback; - -/** - A block that is called right before engaging an interaction. Return `NO` to cancel - the engagement. - */ -@property (copy, nonatomic) ApptentiveInteractionCallback preInteractionCallback; - -/** - Updates the login token with the provided one. Used to refresh a token that has expired or may expire soon. - - @param token The new authorization token. - @param completion handler indicating success or failure. - */ -- (void)updateToken:(NSString *)token completion:(nullable void(^)(BOOL))completion; - -///--------------------------------- -/// @name Logging System -///--------------------------------- - -@property (assign, nonatomic) ApptentiveLogLevel logLevel; - -@end - -@protocol ApptentiveDelegate -@optional - -/** - Returns a view controller from which to present the an interaction. - - @param connection The `Apptentive` object that is requesting a view controller to present from. - - @return The view controller your app would like the interaction to be presented from. - - Deprecation Note: when a suitable view controller is not available for presenting interactions, - the system will now use a new window to present Apptentive UI. */ -- (UIViewController *)viewControllerForInteractionsWithConnection:(Apptentive *)connection NS_SWIFT_NAME(viewControllerForInteractions(with:))DEPRECATED_ATTRIBUTE; - -@end - -/** - The `ApptentiveNavigationController class is an empty subclass of UINavigationController that - can be used to target UIAppearance settings specifically to Apptentive UI. - - For instance, to override the default `barTintColor` (white) for navigation controllers - in the Apptentive UI, you would call: - - [[UINavigationBar appearanceWhenContainedIn:[ApptentiveNavigationController class], nil].barTintColor = [UIColor magentaColor]; - - */ -@interface ApptentiveNavigationController : UINavigationController -@end - -/** - The ApptentiveStyle protocol allows extensive customization of the fonts and colors used by the Apptentive SDK's UI. - - A class implementing this protocol must handle resizing text according to the applications content size to support dynamic type. - */ -@protocol ApptentiveStyle - -/** A typealias for string used to identify a text style or color. */ -typedef NSString *ApptentiveStyleIdentifier NS_EXTENSIBLE_STRING_ENUM; - -/** - @param textStyle the text style whose font should be returned. - @return the font to use for the given style. - */ -- (UIFont *)fontForStyle:(ApptentiveStyleIdentifier)textStyle NS_SWIFT_NAME(font(for:)); - -/** - @param style the style whose color should be returned. - @return the color to use for the given style. - */ -- (UIColor *)colorForStyle:(ApptentiveStyleIdentifier)style NS_SWIFT_NAME(color(for:)); - -@end - -NS_ASSUME_NONNULL_END - -#import "ApptentiveStyleSheet.h" - -NS_ASSUME_NONNULL_BEGIN - -/// The text style for the title text of the greeting view in Message Center. -extern ApptentiveStyleIdentifier ApptentiveTextStyleBody NS_SWIFT_NAME(body); - -/// The text style for the title text of the greeting view in Message Center. -extern ApptentiveStyleIdentifier ApptentiveTextStyleHeaderTitle NS_SWIFT_NAME(headerTitle); - -/// The text style for the message text of the greeting view in Message Center. -extern ApptentiveStyleIdentifier ApptentiveTextStyleHeaderMessage NS_SWIFT_NAME(headerMessage); - -/// The text style for the date lables in Message Center. -extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageDate NS_SWIFT_NAME(messageDate); - -/// The text style for the message sender text in Message Center. -extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageSender NS_SWIFT_NAME(messageSender); - -/// The text style for the message status text in Message Center. -extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageStatus NS_SWIFT_NAME(messageStatus); - -/// The text style for the message center status text in Message Center. -extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageCenterStatus NS_SWIFT_NAME(messageCenterStatus); - -/// The text style for the survey description text. -extern ApptentiveStyleIdentifier ApptentiveTextStyleSurveyInstructions NS_SWIFT_NAME(surveyInstructions); - -/// The text style for buttons that make changes when tapped. -extern ApptentiveStyleIdentifier ApptentiveTextStyleDoneButton NS_SWIFT_NAME(doneButton); - -/// The text style for buttons that cancel or otherwise don't make changes when tapped. -extern ApptentiveStyleIdentifier ApptentiveTextStyleButton NS_SWIFT_NAME(button); - -/// The text style for the the submit button on Surveys. -extern ApptentiveStyleIdentifier ApptentiveTextStyleSubmitButton NS_SWIFT_NAME(submitButton); - -/// The text style for text input fields. -extern ApptentiveStyleIdentifier ApptentiveTextStyleTextInput NS_SWIFT_NAME(textInput); - - -/// The background color for headers in Message Center and Surveys. -extern ApptentiveStyleIdentifier ApptentiveColorHeaderBackground NS_SWIFT_NAME(headerBackground); - -/// The background color for the footer in Surveys. -extern ApptentiveStyleIdentifier ApptentiveColorFooterBackground NS_SWIFT_NAME(footerBackground); - -/// The foreground color for text and borders indicating a failure of validation or sending. -extern ApptentiveStyleIdentifier ApptentiveColorFailure NS_SWIFT_NAME(failure); - -/// The foreground color for borders in Message Center and Surveys. -extern ApptentiveStyleIdentifier ApptentiveColorSeparator NS_SWIFT_NAME(separator); - -/// The background color for cells in Message Center and Surveys. -extern ApptentiveStyleIdentifier ApptentiveColorBackground NS_SWIFT_NAME(background); - -/// The background color for table- and collection views. -extern ApptentiveStyleIdentifier ApptentiveColorCollectionBackground NS_SWIFT_NAME(collectionBackground); - -/// The background color for text input fields. -extern ApptentiveStyleIdentifier ApptentiveColorTextInputBackground NS_SWIFT_NAME(textInputBackground); - -/// The color for text input placeholder text. -extern ApptentiveStyleIdentifier ApptentiveColorTextInputPlaceholder NS_SWIFT_NAME(textInputPlaceholder); - -/// The background color for message cells in Message Center. -extern ApptentiveStyleIdentifier ApptentiveColorMessageBackground NS_SWIFT_NAME(messageBackground); - -/// The background color for reply cells in Message Center. -extern ApptentiveStyleIdentifier ApptentiveColorReplyBackground NS_SWIFT_NAME(replyBackground); - -/// The background color for context cells in Message Center. -extern ApptentiveStyleIdentifier ApptentiveColorContextBackground NS_SWIFT_NAME(contextBackground); - -NS_ASSUME_NONNULL_END +#endif /* Apptentive_h */ diff --git a/Apptentive/Apptentive/Apptentive.m b/Apptentive/Apptentive/Apptentive.m index c25cd57ae..1fb43045d 100644 --- a/Apptentive/Apptentive/Apptentive.m +++ b/Apptentive/Apptentive/Apptentive.m @@ -6,7 +6,7 @@ // Copyright 2011 Apptentive, Inc.. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveAboutViewController.h" #import "ApptentiveAppConfiguration.h" #import "ApptentiveAttachment.h" @@ -848,7 +848,18 @@ - (BOOL)willPresentNotification:(UNNotification *)notification withCompletionHan if ([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { completionHandler(UNNotificationPresentationOptionNone); } else { +#ifdef __IPHONE_14_0 + if (@available(iOS 14.0, *)) { + completionHandler(UNNotificationPresentationOptionBanner); + } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + completionHandler(UNNotificationPresentationOptionAlert); +#pragma clang diagnostic pop + } +#else completionHandler(UNNotificationPresentationOptionAlert); +#endif } return YES; @@ -885,45 +896,26 @@ - (void)fireLocalNotificationWithUserInfo:(NSDictionary *)userInfo { NSDictionary *apptentiveUserInfo = @{ @"apptentive": userInfo[@"apptentive"] }; NSString *soundName = userInfo[@"apptentive"][@"sound"]; - if (@available(iOS 10.0, *)) { - if ([[UNUserNotificationCenter currentNotificationCenter].delegate respondsToSelector:@selector(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)]) { - UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; - content.title = title; - content.body = body; - content.userInfo = apptentiveUserInfo; - content.sound = [soundName isEqualToString:@"default"] ? [UNNotificationSound defaultSound] : [UNNotificationSound soundNamed:soundName]; - - UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO]; - UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"com.apptentive" content:content trigger:trigger]; - - [UNUserNotificationCenter.currentNotificationCenter addNotificationRequest:request - withCompletionHandler:^(NSError *_Nullable error) { - if (error) { - ApptentiveLogError(@"Error posting local notification (%@).", error); - } - }]; - - return; - } - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if ([[UIApplication sharedApplication].delegate respondsToSelector:@selector(application:didReceiveLocalNotification:)]) { - UILocalNotification *localNotification = [[UILocalNotification alloc] init]; - localNotification.alertTitle = title; - localNotification.alertBody = body; - localNotification.userInfo = apptentiveUserInfo; - localNotification.soundName = [soundName isEqualToString:@"default"] ? UILocalNotificationDefaultSoundName : soundName; + if ([[UNUserNotificationCenter currentNotificationCenter].delegate respondsToSelector:@selector(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)]) { + UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; + content.title = title; + content.body = body; + content.userInfo = apptentiveUserInfo; + content.sound = [soundName isEqualToString:@"default"] ? [UNNotificationSound defaultSound] : [UNNotificationSound soundNamed:soundName]; - [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]; + UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO]; + UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"com.apptentive" content:content trigger:trigger]; - return; - } -#pragma clang diagnostic pop + [UNUserNotificationCenter.currentNotificationCenter addNotificationRequest:request + withCompletionHandler:^(NSError *_Nullable error) { + if (error) { + ApptentiveLogError(@"Error posting local notification (%@).", error); + } + }]; + } else { + ApptentiveLogError(ApptentiveLogTagPush, @"Your app is not properly configured to accept Apptentive Message Center push notifications."); + ApptentiveLogError(ApptentiveLogTagPush, @"Please see the push notification section of the integration guide for assistance: https://learn.apptentive.com/knowledge-base/ios-integration-reference/#push-notifications."); } - - ApptentiveLogError(ApptentiveLogTagPush, @"Your app is not properly configured to accept Apptentive Message Center push notifications."); - ApptentiveLogError(ApptentiveLogTagPush, @"Please see the push notification section of the integration guide for assistance: https://learn.apptentive.com/knowledge-base/ios-integration-reference/#push-notifications."); } #pragma mark - UNUserNotificationCenterDelegate methods diff --git a/Apptentive/Apptentive/Apptentive.storyboard b/Apptentive/Apptentive/Apptentive.storyboard index 511537c05..7afe49322 100644 --- a/Apptentive/Apptentive/Apptentive.storyboard +++ b/Apptentive/Apptentive/Apptentive.storyboard @@ -1,10 +1,11 @@ - + - + + @@ -144,7 +145,7 @@ - - - - + + + + + diff --git a/Apptentive/Apptentive/ApptentiveMain.h b/Apptentive/Apptentive/ApptentiveMain.h new file mode 100644 index 000000000..b352261e6 --- /dev/null +++ b/Apptentive/Apptentive/ApptentiveMain.h @@ -0,0 +1,957 @@ +// +// Apptentive.h +// Apptentive +// +// Created by Andrew Wooster on 3/12/11. +// Copyright 2011 Apptentive, Inc.. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +//! Project version number for Apptentive. +/** The Apptentive version number */ +FOUNDATION_EXPORT double ApptentiveVersionNumber; + +//! Project version string for Apptentive. +/** The Apptentive version string */ +FOUNDATION_EXPORT const unsigned char ApptentiveVersionString[]; + +/** The version number of the Apptentive SDK. */ +#define kApptentiveVersionString @"5.3.0" + +/** The version number of the Apptentive API platform. */ +#define kApptentiveAPIVersionString @"9" + +/** The platform that the SDK is built for. */ +#define kApptentivePlatformString @"iOS" + +/** + A code corresponding to the reason that the Apptentive server authentication failed. + */ +typedef NS_ENUM(NSInteger, ApptentiveAuthenticationFailureReason) { + /** An unknown authentication failure. */ + ApptentiveAuthenticationFailureReasonUnknown, + /** An invalid JWT algorithm was used. */ + ApptentiveAuthenticationFailureReasonInvalidAlgorithm, + /** A malformed JWT was encountered. */ + ApptentiveAuthenticationFailureReasonMalformedToken, + /** An invalid JWT was encountered. */ + ApptentiveAuthenticationFailureReasonInvalidToken, + /** A required subclaim was missing. */ + ApptentiveAuthenticationFailureReasonMissingSubClaim, + /** A subclaim didn't match the logged-in session. */ + ApptentiveAuthenticationFailureReasonMismatchedSubClaim, + /** An invalid subclaim was encountered. */ + ApptentiveAuthenticationFailureReasonInvalidSubClaim, + /** The JWT expired. */ + ApptentiveAuthenticationFailureReasonExpiredToken, + /** The JWT was revoked. */ + ApptentiveAuthenticationFailureReasonRevokedToken, + /** The Apptentive App Key was missing. */ + ApptentiveAuthenticationFailureReasonMissingAppKey, + /** The Apptentive App Signature was missing */ + ApptentiveAuthenticationFailureReasonMissingAppSignature, + /** In invalid combination of an Apptentive App Key and an Apptentive App Signature was found. */ + ApptentiveAuthenticationFailureReasonInvalidKeySignaturePair +}; + +/** A block used to notify your app that an authenticated request failed to authenticate. */ +typedef void (^ApptentiveAuthenticationFailureCallback)(ApptentiveAuthenticationFailureReason reason, NSString *errorMessage); + +/** A block used to interact with the default engagement flow. */ +typedef BOOL (^ApptentiveInteractionCallback)(NSString *eventName, NSDictionary * _Nullable customData); + +@protocol ApptentiveDelegate +, ApptentiveStyle; + +/** Notification sent when Message Center unread messages count changes. */ +extern NSNotificationName const ApptentiveMessageCenterUnreadCountChangedNotification; + +/** Notification sent when the user has agreed to rate the application. */ +extern NSNotificationName const ApptentiveAppRatingFlowUserAgreedToRateAppNotification; + +/** Notification sent when a survey is shown. */ +extern NSNotificationName const ApptentiveSurveyShownNotification; + +/** Notification sent when a survey is submitted by the user. */ +extern NSNotificationName const ApptentiveSurveySentNotification; + +/** Notification sent when a survey is cancelled. */ +extern NSNotificationName const ApptentiveSurveyCancelledNotification; + +/** Notification sent when a message is sent, either by the user or using a sendAttachment method. + You can use this notification to ask the user to enable push notifications. */ +extern NSNotificationName const ApptentiveMessageSentNotification; + +/** Notification user info key whose value indicates whether the message was sent by the user or using a sendAttachment method. */ +extern NSString *const ApptentiveSentByUserKey; + +/** Error domain for the Apptentive SDK */ +extern NSString *const ApptentiveErrorDomain; + +/** + When a survey is shown or sent, notification's userInfo dictionary will contain the ApptentiveSurveyIDKey key. + Value is the ID of the survey that was shown or sent. + */ +extern NSString *const ApptentiveSurveyIDKey; + +/** Supported Push Providers for use in `setPushNotificationIntegration:withDeviceToken:` */ +typedef NS_ENUM(NSInteger, ApptentivePushProvider) { + /** Specifies the Apptentive push provider. */ + ApptentivePushProviderApptentive, + /** Specifies the Urban Airship push provider. */ + ApptentivePushProviderUrbanAirship, + /** Specifies the Amazon Simple Notification Service push provider. */ + ApptentivePushProviderAmazonSNS, + /** Specifies the Parse push provider. */ + ApptentivePushProviderParse, +}; + +/** + Log levels supported by the logging system. Each level includes those above it on the list. +*/ +typedef NS_ENUM(NSUInteger, ApptentiveLogLevel) { + /** Undefined. */ + ApptentiveLogLevelUndefined = 0, + /** Critical failure log messages. */ + ApptentiveLogLevelCrit = 1, + /** Error log messages. */ + ApptentiveLogLevelError = 2, + /** Warning log messages. */ + ApptentiveLogLevelWarn = 3, + /** Informational log messages. */ + ApptentiveLogLevelInfo = 4, + /** Log messages that are potentially useful for debugging. */ + ApptentiveLogLevelDebug = 5, + /** All possible log messages enabled. */ + ApptentiveLogLevelVerbose = 6 +}; + +@interface TermsAndConditions : NSObject + +@property (nullable, strong, nonatomic, readonly) NSString *bodyText; +@property (nullable, strong, nonatomic, readonly) NSString *linkText; +@property (nullable, strong, nonatomic, readonly) NSURL *linkURL; + +- (instancetype)initWithBodyText:(nullable NSString *)bodyText linkText:(nullable NSString *)linkText linkURL:(nullable NSURL *)linkURL; + +@end + +/** + An `ApptentiveConfiguration` instance is used to pass configuration + parameters into the `-registerWithConfiguration:` method. + + The `Apptentive` singleton instance makes a copy of the configuration + parameters, so changes made to the configuration later + will have no effect. + */ +@interface ApptentiveConfiguration : NSObject + +/** The Apptentive App Key, obtained from your Apptentive dashboard. */ +@property (copy, nonatomic, readonly) NSString *apptentiveKey; + +/** The Apptentive App Signature, obtained from your Apptentive dashboard. */ +@property (copy, nonatomic, readonly) NSString *apptentiveSignature; + +/** The granularity of log messages emitted from the SDK (defaults to `ApptentiveLogLevelInfo`). */ +@property (assign, nonatomic) ApptentiveLogLevel logLevel; + +/** If set, redacts potentially-sensitive information such as user data and credentials from logging. */ +@property (assign, nonatomic) BOOL shouldSanitizeLogMessages; + +/** The server URL to use for API calls. Should only be used for testing. */ +@property (copy, nonatomic) NSURL *baseURL; + +/** The name of the distribution that includes the Apptentive SDK. For example "Cordova". */ +@property (copy, nonatomic, nullable) NSString *distributionName; + +/** The version of the distribution that includes the Apptentive SDK. */ +@property (copy, nonatomic, nullable) NSString *distributionVersion; + +/** The iTunes store app ID of the app (used for Apptentive rating prompt). */ +@property (copy, nonatomic, nullable) NSString *appID; + +/** If set, shows a button in Surveys and Message Center that presents information about Apptentive including a link to our privacy policy. */ +@property (assign, nonatomic) BOOL showInfoButton; + +/** If set, shows a valid combination of terms & conditions and/or a link with an optional text mask, below the submit button in Surveys. */ +@property (copy, nonatomic, nullable) TermsAndConditions* surveyTermsAndConditions; + +/** + Returns an instance of the `ApptentiveConfiguration` class + initialized with the specified parameters. + + @param apptentiveKey The Apptentive App Key, obtained from your Apptentive dashboard. + @param apptentiveSignature The Apptentive App Signature, obtained from your Apptentive dashboard. + @return The newly-initiazlied configuration object. + */ ++ (nullable instancetype)configurationWithApptentiveKey:(NSString *)apptentiveKey apptentiveSignature:(NSString *)apptentiveSignature; + +@end + +/** + `Apptentive` is a singleton which is used as the main point of entry for the Apptentive service. + +## Configuration + + Before calling any other methods on the shared `Apptentive` instance, register you app key and signature: + + ApptentiveConfiguration *configuration = [ApptentiveConfiguration configurationWithApptentiveKey:@"your APP key here" apptentiveSignature:@"your APP signature here"]; + [Apptentive registerWithConfiguration:configuration]; + + +## Engaging Events + + The Ratings Prompt and other Apptentive interactions are targeted to certain Apptentive events. For example, + you could decide to show the Ratings Prompt after an event named "user_completed_level" has been engaged. + You can later reconfigure the Ratings Prompt interaction to instead show after engaging "user_logged_in". + + You would add calls at these points to optionally engage with the user: + + [[Apptentive sharedConnection] engage:@"completed_level" fromViewController:viewController]; + + See the readme for more information. + +## Notifications + + `ApptentiveMessageCenterUnreadCountChangedNotification` + + Sent when the number of unread messages changes. + The notification object is undefined. The `userInfo` dictionary contains a `count` key, the value of which + is the number of unread messages. + + `ApptentiveAppRatingFlowUserAgreedToRateAppNotification` + + Sent when the user has agreed to rate the application. + + `ApptentiveSurveySentNotification` + + Sent when a survey is submitted by the user. The userInfo dictionary will have a key named `ApptentiveSurveyIDKey`, + with a value of the id of the survey that was sent. + + */ +@interface Apptentive : NSObject + +///--------------------------------- +/// @name Basic Usage +///--------------------------------- +/** The shared singleton of `Apptentive`. */ ++ (instancetype)sharedConnection; + +/** Alias for `sharedConnection` */ +@property (class, readonly, nonatomic) Apptentive *shared; + +/** Initializes Apptentive instance with a given configuration */ ++ (void)registerWithConfiguration:(ApptentiveConfiguration *)configuration; + +/** The key copied from the configuration object. */ +@property (readonly, nonatomic) NSString *apptentiveKey; + +/** The signature copied from the configuration object. */ +@property (readonly, nonatomic) NSString *apptentiveSignature; + +/** + The app's iTunes App ID. + + You can find this in iTunes Connect, and is the numeric "Apple ID" shown on your app details page. + */ +@property (copy, nonatomic, nullable) NSString *appID; + +@property (readonly, nonatomic) BOOL showInfoButton; + +@property (copy, nonatomic, nullable, readonly) TermsAndConditions* surveyTermsAndConditions; + + +/** An object conforming to the `ApptentiveDelegate` protocol. + If a `nil` value is passed for the view controller into methods such as `-engage:fromViewController`, + the SDK will request a view controller from the delegate from which to present an interaction. + + Deprecation Note: when a suitable view controller is not available for presenting interactions, + the system will now use a new window to present Apptentive UI. */ +@property (weak, nonatomic) id delegate DEPRECATED_ATTRIBUTE; + +///-------------------- +/// @name Engage Events +///-------------------- + +/** + Shows interaction UI, if applicable, related to a given event. + + For example, if you have a survey to display on app launch, you might call with event label set to + `@"app.launch"` here, along with the view controller survey should be displayed from. + + @param event A string representing the name of the event. + @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. + */ +- (void)engage:(NSString *)event fromViewController:(UIViewController *_Nullable)viewController NS_SWIFT_NAME(engage(event:from:)); + +/** + Shows interaction UI, if applicable, related to a given event. + + For example, if you have a survey to display on app launch, you might call with event label set to + `@"app.launch"` here, along with the view controller survey should be displayed from. + + @param event A string representing the name of the event. + @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. + @param completion A completion callback + */ +- (void)engage:(NSString *)event fromViewController:(UIViewController *_Nullable)viewController completion:(void (^_Nullable)(BOOL engaged))completion NS_SWIFT_NAME(engage(event:from:completion:)); + +/** + Shows interaction UI, if applicable, related to a given event, and attaches the specified custom data to the event. + + @param event A string representing the name of the event. + @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. + @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. + */ +- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData fromViewController:(UIViewController *_Nullable)viewController NS_SWIFT_NAME(engage(event:withCustomData:from:)); + +/** + Shows interaction UI, if applicable, related to a given event, and attaches the specified custom data to the event. + + @param event A string representing the name of the event. + @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. + @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. + @param completion A completion callback + */ +- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData fromViewController:(UIViewController *_Nullable)viewController completion:(void (^_Nullable)(BOOL engaged))completion NS_SWIFT_NAME(engage(event:withCustomData:from:completion:)); + +/** + Shows interaction UI, if applicable, related to a given event. Attaches the specified custom data to the event along with the specified extended data. + + @param event A string representing the name of the event. + @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. + @param extendedData An array of dictionaries with specific Apptentive formatting. For example, [Apptentive extendedDataDate:[NSDate date]]. + @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. + */ +- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData withExtendedData:(nullable NSArray *)extendedData fromViewController:(UIViewController *_Nullable)viewController NS_SWIFT_NAME(engage(event:withCustomData:withExtendedData:from:)); + +/** + Shows interaction UI, if applicable, related to a given event. Attaches the specified custom data to the event along with the specified extended data. + + @param event A string representing the name of the event. + @param customData A dictionary of key/value pairs to be associated with the event. Keys and values should conform to standards of NSJSONSerialization's `isValidJSONObject:`. + @param extendedData An array of dictionaries with specific Apptentive formatting. For example, [Apptentive extendedDataDate:[NSDate date]]. + @param viewController A view controller Apptentive UI may be presented from. If `nil`, a view controller should be provided by the delegate. + */ +- (void)engage:(NSString *)event withCustomData:(nullable NSDictionary *)customData withExtendedData:(nullable NSArray *)extendedData fromViewController:(UIViewController *_Nullable)viewController completion:(void (^_Nullable)(BOOL engaged))completion NS_SWIFT_NAME(engage(event:withCustomData:withExtendedData:from:completion:)); + +/** + Asynchronously checks whether the given event will cause an Interaction to be shown. + + For example, callback would be invoked with YES parameter if a survey is ready to be shown the next time you engage your survey-targeted event. You can use this method to hide a "Show Survey" button in your app if there is no survey to take. + + @param event A string representing the name of the event. + @param completion Completion callback + */ +- (void)queryCanShowInteractionForEvent:(NSString *)event completion:(void (^)(BOOL canShowInteraction))completion; + +///-------------------- +/// @name Extended Data for Events +///-------------------- + +/** + Used to specify a point in time in an event's extended data. + + @param date A date and time to be included in an event's extended data. + + @return An extended data dictionary representing a point in time, to be included in an event's extended data. + */ ++ (NSDictionary *)extendedDataDate:(NSDate *)date NS_SWIFT_NAME(extendedData(date:)); + +/** + Used to specify a geographic coordinate in an event's extended data. + + @param latitude A location's latitude coordinate. + @param longitude A location's longitude coordinate. + + @return An extended data dictionary representing a geographic coordinate, to be included in an event's extended data. + */ ++ (NSDictionary *)extendedDataLocationForLatitude:(double)latitude longitude:(double)longitude NS_SWIFT_NAME(extendedData(latitude:longitude:)); + +/** + Used to specify a commercial transaction (incorporating multiple items) in an event's extended data. + + @param transactionID The transaction's ID. + @param affiliation The store or affiliation from which this transaction occurred. + @param revenue The transaction's revenue. + @param shipping The transaction's shipping cost. + @param tax Tax on the transaction. + @param currency Currency for revenue/shipping/tax values. + @param commerceItems An array of commerce items contained in the transaction. Create commerce items with [Apptentive extendedDataCommerceItemWithItemID:name:category:price:quantity:currency:]. + + @return An extended data dictionary representing a commerce transaction, to be included in an event's extended data. + */ ++ (NSDictionary *)extendedDataCommerceWithTransactionID:(nullable NSString *)transactionID + affiliation:(nullable NSString *)affiliation + revenue:(nullable NSNumber *)revenue + shipping:(nullable NSNumber *)shipping + tax:(nullable NSNumber *)tax + currency:(nullable NSString *)currency + commerceItems:(nullable NSArray *)commerceItems + NS_SWIFT_NAME(extendedData(transactionID:affiliation:revenue:shipping:tax:currency:commerceItems:)); + +/** + Used to specify a commercial transaction (consisting of a single item) in an event's extended data. + + @param itemID The transaction item's ID. + @param name The transaction item's name. + @param category The transaction item's category. + @param price The individual item price. + @param quantity The number of units purchased. + @param currency Currency for price. + + @return An extended data dictionary representing a single item in a commerce transaction, to be included in an event's extended data. + */ ++ (NSDictionary *)extendedDataCommerceItemWithItemID:(nullable NSString *)itemID + name:(nullable NSString *)name + category:(nullable NSString *)category + price:(nullable NSNumber *)price + quantity:(nullable NSNumber *)quantity + currency:(nullable NSString *)currency + NS_SWIFT_NAME(extendedData(itemID:name:category:price:quantity:currency:)); + +///-------------------- +/// @name Presenting UI +///-------------------- + +/** + Asynchronously determines if Message Center will be displayed when `presentMessageCenterFromViewController:` is called. + + If app has not yet synced with Apptentive, you will be unable to display Message Center. Use `queryCanShowMessageCenterWithCompletion:` + to determine if Message Center is ready to be displayed. If Message Center is not ready you could, for example, + hide the "Message Center" button in your interface. + **/ + +- (void)queryCanShowMessageCenterWithCompletion:(void (^)(BOOL canShowMessageCenter))completion; + +/** + Presents Message Center modally from the specified view controller. + + If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a + "We're attempting to connect" view in place of Message Center. + + @param viewController The view controller from which to present Message Center. + */ +- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController; + +/** + Presents Message Center modally from the specified view controller. + + If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a + "We're attempting to connect" view in place of Message Center. + + @param viewController The view controller from which to present Message Center. + @param completion Completion callback. + */ +- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController completion:(void (^_Nullable)(BOOL presented))completion; + +/** + Presents Message Center from a given view controller with custom data. + + If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a + "We're attempting to connect" view in place of Message Center. + + @param viewController The view controller from which to present Message Center. + @param customData A dictionary of key/value pairs to be associated with any messages sent via Message Center. + */ +- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController withCustomData:(nullable NSDictionary *)customData; + +/** + Presents Message Center from a given view controller with custom data. + + If the SDK has yet to sync with the Apptentive server, this method returns NO and displays a + "We're attempting to connect" view in place of Message Center. + + @param viewController The view controller from which to present Message Center. + @param customData A dictionary of key/value pairs to be associated with any messages sent via Message Center. + @param completion Completion callback. + */ +- (void)presentMessageCenterFromViewController:(nullable UIViewController *)viewController withCustomData:(nullable NSDictionary *)customData completion:(void (^_Nullable)(BOOL presented))completion; + +/** + Dismisses Message Center. + + @param animated `YES` to animate the dismissal, otherwise `NO`. + @param completion A block called at the conclusion of the message center being dismissed. + + @note Under normal circumstances, Message Center will be dismissed by the user tapping the Close button, so it is not necessary to call this method. + */ +- (void)dismissMessageCenterAnimated:(BOOL)animated completion:(nullable void (^)(void))completion; + +///------------------------------------- +/// @name Displaying Unread Message Count +///------------------------------------- + +/** + Returns the current number of unread messages in Message Center. + + These are the messages sent via the Apptentive website to this user. + + @return The number of unread messages. + */ +@property (readonly, nonatomic) NSUInteger unreadMessageCount; + +/** + Returns a "badge" than can be used as a UITableViewCell accessoryView to indicate the current number of unread messages. + + To keep this value updated, your view controller will must register for `ApptentiveMessageCenterUnreadCountChangedNotification` + and reload the table view cell when a notification is received. + + @param apptentiveHeart A Boolean value indicating whether to include a heart logo adjacent to the number. + + @return A badge view suitable for use as a table view cell accessory view. + */ +- (UIView *)unreadMessageCountAccessoryView:(BOOL)apptentiveHeart NS_SWIFT_NAME(unreadMessageCountAccessoryView(apptentiveHeart:)); + +///--------------------------------------- +/// @name Open App Store +///--------------------------------------- + +/** + Open your app's page on the App Store or Mac App Store. + + This method can be used to power, for example, a "Rate this app" button in your settings screen. + `openAppStore` opens the app store directly, without the normal Apptentive Ratings Prompt. + */ +- (void)openAppStore; + +///------------------------------------ +/// @name Enable Push Notifications +///------------------------------------ + +/** + Register for Push Notifications with the given service provider. + + Uses the `deviceToken` from `application:didRegisterForRemoteNotificationsWithDeviceToken:` + + Only one Push Notification Integration can be added at a time. Setting a Push Notification + Integration removes all previously set Push Notification Integrations. + + To enable background fetching of Message Center messages upon receiving a remote notification, + add `remote-notification` as a `UIBackgroundModes` value in your app's Info.plist. + + @param pushProvider The Push Notification provider with which to register. + @param deviceToken The device token used to send Remote Notifications. + **/ + +- (void)setPushNotificationIntegration:(ApptentivePushProvider)pushProvider withDeviceToken:(NSData *)deviceToken NS_SWIFT_NAME(setPushProvider(_:deviceToken:)); + +/** + Forwards a push notification from your application delegate to Apptentive. + + Apptentive will attempt to fetch Messages Center messages in the background when the notification is received. + + To enable background fetching of Message Center messages upon receiving a remote notification, + add `remote-notification` as a `UIBackgroundModes` value in your app's Info.plist. + + The `completionHandler` block will be called when the message fetch is completed. To ensure that messages can be + retrieved, please do not call the `completionHandler` block yourself if the notification was sent by Apptentive. + + If the notification was not sent by Apptentive, the parent app is responsible for calling the `completionHandler` block. + + @param userInfo The `userInfo` dictionary of the notification. + @param completionHandler The block to execute when the message fetch operation is complete. + + @return `YES` if the notification was sent by Apptentive, `NO` otherwise. + */ +- (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler; + +/** + Forwards a push notification from your application delegate to Apptentive. + + Deprecated. The value passed to `fromViewController` is ignored. Use `-didReceveRemoteNotification:fetchCompletionHandler` instead. + + @param userInfo The `userInfo` dictionary of the notification. + @param viewController The view controller Message Center may be presented from. + @param completionHandler The block to execute when the message fetch operation is complete. + + @return `YES` if the notification was sent by Apptentive, `NO` otherwise. + */ +- (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo fromViewController:(UIViewController *)viewController fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler DEPRECATED_ATTRIBUTE; + +/** + Forwards a push notification from your application delegate to Apptentive Connect. + + Deprecated. The value passed to `fromViewController` is ignored. Use `-didReceiveRemoteNotification:fetchCompletionHandler:` instead. + + @param userInfo The `userInfo` dictionary of the notification. + @param viewController The view controller Message Center may be presented from. + + @return `YES` if the notification was sent by Apptentive, `NO` otherwise. + */ +- (BOOL)didReceiveRemoteNotification:(NSDictionary *)userInfo fromViewController:(UIViewController *)viewController DEPRECATED_ATTRIBUTE; + +/** + Forwards a local notification from your application delegate to Apptentive. + + @param notification The `UILocalNotification` object received by the application delegate. + @param viewController The view controller Message Center may be presented from. + @return `YES` if the notification was sent by Apptentive, `NO` otherwise. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (BOOL)didReceiveLocalNotification:(UILocalNotification *)notification fromViewController:(UIViewController *)viewController NS_SWIFT_NAME(didReceiveLocalNotification(_:from:)); +#pragma clang diagnostic pop + +/** + Forwards a user notification from your user notification center delegate to Apptentive. + In the event that this method returns `NO`, your code must call the completion handler. + + @param response The notification response + @param viewController The view controller to present Message Center from. If absent, Message Center will be presented in a new window. + @param completionHandler The completion handler that will be called if the notification was sent by Apptentive. + @return `YES` if the notification was sent by Apptentive, `NO` otherwise. + + */ +- (BOOL)didReceveUserNotificationResponse:(UNNotificationResponse *)response fromViewController:(nullable UIViewController *)viewController withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10_0); + +/** + Forwards a user notification from your user notification center delegate to Apptentive. + In the event that this method returns `NO`, your code must call the completion handler. + + @param response The notification response + @param completionHandler The completion handler that will be called if the notification was sent by Apptentive + @return `YES` if the notification was sent by Apptentive, `NO` otherwise. + +*/ +- (BOOL)didReceveUserNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10_0); + +/** + Tells the system to display an alert, if appropriate, for a notification. + In the event that this method returns `NO`, your code must call the completion handler. + + @param notification The notification + @param completionHandler The completion handler that will be called if the notification was sent by Apptentive + @return `YES` if the notification was sent by Apptentive, `NO` otherwise. + */ +- (BOOL)willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler NS_AVAILABLE_IOS(10_0); + +///------------------------------------- +/// @name Attach Text, Images, and Files +///------------------------------------- + +/** + Attaches text to the user's feedback. This method should be called from the main thread only. + + This will appear in your online Apptentive dashboard, but will *not* appear in Message Center on the device. + + @param text The text to attach to the user's feedback as a file. + */ +- (void)sendAttachmentText:(NSString *)text NS_SWIFT_NAME(sendAttachment(_:)); + +/** + Attaches an image the user's feedback. This method should be called from the main thread only. + + This will appear in your online Apptentive dashboard, but will *not* appear in Message Center on the device. + + @param image The image to attach to the user's feedback as a file. + */ +- (void)sendAttachmentImage:(UIImage *)image NS_SWIFT_NAME(sendAttachment(_:)); + +/** + Attaches an arbitrary file to the user's feedback. This method should be called from the main thread only. + + This will appear in your online Apptentive dashboard, but will *not* appear in Message Center on the device. + + @param fileData The contents of the file as data. + @param mimeType The MIME type of the file data. + */ +- (void)sendAttachmentFile:(NSData *)fileData withMimeType:(NSString *)mimeType NS_SWIFT_NAME(sendAttachment(_:mimeType:)); + +///--------------------------------------- +/// @name Add Custom Device or Person Data +///--------------------------------------- + +/** The name of the app user when communicating with Apptentive. */ +@property (copy, nonatomic, nullable) NSString *personName; +/** The email address of the app user in form fields and communicating with Apptentive. */ +@property (copy, nonatomic, nullable) NSString *personEmailAddress; + +/** + Removes custom data associated with the current person. + + Will remove data, if any, associated with the current person with the key `key`. + + @param key The key of the data. + */ +- (void)removeCustomPersonDataWithKey:(NSString *)key; + +/** + Removes custom data associated with the current device. + + Will remove data, if any, associated with the current device with the key `key`. + + @param key The key of the data. + */ +- (void)removeCustomDeviceDataWithKey:(NSString *)key; + +/** + Adds custom text data associated with the current device. + + Adds an additional data field to any feedback sent. This will show up in the device data in the + conversation on your Apptentive dashboard. + + @param string Custom data of type `NSString`. + @param key A key to associate the data with. + */ +- (void)addCustomDeviceDataString:(NSString *)string withKey:(NSString *)key NS_SWIFT_NAME(addCustomDeviceData(_:withKey:)); + +/** + Adds custom numeric data associated with the current device. + + Adds an additional data field to any feedback sent. This will show up in the device data in the + conversation on your Apptentive dashboard. + + @param number Custom data of type `NSNumber`. + @param key A key to associate the data with. + */ +- (void)addCustomDeviceDataNumber:(NSNumber *)number withKey:(NSString *)key NS_SWIFT_NAME(addCustomDeviceData(_:withKey:)); + +/** + Adds custom Boolean data associated with the current device. + + Adds an additional data field to any feedback sent. This will show up in the device data in the + conversation on your Apptentive dashboard. + + @param boolValue Custom data of type `BOOL`. + @param key A key to associate the data with. + */ +- (void)addCustomDeviceDataBool:(BOOL)boolValue withKey:(NSString *)key NS_SWIFT_NAME(addCustomDeviceData(_:withKey:)); + +/** + Adds custom text data associated with the current person. + + Adds an additional data field to any feedback sent. This will show up in the person data in the + conversation on your Apptentive dashboard. + + @param string Custom data of type `NSString`. + @param key A key to associate the data with. + */ +- (void)addCustomPersonDataString:(NSString *)string withKey:(NSString *)key NS_SWIFT_NAME(addCustomPersonData(_:withKey:)); + +/** + Adds custom numeric data associated with the current person. + + Adds an additional data field to any feedback sent. This will show up in the person data in the + conversation on your Apptentive dashboard. + + @param number Custom data of type `NSNumber`. + @param key A key to associate the data with. + */ +- (void)addCustomPersonDataNumber:(NSNumber *)number withKey:(NSString *)key NS_SWIFT_NAME(addCustomPersonData(_:withKey:)); + + +/** + Adds custom Boolean data associated with the current person. + + Adds an additional data field to any feedback sent. This will show up in the person data in the + conversation on your Apptentive dashboard. + + @param boolValue Custom data of type `BOOL`. + @param key A key to associate the data with. + */ +- (void)addCustomPersonDataBool:(BOOL)boolValue withKey:(NSString *)key NS_SWIFT_NAME(addCustomPersonData(_:withKey:)); + +///------------------------------------ +/// @name Miscellaneous +///------------------------------------ + + +/** + Dismisses any currently-visible interactions. + + @note This method is for internal use and is subject to change. + + @param animated Whether to animate the dismissal. + */ +- (void)dismissAllInteractions:(BOOL)animated NS_SWIFT_NAME(dismissAllInteractions(animated:)); + +///--------------------------------- +/// @name Interface Customization +///--------------------------------- + +/** The style sheet used for styling Apptentive UI. + + @note See the [Apptentive Styling Guide for iOS](https://learn.apptentive.com/knowledge-base/interface-customization-ios/) for information on configuring this property. + */ +@property (strong, nonatomic) id styleSheet; + + +#if APPTENTIVE_DEBUG +- (void)checkSDKConfiguration; +#endif + +///--------------------------------- +/// @name Authentication +///--------------------------------- + +/** + Logs the specified user in, using the value of the proof parameter to + ensure that the login attempt is authorized. + + @param token An authorization token. + @param completion A block that is called when the login attempt succeeds or fails. + */ +- (void)logInWithToken:(NSString *)token completion:(void (^)(BOOL success, NSError *error))completion; + +/** + Ends the current user session. The user session will be persisted in a logged-out state + so that it can be resumed using the logIn: method. + */ +- (void)logOut; + +/** + A block that is called when a logged-in conversation's request fails due to a problem with the user's JWT. + */ +@property (copy, nonatomic) ApptentiveAuthenticationFailureCallback authenticationFailureCallback; + +/** + A block that is called right before engaging an interaction. Return `NO` to cancel + the engagement. + */ +@property (copy, nonatomic) ApptentiveInteractionCallback preInteractionCallback; + +/** + Updates the login token with the provided one. Used to refresh a token that has expired or may expire soon. + + @param token The new authorization token. + @param completion handler indicating success or failure. + */ +- (void)updateToken:(NSString *)token completion:(nullable void(^)(BOOL))completion; + +///--------------------------------- +/// @name Logging System +///--------------------------------- + +@property (assign, nonatomic) ApptentiveLogLevel logLevel; + +@end + +@protocol ApptentiveDelegate +@optional + +/** + Returns a view controller from which to present the an interaction. + + @param connection The `Apptentive` object that is requesting a view controller to present from. + + @return The view controller your app would like the interaction to be presented from. + + Deprecation Note: when a suitable view controller is not available for presenting interactions, + the system will now use a new window to present Apptentive UI. */ +- (UIViewController *)viewControllerForInteractionsWithConnection:(Apptentive *)connection NS_SWIFT_NAME(viewControllerForInteractions(with:))DEPRECATED_ATTRIBUTE; + +@end + +/** + The `ApptentiveNavigationController class is an empty subclass of UINavigationController that + can be used to target UIAppearance settings specifically to Apptentive UI. + + For instance, to override the default `barTintColor` (white) for navigation controllers + in the Apptentive UI, you would call: + + [[UINavigationBar appearanceWhenContainedIn:[ApptentiveNavigationController class], nil].barTintColor = [UIColor magentaColor]; + + */ +@interface ApptentiveNavigationController : UINavigationController +@end + +/** + The ApptentiveStyle protocol allows extensive customization of the fonts and colors used by the Apptentive SDK's UI. + + A class implementing this protocol must handle resizing text according to the applications content size to support dynamic type. + */ +@protocol ApptentiveStyle + +/** A typealias for string used to identify a text style or color. */ +typedef NSString *ApptentiveStyleIdentifier NS_EXTENSIBLE_STRING_ENUM; + +/** + @param textStyle the text style whose font should be returned. + @return the font to use for the given style. + */ +- (UIFont *)fontForStyle:(ApptentiveStyleIdentifier)textStyle NS_SWIFT_NAME(font(for:)); + +/** + @param style the style whose color should be returned. + @return the color to use for the given style. + */ +- (UIColor *)colorForStyle:(ApptentiveStyleIdentifier)style NS_SWIFT_NAME(color(for:)); + +@end + +/// The text style for the title text of the greeting view in Message Center. +extern ApptentiveStyleIdentifier ApptentiveTextStyleBody NS_SWIFT_NAME(body); + +/// The text style for the title text of the greeting view in Message Center. +extern ApptentiveStyleIdentifier ApptentiveTextStyleHeaderTitle NS_SWIFT_NAME(headerTitle); + +/// The text style for the message text of the greeting view in Message Center. +extern ApptentiveStyleIdentifier ApptentiveTextStyleHeaderMessage NS_SWIFT_NAME(headerMessage); + +/// The text style for the date lables in Message Center. +extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageDate NS_SWIFT_NAME(messageDate); + +/// The text style for the message sender text in Message Center. +extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageSender NS_SWIFT_NAME(messageSender); + +/// The text style for the message status text in Message Center. +extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageStatus NS_SWIFT_NAME(messageStatus); + +/// The text style for the message center status text in Message Center. +extern ApptentiveStyleIdentifier ApptentiveTextStyleMessageCenterStatus NS_SWIFT_NAME(messageCenterStatus); + +/// The text style for the survey description text. +extern ApptentiveStyleIdentifier ApptentiveTextStyleSurveyInstructions NS_SWIFT_NAME(surveyInstructions); + +/// The text style for buttons that make changes when tapped. +extern ApptentiveStyleIdentifier ApptentiveTextStyleDoneButton NS_SWIFT_NAME(doneButton); + +/// The text style for buttons that cancel or otherwise don't make changes when tapped. +extern ApptentiveStyleIdentifier ApptentiveTextStyleButton NS_SWIFT_NAME(button); + +/// The text style for the the submit button on Surveys. +extern ApptentiveStyleIdentifier ApptentiveTextStyleSubmitButton NS_SWIFT_NAME(submitButton); + +/// The text style for text input fields. +extern ApptentiveStyleIdentifier ApptentiveTextStyleTextInput NS_SWIFT_NAME(textInput); + + +/// The background color for headers in Message Center and Surveys. +extern ApptentiveStyleIdentifier ApptentiveColorHeaderBackground NS_SWIFT_NAME(headerBackground); + +/// The background color for the footer in Surveys. +extern ApptentiveStyleIdentifier ApptentiveColorFooterBackground NS_SWIFT_NAME(footerBackground); + +/// The foreground color for text and borders indicating a failure of validation or sending. +extern ApptentiveStyleIdentifier ApptentiveColorFailure NS_SWIFT_NAME(failure); + +/// The foreground color for borders in Message Center and Surveys. +extern ApptentiveStyleIdentifier ApptentiveColorSeparator NS_SWIFT_NAME(separator); + +/// The background color for cells in Message Center and Surveys. +extern ApptentiveStyleIdentifier ApptentiveColorBackground NS_SWIFT_NAME(background); + +/// The background color for table- and collection views. +extern ApptentiveStyleIdentifier ApptentiveColorCollectionBackground NS_SWIFT_NAME(collectionBackground); + +/// The background color for text input fields. +extern ApptentiveStyleIdentifier ApptentiveColorTextInputBackground NS_SWIFT_NAME(textInputBackground); + +/// The color for text input placeholder text. +extern ApptentiveStyleIdentifier ApptentiveColorTextInputPlaceholder NS_SWIFT_NAME(textInputPlaceholder); + +/// The background color for message cells in Message Center. +extern ApptentiveStyleIdentifier ApptentiveColorMessageBackground NS_SWIFT_NAME(messageBackground); + +/// The background color for reply cells in Message Center. +extern ApptentiveStyleIdentifier ApptentiveColorReplyBackground NS_SWIFT_NAME(replyBackground); + +/// The background color for context cells in Message Center. +extern ApptentiveStyleIdentifier ApptentiveColorContextBackground NS_SWIFT_NAME(contextBackground); + +NS_ASSUME_NONNULL_END diff --git a/Apptentive/Apptentive/ApptentiveStyleSheet.m b/Apptentive/Apptentive/ApptentiveStyleSheet.m index 537f2c449..526dbafe8 100644 --- a/Apptentive/Apptentive/ApptentiveStyleSheet.m +++ b/Apptentive/Apptentive/ApptentiveStyleSheet.m @@ -7,7 +7,7 @@ // #import "ApptentiveStyleSheet.h" -#import "Apptentive.h" +#import "ApptentiveMain.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Apptentive/Apptentive/Apptentive_Private.h b/Apptentive/Apptentive/Apptentive_Private.h index 60aad3829..ebcb0a8fb 100644 --- a/Apptentive/Apptentive/Apptentive_Private.h +++ b/Apptentive/Apptentive/Apptentive_Private.h @@ -6,7 +6,7 @@ // Copyright (c) 2013 Apptentive, Inc. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Apptentive/Apptentive/Custom Views/ApptentiveUnreadMessagesBadgeView.m b/Apptentive/Apptentive/Custom Views/ApptentiveUnreadMessagesBadgeView.m index 59b4c2d7f..7928a7d5a 100644 --- a/Apptentive/Apptentive/Custom Views/ApptentiveUnreadMessagesBadgeView.m +++ b/Apptentive/Apptentive/Custom Views/ApptentiveUnreadMessagesBadgeView.m @@ -7,7 +7,7 @@ // #import "ApptentiveUnreadMessagesBadgeView.h" -#import "Apptentive.h" +#import "ApptentiveMain.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Apptentive/Apptentive/Engagement/Interactions/Rating Flow/ApptentiveInteractionAppleRatingDialogController.m b/Apptentive/Apptentive/Engagement/Interactions/Rating Flow/ApptentiveInteractionAppleRatingDialogController.m index d2421e8ea..3266ead5c 100644 --- a/Apptentive/Apptentive/Engagement/Interactions/Rating Flow/ApptentiveInteractionAppleRatingDialogController.m +++ b/Apptentive/Apptentive/Engagement/Interactions/Rating Flow/ApptentiveInteractionAppleRatingDialogController.m @@ -40,17 +40,12 @@ - (void)presentInteractionFromViewController:(nullable UIViewController *)viewCo [Apptentive.shared.backend engage:ApptentiveInteractionAppleRatingDialogEventLabelRequest fromInteraction:self.interaction fromViewController:viewController]; - // Guard against not having store review controller class in OS and/or SDK - if (@available(iOS 10.3, *)) { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeVisible:) name:UIWindowDidBecomeVisibleNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeVisible:) name:UIWindowDidBecomeVisibleNotification object:nil]; - [SKStoreReviewController performSelector:@selector(requestReview)]; + [SKStoreReviewController performSelector:@selector(requestReview)]; - // Give the window a sec to appear before (possibly) invoking fallback - [self performSelector:@selector(checkIfAppleRatingDialogShowed) withObject:nil afterDelay:REVIEW_WINDOW_TIMEOUT]; - } else { - [self invokeNotShownInteractionFromViewController:viewController withReason:@"It is not available in this iOS version."]; - } + // Give the window a sec to appear before (possibly) invoking fallback + [self performSelector:@selector(checkIfAppleRatingDialogShowed) withObject:nil afterDelay:REVIEW_WINDOW_TIMEOUT]; } - (void)windowDidBecomeVisible:(NSNotification *)notification { diff --git a/Apptentive/Apptentive/Engagement/Model/ApptentiveConversation.h b/Apptentive/Apptentive/Engagement/Model/ApptentiveConversation.h index 3836a132f..b74e958b5 100644 --- a/Apptentive/Apptentive/Engagement/Model/ApptentiveConversation.h +++ b/Apptentive/Apptentive/Engagement/Model/ApptentiveConversation.h @@ -6,7 +6,7 @@ // Copyright © 2016 Apptentive, Inc. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveAppInstall.h" #import "ApptentiveState.h" diff --git a/Apptentive/Apptentive/Engagement/Model/ApptentiveSDK.m b/Apptentive/Apptentive/Engagement/Model/ApptentiveSDK.m index 3886609c8..0c7ad3778 100644 --- a/Apptentive/Apptentive/Engagement/Model/ApptentiveSDK.m +++ b/Apptentive/Apptentive/Engagement/Model/ApptentiveSDK.m @@ -6,7 +6,7 @@ // Copyright © 2016 Apptentive, Inc. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveSDK.h" #import "ApptentiveVersion.h" diff --git a/Apptentive/Apptentive/Info.plist b/Apptentive/Apptentive/Info.plist index c9181d63d..e6bae41f4 100644 --- a/Apptentive/Apptentive/Info.plist +++ b/Apptentive/Apptentive/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 5.2.14 + 5.3.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/Apptentive/Apptentive/Message Center/ApptentiveMessageCenterViewModel.m b/Apptentive/Apptentive/Message Center/ApptentiveMessageCenterViewModel.m index 6b30a8d8f..07a6bfdb5 100644 --- a/Apptentive/Apptentive/Message Center/ApptentiveMessageCenterViewModel.m +++ b/Apptentive/Apptentive/Message Center/ApptentiveMessageCenterViewModel.m @@ -10,7 +10,7 @@ #import "ApptentiveAttachment.h" #import "ApptentiveMessageSender.h" -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveAttachmentCell.h" #import "ApptentiveBackend.h" #import "ApptentiveDefines.h" diff --git a/Apptentive/Apptentive/Misc/ApptentiveLog.h b/Apptentive/Apptentive/Misc/ApptentiveLog.h index 059d80744..8a4ec9066 100644 --- a/Apptentive/Apptentive/Misc/ApptentiveLog.h +++ b/Apptentive/Apptentive/Misc/ApptentiveLog.h @@ -6,7 +6,7 @@ // Copyright (c) 2017 Apptentive, Inc. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveLogTag.h" #import diff --git a/Apptentive/Apptentive/Misc/ApptentiveLogMonitor.m b/Apptentive/Apptentive/Misc/ApptentiveLogMonitor.m index e3b43ec8a..77913c2b2 100644 --- a/Apptentive/Apptentive/Misc/ApptentiveLogMonitor.m +++ b/Apptentive/Apptentive/Misc/ApptentiveLogMonitor.m @@ -242,19 +242,27 @@ + (BOOL)IsMobileConfigInstalled { OSStatus err = SecTrustCreateWithCertificates((__bridge CFArrayRef) [NSArray arrayWithObject:(__bridge id)cert], policy, &trust); - SecTrustResultType trustResult = -1; + BOOL result = NO; - err = SecTrustEvaluate(trust, &trustResult); + if (@available(iOS 12.0, *)) { + CFErrorRef trustError = NULL; + + err = SecTrustEvaluateWithError(trust, &trustError); + + result = (trustError == nil); + } else { + SecTrustResultType trustResult = -1; + + err = SecTrustEvaluate(trust, &trustResult); + + result = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed); + } CFRelease(trust); CFRelease(policy); CFRelease(cert); - if(trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed) { - return YES; - } else { - return NO; - } + return result; } @end diff --git a/Apptentive/Apptentive/Misc/ApptentiveURLOpener.m b/Apptentive/Apptentive/Misc/ApptentiveURLOpener.m index 6281554e4..1d6b7c009 100644 --- a/Apptentive/Apptentive/Misc/ApptentiveURLOpener.m +++ b/Apptentive/Apptentive/Misc/ApptentiveURLOpener.m @@ -11,17 +11,7 @@ @implementation ApptentiveURLOpener + (void)openURL:(NSURL *)url completionHandler:(void (^ __nullable)(BOOL success))completion { - if (@available(iOS 10.0, *)) { - [UIApplication.sharedApplication openURL:url options:@{} completionHandler:completion]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - BOOL result = [UIApplication.sharedApplication openURL:url]; -#pragma clang diagnostic pop - if (completion) { - completion(result); - } - } + [UIApplication.sharedApplication openURL:url options:@{} completionHandler:completion]; } @end diff --git a/Apptentive/Apptentive/Networking/Requests & Payloads/ApptentiveRequest.m b/Apptentive/Apptentive/Networking/Requests & Payloads/ApptentiveRequest.m index 83bc68177..5858cdcc8 100644 --- a/Apptentive/Apptentive/Networking/Requests & Payloads/ApptentiveRequest.m +++ b/Apptentive/Apptentive/Networking/Requests & Payloads/ApptentiveRequest.m @@ -6,7 +6,7 @@ // Copyright © 2017 Apptentive, Inc. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveDefines.h" #import "ApptentiveJSONSerialization.h" #import "ApptentiveRequest.h" diff --git a/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyCollectionViewLayout.m b/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyCollectionViewLayout.m index ced23e4b7..715284553 100644 --- a/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyCollectionViewLayout.m +++ b/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyCollectionViewLayout.m @@ -28,7 +28,11 @@ - (CGSize)collectionViewContentSize { if ([self.collectionView isKindOfClass:[ApptentiveSurveyCollectionView class]]) { ApptentiveSurveyCollectionView *myCollectionView = (ApptentiveSurveyCollectionView *)self.collectionView; // Add space for the global header, global footer, and spacing between them and their adjacent sections - superSize.height += CGRectGetHeight(myCollectionView.collectionHeaderView.bounds) + CGRectGetHeight(myCollectionView.collectionFooterView.bounds) + self.sectionInset.top + self.sectionInset.bottom; + + CGSize headerSize = [myCollectionView.collectionHeaderView sizeThatFits:self.collectionView.bounds.size]; + CGSize footerSize = [myCollectionView.collectionFooterView sizeThatFits:self.collectionView.bounds.size]; + + superSize.height += headerSize.height + footerSize.height + self.sectionInset.top + self.sectionInset.bottom; UIEdgeInsets contentInset = self.collectionView.contentInset; UIEdgeInsets adjustedContentInset = self.collectionView.contentInset; @@ -36,11 +40,19 @@ - (CGSize)collectionViewContentSize { contentInset = self.collectionView.safeAreaInsets; adjustedContentInset = self.collectionView.adjustedContentInset; } + if (self.shouldExpand) { superSize.height = fmax(superSize.height, CGRectGetHeight(self.collectionView.bounds) - contentInset.top - contentInset.bottom); } else if (adjustedContentInset.bottom > contentInset.bottom || adjustedContentInset.top > contentInset.top) { superSize.height = fmax(superSize.height, CGRectGetHeight(self.collectionView.bounds) - adjustedContentInset.top - adjustedContentInset.bottom); } + + CGFloat top = superSize.height - CGRectGetHeight(myCollectionView.collectionFooterView.bounds); + if (self.shouldExpand) { + top = fmax(top, CGRectGetHeight(myCollectionView.bounds) - CGRectGetHeight(myCollectionView.collectionFooterView.bounds) - contentInset.top - contentInset.bottom); + } + + myCollectionView.footerConstraint.constant = top; } return superSize; @@ -146,7 +158,7 @@ - (void)setShouldExpand:(BOOL)shouldExpand { - (void)updateHeaderHeight { if ([self.collectionView isKindOfClass:[ApptentiveSurveyCollectionView class]]) { UIView *collectionHeaderView = ((ApptentiveSurveyCollectionView *)self.collectionView).collectionHeaderView; - CGSize headerSize = [collectionHeaderView systemLayoutSizeFittingSize:CGSizeMake(self.collectionView.bounds.size.width, 10000.0)]; + CGSize headerSize = [collectionHeaderView systemLayoutSizeFittingSize:self.collectionView.bounds.size withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel]; self.headerHeight = headerSize.height + self.sectionInset.bottom; } else { self.headerHeight = 0; diff --git a/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewController.m b/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewController.m index 05bf92df0..692d66b74 100644 --- a/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewController.m +++ b/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewController.m @@ -141,7 +141,9 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { +- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + [self.collectionViewLayout invalidateLayout]; } @@ -622,17 +624,33 @@ - (void)textViewDidEndEditing:(UITextView *)textView { [self.viewModel commitChangeAtIndexPath:[self.viewModel indexPathForTextFieldTag:textView.tag]]; } -- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange { +- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction API_AVAILABLE(ios(10.0)) { if (textView != self.termsAndConditionsTextView) { return NO; } - + + if ([UIApplication.sharedApplication canOpenURL:URL]) { + [ApptentiveURLOpener openURL:URL completionHandler: NULL]; + } + + return NO; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange { + if (textView != self.termsAndConditionsTextView) { + return NO; + } + if ([UIApplication.sharedApplication canOpenURL:URL]) { [ApptentiveURLOpener openURL:URL completionHandler: NULL]; } - - return NO; + + return NO; } +#pragma clang diagnostic pop + #pragma mark - Text field delegate diff --git a/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewModel.m b/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewModel.m index 080a5a7ce..5e9021cf6 100644 --- a/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewModel.m +++ b/Apptentive/Apptentive/Surveys/View Controllers/ApptentiveSurveyViewModel.m @@ -17,7 +17,7 @@ #import "ApptentiveSurveyResponsePayload.h" #import "Apptentive_Private.h" #import "ApptentiveBackend+Engagement.h" -#import "Apptentive.h" +#import "ApptentiveMain.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.h b/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.h index bb9134254..9756e0415 100644 --- a/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.h +++ b/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.h @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic) UIView *collectionHeaderView; @property (strong, nonatomic) UIView *collectionFooterView; +@property (strong, nonatomic) NSLayoutConstraint *footerConstraint; @end diff --git a/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.m b/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.m index d30b029b5..605aaf2ab 100644 --- a/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.m +++ b/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyCollectionView.m @@ -12,13 +12,6 @@ NS_ASSUME_NONNULL_BEGIN -@interface ApptentiveSurveyCollectionView () - -@property (strong, nonatomic) NSLayoutConstraint *footerConstraint; - -@end - - @implementation ApptentiveSurveyCollectionView - (void)setCollectionHeaderView:(UIView *)collectionHeaderView { @@ -95,27 +88,6 @@ - (void)setCollectionFooterView:(UIView *)collectionFooterView { [self.collectionViewLayout invalidateLayout]; } -- (void)layoutSubviews { - // We might change the layout attributes if the header size changes. Makes sure we warn the OS. - [self.collectionViewLayout invalidateLayout]; - - [super layoutSubviews]; - - UIEdgeInsets contentInset = self.contentInset; - if (@available(iOS 11.0, *)) { - contentInset = self.safeAreaInsets; - } - - CGFloat top = [self.collectionViewLayout collectionViewContentSize].height - CGRectGetHeight(self.collectionFooterView.bounds); - if (((ApptentiveSurveyCollectionViewLayout *)self.collectionViewLayout).shouldExpand) { - top = fmax(top, CGRectGetHeight(self.bounds) - CGRectGetHeight(self.collectionFooterView.bounds) - contentInset.top - contentInset.bottom); - } - - self.footerConstraint.constant = top; - - [super layoutSubviews]; -} - @end NS_ASSUME_NONNULL_END diff --git a/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyGreetingView.m b/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyGreetingView.m index 7c26e6830..357ba43e9 100644 --- a/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyGreetingView.m +++ b/Apptentive/Apptentive/Surveys/Views/ApptentiveSurveyGreetingView.m @@ -23,19 +23,9 @@ @implementation ApptentiveSurveyGreetingView - (void)awakeFromNib { self.borderViewHeight.constant = 1.0 / [UIScreen mainScreen].scale; - self.greetingLabel.numberOfLines = 0; - [super awakeFromNib]; } -- (void)layoutSubviews { - [super layoutSubviews]; - - self.greetingLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.greetingLabel.bounds); - - [super layoutSubviews]; -} - - (void)setShowInfoButton:(BOOL)showInfoButton { _showInfoButton = showInfoButton; diff --git a/Apptentive/ApptentiveTests/ApptentiveConnectTests.m b/Apptentive/ApptentiveTests/ApptentiveConnectTests.m index 0a6bfe712..ea0858dca 100644 --- a/Apptentive/ApptentiveTests/ApptentiveConnectTests.m +++ b/Apptentive/ApptentiveTests/ApptentiveConnectTests.m @@ -6,7 +6,7 @@ // Copyright 2011 Apptentive, Inc.. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveConversation.h" #import "ApptentiveDevice.h" #import "ApptentivePerson.h" diff --git a/Apptentive/ApptentiveTests/ApptentiveMetricsTests.m b/Apptentive/ApptentiveTests/ApptentiveMetricsTests.m index 8fd353309..15ac6965e 100644 --- a/Apptentive/ApptentiveTests/ApptentiveMetricsTests.m +++ b/Apptentive/ApptentiveTests/ApptentiveMetricsTests.m @@ -6,7 +6,7 @@ // Copyright (c) 2011 Apptentive. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import diff --git a/Apptentive/ApptentiveTests/ApptentiveStyleSheetTests.m b/Apptentive/ApptentiveTests/ApptentiveStyleSheetTests.m index 33137d1a0..c0f366f56 100644 --- a/Apptentive/ApptentiveTests/ApptentiveStyleSheetTests.m +++ b/Apptentive/ApptentiveTests/ApptentiveStyleSheetTests.m @@ -6,7 +6,7 @@ // Copyright © 2016 Apptentive, Inc. All rights reserved. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveStyleSheet.h" #import diff --git a/Apptentive/ApptentiveTests/ApptentiveTests-Bridging-Header.h b/Apptentive/ApptentiveTests/ApptentiveTests-Bridging-Header.h index 94062678c..36cb5040d 100644 --- a/Apptentive/ApptentiveTests/ApptentiveTests-Bridging-Header.h +++ b/Apptentive/ApptentiveTests/ApptentiveTests-Bridging-Header.h @@ -2,7 +2,7 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveLog.h" #import "ApptentiveConversationManager.h" diff --git a/Apptentive/ApptentiveTests/CodePointAndInteractionTests.m b/Apptentive/ApptentiveTests/CodePointAndInteractionTests.m index 11c9caa01..c3cee5c9f 100644 --- a/Apptentive/ApptentiveTests/CodePointAndInteractionTests.m +++ b/Apptentive/ApptentiveTests/CodePointAndInteractionTests.m @@ -265,7 +265,7 @@ - (void)testLt { @interface CodePointLastInvokedAt : CodePointTest @end -#import "Apptentive.h" +#import "ApptentiveMain.h" @implementation CodePointLastInvokedAt diff --git a/Apptentive/ApptentiveTests/CriteriaTests.m b/Apptentive/ApptentiveTests/CriteriaTests.m index b3d671d25..a4f30dbec 100644 --- a/Apptentive/ApptentiveTests/CriteriaTests.m +++ b/Apptentive/ApptentiveTests/CriteriaTests.m @@ -7,7 +7,7 @@ // #import "CriteriaTests.h" -#import "Apptentive.h" +#import "ApptentiveMain.h" #import "ApptentiveConversation.h" #import "ApptentiveDevice.h" #import "ApptentiveEngagement.h" diff --git a/Apptentive/ApptentiveTests/Info.plist b/Apptentive/ApptentiveTests/Info.plist index e1a203814..0b2a849d3 100644 --- a/Apptentive/ApptentiveTests/Info.plist +++ b/Apptentive/ApptentiveTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 5.2.14 + 5.3.0 CFBundleVersion 1 diff --git a/CHANGELOG.md b/CHANGELOG.md index bf27305d5..12b1c8c2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 2020-09-15 - v5.3.0 + +Version 5.3 adds support for iOS 14 and drops support for iOS versions prior to 10.3. + +Building projects with Xcode 12 and later *requires* using this version or a later one. + +#### Bugs Fixed + +* Fix an infinite loop/crash in Surveys on iOS 14 (when built with Xcode 12). +* Fix deprecation warnings. +* Fix a warning for framework headers included with double quotes. + # 2020-07-08 - v5.2.14 #### Bugs Fixed diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 1547d69c4..45ac916a3 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 01045DEB1CFF47CD00355633 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01045DE91CFF47CD00355633 /* LaunchScreen.xib */; }; 0116DA191BA37FA800E50BC3 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0116DA0E1BA37FA800E50BC3 /* Accelerate.framework */; }; - 0116DA1A1BA37FA800E50BC3 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0116DA0F1BA37FA800E50BC3 /* AssetsLibrary.framework */; }; 0116DA1B1BA37FA800E50BC3 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0116DA101BA37FA800E50BC3 /* CoreData.framework */; }; 0116DA1C1BA37FA800E50BC3 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0116DA111BA37FA800E50BC3 /* CoreGraphics.framework */; }; 0116DA1D1BA37FA800E50BC3 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0116DA121BA37FA800E50BC3 /* CoreTelephony.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; @@ -64,7 +63,6 @@ buildActionMask = 2147483647; files = ( 0116DA191BA37FA800E50BC3 /* Accelerate.framework in Frameworks */, - 0116DA1A1BA37FA800E50BC3 /* AssetsLibrary.framework in Frameworks */, 0116DA1B1BA37FA800E50BC3 /* CoreData.framework in Frameworks */, 0116DA1C1BA37FA800E50BC3 /* CoreGraphics.framework in Frameworks */, 0116DA1D1BA37FA800E50BC3 /* CoreTelephony.framework in Frameworks */, @@ -105,6 +103,7 @@ 0118C22E1B754945009D6C4B /* Pictures */, 0116DA2B1BA3800A00E50BC3 /* Frameworks */, 01045DE81CFE574900355633 /* iOSExample.app */, + 6417B5DF0CE198E77C165CB6 /* Pods */, ); sourceTree = ""; }; @@ -134,6 +133,13 @@ name = "Supporting Files"; sourceTree = ""; }; + 6417B5DF0CE198E77C165CB6 /* Pods */ = { + isa = PBXGroup; + children = ( + ); + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -162,13 +168,13 @@ attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Apptentive, Inc."; TargetAttributes = { 014E03391B7401A50059A3C6 = { CreatedOnToolsVersion = 6.4; DevelopmentTeam = 86WML2UN43; - LastSwiftMigration = 0920; + LastSwiftMigration = 1200; SystemCapabilities = { com.apple.InAppPurchase = { enabled = 0; @@ -179,7 +185,7 @@ }; buildConfigurationList = 014E03351B7401A50059A3C6 /* Build configuration list for PBXProject "Example" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -250,6 +256,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -268,6 +275,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -305,6 +313,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -323,6 +332,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -359,7 +369,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.apptentive.iOSExample; PRODUCT_NAME = iOSExample; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; name = Debug; @@ -374,7 +384,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.apptentive.iOSExample; PRODUCT_NAME = iOSExample; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; name = Release; diff --git a/Example/Example.xcodeproj/xcshareddata/xcschemes/iOSExample.xcscheme b/Example/Example.xcodeproj/xcshareddata/xcschemes/iOSExample.xcscheme index b3f71d45d..b57d2b4c7 100644 --- a/Example/Example.xcodeproj/xcshareddata/xcschemes/iOSExample.xcscheme +++ b/Example/Example.xcodeproj/xcshareddata/xcschemes/iOSExample.xcscheme @@ -1,6 +1,6 @@ - - - - - - - - Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { if let configuration = ApptentiveConfiguration(apptentiveKey: "<#Your Apptentive Key#>", apptentiveSignature: "<#Your Apptentive Signature#>") { precondition(configuration.apptentiveKey != "<#Your Apptentive Key#>" && configuration.apptentiveSignature != "<#Your Apptentive Signature#>", "Please set your Apptentive key and signature above") @@ -31,7 +31,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UITabBarControllerDelegat // MARK: Tab bar controller delegate func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { - if tabBarController.viewControllers?.index(of: viewController) ?? 0 == 0 { + if tabBarController.viewControllers?.firstIndex(of: viewController) ?? 0 == 0 { Apptentive.shared.engage(event: "photos_tab_selected", from: tabBarController) } else { Apptentive.shared.engage(event: "favorites_tab_selected", from: tabBarController) diff --git a/Example/iOSExample/PictureManager.swift b/Example/iOSExample/PictureManager.swift index 58ce4c8d7..9c0a38795 100644 --- a/Example/iOSExample/PictureManager.swift +++ b/Example/iOSExample/PictureManager.swift @@ -48,7 +48,7 @@ class PictureManager { } fileprivate func indexOfFavorite(_ picture: Picture) -> Int? { - return self.favoriteDataSource.pictures.index(of: picture) + return self.favoriteDataSource.pictures.firstIndex(of: picture) } func isFavorite(_ picture: Picture) -> Bool { diff --git a/Example/podfile b/Example/podfile index edd1d7c48..1a301c19c 100644 --- a/Example/podfile +++ b/Example/podfile @@ -1,4 +1,4 @@ -platform :ios, '9.0' +platform :ios, '10.3' use_frameworks! target 'iOSExample' do diff --git a/apptentive-ios.podspec b/apptentive-ios.podspec index c526494ee..53310cb2d 100644 --- a/apptentive-ios.podspec +++ b/apptentive-ios.podspec @@ -1,13 +1,13 @@ Pod::Spec.new do |s| s.name = 'apptentive-ios' s.module_name = 'Apptentive' - s.version = '5.2.14' + s.version = '5.3.0' s.license = 'BSD' s.summary = 'Apptentive Customer Communications SDK.' s.homepage = 'https://www.apptentive.com/' s.authors = { 'Apptentive SDK Team' => 'sdks@apptentive.com' } s.source = { :git => 'https://github.com/apptentive/apptentive-ios.git', :tag => "v#{s.version}" } - s.platform = :ios, '9.0' + s.platform = :ios, '10.3' s.source_files = 'Apptentive/Apptentive/**/*.{h,m}' s.requires_arc = true s.frameworks = 'AVFoundation', 'CoreData', 'CoreGraphics', 'Foundation', 'ImageIO', 'QuartzCore', 'QuickLook', 'SystemConfiguration', 'UIKit' @@ -22,5 +22,5 @@ Pod::Spec.new do |s| s.prefix_header_contents = '#import "ApptentiveLog.h"', '#import "ApptentiveAssert.h"', '#import "ApptentiveSafeCollections.h"' s.pod_target_xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS[config=Debug]" => "APPTENTIVE_DEBUG=1 APPTENTIVE_COCOAPODS=1", "GCC_PREPROCESSOR_DEFINITIONS[config=Release]" => "APPTENTIVE_COCOAPODS=1" } - s.public_header_files = 'Apptentive/Apptentive/Apptentive.h', 'Apptentive/Apptentive/ApptentiveStyleSheet.h' + s.public_header_files = 'Apptentive/Apptentive/Apptentive.h', 'Apptentive/Apptentive/ApptentiveMain.h', 'Apptentive/Apptentive/ApptentiveStyleSheet.h' end