From 9ac2f1422343cf32ac962200ee36749ce927fdab Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Mon, 22 Jan 2018 12:27:36 +0300 Subject: [PATCH 01/27] Use UIAlertController in the examples --- .../Guides/Set Custom AlertViewHandler.md | 163 +++++++++--------- 1 file changed, 80 insertions(+), 83 deletions(-) diff --git a/Documentation/Guides/Set Custom AlertViewHandler.md b/Documentation/Guides/Set Custom AlertViewHandler.md index b11ea780..15c64ed2 100644 --- a/Documentation/Guides/Set Custom AlertViewHandler.md +++ b/Documentation/Guides/Set Custom AlertViewHandler.md @@ -18,59 +18,63 @@ The following example shows how this could be implemented. We'll present a custo **Objective-C** ```objc -@interface BITAppDelegate () -@end - @implementation BITAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [self.window makeKeyAndVisible]; + [self.window makeKeyAndVisible]; - [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"<>" - delegate:nil]; - - // optionally enable logging to get more information about states. - [BITHockeyManager sharedHockeyManager].debugLogEnabled = YES; - - [[BITHockeyManager sharedHockeyManager].crashManager setAlertViewHandler:^(){ - NSString *exceptionReason = [[BITHockeyManager sharedHockeyManager].crashManager lastSessionCrashDetails].exceptionReason; - UIAlertView *customAlertView = [[UIAlertView alloc] initWithTitle: @"Oh no! The App crashed" - message: nil - delegate: self - cancelButtonTitle: @"Don't send" - otherButtonTitles: @"Send", @"Always send", nil]; - if (exceptionReason) { - customAlertView.message = @"We would like to send a crash report to the developers. Please enter a short description of what happened:"; - customAlertView.alertViewStyle = UIAlertViewStylePlainTextInput; - } else { - customAlertView.message = @"We would like to send a crash report to the developers"; - } + [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER" delegate:nil]; - [customAlertView show]; - }]; - - [[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; - - return YES; -} - -- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { - BITCrashMetaData *crashMetaData = [BITCrashMetaData new]; - if (alertView.alertViewStyle != UIAlertViewStyleDefault) { - crashMetaData.userDescription = [alertView textFieldAtIndex:0].text; - } - switch (buttonIndex) { - case 0: - [[BITHockeyManager sharedHockeyManager].crashManager handleUserInput:BITCrashManagerUserInputDontSend withUserProvidedMetaData:nil]; - break; - case 1: - [[BITHockeyManager sharedHockeyManager].crashManager handleUserInput:BITCrashManagerUserInputSend withUserProvidedMetaData:crashMetaData]; - break; - case 2: - [[BITHockeyManager sharedHockeyManager].crashManager handleUserInput:BITCrashManagerUserInputAlwaysSend withUserProvidedMetaData:crashMetaData]; - break; - } + // optionally enable logging to get more information about states. + [BITHockeyManager sharedHockeyManager].logLevel = BITLogLevelVerbose; + + [[BITHockeyManager sharedHockeyManager].crashManager setAlertViewHandler:^() { + NSString *exceptionReason = [[BITHockeyManager sharedHockeyManager].crashManager lastSessionCrashDetails].exceptionReason; + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Oh no! The App crashed" + message:@"We would like to send a crash report to the developers." + preferredStyle:UIAlertControllerStyleAlert]; + if (exceptionReason) { + alertController.message = [NSString stringWithFormat:@"%@ Please enter a short description of what happened:", alertController.message]; + [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.placeholder = @"Description"; + textField.keyboardType = UIKeyboardTypeDefault; + }]; + } + [alertController addAction:[UIAlertAction actionWithTitle:@"Don't send" + style:UIAlertActionStyleCancel + handler:^(UIAlertAction __unused *action) { + [[BITHockeyManager sharedHockeyManager].crashManager + handleUserInput:BITCrashManagerUserInputDontSend + withUserProvidedMetaData:nil]; + }]]; + [alertController addAction:[UIAlertAction actionWithTitle:@"Send" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction __unused *action) { + BITCrashMetaData *crashMetaData = [BITCrashMetaData new]; + if (exceptionReason) { + crashMetaData.userProvidedDescription = alertController.textFields[0].text; + } + [[BITHockeyManager sharedHockeyManager].crashManager + handleUserInput:BITCrashManagerUserInputSend + withUserProvidedMetaData:crashMetaData]; +c }]]; + [alertController addAction:[UIAlertAction actionWithTitle:@"Always send" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction __unused *action) { + BITCrashMetaData *crashMetaData = [BITCrashMetaData new]; + if (exceptionReason) { + crashMetaData.userProvidedDescription = alertController.textFields[0].text; + } + [[BITHockeyManager sharedHockeyManager].crashManager + handleUserInput:BITCrashManagerUserInputAlwaysSend + withUserProvidedMetaData:crashMetaData]; + }]]; + + [self.window.rootViewController presentViewController:alertController animated:YES completion:nil]; + }]; + + return YES; } @end @@ -79,55 +83,48 @@ The following example shows how this could be implemented. We'll present a custo **Swift** ```swift -import UIKit -import HockeySDK @UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate, UIAlertViewDelegate { - +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? - + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { window?.makeKeyAndVisible() - + BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER") + // optionally enable logging to get more information about states. BITHockeyManager.shared().logLevel = BITLogLevel.verbose - + BITHockeyManager.shared().crashManager.setAlertViewHandler { let exceptionReason = BITHockeyManager.shared().crashManager.lastSessionCrashDetails.exceptionReason - let customAlertView = UIAlertView.init(title: "Oh no! The App crashed", - message: "The App crashed", - delegate: self, - cancelButtonTitle: "Don't send", - otherButtonTitles: "Send", "Always send") - if (exceptionReason != nil) { - customAlertView.message = "We would like to send a crash report to the developers. Please enter a short description of what happened:" - customAlertView.alertViewStyle = UIAlertViewStyle.plainTextInput; - } else { - customAlertView.message = "We would like to send a crash report to the developers" + let alertController = UIAlertController(title: "Oh no! The App crashed", message: "We would like to send a crash report to the developers.", preferredStyle: .alert) + if exceptionReason != nil { + alertController.message = alertController.message! + " Please enter a short description of what happened:" + alertController.addTextField(configurationHandler: { (textField) in + textField.placeholder = "Description" + textField.keyboardType = .default + }) } - customAlertView.show() + alertController.addAction(UIAlertAction(title: "Don't send", style: .cancel, handler: { (action) in + BITHockeyManager.shared().crashManager.handle(BITCrashManagerUserInput.dontSend, withUserProvidedMetaData: nil) + })) + alertController.addAction(UIAlertAction(title: "Send", style: .default, handler: { (action) in + let crashMetaData = BITCrashMetaData() + crashMetaData.userProvidedDescription = alertController.textFields?[0].text + BITHockeyManager.shared().crashManager.handle(BITCrashManagerUserInput.send, withUserProvidedMetaData: crashMetaData) + })) + alertController.addAction(UIAlertAction(title: "Always send", style: .default, handler: { (action) in + let crashMetaData = BITCrashMetaData() + crashMetaData.userProvidedDescription = alertController.textFields?[0].text + BITHockeyManager.shared().crashManager.handle(BITCrashManagerUserInput.alwaysSend, withUserProvidedMetaData: crashMetaData) + })) + self.window?.rootViewController?.present(alertController, animated: true) } - + return true } - - func alertView(_ alertView: UIAlertView, didDismissWithButtonIndex buttonIndex: Int) { - let crashMetaData = BITCrashMetaData(); - if (alertView.alertViewStyle != UIAlertViewStyle.default) { - crashMetaData.userProvidedDescription = alertView.textField(at: 0)?.text - } - switch (buttonIndex) { - case 0: - BITHockeyManager.shared().crashManager.handle(BITCrashManagerUserInput.dontSend, withUserProvidedMetaData: nil) - case 1: - BITHockeyManager.shared().crashManager.handle(BITCrashManagerUserInput.send, withUserProvidedMetaData: crashMetaData) - case 2: - BITHockeyManager.shared().crashManager.handle(BITCrashManagerUserInput.alwaysSend, withUserProvidedMetaData: crashMetaData) - } - } } -``` - +``` From d48961dfb4a9a781cef9084720071f84e168794b Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Wed, 24 Jan 2018 16:38:50 +0300 Subject: [PATCH 02/27] Bump deployment target to iOS 9 --- Documentation/Guides/Installation & Setup.md | 6 +-- HockeySDK-Source.podspec | 2 +- HockeySDK.podspec | 2 +- Support/HockeySDK.xcodeproj/project.pbxproj | 56 ++++++++++---------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Documentation/Guides/Installation & Setup.md b/Documentation/Guides/Installation & Setup.md index 2ca0440c..9c6e5781 100644 --- a/Documentation/Guides/Installation & Setup.md +++ b/Documentation/Guides/Installation & Setup.md @@ -64,7 +64,7 @@ This document contains the following sections: ## 1. Requirements 1. We assume that you already have a project in Xcode and that this project is opened in Xcode 8 or later. -2. The SDK supports iOS 8.0 and later. +2. The SDK supports iOS 9.0 and later. ## 2. Setup @@ -215,7 +215,7 @@ Note that not using clang modules also means that you can't use the `@import` sy **Podfile** ```ruby -platform :ios, '8.0' +platform :ios, '9.0' pod "HockeySDK" ``` @@ -224,7 +224,7 @@ pod "HockeySDK" The default and recommended distribution is a binary (static library) and a resource bundle with translations and images for all SDK features. ```ruby -platform :ios, '8.0' +platform :ios, '9.0' pod "HockeySDK" ``` diff --git a/HockeySDK-Source.podspec b/HockeySDK-Source.podspec index ae63f81b..e04d3622 100644 --- a/HockeySDK-Source.podspec +++ b/HockeySDK-Source.podspec @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.author = { 'Microsoft' => 'support@hockeyapp.net' } s.source = { :git => 'https://github.com/bitstadium/HockeySDK-iOS.git', :tag => s.version.to_s } - s.platform = :ios, '8.0' + s.platform = :ios, '9.0' s.source_files = 'Classes' s.requires_arc = true diff --git a/HockeySDK.podspec b/HockeySDK.podspec index 99227a97..ce2eda9f 100644 --- a/HockeySDK.podspec +++ b/HockeySDK.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.license = { :type => 'MIT', :file => 'HockeySDK-iOS/LICENSE' } s.author = { 'Microsoft' => 'support@hockeyapp.net' } - s.platform = :ios, '8.0' + s.platform = :ios, '9.0' s.requires_arc = true s.preserve_path = 'HockeySDK-iOS/README.md' diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index 4011ac93..813fdf9e 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -2067,7 +2067,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; VALIDATE_PRODUCT = NO; @@ -2125,7 +2125,7 @@ "$(SRCROOT)/HockeySDKTests/Vendor/**", ); INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -2212,7 +2212,7 @@ HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "HockeySDK Framework/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.ios; @@ -2254,7 +2254,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = "$(SRCROOT)/HockeySDKTests/Vendor"; INFOPLIST_FILE = "HockeySDK FrameworkTests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -2431,7 +2431,7 @@ "$(SRCROOT)/HockeySDKTests/Vendor/**", ); INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -2489,7 +2489,7 @@ "$(SRCROOT)/HockeySDKTests/Vendor/**", ); INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -2564,8 +2564,8 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; @@ -2653,7 +2653,7 @@ "$(SRCROOT)/HockeySDKTests/Vendor/**", ); INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -2743,7 +2743,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "HockeySDK Framework/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.ios; @@ -2793,7 +2793,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "HockeySDK Framework/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.ios; @@ -2844,7 +2844,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "HockeySDK Framework/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.ios; @@ -2891,7 +2891,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = "$(SRCROOT)/HockeySDKTests/Vendor"; INFOPLIST_FILE = "HockeySDK FrameworkTests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -2955,7 +2955,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = "$(SRCROOT)/HockeySDKTests/Vendor"; INFOPLIST_FILE = "HockeySDK FrameworkTests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -3020,7 +3020,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = "$(SRCROOT)/HockeySDKTests/Vendor"; INFOPLIST_FILE = "HockeySDK FrameworkTests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -3096,7 +3096,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; VALIDATE_PRODUCT = NO; @@ -3154,7 +3154,7 @@ "$(SRCROOT)/HockeySDKTests/Vendor/**", ); INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -3241,7 +3241,7 @@ HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "HockeySDK Framework/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.ios; @@ -3283,7 +3283,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = "$(SRCROOT)/HockeySDKTests/Vendor"; INFOPLIST_FILE = "HockeySDK FrameworkTests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -3376,8 +3376,8 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; @@ -3435,7 +3435,7 @@ "$(SRCROOT)/HockeySDKTests/Vendor/**", ); INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -3521,7 +3521,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "HockeySDK Framework/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.ios; @@ -3563,7 +3563,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = "$(SRCROOT)/HockeySDKTests/Vendor"; INFOPLIST_FILE = "HockeySDK FrameworkTests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/HockeySDKTests/Vendor"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -3663,8 +3663,8 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; @@ -3711,8 +3711,8 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; From 84e99c559ea6e85fbb7c911aca9fa4e410df2db1 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Wed, 24 Jan 2018 17:37:47 +0300 Subject: [PATCH 03/27] Cleanup deprecations --- Classes/BITAttributedLabel.m | 1 - Classes/BITCrashManager.m | 9 ++-- Classes/BITFeedbackListViewCell.m | 27 ++--------- Classes/BITFeedbackManager.h | 2 +- Classes/BITImageAnnotationViewController.m | 55 +++------------------- Classes/BITStoreButton.m | 22 ++------- Classes/HockeySDK.h | 6 --- 7 files changed, 23 insertions(+), 99 deletions(-) diff --git a/Classes/BITAttributedLabel.m b/Classes/BITAttributedLabel.m index 0e48cea4..0ae1acf0 100644 --- a/Classes/BITAttributedLabel.m +++ b/Classes/BITAttributedLabel.m @@ -33,7 +33,6 @@ #define kBITLineBreakWordWrapTextWidthScalingFactor (M_PI / M_E) #pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wunused-variable" #pragma clang diagnostic ignored "-Wunused-parameter" #pragma clang diagnostic ignored "-Wcast-qual" diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index 61da7ad1..22a46549 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -478,7 +478,8 @@ - (void) registerObservers { NSNotificationName name = UIApplicationDidBecomeActiveNotification; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpartial-availability" - if (bit_isRunningInAppExtension() && &NSExtensionHostDidBecomeActiveNotification != NULL) { +#pragma clang diagnostic ignored "-Wtautological-pointer-compare" + if (bit_isRunningInAppExtension() && &NSExtensionHostDidBecomeActiveNotification != nil) { name = NSExtensionHostDidBecomeActiveNotification; } #pragma clang diagnostic pop @@ -515,7 +516,8 @@ - (void) registerObservers { NSNotificationName name = UIApplicationDidEnterBackgroundNotification; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpartial-availability" - if (bit_isRunningInAppExtension() && &NSExtensionHostDidEnterBackgroundNotification != NULL) { +#pragma clang diagnostic ignored "-Wtautological-pointer-compare" + if (bit_isRunningInAppExtension() && &NSExtensionHostDidEnterBackgroundNotification != nil) { name = NSExtensionHostDidEnterBackgroundNotification; } #pragma clang diagnostic pop @@ -532,7 +534,8 @@ - (void) registerObservers { NSNotificationName name = UIApplicationWillEnterForegroundNotification; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpartial-availability" - if (bit_isRunningInAppExtension() && &NSExtensionHostWillEnterForegroundNotification != NULL) { +#pragma clang diagnostic ignored "-Wtautological-pointer-compare" + if (bit_isRunningInAppExtension() && &NSExtensionHostWillEnterForegroundNotification != nil) { name = NSExtensionHostWillEnterForegroundNotification; } #pragma clang diagnostic pop diff --git a/Classes/BITFeedbackListViewCell.m b/Classes/BITFeedbackListViewCell.m index 59d661ad..2fb8daee 100644 --- a/Classes/BITFeedbackListViewCell.m +++ b/Classes/BITFeedbackListViewCell.m @@ -197,28 +197,11 @@ + (CGFloat) heightForRowWithMessage:(BITFeedbackMessage *)message tableViewWidth + (CGFloat) heightForTextInRowWithMessage:(BITFeedbackMessage *)message tableViewWidth:(CGFloat)width { - CGFloat calculatedHeight; - - if ([message.text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) { - CGRect calculatedRect = [message.text boundingRectWithSize:CGSizeMake(width - (2 * FRAME_SIDE_BORDER), CGFLOAT_MAX) - options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading - attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:TEXT_FONTSIZE]} - context:nil]; - calculatedHeight = calculatedRect.size.height + FRAME_TOP_BORDER + LABEL_TEXT_Y + FRAME_BOTTOM_BORDER; - - // added to make space for the images. - - - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - calculatedHeight = [message.text sizeWithFont:[UIFont systemFontOfSize:TEXT_FONTSIZE] - constrainedToSize:CGSizeMake(width - (2 * FRAME_SIDE_BORDER), CGFLOAT_MAX) - ].height + FRAME_TOP_BORDER + LABEL_TEXT_Y + FRAME_BOTTOM_BORDER; - -#pragma clang diagnostic pop - } - + CGRect calculatedRect = [message.text boundingRectWithSize:CGSizeMake(width - (2 * FRAME_SIDE_BORDER), CGFLOAT_MAX) + options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading + attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:TEXT_FONTSIZE]} + context:nil]; + CGFloat calculatedHeight = calculatedRect.size.height + FRAME_TOP_BORDER + LABEL_TEXT_Y + FRAME_BOTTOM_BORDER; return ceil(calculatedHeight); } diff --git a/Classes/BITFeedbackManager.h b/Classes/BITFeedbackManager.h index 507788df..ba4f4272 100644 --- a/Classes/BITFeedbackManager.h +++ b/Classes/BITFeedbackManager.h @@ -70,7 +70,7 @@ typedef NS_ENUM(NSInteger, BITFeedbackObservationMode) { */ BITFeedbackObservationNone = 0, /** - * Triggers when the user takes a screenshot. This will grab the latest image from the camera roll. Requires iOS 7 or later! + * Triggers when the user takes a screenshot. This will grab the latest image from the camera roll. */ BITFeedbackObservationModeOnScreenshot = 1, /** diff --git a/Classes/BITImageAnnotationViewController.m b/Classes/BITImageAnnotationViewController.m index f8d95972..763d5ef6 100644 --- a/Classes/BITImageAnnotationViewController.m +++ b/Classes/BITImageAnnotationViewController.m @@ -82,11 +82,6 @@ - (void)viewDidLoad { [self.editingControls setImage:bit_imageNamed(imageName, BITHOCKEYSDK_BUNDLE) forSegmentAtIndex:i++]; } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self.editingControls setSegmentedControlStyle:UISegmentedControlStyleBar]; -#pragma clang diagnostic pop - self.navigationItem.titleView = self.editingControls; self.objects = [NSMutableArray new]; @@ -349,50 +344,12 @@ - (void)pinched:(UIPinchGestureRecognizer *)gestureRecognizer { } - (void)tapped:(UIGestureRecognizer *) __unused tapRecognizer { - - // TODO: remove pre-iOS 8 code. - - // This toggles the nav and status bar. Since iOS7 and pre-iOS7 behave weirdly different, - // this might look rather hacky, but hiding the navbar under iOS6 leads to some ugly - // animation effect which is avoided by simply hiding the navbar setting it's alpha to 0. // moritzh - - if (self.navigationController.navigationBar.alpha == 0 || self.navigationController.navigationBarHidden ){ - - [UIView animateWithDuration:0.35 animations:^{ - [self.navigationController setNavigationBarHidden:NO animated:NO]; - - if ([self respondsToSelector:@selector(prefersStatusBarHidden)]) { - [self setNeedsStatusBarAppearanceUpdate]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[UIApplication sharedApplication] setStatusBarHidden:NO]; -#pragma clang diagnostic pop - } - - } completion:^(BOOL __unused finished) { - [self fitImageViewFrame]; - - }]; - } else { - [UIView animateWithDuration:0.35 animations:^{ - [self.navigationController setNavigationBarHidden:YES animated:NO]; - - if ([self respondsToSelector:@selector(prefersStatusBarHidden)]) { - [self setNeedsStatusBarAppearanceUpdate]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[UIApplication sharedApplication] setStatusBarHidden:YES]; -#pragma clang diagnostic pop - } - - } completion:^(BOOL __unused finished) { - [self fitImageViewFrame]; - - }]; - } - + [UIView animateWithDuration:0.35 animations:^{ + [self.navigationController setNavigationBarHidden:!self.prefersStatusBarHidden animated:NO]; + [self setNeedsStatusBarAppearanceUpdate]; + } completion:^(BOOL __unused finished) { + [self fitImageViewFrame]; + }]; } #pragma mark - Helpers diff --git a/Classes/BITStoreButton.m b/Classes/BITStoreButton.m index 8ac67a3e..8c4142f2 100644 --- a/Classes/BITStoreButton.m +++ b/Classes/BITStoreButton.m @@ -206,23 +206,11 @@ - (instancetype)initWithPadding:(CGPoint)padding style:(BITStoreButtonStyle)styl - (CGSize)sizeThatFits:(CGSize) __unused size { CGSize constr = (CGSize){.height = self.frame.size.height, .width = BIT_MAX_WIDTH}; - CGSize newSize; - - if ([self.buttonData.label respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) { - CGRect calculatedRect = [self.buttonData.label boundingRectWithSize:constr - options:NSStringDrawingUsesFontLeading - attributes:@{NSFontAttributeName:(id)self.titleLabel.font} - context:nil]; - newSize = calculatedRect.size; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - newSize = [self.buttonData.label sizeWithFont:self.titleLabel.font - constrainedToSize:constr - lineBreakMode:NSLineBreakByTruncatingMiddle]; -#pragma clang diagnostic pop - } - + CGRect calculatedRect = [self.buttonData.label boundingRectWithSize:constr + options:NSStringDrawingUsesFontLeading + attributes:@{NSFontAttributeName:(id)self.titleLabel.font} + context:nil]; + CGSize newSize = calculatedRect.size; CGFloat newWidth = newSize.width + ((CGFloat)BIT_PADDING * 2); CGFloat newHeight = (CGFloat)BIT_MIN_HEIGHT > newSize.height ? (CGFloat)BIT_MIN_HEIGHT : newSize.height; diff --git a/Classes/HockeySDK.h b/Classes/HockeySDK.h index 07abc822..26c02f0c 100644 --- a/Classes/HockeySDK.h +++ b/Classes/HockeySDK.h @@ -29,12 +29,6 @@ #import - -#if !defined (TARGET_OS_IOS) // Defined starting in iOS 9 -#define TARGET_OS_IOS 1 -#endif - - #import "HockeySDKFeatureConfig.h" #import "HockeySDKEnums.h" #import "HockeySDKNullability.h" From 81ff8ed1f234308920d8a766e9ff72f1d280619d Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Wed, 24 Jan 2018 20:01:25 +0300 Subject: [PATCH 04/27] Remove reduntant version checks --- Classes/BITFeedbackComposeViewController.m | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index de7274fb..a05f97ec 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -564,9 +564,7 @@ - (void)imageButtonAction:(UIButton *)sender { [self presentViewController:alertController animated:YES completion:nil]; self.actionSheetVisible = YES; - if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,0,0}])) { - [self.textView resignFirstResponder]; - } + [self.textView resignFirstResponder]; } @@ -619,10 +617,7 @@ - (void)deleteAction { self.selectedAttachmentIndex = NSNotFound; [self refreshAttachmentScrollview]; - - if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || ([[NSProcessInfo processInfo] respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,0,0}])) { - [self.textView becomeFirstResponder]; - } + [self.textView becomeFirstResponder]; } - (void)editAction { @@ -637,9 +632,7 @@ - (void)editAction { } - (void)cancelAction { - if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || ([[NSProcessInfo processInfo] respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,0,0}])) { - [self.textView becomeFirstResponder]; - } + [self.textView becomeFirstResponder]; } - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { From 4324a26923c202a3187254521462287f90bc86b8 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 25 Jan 2018 14:21:02 +0300 Subject: [PATCH 05/27] Fix images ratio in feedback's scrollview, remove action sheet delegate, cleanup --- Classes/BITFeedbackComposeViewController.m | 151 ++++++++------------- Classes/BITFeedbackMessageAttachment.m | 9 +- Classes/BITHockeyHelper.m | 3 +- 3 files changed, 59 insertions(+), 104 deletions(-) diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index a05f97ec..26117642 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -39,13 +39,17 @@ #import "BITFeedbackUserDataViewController.h" #import "BITHockeyBaseManagerPrivate.h" - #import "BITHockeyHelper.h" - #import "BITImageAnnotationViewController.h" #import "BITHockeyAttachment.h" -@interface BITFeedbackComposeViewController () { +#import + + +static const CGFloat kPhotoCompressionQuality = 0.7; +static const CGFloat kSscrollViewWidth = 100; + +@interface BITFeedbackComposeViewController () { } @property (nonatomic, weak) BITFeedbackManager *manager; @@ -319,19 +323,15 @@ - (void)viewDidDisappear:(BOOL)animated { - (void)refreshAttachmentScrollview { CGFloat scrollViewWidth = 0; - - if (self.imageAttachments.count){ - scrollViewWidth = 100; + if (self.imageAttachments.count) { + scrollViewWidth = kSscrollViewWidth; } CGRect textViewFrame = self.textView.frame; - CGRect scrollViewFrame = self.attachmentScrollView.frame; - BOOL alreadySetup = CGRectGetWidth(scrollViewFrame) > 0; - if (alreadySetup && self.imageAttachments.count == 0) { - textViewFrame.size.width += 100; + textViewFrame.size.width += kSscrollViewWidth; self.textView.frame = textViewFrame; scrollViewFrame.size.width = 0; self.attachmentScrollView.frame = scrollViewFrame; @@ -349,9 +349,9 @@ - (void)refreshAttachmentScrollview { self.attachmentScrollView.contentInset = self.textView.contentInset; } - if (self.imageAttachments.count > self.attachmentScrollViewImageViews.count){ + if (self.imageAttachments.count > self.attachmentScrollViewImageViews.count) { NSInteger numberOfViewsToCreate = self.imageAttachments.count - self.attachmentScrollViewImageViews.count; - for (int i = 0; i 0 ) { - self.navigationItem.rightBarButtonItem.enabled = YES; - } else { - self.navigationItem.rightBarButtonItem.enabled = NO; - } - - if(self.addPhotoButton) { - if (self.imageAttachments.count > 2){ - [self.addPhotoButton setEnabled:NO]; - } else { - [self.addPhotoButton setEnabled:YES]; - } + self.navigationItem.rightBarButtonItem.enabled = self.textView.text.length > 0; + if (self.addPhotoButton) { + [self.addPhotoButton setEnabled:self.imageAttachments.count <= 2]; } } @@ -500,9 +485,8 @@ - (void)paste:(id) __unused sender { - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *pickedImage = info[UIImagePickerControllerOriginalImage]; - - if (pickedImage){ - NSData *imageData = UIImageJPEGRepresentation(pickedImage, (CGFloat)0.7); + if (pickedImage) { + NSData *imageData = UIImageJPEGRepresentation(pickedImage, kPhotoCompressionQuality); BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment attachmentWithData:imageData contentType:@"image/jpeg"]; NSURL *imagePath = [info objectForKey:@"UIImagePickerControllerReferenceURL"]; NSString *imageName = [imagePath lastPathComponent]; @@ -510,7 +494,6 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking [self.attachments addObject:newAttachment]; [self.imageAttachments addObject:newAttachment]; } - [picker dismissViewControllerAnimated:YES completion:nil]; } @@ -518,49 +501,41 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:nil]; } +// Click on screenshot in the scroll view - (void)imageButtonAction:(UIButton *)sender { - // determine the index of the feedback - NSInteger index = [self.attachmentScrollViewImageViews indexOfObject:sender]; + // Determine the index of the feedback + NSInteger index = [self.attachmentScrollViewImageViews indexOfObject:sender]; self.selectedAttachmentIndex = (self.attachmentScrollViewImageViews.count - index - 1); __weak typeof(self) weakSelf = self; - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - - - UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentCancel") - style:UIAlertActionStyleCancel - handler:^(UIAlertAction __unused *action) { - typeof(self) strongSelf = weakSelf; - [strongSelf cancelAction]; - strongSelf.actionSheetVisible = NO; - }]; - - [alertController addAction:cancelAction]; - - UIAlertAction *editAction = [UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentEdit") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction __unused *action) { - typeof(self) strongSelf = weakSelf; - [strongSelf editAction]; - strongSelf.actionSheetVisible = NO; - }]; - - [alertController addAction:editAction]; - - UIAlertAction *deleteAction = [UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentDelete") - style:UIAlertActionStyleDestructive - handler:^(UIAlertAction __unused *action) { - typeof(self) strongSelf = weakSelf; - [strongSelf deleteAction]; - strongSelf.actionSheetVisible = NO; - }]; - - [alertController addAction:deleteAction]; - + [alertController + addAction:[UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentCancel") + style:UIAlertActionStyleCancel + handler:^(UIAlertAction __unused *action) { + typeof(self) strongSelf = weakSelf; + [strongSelf cancelAction]; + strongSelf.actionSheetVisible = NO; + }]]; + [alertController + addAction:[UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentEdit") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction __unused *action) { + typeof(self) strongSelf = weakSelf; + [strongSelf editAction]; + strongSelf.actionSheetVisible = NO; + }]]; + [alertController + addAction:[UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentDelete") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction __unused *action) { + typeof(self) strongSelf = weakSelf; + [strongSelf deleteAction]; + strongSelf.actionSheetVisible = NO; + }]]; [self presentViewController:alertController animated:YES completion:nil]; self.actionSheetVisible = YES; @@ -605,7 +580,7 @@ - (void)textViewDidChange:(UITextView *) __unused textView { #pragma mark - UIActionSheet Delegate - (void)deleteAction { - if (self.selectedAttachmentIndex != NSNotFound){ + if (self.selectedAttachmentIndex != NSNotFound) { UIButton *imageButton = self.attachmentScrollViewImageViews[self.selectedAttachmentIndex]; BITFeedbackMessageAttachment *attachment = self.imageAttachments[self.selectedAttachmentIndex]; [attachment deleteContents]; // mandatory call to delete the files associated. @@ -621,7 +596,7 @@ - (void)deleteAction { } - (void)editAction { - if (self.selectedAttachmentIndex != NSNotFound){ + if (self.selectedAttachmentIndex != NSNotFound) { BITFeedbackMessageAttachment *attachment = self.imageAttachments[self.selectedAttachmentIndex]; BITImageAnnotationViewController *annotationEditor = [[BITImageAnnotationViewController alloc ] init]; annotationEditor.delegate = self; @@ -635,24 +610,12 @@ - (void)cancelAction { [self.textView becomeFirstResponder]; } -- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { - if (buttonIndex == [actionSheet destructiveButtonIndex]) { - [self deleteAction]; - } else if (buttonIndex != [actionSheet cancelButtonIndex]) { - [self editAction]; - } else { - [self cancelAction]; - } - self.actionSheetVisible = NO; -} - - #pragma mark - Image Annotation Delegate - (void)annotationController:(BITImageAnnotationViewController *) __unused annotationController didFinishWithImage:(UIImage *)image { - if (self.selectedAttachmentIndex != NSNotFound){ + if (self.selectedAttachmentIndex != NSNotFound) { BITFeedbackMessageAttachment *attachment = self.imageAttachments[self.selectedAttachmentIndex]; - [attachment replaceData:UIImageJPEGRepresentation(image, (CGFloat)0.7)]; + [attachment replaceData:UIImageJPEGRepresentation(image, kPhotoCompressionQuality)]; } self.selectedAttachmentIndex = NSNotFound; diff --git a/Classes/BITFeedbackMessageAttachment.m b/Classes/BITFeedbackMessageAttachment.m index 1ea27ed7..a23bdd76 100644 --- a/Classes/BITFeedbackMessageAttachment.m +++ b/Classes/BITFeedbackMessageAttachment.m @@ -178,24 +178,17 @@ - (UIImage *)thumbnailWithSize:(CGSize)size { } CGFloat scale = [UIScreen mainScreen].scale; - if (scale != image.scale) { - CGSize scaledSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale)); - UIImage *thumbnail = bit_imageToFitSize(image, scaledSize, YES) ; - + UIImage *thumbnail = bit_imageToFitSize(image, scaledSize, YES); UIImage *scaledThumbnail = [UIImage imageWithCGImage:(CGImageRef)thumbnail.CGImage scale:scale orientation:thumbnail.imageOrientation]; if (thumbnail) { [self.thumbnailRepresentations setObject:scaledThumbnail forKey:cacheKey]; } - } else { UIImage *thumbnail = bit_imageToFitSize(image, size, YES) ; - [self.thumbnailRepresentations setObject:thumbnail forKey:cacheKey]; - } - } return self.thumbnailRepresentations[cacheKey]; diff --git a/Classes/BITHockeyHelper.m b/Classes/BITHockeyHelper.m index c4d6a1cc..47d22f17 100644 --- a/Classes/BITHockeyHelper.m +++ b/Classes/BITHockeyHelper.m @@ -736,8 +736,7 @@ BOOL bit_hasAlpha(UIImage *inputImage) { #pragma mark UIImage helpers UIImage *bit_imageToFitSize(UIImage *inputImage, CGSize fitSize, BOOL honorScaleFactor) { - - if (!inputImage){ + if (!inputImage) { return nil; } From ea6b16cdac6414eed1da0bb8dfda580c2db66472 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 25 Jan 2018 16:44:03 +0300 Subject: [PATCH 06/27] Fix feedback's scrollview position on orientation change and on iPhone X --- Classes/BITFeedbackComposeViewController.m | 146 ++++++++------------- 1 file changed, 52 insertions(+), 94 deletions(-) diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index 26117642..6932bbe9 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -58,6 +58,8 @@ @interface BITFeedbackComposeViewController () = __IPHONE_11_0 + if (@available(iOS 11, *)) { + UILayoutGuide *safeArea = self.view.safeAreaLayoutGuide; + self.contentViewContainer.translatesAutoresizingMaskIntoConstraints = NO; + [NSLayoutConstraint activateConstraints:@[ + [self.contentViewContainer.trailingAnchor constraintEqualToAnchor:safeArea.trailingAnchor], + [self.contentViewContainer.leadingAnchor constraintEqualToAnchor:safeArea.leadingAnchor], + [self.contentViewContainer.topAnchor constraintEqualToAnchor:safeArea.topAnchor], + [self.contentViewContainer.bottomAnchor constraintLessThanOrEqualToAnchor:safeArea.bottomAnchor] + ]]; + } +#endif + + // Message input textfield + self.textView = [[UITextView alloc] initWithFrame:CGRectZero]; self.textView.font = [UIFont systemFontOfSize:17]; self.textView.delegate = self; self.textView.backgroundColor = [UIColor whiteColor]; self.textView.returnKeyType = UIReturnKeyDefault; - self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.textView.accessibilityHint = BITHockeyLocalizedString(@"HockeyAccessibilityHintRequired"); [self.contentViewContainer addSubview:self.textView]; // Add Photo Button + Container that's displayed above the keyboard. - if([BITHockeyHelper isPhotoAccessPossible]) { + if ([BITHockeyHelper isPhotoAccessPossible]) { self.textAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44)]; self.textAccessoryView.backgroundColor = [UIColor colorWithRed:(CGFloat)0.9 green:(CGFloat)0.9 blue:(CGFloat)0.9 alpha:(CGFloat)1.0]; - + self.addPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom]; [self.addPhotoButton setTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentAddImage") forState:UIControlStateNormal]; [self.addPhotoButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal]; [self.addPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled]; self.addPhotoButton.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44); [self.addPhotoButton addTarget:self action:@selector(addPhotoAction:) forControlEvents:UIControlEventTouchUpInside]; - self.addPhotoButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin; + self.addPhotoButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; [self.textAccessoryView addSubview:self.addPhotoButton]; } - - if (!self.hideImageAttachmentButton) { self.textView.inputAccessoryView = self.textAccessoryView; } @@ -249,7 +246,7 @@ - (void)viewDidLoad { self.attachmentScrollView.scrollEnabled = YES; self.attachmentScrollView.bounces = YES; self.attachmentScrollView.autoresizesSubviews = NO; - self.attachmentScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleRightMargin; + self.attachmentScrollView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0 if (@available(iOS 11.0, *)) { self.attachmentScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAlways; @@ -260,12 +257,9 @@ - (void)viewDidLoad { - (void)viewWillAppear:(BOOL)animated { [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(keyboardWasShown:) - name:UIKeyboardDidShowNotification object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(keyboardWillBeHidden:) - name:UIKeyboardWillHideNotification object:nil]; + selector:@selector(keyboardWillChange:) + name:UIKeyboardWillChangeFrameNotification + object:nil]; self.manager.currentFeedbackComposeViewController = self; @@ -309,8 +303,7 @@ - (void)viewDidAppear:(BOOL)animated { } - (void)viewWillDisappear:(BOOL)animated { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil]; self.manager.currentFeedbackComposeViewController = nil; @@ -326,28 +319,9 @@ - (void)refreshAttachmentScrollview { if (self.imageAttachments.count) { scrollViewWidth = kSscrollViewWidth; } - - CGRect textViewFrame = self.textView.frame; - CGRect scrollViewFrame = self.attachmentScrollView.frame; - BOOL alreadySetup = CGRectGetWidth(scrollViewFrame) > 0; - if (alreadySetup && self.imageAttachments.count == 0) { - textViewFrame.size.width += kSscrollViewWidth; - self.textView.frame = textViewFrame; - scrollViewFrame.size.width = 0; - self.attachmentScrollView.frame = scrollViewFrame; - return; - } - - if (!alreadySetup) { - CGSize tempTextViewSize = CGSizeMake(self.contentViewContainer.frame.size.width, self.contentViewContainer.frame.size.height); - textViewFrame.size = tempTextViewSize; - textViewFrame.size.width -= scrollViewWidth; - // height has to be identical to the textview! - scrollViewFrame = CGRectMake(CGRectGetMaxX(textViewFrame), self.view.frame.origin.y, scrollViewWidth, CGRectGetHeight(self.textView.bounds)); - self.textView.frame = textViewFrame; - self.attachmentScrollView.frame = scrollViewFrame; - self.attachmentScrollView.contentInset = self.textView.contentInset; - } + CGSize contentSize = self.contentViewContainer.frame.size; + self.textView.frame = CGRectMake(0, 0, contentSize.width - scrollViewWidth, contentSize.height); + self.attachmentScrollView.frame = CGRectMake(CGRectGetMaxX(self.textView.frame), 0, scrollViewWidth, contentSize.height); if (self.imageAttachments.count > self.attachmentScrollViewImageViews.count) { NSInteger numberOfViewsToCreate = self.imageAttachments.count - self.attachmentScrollViewImageViews.count; @@ -373,7 +347,7 @@ - (void)refreshAttachmentScrollview { CGFloat scaleFactor = width / image.size.width; CGFloat height = round(image.size.height * scaleFactor); imageButton.frame = CGRectMake(offsetX, currentYOffset + offsetY, width, height); - currentYOffset += height; + currentYOffset += height + offsetY; [imageButton setImage:image forState:UIControlStateNormal]; index++; } @@ -399,22 +373,6 @@ - (void)removeAttachmentScrollView { self.textView.frame = frame; } - -#pragma mark - UIViewController Rotation - -- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ - return UIInterfaceOrientationMaskAll; -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" -- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation) __unused fromInterfaceOrientation { - [self removeAttachmentScrollView]; - - [self refreshAttachmentScrollview]; -} -#pragma clang diagnostic pop - #pragma mark - Private methods - (void)setUserDataAction { From 2230076386c625037d0a1d62a1cc17c172057a93 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 25 Jan 2018 17:48:46 +0300 Subject: [PATCH 07/27] Fix feedback layout on previous iOS versions --- Classes/BITFeedbackComposeViewController.m | 38 +++++++++++++--------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index 6932bbe9..18cf8be0 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -46,7 +46,7 @@ #import -static const CGFloat kPhotoCompressionQuality = 0.7; +static const CGFloat kPhotoCompressionQuality = (CGFloat)0.7; static const CGFloat kSscrollViewWidth = 100; @interface BITFeedbackComposeViewController () { @@ -157,8 +157,7 @@ - (void)keyboardWillChange:(NSNotification *)notification { NSDictionary *info = [notification userInfo]; NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; - CGRect screen = [UIScreen mainScreen].bounds; - self.keyboardConstraint.constant = keyboardFrame.origin.y - screen.size.height; + self.keyboardConstraint.constant = keyboardFrame.origin.y - CGRectGetHeight(self.view.frame); [UIView animateWithDuration:animationDuration animations:^{ [self.view layoutIfNeeded]; @@ -171,6 +170,7 @@ - (void)viewDidLoad { [super viewDidLoad]; self.title = BITHockeyLocalizedString(@"HockeyFeedbackComposeTitle"); + self.edgesForExtendedLayout = UIRectEdgeNone; self.view.backgroundColor = [UIColor whiteColor]; // Do any additional setup after loading the view. @@ -183,7 +183,8 @@ - (void)viewDidLoad { action:@selector(sendAction:)]; // Container that contains both the textfield and eventually the photo scroll view on the right side - self.contentViewContainer = [UIView new]; + self.contentViewContainer = [[UIView alloc] initWithFrame:self.view.bounds]; + self.contentViewContainer.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:self.contentViewContainer]; // Use keyboard constraint @@ -201,15 +202,22 @@ - (void)viewDidLoad { #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0 if (@available(iOS 11, *)) { UILayoutGuide *safeArea = self.view.safeAreaLayoutGuide; - self.contentViewContainer.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ - [self.contentViewContainer.trailingAnchor constraintEqualToAnchor:safeArea.trailingAnchor], - [self.contentViewContainer.leadingAnchor constraintEqualToAnchor:safeArea.leadingAnchor], - [self.contentViewContainer.topAnchor constraintEqualToAnchor:safeArea.topAnchor], - [self.contentViewContainer.bottomAnchor constraintLessThanOrEqualToAnchor:safeArea.bottomAnchor] - ]]; - } + [self.contentViewContainer.trailingAnchor constraintEqualToAnchor:safeArea.trailingAnchor], + [self.contentViewContainer.leadingAnchor constraintEqualToAnchor:safeArea.leadingAnchor], + [self.contentViewContainer.topAnchor constraintEqualToAnchor:safeArea.topAnchor], + [self.contentViewContainer.bottomAnchor constraintLessThanOrEqualToAnchor:safeArea.bottomAnchor] + ]]; + } else #endif + { + [NSLayoutConstraint activateConstraints:@[ + [self.contentViewContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], + [self.contentViewContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.contentViewContainer.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor], + [self.contentViewContainer.bottomAnchor constraintLessThanOrEqualToAnchor:self.bottomLayoutGuide.topAnchor] + ]]; + } // Message input textfield self.textView = [[UITextView alloc] initWithFrame:CGRectZero]; @@ -334,6 +342,8 @@ - (void)refreshAttachmentScrollview { } int index = 0; + const CGFloat offsetX = 10.0; + const CGFloat offsetY = 10.0; CGFloat currentYOffset = 0.0; NSEnumerator *reverseAttachments = self.imageAttachments.reverseObjectEnumerator; for (BITFeedbackMessageAttachment *attachment in reverseAttachments.allObjects) { @@ -341,9 +351,7 @@ - (void)refreshAttachmentScrollview { UIImage *image = [attachment thumbnailWithSize:CGSizeMake(kSscrollViewWidth, kSscrollViewWidth)]; // Scale to scrollview size with offsets - const CGFloat offsetX = 10.0; - const CGFloat offsetY = 10.0; - CGFloat width = kSscrollViewWidth - 2.0 * offsetX; + CGFloat width = kSscrollViewWidth - (CGFloat)2.0 * offsetX; CGFloat scaleFactor = width / image.size.width; CGFloat height = round(image.size.height * scaleFactor); imageButton.frame = CGRectMake(offsetX, currentYOffset + offsetY, width, height); @@ -352,7 +360,7 @@ - (void)refreshAttachmentScrollview { index++; } - [self.attachmentScrollView setContentSize:CGSizeMake(CGRectGetWidth(self.attachmentScrollView.frame), currentYOffset)]; + [self.attachmentScrollView setContentSize:CGSizeMake(CGRectGetWidth(self.attachmentScrollView.frame), currentYOffset + offsetY)]; [self updateBarButtonState]; } From 95a6eb1de6f8fa8adffc1902020b5bf3cc81235f Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 25 Jan 2018 18:27:28 +0300 Subject: [PATCH 08/27] Cleanup deprecations --- Classes/BITCrashCXXExceptionHandler.mm | 3 -- Classes/BITCrashReportTextFormatter.m | 4 +- Classes/BITFeedbackListViewController.h | 2 +- Classes/BITFeedbackListViewController.m | 55 +++++++------------------ Classes/BITUpdateViewController.m | 3 -- 5 files changed, 16 insertions(+), 51 deletions(-) diff --git a/Classes/BITCrashCXXExceptionHandler.mm b/Classes/BITCrashCXXExceptionHandler.mm index 233ab5ea..162d1164 100644 --- a/Classes/BITCrashCXXExceptionHandler.mm +++ b/Classes/BITCrashCXXExceptionHandler.mm @@ -130,8 +130,6 @@ static inline void BITCrashIterateExceptionHandlers_unlocked(const BITCrashUncau } } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" static void BITCrashUncaughtCXXTerminateHandler(void) { BITCrashUncaughtCXXExceptionInfo info = { @@ -240,7 +238,6 @@ + (void)removeCXXExceptionHandler:(BITCrashUncaughtCXXExceptionHandler)handler } } OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock); } -#pragma clang diagnostic pop @end diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 4c896802..03fdd032 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -277,8 +277,7 @@ + (NSString *)stringValueForCrashReport:(BITPLCrashReport *)report crashReporter if (codeType != nil) break; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /* If we were unable to determine the code type, fall back on the legacy architecture value. */ if (codeType == nil) { switch (report.systemInfo.architecture) { @@ -305,7 +304,6 @@ + (NSString *)stringValueForCrashReport:(BITPLCrashReport *)report crashReporter break; } } -#pragma GCC diagnostic pop } { diff --git a/Classes/BITFeedbackListViewController.h b/Classes/BITFeedbackListViewController.h index 62fd91d5..427ca708 100644 --- a/Classes/BITFeedbackListViewController.h +++ b/Classes/BITFeedbackListViewController.h @@ -55,7 +55,7 @@ This ensures that the presentation on iOS 6 and iOS 7 will use the current design on each OS Version. */ -@interface BITFeedbackListViewController : BITHockeyBaseViewController { +@interface BITFeedbackListViewController : BITHockeyBaseViewController { } @end diff --git a/Classes/BITFeedbackListViewController.m b/Classes/BITFeedbackListViewController.m index 09d05230..9cec36f9 100644 --- a/Classes/BITFeedbackListViewController.m +++ b/Classes/BITFeedbackListViewController.m @@ -373,8 +373,6 @@ - (void)feedbackComposeViewController:(BITFeedbackComposeViewController *)compos #pragma mark - UIViewController Rotation -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { self.numberOfSectionsBeforeRotation = [self numberOfSectionsInTableView:self.tableView]; self.numberOfMessagesBeforeRotation = [self.manager numberOfMessages]; @@ -388,7 +386,6 @@ - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrie [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; } -#pragma clang diagnostic pop - (UIInterfaceOrientationMask)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskAll; @@ -672,47 +669,23 @@ - (void)attributedLabel:(BITAttributedLabel *) __unused label didSelectLinkWithU UIAlertController *linkAction = [UIAlertController alertControllerWithTitle:[url absoluteString] message:nil preferredStyle:controllerStyle]; - UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionCancel") - style:UIAlertActionStyleCancel - handler:^(UIAlertAction __unused *action) {}]; - [linkAction addAction:cancelAction]; - UIAlertAction* openAction = [UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionOpen") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction __unused *action) { - [[UIApplication sharedApplication] openURL:(NSURL*)[NSURL URLWithString:(NSString*)[url absoluteString]]]; - }]; - [linkAction addAction:openAction]; - UIAlertAction* copyAction = [UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionCopy") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction __unused *action) { - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - pasteboard.URL = [NSURL URLWithString:(NSString*)[url absoluteString]]; - }]; - [linkAction addAction:copyAction]; + [linkAction addAction:[UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionCancel") + style:UIAlertActionStyleCancel + handler:nil]]; + [linkAction addAction:[UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionOpen") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction __unused *action) { + [[UIApplication sharedApplication] openURL:url]; + }]]; + [linkAction addAction:[UIAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionCopy") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction __unused *action) { + UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; + pasteboard.URL = url; + }]]; [self presentViewController:linkAction animated:YES completion:nil]; } -#pragma mark - UIActionSheetDelegate - -- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { - if (buttonIndex == actionSheet.cancelButtonIndex) { - return; - } - - if ([actionSheet tag] == 0) { - if (buttonIndex == [actionSheet destructiveButtonIndex]) { - [self deleteAllMessages]; - } - } else { - if (buttonIndex == [actionSheet firstOtherButtonIndex]) { - [[UIApplication sharedApplication] openURL:(NSURL *)[NSURL URLWithString:actionSheet.title]]; - } else { - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - pasteboard.URL = [NSURL URLWithString:actionSheet.title]; - } - } -} - #pragma mark - ListViewCellDelegate - (void)listCell:(id) __unused cell didSelectAttachment:(BITFeedbackMessageAttachment *)attachment { diff --git a/Classes/BITUpdateViewController.m b/Classes/BITUpdateViewController.m index ee9ab55d..9e5c7580 100644 --- a/Classes/BITUpdateViewController.m +++ b/Classes/BITUpdateViewController.m @@ -477,13 +477,10 @@ - (UITableViewCell *)tableView:(UITableView *) __unused tableView cellForRowAtIn #pragma mark - Rotation -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation) __unused interfaceOrientation duration:(NSTimeInterval) __unused duration { // update all cells [self.cells makeObjectsPerformSelector:@selector(addWebView)]; } -#pragma clang diagnostic pop #pragma mark - PSAppStoreHeaderDelegate From 5300f8a1b8f9d59a7620f28075df337a65d5ab2c Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 25 Jan 2018 18:38:52 +0300 Subject: [PATCH 09/27] Remove deprecated orientation callbacks --- Classes/BITFeedbackListViewController.m | 21 --------------------- Classes/BITUpdateViewController.m | 8 -------- 2 files changed, 29 deletions(-) diff --git a/Classes/BITFeedbackListViewController.m b/Classes/BITFeedbackListViewController.m index 9cec36f9..371f65e7 100644 --- a/Classes/BITFeedbackListViewController.m +++ b/Classes/BITFeedbackListViewController.m @@ -370,27 +370,6 @@ - (void)feedbackComposeViewController:(BITFeedbackComposeViewController *)compos } } - -#pragma mark - UIViewController Rotation - -- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - self.numberOfSectionsBeforeRotation = [self numberOfSectionsInTableView:self.tableView]; - self.numberOfMessagesBeforeRotation = [self.manager numberOfMessages]; - [self.tableView reloadData]; - [self.tableView beginUpdates]; - [self.tableView endUpdates]; - - self.numberOfSectionsBeforeRotation = -1; - self.numberOfMessagesBeforeRotation = -1; - [self.tableView reloadData]; - - [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; -} - -- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ - return UIInterfaceOrientationMaskAll; -} - #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *) __unused tableView { diff --git a/Classes/BITUpdateViewController.m b/Classes/BITUpdateViewController.m index 9e5c7580..4f28cc5a 100644 --- a/Classes/BITUpdateViewController.m +++ b/Classes/BITUpdateViewController.m @@ -474,14 +474,6 @@ - (UITableViewCell *)tableView:(UITableView *) __unused tableView cellForRowAtIn } } - -#pragma mark - Rotation - -- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation) __unused interfaceOrientation duration:(NSTimeInterval) __unused duration { - // update all cells - [self.cells makeObjectsPerformSelector:@selector(addWebView)]; -} - #pragma mark - PSAppStoreHeaderDelegate - (void)setAppStoreButtonState:(AppStoreButtonState)anAppStoreButtonState { From ea0dcaf44b548243f5d22a9240512e4a5729f922 Mon Sep 17 00:00:00 2001 From: Murat Baysangurov Date: Thu, 25 Jan 2018 22:38:25 +0300 Subject: [PATCH 10/27] Remove text metadata from png images --- Resources/AppIconPlaceHolder.png | Bin 12868 -> 10356 bytes Resources/Blur@3x.png | Bin 754 -> 276 bytes Resources/FeedbackPlaceholder.png | Bin 14384 -> 12756 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/AppIconPlaceHolder.png b/Resources/AppIconPlaceHolder.png index 02831a38fd04507841d80944e99ecafa37cafda6..2e4eb52e2d66b098d7da571352941e2905fb6a10 100644 GIT binary patch literal 10356 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 literal 754 zcmeAS@N?(olHy`uVBq!ia0vp^u0X8I!3HFMXf2ZiQY`6?zK#qG8~eHcB(ehe3dtTp zz6=aiY77hwEes65fIG?WUP)qwZeFo6#1NP{E~&-IMVSR9nfZANAafIw@=Hr>m6Sjh!2!gb zC7EdmoAQdG-U511A0(r1sAr%LHyfzc1|(|bUzC{&v>9Z+ouLg_C5jl-9vgj-S;EuBF(iZa?TkRaCIbQ1gB4zUCrm{bPuV1SsWf{E^hAK*Bp1c zAgjXSibaOK&JBN$xHi?l*z=DTydBOkBpn%Hgm?(}|HuAQM@bVakqD zgP4ELy(Lp({w;rf@W`ZprmQEpSQkimIxy7>&v?H>xrO)DBx|Q1ExFCV`u_c0$h*b9 z-HB0SxqZH4^^7`MRnxp%@!`8{jQ8-Y{&ijC2VVc)F!@0?^i(B_=>ywGSRy e1+?`6(AGVSw_G%(6}}~blbffjpUXO@geCxy=KM|o diff --git a/Resources/FeedbackPlaceholder.png b/Resources/FeedbackPlaceholder.png index 4f09d36195066f34ab39cf98f8bfd9f62bbc552d..41ea7bd7acfafe9b5655f876cc7860c74c3646df 100644 GIT binary patch literal 12756 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 i@c&I^*s6u-v`7jS1aX)&;x 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 From 03d49e99aa640432edee6a7051863f8014788ee9 Mon Sep 17 00:00:00 2001 From: Murat Baysangurov Date: Thu, 25 Jan 2018 22:42:31 +0300 Subject: [PATCH 11/27] Set strip png text metadata option to NO --- Support/HockeySDK.xcodeproj/project.pbxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index 4011ac93..444bba4e 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -2170,6 +2170,7 @@ PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.resources.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + STRIP_PNG_TEXT = NO; WRAPPER_EXTENSION = bundle; }; name = ReleaseCrashOnlyExtensions; @@ -2386,6 +2387,7 @@ PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.resources.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + STRIP_PNG_TEXT = NO; WRAPPER_EXTENSION = bundle; }; name = Debug; @@ -2399,6 +2401,7 @@ PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.resources.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + STRIP_PNG_TEXT = NO; WRAPPER_EXTENSION = bundle; }; name = ReleaseDefault; @@ -2609,6 +2612,7 @@ PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.resources.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + STRIP_PNG_TEXT = NO; WRAPPER_EXTENSION = bundle; }; name = ReleaseCrashOnly; @@ -3199,6 +3203,7 @@ PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.resources.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + STRIP_PNG_TEXT = NO; WRAPPER_EXTENSION = bundle; }; name = ReleaseFeedbackOnly; @@ -3480,6 +3485,7 @@ PRODUCT_BUNDLE_IDENTIFIER = net.hockeyapp.sdk.resources.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + STRIP_PNG_TEXT = NO; WRAPPER_EXTENSION = bundle; }; name = Release; From 8277dd8c9aa4f78fd29cc708fd6fbf83dc30afe1 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Wed, 28 Mar 2018 15:49:29 +0300 Subject: [PATCH 12/27] Use iOS 11 safe area for input accessory view --- Classes/BITFeedbackComposeViewController.m | 51 ++++++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index 18cf8be0..7df02f25 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -49,6 +49,27 @@ static const CGFloat kPhotoCompressionQuality = (CGFloat)0.7; static const CGFloat kSscrollViewWidth = 100; + +@interface InputAccessoryView : UIView +@end + +@implementation InputAccessoryView + +- (id)init { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.backgroundColor = [UIColor colorWithRed:(CGFloat)0.9 green:(CGFloat)0.9 blue:(CGFloat)0.9 alpha:(CGFloat)1.0]; + self.autoresizingMask = UIViewAutoresizingFlexibleHeight; + } + return self; +} + +- (CGSize)intrinsicContentSize { + return CGSizeZero; +} + +@end + @interface BITFeedbackComposeViewController () { } @@ -232,17 +253,39 @@ - (void)viewDidLoad { // Add Photo Button + Container that's displayed above the keyboard. if ([BITHockeyHelper isPhotoAccessPossible]) { - self.textAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44)]; - self.textAccessoryView.backgroundColor = [UIColor colorWithRed:(CGFloat)0.9 green:(CGFloat)0.9 blue:(CGFloat)0.9 alpha:(CGFloat)1.0]; self.addPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom]; [self.addPhotoButton setTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentAddImage") forState:UIControlStateNormal]; [self.addPhotoButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal]; [self.addPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled]; - self.addPhotoButton.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44); [self.addPhotoButton addTarget:self action:@selector(addPhotoAction:) forControlEvents:UIControlEventTouchUpInside]; - self.addPhotoButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + [self.addPhotoButton setTranslatesAutoresizingMaskIntoConstraints:NO]; + [NSLayoutConstraint activateConstraints:@[ + [self.addPhotoButton.heightAnchor constraintGreaterThanOrEqualToConstant:44] + ]]; + + self.textAccessoryView = [[InputAccessoryView alloc] init]; [self.textAccessoryView addSubview:self.addPhotoButton]; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0 + if (@available(iOS 11, *)) { + UILayoutGuide *safeArea = self.textAccessoryView.safeAreaLayoutGuide; + [NSLayoutConstraint activateConstraints:@[ + [self.addPhotoButton.leadingAnchor constraintEqualToAnchor:safeArea.leadingAnchor], + [self.addPhotoButton.trailingAnchor constraintEqualToAnchor:safeArea.trailingAnchor], + [self.addPhotoButton.topAnchor constraintEqualToAnchor:safeArea.topAnchor], + [self.addPhotoButton.bottomAnchor constraintEqualToAnchor:safeArea.bottomAnchor] + ]]; + } else +#endif + { + [NSLayoutConstraint activateConstraints:@[ + [self.addPhotoButton.leadingAnchor constraintEqualToAnchor:self.textAccessoryView.leadingAnchor], + [self.addPhotoButton.trailingAnchor constraintEqualToAnchor:self.textAccessoryView.trailingAnchor], + [self.addPhotoButton.topAnchor constraintEqualToAnchor:self.textAccessoryView.topAnchor], + [self.addPhotoButton.bottomAnchor constraintEqualToAnchor:self.textAccessoryView.bottomAnchor] + ]]; + } } if (!self.hideImageAttachmentButton) { From 060c2933090db974b2ee60fb80fcd9e56f17ea72 Mon Sep 17 00:00:00 2001 From: Piotr Wach Date: Tue, 24 Apr 2018 08:29:35 +0100 Subject: [PATCH 13/27] Make it possible to change current logging handler --- Classes/HockeySDK.h | 2 ++ Support/HockeySDK.xcodeproj/project.pbxproj | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Classes/HockeySDK.h b/Classes/HockeySDK.h index 26c02f0c..b206efb0 100644 --- a/Classes/HockeySDK.h +++ b/Classes/HockeySDK.h @@ -36,6 +36,8 @@ #import "BITHockeyManager.h" #import "BITHockeyManagerDelegate.h" +#import "BITHockeyLogger.h" + #if HOCKEYSDK_FEATURE_CRASH_REPORTER || HOCKEYSDK_FEATURE_FEEDBACK #import "BITHockeyAttachment.h" #endif diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index 0bfff9d8..c9257b3f 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -376,8 +376,8 @@ 807756411BC6B6050037C3DA /* HockeySDKEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = 8077563F1BC6A44D0037C3DA /* HockeySDKEnums.h */; settings = {ATTRIBUTES = (Public, ); }; }; 807F75051C9AEDAA009E6DCB /* BITChannelPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 807F75041C9AEDAA009E6DCB /* BITChannelPrivate.h */; }; 807F75061C9AEDAA009E6DCB /* BITChannelPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 807F75041C9AEDAA009E6DCB /* BITChannelPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8080576D1C5818AE00BB319D /* BITHockeyLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 8080576B1C5818AE00BB319D /* BITHockeyLogger.h */; }; - 8080576E1C5818AE00BB319D /* BITHockeyLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 8080576B1C5818AE00BB319D /* BITHockeyLogger.h */; }; + 8080576D1C5818AE00BB319D /* BITHockeyLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 8080576B1C5818AE00BB319D /* BITHockeyLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8080576E1C5818AE00BB319D /* BITHockeyLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 8080576B1C5818AE00BB319D /* BITHockeyLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8080576F1C5818AE00BB319D /* BITHockeyLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 8080576C1C5818AE00BB319D /* BITHockeyLogger.m */; }; 808057701C5818AE00BB319D /* BITHockeyLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 8080576C1C5818AE00BB319D /* BITHockeyLogger.m */; }; 80807B8C1C46BF2F00F4C44F /* OCHamcrestIOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80807B8A1C46BF2F00F4C44F /* OCHamcrestIOS.framework */; }; From 352f5b03589f0a6d982ca729fd65dc629dad2261 Mon Sep 17 00:00:00 2001 From: "Benjamin Scholtysik (Reimold)" Date: Fri, 15 Jun 2018 09:52:51 -0700 Subject: [PATCH 14/27] Remove code to magically authenticate using the itunesartwork. This is no longer working in iOS 8+ --- Classes/BITAuthenticator.m | 91 -------------------------------------- 1 file changed, 91 deletions(-) diff --git a/Classes/BITAuthenticator.m b/Classes/BITAuthenticator.m index 5a04d64d..6f272ce1 100644 --- a/Classes/BITAuthenticator.m +++ b/Classes/BITAuthenticator.m @@ -52,9 +52,6 @@ static NSString *const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAuthTokenTypeKey"; typedef unsigned int bit_uint32; -static unsigned char kBITPNGHeader[8] = {137, 80, 78, 71, 13, 10, 26, 10}; -static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44}; - @interface BITAuthenticator() @@ -158,7 +155,6 @@ - (void)identifyWithCompletion:(void (^)(BOOL identified, NSError *))completion return; } - [self processFullSizeImage]; if (self.identified) { if (completion) { completion(YES, nil); } return; @@ -766,93 +762,6 @@ - (void)cleanupInternalStorage { [self removeKeyFromKeychain:kBITAuthenticatorAuthTokenTypeKey]; } -- (void)processFullSizeImage { -#ifdef BIT_INTERNAL_DEBUG - NSString* path = [[NSBundle mainBundle] pathForResource:@"iTunesArtwork" ofType:@"png"]; -#else - NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/../iTunesArtwork"]; -#endif - - struct stat fs; - int fd = open([path UTF8String], O_RDONLY, 0); - if (fstat(fd, &fs) < 0) { - // File not found - close(fd); - return; - } - - BITHockeyLogDebug(@"Processing full size image for possible authentication"); - - unsigned char *buffer, *source; - source = (unsigned char *)malloc((unsigned long)fs.st_size); - if (read(fd, source, (unsigned long)fs.st_size) != fs.st_size) { - close(fd); - // Couldn't read file - free(source); - return; - } - - if ((fs.st_size < 20) || (memcmp(source, kBITPNGHeader, 8))) { - // Not a PNG - free(source); - return; - } - - buffer = source + 8; - - NSString *result = nil; - bit_uint32 length; - unsigned char *name; - unsigned char *data; - int chunk_index = 0; - long long bytes_left = fs.st_size - 8; - do { - memcpy(&length, buffer, 4); - length = ntohl(length); - - buffer += 4; - name = (unsigned char *)malloc(5); - name[4] = 0; - memcpy(name, buffer, 4); - - buffer += 4; - data = (unsigned char *)malloc(length + 1); - - if (bytes_left >= length) { - memcpy(data, buffer, length); - - buffer += length; - buffer += 4; - if (!strcmp((const char *)name, "tEXt")) { - data[length] = 0; - NSString *key = [NSString stringWithCString:(char *)data encoding:NSUTF8StringEncoding]; - - if ([key isEqualToString:@"Data"]) { - result = [NSString stringWithCString:(char *)(data + key.length + 1) encoding:NSUTF8StringEncoding]; - } - } - - if (!memcmp(name, kBITPNGEndChunk, 4)) { - chunk_index = 128; - } - } - - free(data); - free(name); - - bytes_left -= (length + 3 * 4); - } while ((chunk_index++ < 128) && (bytes_left > 8)); - - free(source); - - if (result) { - BITHockeyLogDebug(@"Authenticating using full size image information: %@", result); - [self handleOpenURL:[NSURL URLWithString:result] sourceApplication:nil annotation:nil]; - } else { - BITHockeyLogDebug(@"No authentication information found"); - } -} - #pragma mark - NSNotification - (void)registerObservers { From ba857432f48dcc949ab6b1d8ea343c1b1a0bdde8 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 21 Jun 2018 16:07:47 +0300 Subject: [PATCH 15/27] Fix part of "Messaging unqualified id" warnings --- Classes/BITAuthenticator.m | 10 +++++----- Classes/BITCrashManager.m | 22 +++++++++++----------- Classes/BITCrashManagerPrivate.h | 2 +- Classes/BITCrashReportTextFormatter.m | 4 ++-- Classes/BITFeedbackActivity.m | 2 +- Classes/BITFeedbackComposeViewController.m | 8 ++++---- Classes/BITFeedbackListViewCell.m | 2 +- Classes/BITFeedbackListViewController.m | 2 +- Classes/BITFeedbackManager.m | 14 +++++++------- Classes/BITHockeyBaseManager.m | 2 +- Classes/BITHockeyHelper.m | 2 +- Classes/BITHockeyManager.h | 2 ++ Classes/BITHockeyManagerDelegate.h | 7 +++++++ Classes/BITStoreUpdateManager.m | 2 +- Classes/BITStoreUpdateManagerPrivate.h | 2 +- Classes/BITUpdateManager.m | 10 +++++----- Classes/BITUpdateManagerPrivate.h | 2 +- Classes/BITUpdateViewController.m | 4 ---- 18 files changed, 52 insertions(+), 47 deletions(-) diff --git a/Classes/BITAuthenticator.m b/Classes/BITAuthenticator.m index 6f272ce1..b7e7248f 100644 --- a/Classes/BITAuthenticator.m +++ b/Classes/BITAuthenticator.m @@ -198,7 +198,7 @@ - (void)identifyWithCompletion:(void (^)(BOOL identified, NSError *))completion viewController.tableViewTitle = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerDataEmailDescription"); break; } - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(authenticator:willShowAuthenticationController:)]) { [strongDelegate authenticator:self willShowAuthenticationController:viewController]; } @@ -366,7 +366,7 @@ + (BOOL)isValidationResponseValid:(id)response error:(NSError *__autoreleasing * } return NO; } - if (![jsonObject isKindOfClass:[NSDictionary class]]) { + if (![(NSObject *)jsonObject isKindOfClass:[NSDictionary class]]) { if (error) { *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain code:BITAuthenticatorAPIServerReturnedInvalidResponse @@ -583,7 +583,7 @@ + (NSString *)authenticationTokenFromURLResponse:(NSHTTPURLResponse *)urlRespons options:0 error:&jsonParseError]; //no json or unexpected json - if (nil == jsonObject || ![jsonObject isKindOfClass:[NSDictionary class]]) { + if (nil == jsonObject || ![(NSObject *)jsonObject isKindOfClass:[NSDictionary class]]) { if (error) { NSDictionary *userInfo = @{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")}; if (jsonParseError) { @@ -714,7 +714,7 @@ + (NSString *)UDIDFromOpenURL:(NSURL *)url annotation:(id) __unused annotation { //there should actually only one static NSString *const UDIDQuerySpecifier = @"udid"; for (NSString *queryComponents in [query componentsSeparatedByString:@"&"]) { - NSArray *parameterComponents = [queryComponents componentsSeparatedByString:@"="]; + NSArray *parameterComponents = [queryComponents componentsSeparatedByString:@"="]; if (2 == parameterComponents.count && [parameterComponents[0] isEqualToString:UDIDQuerySpecifier]) { udid = parameterComponents[1]; break; @@ -729,7 +729,7 @@ + (void)email:(NSString *__autoreleasing *)email andIUID:(NSString *__autoreleas static NSString *const EmailQuerySpecifier = @"email"; static NSString *const IUIDQuerySpecifier = @"iuid"; for (NSString *queryComponents in [query componentsSeparatedByString:@"&"]) { - NSArray *parameterComponents = [queryComponents componentsSeparatedByString:@"="]; + NSArray *parameterComponents = [queryComponents componentsSeparatedByString:@"="]; if (email && 2 == parameterComponents.count && [parameterComponents[0] isEqualToString:EmailQuerySpecifier]) { *email = parameterComponents[1]; } else if (iuid && 2 == parameterComponents.count && [parameterComponents[0] isEqualToString:IUIDQuerySpecifier]) { diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index 22a46549..e5a6b5a6 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -685,7 +685,7 @@ - (NSString *)userIDForCrashReport { if (userIdFromKeychain) { userID = userIdFromKeychain; } - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(userIDForHockeyManager:componentManager:)]) { userID = [strongDelegate userIDForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self]; } @@ -700,7 +700,7 @@ - (NSString *)userIDForCrashReport { - (NSString *)userNameForCrashReport { // first check the global keychain storage NSString *username = [self stringValueFromKeychainForKey:kBITHockeyMetaUserName] ?: @""; - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(userNameForHockeyManager:componentManager:)]) { username = [strongDelegate userNameForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self] ?: @""; } @@ -727,7 +727,7 @@ - (NSString *)userEmailForCrashReport { useremail = self.installationIdentification; } #endif - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(userEmailForHockeyManager:componentManager:)]) { useremail = [strongDelegate userEmailForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self] ?: @""; } @@ -800,7 +800,7 @@ - (void)storeMetaDataForCrashReportFilename:(NSString *)filename { [self addStringValueToKeychain:[self userNameForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserName]]; [self addStringValueToKeychain:[self userEmailForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserEmail]]; [self addStringValueToKeychain:[self userIDForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserID]]; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(applicationLogForCrashManager:)]) { applicationLog = [strongDelegate applicationLogForCrashManager:self] ?: @""; } @@ -838,7 +838,7 @@ - (void)storeMetaDataForCrashReportFilename:(NSString *)filename { } - (BOOL)handleUserInput:(BITCrashManagerUserInput)userInput withUserProvidedMetaData:(BITCrashMetaData *)userProvidedMetaData { - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; switch (userInput) { case BITCrashManagerUserInputDontSend: if ([strongDelegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) { @@ -1002,7 +1002,7 @@ - (BOOL)hasPendingCrashReport { for (NSString *file in dirArray) { NSString *filePath = [self.crashesDir stringByAppendingPathComponent:file]; - NSDictionary *fileAttributes = [self.fileManager attributesOfItemAtPath:filePath error:&error]; + NSDictionary *fileAttributes = [self.fileManager attributesOfItemAtPath:filePath error:&error]; if ([[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeRegular] && [[fileAttributes objectForKey:NSFileSize] intValue] > 0 && ![file hasSuffix:@".DS_Store"] && @@ -1021,7 +1021,7 @@ - (BOOL)hasPendingCrashReport { return YES; } else { if (self.didCrashInLastSession) { - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) { [strongDelegate crashManagerWillCancelSendingCrashReport:self]; } @@ -1093,7 +1093,7 @@ - (void)invokeDelayedProcessing { #if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions) } else if (self.crashManagerStatus != BITCrashManagerStatusAutoSend && notApprovedReportFilename) { - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(crashManagerWillShowSubmitCrashReportAlert:)]) { [strongDelegate crashManagerWillShowSubmitCrashReportAlert:self]; } @@ -1266,7 +1266,7 @@ - (void)startManager { if (!didAppSwitchToBackgroundSafely) { BOOL considerReport = YES; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(considerAppNotTerminatedCleanlyReportForCrashManager:)]) { considerReport = [strongDelegate considerAppNotTerminatedCleanlyReportForCrashManager:self]; } @@ -1615,7 +1615,7 @@ - (void)processUploadResultWithFilename:(NSString *)filename responseData:(NSDat dispatch_async(dispatch_get_main_queue(), ^{ self.sendingInProgress = NO; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if (nil == theError) { if (nil == responseData || [responseData length] == 0) { theError = [NSError errorWithDomain:kBITCrashErrorDomain @@ -1698,7 +1698,7 @@ - (void)sendCrashReportWithFilename:(NSString *)filename xml:(NSString*)xml atta [uploadTask resume]; } - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(crashManagerWillSendCrashReport:)]) { [strongDelegate crashManagerWillSendCrashReport:self]; } diff --git a/Classes/BITCrashManagerPrivate.h b/Classes/BITCrashManagerPrivate.h index 0add0c80..25d5c9e6 100644 --- a/Classes/BITCrashManagerPrivate.h +++ b/Classes/BITCrashManagerPrivate.h @@ -51,7 +51,7 @@ @see `[BITHockeyManager setDelegate:]` */ -@property (nonatomic, weak) id delegate; +@property (nonatomic, weak) id delegate; /** * must be set diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 03fdd032..8cc5cd13 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -72,8 +72,8 @@ * Sort PLCrashReportBinaryImageInfo instances by their starting address. */ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *__unused context) { - uint64_t addr1 = [binary1 imageBaseAddress]; - uint64_t addr2 = [binary2 imageBaseAddress]; + uint64_t addr1 = [(BITPLCrashReportBinaryImageInfo *)binary1 imageBaseAddress]; + uint64_t addr2 = [(BITPLCrashReportBinaryImageInfo *)binary2 imageBaseAddress]; if (addr1 < addr2) return NSOrderedAscending; diff --git a/Classes/BITFeedbackActivity.m b/Classes/BITFeedbackActivity.m index 08e17750..652be5b4 100644 --- a/Classes/BITFeedbackActivity.m +++ b/Classes/BITFeedbackActivity.m @@ -111,7 +111,7 @@ - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems { } - (void)prepareWithActivityItems:(NSArray *)activityItems { - for (id item in activityItems) { + for (id item in activityItems) { if ([item isKindOfClass:[NSString class]] || [item isKindOfClass:[UIImage class]] || [item isKindOfClass:[NSData class]] || diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index 7df02f25..77387797 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -134,19 +134,19 @@ - (instancetype)init { #pragma mark - Public - (void)prepareWithItems:(NSArray *)items { - for (id item in items) { + for (id item in items) { if ([item isKindOfClass:[NSString class]]) { self.text = [(self.text ? self.text : @"") stringByAppendingFormat:@"%@%@", (self.text ? @" " : @""), item]; } else if ([item isKindOfClass:[NSURL class]]) { self.text = [(self.text ? self.text : @"") stringByAppendingFormat:@"%@%@", (self.text ? @" " : @""), [(NSURL *)item absoluteString]]; } else if ([item isKindOfClass:[UIImage class]]) { - UIImage *image = item; + UIImage *image = (UIImage *)item; BITFeedbackMessageAttachment *attachment = [BITFeedbackMessageAttachment attachmentWithData:UIImageJPEGRepresentation(image, (CGFloat)0.7) contentType:@"image/jpeg"]; attachment.originalFilename = [NSString stringWithFormat:@"Image_%li.jpg", (unsigned long)[self.attachments count]]; [self.attachments addObject:attachment]; [self.imageAttachments addObject:attachment]; } else if ([item isKindOfClass:[NSData class]]) { - BITFeedbackMessageAttachment *attachment = [BITFeedbackMessageAttachment attachmentWithData:item contentType:@"application/octet-stream"]; + BITFeedbackMessageAttachment *attachment = [BITFeedbackMessageAttachment attachmentWithData:(NSData *)item contentType:@"application/octet-stream"]; attachment.originalFilename = [NSString stringWithFormat:@"Attachment_%li.data", (unsigned long)[self.attachments count]]; [self.attachments addObject:attachment]; } else if ([item isKindOfClass:[BITHockeyAttachment class]]) { @@ -458,7 +458,7 @@ - (void)sendAction:(id) __unused sender { } - (void)dismissWithResult:(BITFeedbackComposeResult) result { - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if([strongDelegate respondsToSelector:@selector(feedbackComposeViewController:didFinishWithResult:)]) { [strongDelegate feedbackComposeViewController:self didFinishWithResult:result]; } else { diff --git a/Classes/BITFeedbackListViewCell.m b/Classes/BITFeedbackListViewCell.m index 2fb8daee..c58d510a 100644 --- a/Classes/BITFeedbackListViewCell.m +++ b/Classes/BITFeedbackListViewCell.m @@ -324,7 +324,7 @@ - (void)layoutSubviews { } - (void)imageButtonPressed:(id)sender { - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(listCell:didSelectAttachment:)]) { NSUInteger index = [self.attachmentViews indexOfObject:sender]; if (index != NSNotFound && [self.message previewableAttachments].count > index) { diff --git a/Classes/BITFeedbackListViewController.m b/Classes/BITFeedbackListViewController.m index 371f65e7..d4c5c211 100644 --- a/Classes/BITFeedbackListViewController.m +++ b/Classes/BITFeedbackListViewController.m @@ -364,7 +364,7 @@ - (void)feedbackComposeViewController:(BITFeedbackComposeViewController *)compos } else { [self dismissViewControllerAnimated:YES completion:^(void){}]; } - id strongDelegate = strongManager.delegate; + id strongDelegate = strongManager.delegate; if ([strongDelegate respondsToSelector:@selector(feedbackComposeViewController:didFinishWithResult:)]) { [strongDelegate feedbackComposeViewController:composeViewController didFinishWithResult:composeResult]; } diff --git a/Classes/BITFeedbackManager.m b/Classes/BITFeedbackManager.m index caaa619a..3946162f 100644 --- a/Classes/BITFeedbackManager.m +++ b/Classes/BITFeedbackManager.m @@ -227,7 +227,7 @@ - (BITFeedbackComposeViewController *)feedbackComposeViewController { BITFeedbackComposeViewController *composeViewController = [[BITFeedbackComposeViewController alloc] init]; NSArray *preparedItems = [NSArray array]; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(preparedItemsForFeedbackManager:)]) { preparedItems = [preparedItems arrayByAddingObjectsFromArray:(NSArray *)[strongDelegate preparedItemsForFeedbackManager:self]]; } @@ -288,7 +288,7 @@ - (void)startManager { - (BOOL)allowFetchingNewMessages { BOOL fetchNewMessages = YES; - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(allowAutomaticFetchingForNewFeedbackForManager:)]) { fetchNewMessages = [strongDelegate allowAutomaticFetchingForNewFeedbackForManager:self]; } @@ -317,7 +317,7 @@ - (BOOL)updateUserIDUsingKeychainAndDelegate { BOOL availableViaDelegate = NO; NSString *userID = [self stringValueFromKeychainForKey:kBITHockeyMetaUserID]; - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(userIDForHockeyManager:componentManager:)]) { userID = [strongDelegate userIDForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self]; } @@ -334,7 +334,7 @@ - (BOOL)updateUserNameUsingKeychainAndDelegate { BOOL availableViaDelegate = NO; NSString *userName = [self stringValueFromKeychainForKey:kBITHockeyMetaUserName]; - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(userNameForHockeyManager:componentManager:)]) { userName = [strongDelegate userNameForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self]; } @@ -352,7 +352,7 @@ - (BOOL)updateUserEmailUsingKeychainAndDelegate { BOOL availableViaDelegate = NO; NSString *userEmail = [self stringValueFromKeychainForKey:kBITHockeyMetaUserEmail]; - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(userEmailForHockeyManager:componentManager:)]) { userEmail = [strongDelegate userEmailForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self]; } @@ -649,7 +649,7 @@ - (void)deleteAllMessages { } - (BOOL)shouldForceNewThread { - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if (strongDelegate && [strongDelegate respondsToSelector:@selector(forceNewFeedbackThreadForFeedbackManager:)]) { return [strongDelegate forceNewFeedbackThreadForFeedbackManager:self]; } else { @@ -826,7 +826,7 @@ - (void)updateMessageListFromResponse:(NSDictionary *)jsonDictionary { BITFeedbackMessage *latestMessage = [self lastMessageHavingID]; if (self.userEmail && latestMessage.email && [self.userEmail compare:latestMessage.email] == NSOrderedSame) latestMessageFromUser = YES; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if (!latestMessageFromUser) { if ([strongDelegate respondsToSelector:@selector(feedbackManagerDidReceiveNewFeedback:)]) { [strongDelegate feedbackManagerDidReceiveNewFeedback:self]; diff --git a/Classes/BITHockeyBaseManager.m b/Classes/BITHockeyBaseManager.m index bf971881..6a1cff66 100644 --- a/Classes/BITHockeyBaseManager.m +++ b/Classes/BITHockeyBaseManager.m @@ -194,7 +194,7 @@ - (UINavigationController *)customNavigationControllerWithRootViewController:(UI - (UIViewController *)visibleWindowRootViewController { UIViewController *parentViewController = nil; - id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; + id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate; if ([strongDelegate respondsToSelector:@selector(viewControllerForHockeyManager:componentManager:)]) { parentViewController = [strongDelegate viewControllerForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self]; } diff --git a/Classes/BITHockeyHelper.m b/Classes/BITHockeyHelper.m index 47d22f17..4af664bf 100644 --- a/Classes/BITHockeyHelper.m +++ b/Classes/BITHockeyHelper.m @@ -95,7 +95,7 @@ static bit_info_t hockeyapp_library_info __attribute__((section("__TEXT,__bit_io NSFileManager *fileManager = [[NSFileManager alloc] init]; // temporary directory for crashes grabbed from PLCrashReporter - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); settingsDir = [[paths objectAtIndex:0] stringByAppendingPathComponent:BITHOCKEY_IDENTIFIER]; if (![fileManager fileExistsAtPath:settingsDir]) { diff --git a/Classes/BITHockeyManager.h b/Classes/BITHockeyManager.h index 1060a1f2..6774aa85 100644 --- a/Classes/BITHockeyManager.h +++ b/Classes/BITHockeyManager.h @@ -212,6 +212,8 @@ NS_ASSUME_NONNULL_BEGIN @see BITCrashManagerDelegate @see BITUpdateManagerDelegate @see BITFeedbackManagerDelegate + @see BITAuthenticatorDelegate + @see BITStoreUpdateManagerDelegate */ @property (nonatomic, weak, nullable) id delegate; diff --git a/Classes/BITHockeyManagerDelegate.h b/Classes/BITHockeyManagerDelegate.h index c4f099b7..ea863900 100644 --- a/Classes/BITHockeyManagerDelegate.h +++ b/Classes/BITHockeyManagerDelegate.h @@ -41,6 +41,10 @@ #import "BITFeedbackManagerDelegate.h" #endif +#if HOCKEYSDK_FEATURE_STORE_UPDATES +#import "BITStoreUpdateManagerDelegate.h" +#endif + #if HOCKEYSDK_FEATURE_AUTHENTICATOR #import "BITAuthenticator.h" #endif @@ -63,6 +67,9 @@ #if HOCKEYSDK_FEATURE_FEEDBACK , BITFeedbackManagerDelegate #endif +#if HOCKEYSDK_FEATURE_STORE_UPDATES + , BITStoreUpdateManagerDelegate +#endif #if HOCKEYSDK_FEATURE_AUTHENTICATOR , BITAuthenticatorDelegate #endif diff --git a/Classes/BITStoreUpdateManager.m b/Classes/BITStoreUpdateManager.m index 65e06a7c..d40ed578 100644 --- a/Classes/BITStoreUpdateManager.m +++ b/Classes/BITStoreUpdateManager.m @@ -300,7 +300,7 @@ - (BOOL)processStoreResponseWithString:(NSString *)responseString { } if ([self isUpdateAvailable]) { - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(detectedUpdateFromStoreUpdateManager:newVersion:storeURL:)]) { [strongDelegate detectedUpdateFromStoreUpdateManager:self newVersion:self.latestStoreVersion storeURL:[NSURL URLWithString:self.appStoreURLString]]; } diff --git a/Classes/BITStoreUpdateManagerPrivate.h b/Classes/BITStoreUpdateManagerPrivate.h index 156913c5..a092a43c 100644 --- a/Classes/BITStoreUpdateManagerPrivate.h +++ b/Classes/BITStoreUpdateManagerPrivate.h @@ -41,7 +41,7 @@ /** Sets the optional `BITStoreUpdateManagerDelegate` delegate. */ -@property (nonatomic, weak) id delegate; +@property (nonatomic, weak) id delegate; // is an update available? diff --git a/Classes/BITUpdateManager.m b/Classes/BITUpdateManager.m index c52bf7b9..d02fe6ec 100644 --- a/Classes/BITUpdateManager.m +++ b/Classes/BITUpdateManager.m @@ -111,7 +111,7 @@ - (void)didBecomeActiveActions { // was tapped, so we assume the user agreed if (self.didStartUpdateProcess) { self.didStartUpdateProcess = NO; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(updateManagerWillExitApp:)]) { [strongDelegate updateManagerWillExitApp:self]; } @@ -217,7 +217,7 @@ - (void)checkExpiryDateReached { if (![self expiryDateReached]) return; BOOL shouldShowDefaultAlert = YES; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(shouldDisplayExpiryAlertForUpdateManager:)]) { shouldShowDefaultAlert = [strongDelegate shouldDisplayExpiryAlertForUpdateManager:self]; } @@ -523,7 +523,7 @@ - (void)showUpdateView { - (void)showCheckForUpdateAlert { if (self.appEnvironment != BITEnvironmentOther) return; if ([self isUpdateManagerDisabled]) return; - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(shouldDisplayUpdateAlertForUpdateManager:forShortVersion:forVersion:)] && ![strongDelegate shouldDisplayUpdateAlertForUpdateManager:self forShortVersion:[self.newestAppVersion shortVersion] forVersion:[self.newestAppVersion version]]) { return; @@ -837,7 +837,7 @@ - (BOOL)initiateAppDownload { NSString *iOSUpdateURL = [NSString stringWithFormat:@"itms-services://?action=download-manifest&url=%@", bit_URLEncodedString(hockeyAPIURL)]; // Notify delegate of update intent before placing the call - id stronDelegate = self.delegate; + id stronDelegate = self.delegate; if ([stronDelegate respondsToSelector:@selector(willStartDownloadAndUpdate:)]) { [stronDelegate willStartDownloadAndUpdate:self]; } @@ -860,7 +860,7 @@ - (void)startManager { if ([self isUpdateManagerDisabled]) return; BITHockeyLogDebug(@"INFO: Starting UpdateManager"); - id strongDelegate = self.delegate; + id strongDelegate = self.delegate; if ([strongDelegate respondsToSelector:@selector(updateManagerShouldSendUsageData:)]) { self.sendUsageData = [strongDelegate updateManagerShouldSendUsageData:self]; } diff --git a/Classes/BITUpdateManagerPrivate.h b/Classes/BITUpdateManagerPrivate.h index f578247a..bb60aa91 100644 --- a/Classes/BITUpdateManagerPrivate.h +++ b/Classes/BITUpdateManagerPrivate.h @@ -50,7 +50,7 @@ @see `[BITHockeyManager setDelegate:]` */ -@property (nonatomic, weak) id delegate; +@property (nonatomic, weak) id delegate; // is an update available? diff --git a/Classes/BITUpdateViewController.m b/Classes/BITUpdateViewController.m index 4f28cc5a..d32a4c07 100644 --- a/Classes/BITUpdateViewController.m +++ b/Classes/BITUpdateViewController.m @@ -54,7 +54,6 @@ @interface BITUpdateViewController () @property (nonatomic) BOOL showAllVersions; @property (nonatomic, strong) BITAppStoreHeader *appStoreHeader; @property (nonatomic, strong) BITStoreButton *appStoreButton; -@property (nonatomic, strong) id popOverController; @property (nonatomic, strong) NSMutableArray *cells; @property (nonatomic) BITEnvironment appEnvironment; @@ -254,7 +253,6 @@ - (instancetype)initWithStyle:(UITableViewStyle) __unused style { self.title = BITHockeyLocalizedString(@"UpdateScreenTitle"); self.cells = [[NSMutableArray alloc] initWithCapacity:5]; - self.popOverController = nil; } return self; } @@ -336,8 +334,6 @@ - (void)viewWillAppear:(BOOL)animated { - (void)viewWillDisappear:(BOOL)animated { self.updateManager.currentHockeyViewController = nil; - //if the popover is still visible, dismiss it - [self.popOverController dismissPopoverAnimated:YES]; [super viewWillDisappear:animated]; } From a7deca2cfc467bb939507017faca6a77dc254aff Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 21 Jun 2018 17:37:01 +0300 Subject: [PATCH 16/27] Add casting to avoid warnings --- Classes/BITAppVersionMetaInfo.m | 4 +- Classes/BITAttributedLabel.m | 44 +++++++++++----------- Classes/BITCrashManager.m | 8 ++-- Classes/BITFeedbackComposeViewController.m | 4 +- Classes/BITFeedbackListViewCell.m | 2 +- Classes/BITFeedbackManager.m | 2 +- Classes/BITStoreUpdateManager.m | 2 +- Classes/BITUpdateManager.m | 6 +-- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Classes/BITAppVersionMetaInfo.m b/Classes/BITAppVersionMetaInfo.m index 3f4906e0..4814ce7e 100644 --- a/Classes/BITAppVersionMetaInfo.m +++ b/Classes/BITAppVersionMetaInfo.m @@ -45,7 +45,7 @@ + (BITAppVersionMetaInfo *)appVersionMetaInfoFromDict:(NSDictionary *)dict { appVersionMetaInfo.version = [dict objectForKey:@"version"]; appVersionMetaInfo.shortVersion = [dict objectForKey:@"shortversion"]; appVersionMetaInfo.minOSVersion = [dict objectForKey:@"minimum_os_version"]; - [appVersionMetaInfo setDateWithTimestamp:[[dict objectForKey:@"timestamp"] doubleValue]]; + [appVersionMetaInfo setDateWithTimestamp:[(NSNumber *)[dict objectForKey:@"timestamp"] doubleValue]]; appVersionMetaInfo.size = [dict objectForKey:@"appsize"]; appVersionMetaInfo.notes = [dict objectForKey:@"notes"]; appVersionMetaInfo.mandatory = [dict objectForKey:@"mandatory"]; @@ -62,7 +62,7 @@ + (BITAppVersionMetaInfo *)appVersionMetaInfoFromDict:(NSDictionary *)dict { - (BOOL)isEqual:(id)other { if (other == self) return YES; - if (!other || ![other isKindOfClass:[self class]]) + if (!other || ![(NSObject *)other isKindOfClass:[self class]]) return NO; return [self isEqualToAppVersionMetaInfo:other]; } diff --git a/Classes/BITAttributedLabel.m b/Classes/BITAttributedLabel.m index 0ae1acf0..458ba01f 100644 --- a/Classes/BITAttributedLabel.m +++ b/Classes/BITAttributedLabel.m @@ -881,9 +881,9 @@ - (void)drawBackground:(CTFrameRef)frame NSDictionary *attributes = (__bridge NSDictionary *)CTRunGetAttributes((__bridge CTRunRef) glyphRun); CGColorRef strokeColor = CGColorRefFromColor([attributes objectForKey:kBITBackgroundStrokeColorAttributeName]); CGColorRef fillColor = CGColorRefFromColor([attributes objectForKey:kBITBackgroundFillColorAttributeName]); - UIEdgeInsets fillPadding = [[attributes objectForKey:kBITBackgroundFillPaddingAttributeName] UIEdgeInsetsValue]; - CGFloat cornerRadius = [[attributes objectForKey:kBITBackgroundCornerRadiusAttributeName] floatValue]; - CGFloat lineWidth = [[attributes objectForKey:kBITBackgroundLineWidthAttributeName] floatValue]; + UIEdgeInsets fillPadding = [(NSValue *)[attributes objectForKey:kBITBackgroundFillPaddingAttributeName] UIEdgeInsetsValue]; + CGFloat cornerRadius = [(NSNumber *)[attributes objectForKey:kBITBackgroundCornerRadiusAttributeName] floatValue]; + CGFloat lineWidth = [(NSNumber *)[attributes objectForKey:kBITBackgroundLineWidthAttributeName] floatValue]; if (strokeColor || fillColor) { CGRect runBounds = CGRectZero; @@ -950,8 +950,8 @@ - (void)drawStrike:(CTFrameRef)frame for (id glyphRun in (__bridge NSArray *)CTLineGetGlyphRuns((__bridge CTLineRef)line)) { NSDictionary *attributes = (__bridge NSDictionary *)CTRunGetAttributes((__bridge CTRunRef) glyphRun); - BOOL strikeOut = [[attributes objectForKey:kBITStrikeOutAttributeName] boolValue]; - NSInteger superscriptStyle = [[attributes objectForKey:(id)kCTSuperscriptAttributeName] integerValue]; + BOOL strikeOut = [(NSNumber *)[attributes objectForKey:kBITStrikeOutAttributeName] boolValue]; + NSInteger superscriptStyle = [(NSNumber *)[attributes objectForKey:(id)kCTSuperscriptAttributeName] integerValue]; if (strikeOut) { CGRect runBounds = CGRectZero; @@ -1018,9 +1018,9 @@ - (void)drawStrike:(CTFrameRef)frame #pragma mark - BITAttributedLabel - (void)setText:(id)text { - NSParameterAssert(!text || [text isKindOfClass:[NSAttributedString class]] || [text isKindOfClass:[NSString class]]); + NSParameterAssert(!text || [(NSObject *)text isKindOfClass:[NSAttributedString class]] || [(NSObject *)text isKindOfClass:[NSString class]]); - if ([text isKindOfClass:[NSString class]]) { + if ([(NSObject *)text isKindOfClass:[NSString class]]) { [self setText:text afterInheritingLabelAttributesAndConfiguringWithBlock:nil]; return; } @@ -1050,7 +1050,7 @@ - (void)setText:(id)text { [self.attributedText enumerateAttribute:NSLinkAttributeName inRange:NSMakeRange(0, self.attributedText.length) options:0 usingBlock:^(id value, NSRange range, __unused BOOL *stop) { if (value) { - NSURL *URL = [value isKindOfClass:[NSString class]] ? [NSURL URLWithString:value] : value; + NSURL *URL = [(NSObject *)value isKindOfClass:[NSString class]] ? [NSURL URLWithString:value] : value; [self addLinkToURL:URL withRange:range]; } }]; @@ -1060,7 +1060,7 @@ - (void)setText:(id)text afterInheritingLabelAttributesAndConfiguringWithBlock:(NSMutableAttributedString * (^)(NSMutableAttributedString *mutableAttributedString))block { NSMutableAttributedString *mutableAttributedString = nil; - if ([text isKindOfClass:[NSString class]]) { + if ([(NSObject *)text isKindOfClass:[NSString class]]) { mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:text attributes:NSAttributedStringAttributesFromLabel(self)]; } else { mutableAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:text]; @@ -1298,7 +1298,7 @@ - (NSArray *)accessibilityElements { continue; } - NSString *sourceText = [self.text isKindOfClass:[NSString class]] ? self.text : [(NSAttributedString *)self.text string]; + NSString *sourceText = [(NSObject *)self.text isKindOfClass:[NSString class]] ? self.text : [(NSAttributedString *)self.text string]; NSString *accessibilityLabel = [sourceText substringWithRange:link.result.range]; NSString *accessibilityValue = link.accessibilityValue; @@ -1630,7 +1630,7 @@ - (id)initWithCoder:(NSCoder *)coder { [self commonInit]; if ([coder containsValueForKey:NSStringFromSelector(@selector(enabledTextCheckingTypes))]) { - self.enabledTextCheckingTypes = [[coder decodeObjectForKey:NSStringFromSelector(@selector(enabledTextCheckingTypes))] unsignedLongLongValue]; + self.enabledTextCheckingTypes = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(enabledTextCheckingTypes))] unsignedLongLongValue]; } if ([NSMutableParagraphStyle class]) { @@ -1657,11 +1657,11 @@ - (id)initWithCoder:(NSCoder *)coder { } if ([coder containsValueForKey:NSStringFromSelector(@selector(shadowRadius))]) { - self.shadowRadius = [[coder decodeObjectForKey:NSStringFromSelector(@selector(shadowRadius))] floatValue]; + self.shadowRadius = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(shadowRadius))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(highlightedShadowRadius))]) { - self.highlightedShadowRadius = [[coder decodeObjectForKey:NSStringFromSelector(@selector(highlightedShadowRadius))] floatValue]; + self.highlightedShadowRadius = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(highlightedShadowRadius))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(highlightedShadowOffset))]) { @@ -1673,27 +1673,27 @@ - (id)initWithCoder:(NSCoder *)coder { } if ([coder containsValueForKey:NSStringFromSelector(@selector(kern))]) { - self.kern = [[coder decodeObjectForKey:NSStringFromSelector(@selector(kern))] floatValue]; + self.kern = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(kern))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(firstLineIndent))]) { - self.firstLineIndent = [[coder decodeObjectForKey:NSStringFromSelector(@selector(firstLineIndent))] floatValue]; + self.firstLineIndent = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(firstLineIndent))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(lineSpacing))]) { - self.lineSpacing = [[coder decodeObjectForKey:NSStringFromSelector(@selector(lineSpacing))] floatValue]; + self.lineSpacing = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(lineSpacing))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(minimumLineHeight))]) { - self.minimumLineHeight = [[coder decodeObjectForKey:NSStringFromSelector(@selector(minimumLineHeight))] floatValue]; + self.minimumLineHeight = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(minimumLineHeight))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(maximumLineHeight))]) { - self.maximumLineHeight = [[coder decodeObjectForKey:NSStringFromSelector(@selector(maximumLineHeight))] floatValue]; + self.maximumLineHeight = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(maximumLineHeight))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(lineHeightMultiple))]) { - self.lineHeightMultiple = [[coder decodeObjectForKey:NSStringFromSelector(@selector(lineHeightMultiple))] floatValue]; + self.lineHeightMultiple = [(NSNumber *)[coder decodeObjectForKey:NSStringFromSelector(@selector(lineHeightMultiple))] floatValue]; } if ([coder containsValueForKey:NSStringFromSelector(@selector(textInsets))]) { @@ -1802,7 +1802,7 @@ - (id)initWithCoder:(NSCoder *)aDecoder { #pragma mark - static inline CGColorRef CGColorRefFromColor(id color) { - return [color isKindOfClass:[UIColor class]] ? [color CGColor] : (__bridge CGColorRef)color; + return [(NSObject *)color isKindOfClass:[UIColor class]] ? [(UIColor *)color CGColor] : (__bridge CGColorRef)color; } static inline CTFontRef CTFontRefFromUIFont(UIFont * font) { @@ -1831,9 +1831,9 @@ static inline CTFontRef CTFontRefFromUIFont(UIFont * font) { key = [NSToCTAttributeNamesMap objectForKey:key] ? : key; if (![NSMutableParagraphStyle class]) { - if ([value isKindOfClass:[UIFont class]]) { + if ([(NSObject *)value isKindOfClass:[UIFont class]]) { value = (__bridge id)CTFontRefFromUIFont(value); - } else if ([value isKindOfClass:[UIColor class]]) { + } else if ([(NSObject *)value isKindOfClass:[UIColor class]]) { value = (__bridge id)((UIColor *)value).CGColor; } } diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index e5a6b5a6..6ad4591c 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -610,11 +610,11 @@ - (void)appEnteredForeground { static dispatch_once_t predAppData; dispatch_once(&predAppData, ^{ - id marketingVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + id marketingVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; if (marketingVersion && [marketingVersion isKindOfClass:[NSString class]]) [[NSUserDefaults standardUserDefaults] setObject:marketingVersion forKey:kBITAppMarketingVersion]; - id bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; + id bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; if (bundleVersion && [bundleVersion isKindOfClass:[NSString class]]) [[NSUserDefaults standardUserDefaults] setObject:bundleVersion forKey:kBITAppVersion]; @@ -1003,8 +1003,8 @@ - (BOOL)hasPendingCrashReport { NSString *filePath = [self.crashesDir stringByAppendingPathComponent:file]; NSDictionary *fileAttributes = [self.fileManager attributesOfItemAtPath:filePath error:&error]; - if ([[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeRegular] && - [[fileAttributes objectForKey:NSFileSize] intValue] > 0 && + if ([(NSString *)[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeRegular] && + [(NSNumber *)[fileAttributes objectForKey:NSFileSize] intValue] > 0 && ![file hasSuffix:@".DS_Store"] && ![file hasSuffix:@".analyzer"] && ![file hasSuffix:@".plist"] && diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index 77387797..e948a677 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -176,8 +176,8 @@ - (void)prepareWithItems:(NSArray *)items { - (void)keyboardWillChange:(NSNotification *)notification { NSDictionary *info = [notification userInfo]; - NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; - CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; + NSTimeInterval animationDuration = [(NSNumber *)[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + CGRect keyboardFrame = [(NSValue *)[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; self.keyboardConstraint.constant = keyboardFrame.origin.y - CGRectGetHeight(self.view.frame); [UIView animateWithDuration:animationDuration animations:^{ diff --git a/Classes/BITFeedbackListViewCell.m b/Classes/BITFeedbackListViewCell.m index c58d510a..bac44bbf 100644 --- a/Classes/BITFeedbackListViewCell.m +++ b/Classes/BITFeedbackListViewCell.m @@ -148,7 +148,7 @@ - (void) updateAttachmentFromNotification:(NSNotification *)note { if (!self.message.attachments) return; if (self.message.attachments.count == 0) return; if (!note.object) return; - if (![note.object isKindOfClass:[BITFeedbackMessageAttachment class]]) return; + if (![(NSObject *)note.object isKindOfClass:[BITFeedbackMessageAttachment class]]) return; BITFeedbackMessageAttachment *attachment = (BITFeedbackMessageAttachment *)note.object; if (![self.message.attachments containsObject:attachment]) return; diff --git a/Classes/BITFeedbackManager.m b/Classes/BITFeedbackManager.m index 3946162f..9a3a8e23 100644 --- a/Classes/BITFeedbackManager.m +++ b/Classes/BITFeedbackManager.m @@ -762,7 +762,7 @@ - (void)updateMessageListFromResponse:(NSDictionary *)jsonDictionary { // TODO: match messages in state conflict [messagesSendInProgress enumerateObjectsUsingBlock:^(id objSendInProgressMessage, NSUInteger __unused messagesSendInProgressIdx, BOOL *stop2) { - if ([[(NSDictionary *) objMessage objectForKey:@"token"] isEqualToString:[(BITFeedbackMessage *) objSendInProgressMessage token]]) { + if ([(NSString *)[(NSDictionary *) objMessage objectForKey:@"token"] isEqualToString:[(BITFeedbackMessage *) objSendInProgressMessage token]]) { matchingSendInProgressOrInConflictMessage = objSendInProgressMessage; *stop2 = YES; } diff --git a/Classes/BITStoreUpdateManager.m b/Classes/BITStoreUpdateManager.m index d40ed578..1e52574f 100644 --- a/Classes/BITStoreUpdateManager.m +++ b/Classes/BITStoreUpdateManager.m @@ -179,7 +179,7 @@ - (BOOL)hasNewVersion:(NSDictionary *)dictionary { NSString *lastStoreVersion = [self lastStoreVersion]; - if ([[dictionary objectForKey:@"results"] isKindOfClass:[NSArray class]] && + if ([(NSObject *)[dictionary objectForKey:@"results"] isKindOfClass:[NSArray class]] && [(NSArray *)[dictionary objectForKey:@"results"] count] > 0 ) { self.lastCheckFailed = NO; diff --git a/Classes/BITUpdateManager.m b/Classes/BITUpdateManager.m index d02fe6ec..7a173b41 100644 --- a/Classes/BITUpdateManager.m +++ b/Classes/BITUpdateManager.m @@ -353,7 +353,7 @@ - (void)checkUpdateAvailable { [self saveAppCache]; } else { [self.appVersions enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - if (idx > 0 && [obj isKindOfClass:[BITAppVersionMetaInfo class]]) { + if (idx > 0 && [(NSObject *)obj isKindOfClass:[BITAppVersionMetaInfo class]]) { NSComparisonResult compareVersions = bit_versionCompare([(BITAppVersionMetaInfo *)obj version], self.currentAppVersion); BOOL uuidFound = [(BITAppVersionMetaInfo *)obj hasUUID:self.uuid]; @@ -449,7 +449,7 @@ - (instancetype)init { if ([[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateDateOfLastCheck]) { // we did write something else in the past, so for compatibility reasons do this id tempLastCheck = [[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateDateOfLastCheck]; - if ([tempLastCheck isKindOfClass:[NSDate class]]) { + if ([(NSObject *)tempLastCheck isKindOfClass:[NSDate class]]) { _lastCheck = tempLastCheck; } } @@ -907,7 +907,7 @@ - (void)finishLoading { NSError *error = nil; NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:(NSData *)[responseString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error]; - self.companyName = (([[json valueForKey:@"company"] isKindOfClass:[NSString class]]) ? [json valueForKey:@"company"] : nil); + self.companyName = (([(NSObject *)[json valueForKey:@"company"] isKindOfClass:[NSString class]]) ? [json valueForKey:@"company"] : nil); if (self.appEnvironment == BITEnvironmentOther) { NSArray *feedArray = (NSArray *)[json valueForKey:@"versions"]; From 7c8aa1cc664541d405f121ae1f74c355c89b3532 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Fri, 6 Jul 2018 14:57:39 +0300 Subject: [PATCH 17/27] Fix application state check --- Classes/BITCrashManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index 6ad4591c..4bd429f6 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -1281,7 +1281,7 @@ - (void)startManager { } #if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions) - if ([BITHockeyHelper applicationState] != BITApplicationStateActive) { + if ([BITHockeyHelper applicationState] == BITApplicationStateActive) { [self appEnteredForeground]; } #else From 3551bd42918259be79aa160170f67dce1f16c271 Mon Sep 17 00:00:00 2001 From: "Benjamin Scholtysik (Reimold)" Date: Wed, 18 Jul 2018 13:21:51 -0700 Subject: [PATCH 18/27] Remove the bitrise badge --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index fc2126c6..537cb36a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -[![Build Status](https://app.bitrise.io/app/30bf519f6bd0a5e2/status.svg?token=RKqHc7-ojjLiEFds53d-ZA&branch=master)](https://app.bitrise.io/app/30bf519f6bd0a5e2) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Version](http://cocoapod-badges.herokuapp.com/v/HockeySDK/badge.png)](http://cocoadocs.org/docsets/HockeySDK) [![Slack Status](https://slack.hockeyapp.net/badge.svg)](https://slack.hockeyapp.net) From ca00851a9decfecf947946b4a4853d4da00555fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Fri, 21 Sep 2018 22:17:03 +0200 Subject: [PATCH 19/27] Use correct built-in CPU subtypes --- Classes/BITCrashReportTextFormatter.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 4c896802..9b07eaf3 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -773,11 +773,11 @@ + (NSString *)bit_archNameFromCPUType:(uint64_t)cpuType subType:(uint64_t)subTyp case CPU_TYPE_ARM64: /* Apple includes subtype for ARM64 binaries. */ switch (subType) { - case CPU_SUBTYPE_ARM_ALL: + case CPU_SUBTYPE_ARM64_ALL: archName = @"arm64"; break; - case CPU_SUBTYPE_ARM_V8: + case CPU_SUBTYPE_ARM64_V8: archName = @"arm64"; break; From 8a6ba86afadd7ab6d1875bdd538a22e6fff4bcb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Fri, 21 Sep 2018 22:17:58 +0200 Subject: [PATCH 20/27] Remove no longer needed custom CPU subtype definitions --- Classes/BITCrashReportTextFormatter.m | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 9b07eaf3..1d7c6e4f 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -52,21 +52,6 @@ #import "BITCrashReportTextFormatter.h" -/* - * XXX: The ARM64 CPU type, and ARM_V7S and ARM_V8 Mach-O CPU subtypes are not - * defined in the Mac OS X 10.8 headers. - */ -#ifndef CPU_SUBTYPE_ARM_V7S -# define CPU_SUBTYPE_ARM_V7S 11 -#endif - -#ifndef CPU_TYPE_ARM64 -#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) -#endif - -#ifndef CPU_SUBTYPE_ARM_V8 -# define CPU_SUBTYPE_ARM_V8 13 -#endif /** * Sort PLCrashReportBinaryImageInfo instances by their starting address. From 60f3011ea14d6486afcc086b408cbe7d757b0d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Fri, 21 Sep 2018 22:20:13 +0200 Subject: [PATCH 21/27] Minor formatting fixes --- Classes/BITCrashReportTextFormatter.m | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 1d7c6e4f..a4c51225 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -449,8 +449,9 @@ + (NSString *)stringValueForCrashReport:(BITPLCrashReport *)report crashReporter #if TARGET_OS_SIMULATOR if (lp64) { foundSelector = [[self class] selectorForRegisterWithName:@"rsi" ofThread:crashed_thread report:report]; - if (foundSelector == NULL) + if (foundSelector == NULL) { foundSelector = [[self class] selectorForRegisterWithName:@"rdx" ofThread:crashed_thread report:report]; + } } else { foundSelector = [[self class] selectorForRegisterWithName:@"ecx" ofThread:crashed_thread report:report]; } @@ -482,7 +483,7 @@ + (NSString *)stringValueForCrashReport:(BITPLCrashReport *)report crashReporter * post-processed report, Apple writes this out as full frame entries. We use the latter format. */ for (NSUInteger frame_idx = 0; frame_idx < [exception.stackFrames count]; frame_idx++) { BITPLCrashReportStackFrameInfo *frameInfo = exception.stackFrames[frame_idx]; - [text appendString: [[self class] bit_formatStackFrame: frameInfo frameIndex: frame_idx report: report lp64: lp64]]; + [text appendString: [[self class] bit_formatStackFrame:frameInfo frameIndex:frame_idx report:report lp64:lp64]]; } [text appendString: @"\n"]; } @@ -628,8 +629,9 @@ + (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(BITPLCra } } - if (regAddress == 0) + if (regAddress == 0) { return nil; + } BITPLCrashReportBinaryImageInfo *imageForRegAddress = [report imageForAddress:regAddress]; if (imageForRegAddress) { From b2519c1aca9532e2e24c124e918a5a665a24044f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Fri, 21 Sep 2018 22:19:25 +0200 Subject: [PATCH 22/27] Add temporary custom ARM V8.3 CPU subtype --- Classes/BITCrashReportTextFormatter.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index a4c51225..3644c498 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -52,6 +52,12 @@ #import "BITCrashReportTextFormatter.h" +/** + * With Xcode 10, the new ARM64 V8_3A architecture, used by iPhone XS and XR, is not yet in the headers. + */ +#ifndef CPU_SUBTYPE_ARM64_V8_3 +# define CPU_SUBTYPE_ARM64_V8_3 ((cpu_subtype_t) 2) +#endif /** * Sort PLCrashReportBinaryImageInfo instances by their starting address. From cb9bda21e911ebf5e32407d4d474ad7ce4e62970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Fri, 21 Sep 2018 22:20:37 +0200 Subject: [PATCH 23/27] Add handling of new arm64e CPU subtype --- Classes/BITCrashReportTextFormatter.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 3644c498..05ac4a9e 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -774,6 +774,10 @@ + (NSString *)bit_archNameFromCPUType:(uint64_t)cpuType subType:(uint64_t)subTyp archName = @"arm64"; break; + case CPU_SUBTYPE_ARM64_V8_3: + archName = @"arm64e"; + break; + default: archName = @"arm64-unknown"; break; From 357292dc3bd1c17502bc4dc659e6355996f0ee7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Fri, 21 Sep 2018 22:21:00 +0200 Subject: [PATCH 24/27] Normalize 64bit addresses to remove possible pointer signatures --- Classes/BITCrashReportTextFormatter.m | 35 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 05ac4a9e..251fa82c 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -454,20 +454,21 @@ + (NSString *)stringValueForCrashReport:(BITPLCrashReport *)report crashReporter // search the registers value for the current arch #if TARGET_OS_SIMULATOR if (lp64) { - foundSelector = [[self class] selectorForRegisterWithName:@"rsi" ofThread:crashed_thread report:report]; + foundSelector = [[self class] selectorForRegisterWithName:@"rsi" ofThread:crashed_thread report:report lp64:lp64]; if (foundSelector == NULL) { - foundSelector = [[self class] selectorForRegisterWithName:@"rdx" ofThread:crashed_thread report:report]; + foundSelector = [[self class] selectorForRegisterWithName:@"rdx" ofThread:crashed_thread report:report lp64:lp64]; } } else { - foundSelector = [[self class] selectorForRegisterWithName:@"ecx" ofThread:crashed_thread report:report]; + foundSelector = [[self class] selectorForRegisterWithName:@"ecx" ofThread:crashed_thread report:report lp64:lp64]; } #else if (lp64) { - foundSelector = [[self class] selectorForRegisterWithName:@"x1" ofThread:crashed_thread report:report]; + foundSelector = [[self class] selectorForRegisterWithName:@"x1" ofThread:crashed_thread report:report lp64:lp64]; } else { - foundSelector = [[self class] selectorForRegisterWithName:@"r1" ofThread:crashed_thread report:report]; - if (foundSelector == NULL) - foundSelector = [[self class] selectorForRegisterWithName:@"r2" ofThread:crashed_thread report:report]; + foundSelector = [[self class] selectorForRegisterWithName:@"r1" ofThread:crashed_thread report:report lp64:lp64]; + if (foundSelector == NULL) { + foundSelector = [[self class] selectorForRegisterWithName:@"r2" ofThread:crashed_thread report:report lp64:lp64]; + } } #endif @@ -624,7 +625,7 @@ + (NSString *)stringValueForCrashReport:(BITPLCrashReport *)report crashReporter * * @return The selector as a C string or NULL if no selector was found */ -+ (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(BITPLCrashReportThreadInfo *)thread report:(BITPLCrashReport *)report { ++ (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(BITPLCrashReportThreadInfo *)thread report:(BITPLCrashReport *)report lp64:(boolean_t)lp64 { // get the address for the register uint64_t regAddress = 0; @@ -639,6 +640,11 @@ + (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(BITPLCra return nil; } + // When on an ARM64 architecture, normalize the address to remove possible pointer signatures + if (lp64) { + regAddress = regAddress & 0x0000000fffffffff; + } + BITPLCrashReportBinaryImageInfo *imageForRegAddress = [report imageForAddress:regAddress]; if (imageForRegAddress) { // get the SEL @@ -827,11 +833,16 @@ + (NSString *)bit_formatStackFrame: (BITPLCrashReportStackFrameInfo *) frameInfo NSString *imageName = @"\?\?\?"; NSString *symbolString = nil; - BITPLCrashReportBinaryImageInfo *imageInfo = [report imageForAddress: frameInfo.instructionPointer]; + // When on an ARM64 architecture, normalize the address to remove possible pointer signatures + uint64_t instructionPointer = lp64 ? (frameInfo.instructionPointer & 0x0000000fffffffff) : frameInfo.instructionPointer; + uint64_t untouchedInstructionPointer = frameInfo.instructionPointer; + + BITPLCrashReportBinaryImageInfo *imageInfo = [report imageForAddress: instructionPointer]; + if (imageInfo != nil) { imageName = [imageInfo.imageName lastPathComponent]; baseAddress = imageInfo.imageBaseAddress; - pcOffset = frameInfo.instructionPointer - imageInfo.imageBaseAddress; + pcOffset = instructionPointer - imageInfo.imageBaseAddress; } /* Make sure UTF8/16 characters are handled correctly */ @@ -877,7 +888,7 @@ + (NSString *)bit_formatStackFrame: (BITPLCrashReportStackFrameInfo *) frameInfo } - uint64_t symOffset = frameInfo.instructionPointer - frameInfo.symbolInfo.startAddress; + uint64_t symOffset = instructionPointer - frameInfo.symbolInfo.startAddress; symbolString = [NSString stringWithFormat: @"%@ + %" PRId64, symbolName, symOffset]; } else { symbolString = [NSString stringWithFormat: @"0x%" PRIx64 " + %" PRId64, baseAddress, pcOffset]; @@ -889,7 +900,7 @@ + (NSString *)bit_formatStackFrame: (BITPLCrashReportStackFrameInfo *) frameInfo return [NSString stringWithFormat: @"%-4ld%-35S 0x%0*" PRIx64 " %@\n", (long) frameIndex, (const uint16_t *)[imageName cStringUsingEncoding: NSUTF16StringEncoding], - lp64 ? 16 : 8, frameInfo.instructionPointer, + lp64 ? 16 : 8, untouchedInstructionPointer, symbolString]; } From d023277b136afca9aef0d0c6c517de04050fa2d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Tue, 25 Sep 2018 03:03:41 +0200 Subject: [PATCH 25/27] Improve variable names for normalized memory addresses --- Classes/BITCrashReportTextFormatter.m | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 251fa82c..20a93959 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -641,14 +641,15 @@ + (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(BITPLCra } // When on an ARM64 architecture, normalize the address to remove possible pointer signatures + uint64_t normalizedRegAddress = regAddress; if (lp64) { - regAddress = regAddress & 0x0000000fffffffff; + normalizedRegAddress = regAddress & 0x0000000fffffffff; } - BITPLCrashReportBinaryImageInfo *imageForRegAddress = [report imageForAddress:regAddress]; + BITPLCrashReportBinaryImageInfo *imageForRegAddress = [report imageForAddress:normalizedRegAddress]; if (imageForRegAddress) { // get the SEL - const char *foundSelector = findSEL([imageForRegAddress.imageName UTF8String], imageForRegAddress.imageUUID, regAddress - (uint64_t)imageForRegAddress.imageBaseAddress); + const char *foundSelector = findSEL([imageForRegAddress.imageName UTF8String], imageForRegAddress.imageUUID, normalizedRegAddress - (uint64_t)imageForRegAddress.imageBaseAddress); if (foundSelector != NULL) { return [NSString stringWithUTF8String:foundSelector]; @@ -834,15 +835,15 @@ + (NSString *)bit_formatStackFrame: (BITPLCrashReportStackFrameInfo *) frameInfo NSString *symbolString = nil; // When on an ARM64 architecture, normalize the address to remove possible pointer signatures - uint64_t instructionPointer = lp64 ? (frameInfo.instructionPointer & 0x0000000fffffffff) : frameInfo.instructionPointer; + uint64_t normalizedInstructionPointer = lp64 ? (frameInfo.instructionPointer & 0x0000000fffffffff) : frameInfo.instructionPointer; uint64_t untouchedInstructionPointer = frameInfo.instructionPointer; - BITPLCrashReportBinaryImageInfo *imageInfo = [report imageForAddress: instructionPointer]; + BITPLCrashReportBinaryImageInfo *imageInfo = [report imageForAddress: normalizedInstructionPointer]; if (imageInfo != nil) { imageName = [imageInfo.imageName lastPathComponent]; baseAddress = imageInfo.imageBaseAddress; - pcOffset = instructionPointer - imageInfo.imageBaseAddress; + pcOffset = normalizedInstructionPointer - imageInfo.imageBaseAddress; } /* Make sure UTF8/16 characters are handled correctly */ @@ -888,7 +889,7 @@ + (NSString *)bit_formatStackFrame: (BITPLCrashReportStackFrameInfo *) frameInfo } - uint64_t symOffset = instructionPointer - frameInfo.symbolInfo.startAddress; + uint64_t symOffset = normalizedInstructionPointer - frameInfo.symbolInfo.startAddress; symbolString = [NSString stringWithFormat: @"%@ + %" PRId64, symbolName, symOffset]; } else { symbolString = [NSString stringWithFormat: @"0x%" PRIx64 " + %" PRId64, baseAddress, pcOffset]; From f864840bb3d17f8c5d747dac06650c09ecc6495d Mon Sep 17 00:00:00 2001 From: "Benjamin Scholtysik (Reimold)" Date: Tue, 25 Sep 2018 18:12:50 -0700 Subject: [PATCH 26/27] Bump version and write changelog --- Documentation/Guides/Changelog.md | 7 +++++++ Documentation/Guides/Installation & Setup.md | 8 ++++---- Documentation/HockeySDK/.jazzy.yaml | 2 +- HockeySDK-Source.podspec | 4 ++-- HockeySDK.podspec | 2 +- README.md | 10 +++++----- Support/HockeySDKBase.xcconfig | 4 ++-- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Documentation/Guides/Changelog.md b/Documentation/Guides/Changelog.md index 64aa7af5..bf187283 100644 --- a/Documentation/Guides/Changelog.md +++ b/Documentation/Guides/Changelog.md @@ -1,3 +1,10 @@ +## 5.1.3 + +- [FIX] Support new arm64e architecture in crash reports. [#527](https://github.com/bitstadium/HockeySDK-iOS/pull/526) +- [FIX] Fix bug in app termination heuristic. [#523](https://github.com/bitstadium/HockeySDK-iOS/pull/523) +- [FIX] Fix Feedback UI on iPhone X. [#513](https://github.com/bitstadium/HockeySDK-iOS/pull/513)[#508](https://github.com/bitstadium/HockeySDK-iOS/pull/508) +- [IMPROVEMENT] Make it possible to use own logging handler. [#516](https://github.com/bitstadium/HockeySDK-iOS/pull/516) + ## 5.1.2 - [IMPROVEMENT] This release uses Xcode 9.2 to compile the SDK. [#502](https://github.com/bitstadium/HockeySDK-iOS/pull/503) diff --git a/Documentation/Guides/Installation & Setup.md b/Documentation/Guides/Installation & Setup.md index 9c6e5781..04a6b2f7 100644 --- a/Documentation/Guides/Installation & Setup.md +++ b/Documentation/Guides/Installation & Setup.md @@ -3,9 +3,9 @@ [![Version](http://cocoapod-badges.herokuapp.com/v/HockeySDK/badge.png)](http://cocoadocs.org/docsets/HockeySDK) [![Slack Status](https://slack.hockeyapp.net/badge.svg)](https://slack.hockeyapp.net) -## Version 5.1.2 +## Version 5.1.3 -- [Changelog](http://www.hockeyapp.net/help/sdk/ios/5.1.2/docs/docs/Changelog.html) +- [Changelog](http://www.hockeyapp.net/help/sdk/ios/5.1.3/docs/docs/Changelog.html) **NOTE** If your are using the binary integration of our SDK, make sure that the `HockeySDKResources.bundle` inside the `HockeySDK.embeddedframework`-folder has been added to your application. @@ -821,7 +821,7 @@ To check if data is send properly to HockeyApp and also see some additional SDK ## 4. Documentation -Our documentation can be found on [HockeyApp](http://hockeyapp.net/help/sdk/ios/5.1.2/index.html). +Our documentation can be found on [HockeyApp](http://hockeyapp.net/help/sdk/ios/5.1.3/index.html). ## 5.Troubleshooting @@ -835,7 +835,7 @@ Our documentation can be found on [HockeyApp](http://hockeyapp.net/help/sdk/ios/ Make sure none of the following files are copied into your app bundle, check under app target, `Build Phases`, `Copy Bundle Resources` or in the `.app` bundle after building: - `HockeySDK.framework` (except if you build a dynamic framework version of the SDK yourself!) - - `de.bitstadium.HockeySDK-iOS-5.1.2.docset` + - `de.bitstadium.HockeySDK-iOS-5.1.3.docset` ### Features are not working as expected diff --git a/Documentation/HockeySDK/.jazzy.yaml b/Documentation/HockeySDK/.jazzy.yaml index 5e5c34f9..71127bc5 100644 --- a/Documentation/HockeySDK/.jazzy.yaml +++ b/Documentation/HockeySDK/.jazzy.yaml @@ -5,7 +5,7 @@ sdk: iphonesimulator theme: ../Themes/apple module: HockeySDK -module_version: 5.1.2 +module_version: 5.1.3 author: Microsoft Corp author_url: https://www.microsoft.com diff --git a/HockeySDK-Source.podspec b/HockeySDK-Source.podspec index e04d3622..87adc47e 100644 --- a/HockeySDK-Source.podspec +++ b/HockeySDK-Source.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'HockeySDK-Source' - s.version = '5.1.2' + s.version = '5.1.3' s.summary = 'Collect live crash reports, get feedback from your users, distribute your betas, and analyze your test coverage with HockeyApp.' s.description = <<-DESC @@ -25,7 +25,7 @@ Pod::Spec.new do |s| s.frameworks = 'CoreGraphics', 'CoreTelephony', 'CoreText', 'MobileCoreServices', 'Photos', 'QuartzCore', 'QuickLook', 'Security', 'SystemConfiguration', 'UIKit' s.libraries = 'c++', 'z' s.vendored_frameworks = 'Vendor/CrashReporter.framework' - s.pod_target_xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_C_VERSION="\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"108\\"" BITHOCKEY_C_BUILD="\\"108\\""} } + s.pod_target_xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_C_VERSION="\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"109\\"" BITHOCKEY_C_BUILD="\\"109\\""} } s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] } s.preserve_paths = 'Resources', 'Support' s.private_header_files = 'Classes/*Private.h' diff --git a/HockeySDK.podspec b/HockeySDK.podspec index ce2eda9f..c4531ed0 100644 --- a/HockeySDK.podspec +++ b/HockeySDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'HockeySDK' - s.version = '5.1.2' + s.version = '5.1.3' s.summary = 'Collect live crash reports, get feedback from your users, distribute your betas, and analyze your test coverage with HockeyApp.' s.description = <<-DESC diff --git a/README.md b/README.md index 537cb36a..6a75155c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Version](http://cocoapod-badges.herokuapp.com/v/HockeySDK/badge.png)](http://cocoadocs.org/docsets/HockeySDK) [![Slack Status](https://slack.hockeyapp.net/badge.svg)](https://slack.hockeyapp.net) -## Version 5.1.2 +## Version 5.1.3 HockeySDK-iOS implements support for using HockeyApp in your iOS applications. @@ -22,13 +22,13 @@ The following features are currently supported: ## 1. Setup -It is super easy to use HockeyApp in your iOS app. Have a look at our [documentation](https://www.hockeyapp.net/help/sdk/ios/5.1.2/index.html) and onboard your app within minutes. +It is super easy to use HockeyApp in your iOS app. Have a look at our [documentation](https://www.hockeyapp.net/help/sdk/ios/5.1.3/index.html) and onboard your app within minutes. ## 2. Documentation -Please visit [our landing page](https://www.hockeyapp.net/help/sdk/ios/5.1.2/index.html) as a starting point for all of our documentation. +Please visit [our landing page](https://www.hockeyapp.net/help/sdk/ios/5.1.3/index.html) as a starting point for all of our documentation. -Please check out our [changelog](http://www.hockeyapp.net/help/sdk/ios/5.1.2/changelog.html), as well as our [troubleshooting section](https://www.hockeyapp.net/help/sdk/ios/5.1.2/installation--setup.html#troubleshooting). +Please check out our [changelog](http://www.hockeyapp.net/help/sdk/ios/5.1.3/changelog.html), as well as our [troubleshooting section](https://www.hockeyapp.net/help/sdk/ios/5.1.3/installation--setup.html#troubleshooting). ## 3. Contributing @@ -52,4 +52,4 @@ You must sign a [Contributor License Agreement](https://cla.microsoft.com/) befo ## 4. Contact -If you have further questions or are running into trouble that cannot be resolved by any of the steps [in our troubleshooting section](https://www.hockeyapp.net/help/sdk/ios/5.1.2/installation--setup.html#troubleshooting), feel free to open an issue here, contact us at [support@hockeyapp.net](mailto:support@hockeyapp.net) or join our [Slack](https://slack.hockeyapp.net). +If you have further questions or are running into trouble that cannot be resolved by any of the steps [in our troubleshooting section](https://www.hockeyapp.net/help/sdk/ios/5.1.3/installation--setup.html#troubleshooting), feel free to open an issue here, contact us at [support@hockeyapp.net](mailto:support@hockeyapp.net) or join our [Slack](https://slack.hockeyapp.net). diff --git a/Support/HockeySDKBase.xcconfig b/Support/HockeySDKBase.xcconfig index b915fd0f..26de90c2 100644 --- a/Support/HockeySDKBase.xcconfig +++ b/Support/HockeySDKBase.xcconfig @@ -1,5 +1,5 @@ -BUILD_NUMBER = 108 -VERSION_STRING = 5.1.2 +BUILD_NUMBER = 109 +VERSION_STRING = 5.1.3 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(HOCKEYSDK_GCC_PREPROCESSOR_DEFINITIONS) HOCKEYSDK_CONFIGURATION_$(CONFIGURATION) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\"" BITHOCKEY_BUILD="@\""$(BUILD_NUMBER)"\"" BITHOCKEY_C_VERSION="\""$(VERSION_STRING)"\"" BITHOCKEY_C_BUILD="\""$(BUILD_NUMBER)"\"" BIT_ARM_ARCHS = armv7 armv7s arm64 BIT_SIM_ARCHS = x86_64 i386 From c4bd806701ddaa76ba630aaacd56761fbcacdc52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Spie=C3=9F?= Date: Wed, 26 Sep 2018 16:23:45 +0200 Subject: [PATCH 27/27] Update CPU subtype fallback definition to use Apple's own naming --- Classes/BITCrashReportTextFormatter.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Classes/BITCrashReportTextFormatter.m b/Classes/BITCrashReportTextFormatter.m index 20a93959..a54ac5d6 100644 --- a/Classes/BITCrashReportTextFormatter.m +++ b/Classes/BITCrashReportTextFormatter.m @@ -53,10 +53,10 @@ #import "BITCrashReportTextFormatter.h" /** - * With Xcode 10, the new ARM64 V8_3A architecture, used by iPhone XS and XR, is not yet in the headers. + * Before macOS Mojave, the new ARM64E architecture, used by iPhone XS and XR, is not yet in the headers. */ -#ifndef CPU_SUBTYPE_ARM64_V8_3 -# define CPU_SUBTYPE_ARM64_V8_3 ((cpu_subtype_t) 2) +#ifndef CPU_SUBTYPE_ARM64E +# define CPU_SUBTYPE_ARM64E ((cpu_subtype_t) 2) #endif /** @@ -781,7 +781,7 @@ + (NSString *)bit_archNameFromCPUType:(uint64_t)cpuType subType:(uint64_t)subTyp archName = @"arm64"; break; - case CPU_SUBTYPE_ARM64_V8_3: + case CPU_SUBTYPE_ARM64E: archName = @"arm64e"; break;