diff --git a/Documentation/Guides/Installation & Setup.md b/Documentation/Guides/Installation & Setup.md
index 43cef6c29c..732678e28e 100644
--- a/Documentation/Guides/Installation & Setup.md
+++ b/Documentation/Guides/Installation & Setup.md
@@ -125,30 +125,7 @@ Our examples will use the **default** SDK (`HockeySDK.embeddedframework`).
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; // This line is obsolete in the crash only builds
```
-**Swift 2.3**
-
-1. Open your `AppDelegate.swift` file.
-2. Add the following line at the top of the file below your own import statements:
-
- ```swift
- import HockeySDK
- ```
-
-3. Search for the method
-
- ```swift
- application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:[NSObject: AnyObject]?) -> Bool
- ```
-
-4. Add the following lines to setup and start the HockeyApp SDK:
-
- ```swift
- BITHockeyManager.sharedHockeyManager().configureWithIdentifier("APP_IDENTIFIER")
- BITHockeyManager.sharedHockeyManager().startManager()
- BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation() // This line is obsolete in the crash only builds
- ```
-
-**Swift 3**
+**Swift**
1. Open your `AppDelegate.swift` file.
2. Add the following line at the top of the file below your own import statements:
@@ -313,6 +290,8 @@ The following points need to be considered to use the HockeySDK SDK with iOS Ext
1. Each extension is required to use the same values for version (`CFBundleShortVersionString`) and build number (`CFBundleVersion`) as the main app uses. (This is required only if you are using the same `APP_IDENTIFIER` for your app and extensions).
2. You need to make sure the SDK setup code is only invoked **once**. Since there is no `applicationDidFinishLaunching:` equivalent and `viewDidLoad` can run multiple times, you need to use a setup like the following example:
+**Objective-C**
+
```objc
static BOOL didSetupHockeySDK = NO;
@@ -332,6 +311,24 @@ The following points need to be considered to use the HockeySDK SDK with iOS Ext
}
```
+ **Swift**
+
+ ```swift
+ class TodayViewController: UIViewController, NCWidgetProviding {
+
+ static var didSetupHockeySDK = false;
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ if !TodayViewController.didSetupHockeySDK {
+ BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+ BITHockeyManager.shared().start()
+ TodayViewController.didSetupHockeySDK = true
+ }
+ }
+ }
+ ```
+
3. The binary distribution provides a special framework build in the `HockeySDKCrashOnly` or `HockeySDKCrashOnlyExtension` folder of the distribution zip file, which only contains crash reporting functionality (also automatic sending crash reports only).
@@ -343,6 +340,8 @@ The following points need to be considered to use HockeySDK with WatchKit 1 Exte
To make sure that the HockeySDK is only instantiated once in the WatchKit extension's lifecycle we recommend using a helper class similar to this:
+ **Objective-C**
+
```objc
@import Foundation;
@@ -372,8 +371,30 @@ The following points need to be considered to use HockeySDK with WatchKit 1 Exte
@end
```
+ **Swift**
+
+ ```swift
+ import HockeySDK
+
+ class BITWatchSDKSetup {
+
+ static var hockeySDKIsSetup = false;
+
+ static func setupHockeySDKIfNeeded() {
+ if !BITWatchSDKSetup.hockeySDKIsSetup {
+ BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+ BITHockeyManager.shared().start()
+ BITWatchSDKSetup.hockeySDKIsSetup = true;
+ }
+ }
+ }
+ ```
+
+
Then, in each of your WKInterfaceControllers where you want to use the HockeySDK, you should do this:
+ **Objective-C**
+
```objc
#import "InterfaceController.h"
@import HockeySDK
@@ -397,6 +418,26 @@ The following points need to be considered to use HockeySDK with WatchKit 1 Exte
@end
```
+ **Swift**
+
+ ```swift
+ class InterfaceController: WKInterfaceController {
+
+ override func awake(withContext context: Any?) {
+ super.awake(withContext: context)
+ BITWatchSDKSetup.setupHockeySDKIfNeeded()
+ }
+
+ override func willActivate() {
+ super.willActivate()
+ }
+
+ override func didDeactivate() {
+ super.didDeactivate()
+ }
+
+ }
+ ```
2. The binary distribution provides a special framework build in the `HockeySDKCrashOnly` or `HockeySDKCrashOnlyExtension` folder of the distribution zip file, which only contains crash reporting functionality (also automatic sending crash reports only).
@@ -411,6 +452,8 @@ To provide you with the best crash reporting, we are using a build of [PLCrashRe
This feature can be disabled as follows:
+**Objective-C**
+
```objc
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
@@ -419,10 +462,19 @@ This feature can be disabled as follows:
[[BITHockeyManager sharedHockeyManager] startManager];
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+BITHockeyManager.shared().isCrashManagerDisabled = true
+BITHockeyManager.shared().start()
+```
#### 3.6.2 Auto send crash reports
Crashes are send the next time the app starts. If `crashManagerStatus` is set to `BITCrashManagerStatusAutoSend`, crashes will be send without any user interaction, otherwise an alert will appear allowing the users to decide whether they want to send the report or not.
+**Objective-C**
+
```objc
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
@@ -431,6 +483,14 @@ Crashes are send the next time the app starts. If `crashManagerStatus` is set to
[[BITHockeyManager sharedHockeyManager] startManager];
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+BITHockeyManager.shared().crashManager.crashManagerStatus = BITCrashManagerStatus.autoSend
+BITHockeyManager.shared().start()
+```
+
The SDK is not sending the reports right when the crash happens deliberately, because if is not safe to implement such a mechanism while being async-safe (any Objective-C code is _NOT_ async-safe!) and not causing more danger like a deadlock of the device, than helping. We found that users do start the app again because most don't know what happened, and you will get by far most of the reports.
Sending the reports on start-up is done asynchronously (non-blocking). This is the only safe way to ensure that the app won't be possibly killed by the iOS watchdog process, because start-up could take too long and the app could not react to any user input when network conditions are bad or connectivity might be very slow.
@@ -442,7 +502,9 @@ By default the SDK is using the safe and proven in-process BSD Signals for catch
We strongly advise _NOT_ to enable Mach exception handler in release versions of your apps!
*Warning:* The Mach exception handler executes in-process, and will interfere with debuggers when they attempt to suspend all active threads (which will include the Mach exception handler). Mach-based handling should _NOT_ be used when a debugger is attached. The SDK will not enable catching exceptions if the app is started with the debugger running. If you attach the debugger during runtime, this may cause issues the Mach exception handler is enabled!
-
+
+**Objective-C**
+
```objc
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
@@ -451,31 +513,93 @@ We strongly advise _NOT_ to enable Mach exception handler in release versions of
[[BITHockeyManager sharedHockeyManager] startManager];
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+BITHockeyManager.shared().crashManager.isMachExceptionHandlerEnabled = true
+BITHockeyManager.shared().start()
+```
+
#### 3.6.4 Attach additional data
The `BITHockeyManagerDelegate` protocol provides methods to add additional data to a crash report:
-1. UserID: `- (NSString *)userIDForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;`
-2. UserName: `- (NSString *)userNameForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;`
-3. UserEmail: `- (NSString *)userEmailForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;`
+1. UserID:
+
+**Objective-C**
+
+`- (NSString *)userIDForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;`
+
+**Swift**
+
+`optional public func userID(for hockeyManager: BITHockeyManager!, componentManager: BITHockeyBaseManager!) -> String!`
+
+2. UserName:
+
+**Objective-C**
+
+`- (NSString *)userNameForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;`
+
+**Swift**
+
+`optional public func userName(for hockeyManager: BITHockeyManager!, componentManager: BITHockeyBaseManager!) -> String!`
+
+3. UserEmail:
+
+**Objective-C**
+
+`- (NSString *)userEmailForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;`
+
+**Swift**
+
+`optional public func userEmail(for hockeyManager: BITHockeyManager!, componentManager: BITHockeyBaseManager!) -> String!`
The `BITCrashManagerDelegate` protocol (which is automatically included in `BITHockeyManagerDelegate`) provides methods to add more crash specific data to a crash report:
-1. Text attachments: `-(NSString *)applicationLogForCrashManager:(BITCrashManager *)crashManager`
+1. Text attachments:
+
+**Objective-C**
+
+`-(NSString *)applicationLogForCrashManager:(BITCrashManager *)crashManager`
+
+**Swift**
+
+`optional public func applicationLog(for crashManager: BITCrashManager!) -> String!`
Check the following tutorial for an example on how to add CocoaLumberjack log data: [How to Add Application Specific Log Data on iOS or OS X](http://support.hockeyapp.net/kb/client-integration-ios-mac-os-x/how-to-add-application-specific-log-data-on-ios-or-os-x)
-2. Binary attachments: `-(BITHockeyAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager`
+2. Binary attachments:
+
+**Objective-C**
+
+`-(BITHockeyAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager`
+
+**Swift**
+
+`optional public func attachment(for crashManager: BITCrashManager!) -> BITHockeyAttachment!`
Make sure to implement the protocol
+**Objective-C**
+
```objc
@interface YourAppDelegate () {}
@end
```
+**Swift**
+
+```swift
+class YourAppDelegate: BITHockeyManagerDelegate {
+
+}
+```
+
and set the delegate:
+**Objective-C**
+
```objc
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
@@ -484,6 +608,14 @@ and set the delegate:
[[BITHockeyManager sharedHockeyManager] startManager];
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+BITHockeyManager.shared().delegate = self
+BITHockeyManager.shared().start()
+```
+
### 3.7 User Metrics
@@ -496,10 +628,18 @@ HockeyApp automatically provides you with nice, intelligible, and informative me
Just in case you want to opt-out of the automatic collection of anonymous users and sessions statistics, there is a way to turn this functionality off at any time:
+**Objective-C**
+
```objc
[BITHockeyManager sharedHockeyManager].disableMetricsManager = YES;
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().isMetricsManagerDisabled = true
+```
+
#### 3.7.1 Custom Events
By tracking custom events, you can now get insight into how your customers use your app, understand their behavior and answer important business or user experience questions while improving your app.
@@ -518,9 +658,9 @@ BITMetricsManager *metricsManager = [BITHockeyManager sharedHockeyManager].metri
**Swift**
```swift
-let metricsManager = BITHockeyManager.sharedHockeyManager().metricsManager
+let metricsManager = BITHockeyManager.shared().metricsManager
-metricsManager.trackEventWithName(eventName)
+metricsManager.trackEvent(withName: eventName)
```
**Limitations**
@@ -557,8 +697,8 @@ NSDictionary *myMeasurements = @{@"Measurement 1" : @1,
let myProperties = ["Property 1": "Something", "Property 2": "Other thing", "Property 3" : "Totally different thing."]
let myMeasurements = ["Measurement 1": 1, "Measurement 2": 2.3, "Measurement 3" : 30000]
-let metricsManager = BITHockeyManager.sharedHockeyManager().metricsManager
-metricsManager.trackEventWithName(eventName, properties: myProperties, myMeasurements: measurements)
+let metricsManager = BITHockeyManager.shared().metricsManager
+metricsManager.trackEvent(withName: eventName, properties: myProperties, measurements: myMeasurements)
```
@@ -579,11 +719,19 @@ in your podfile.
`BITFeedbackManager` lets your users communicate directly with you via the app and an integrated user interface. It provides a single threaded discussion with a user running your app. This feature is only enabled if you integrate the actual view controllers into your app.
You should never create your own instance of `BITFeedbackManager` but use the one provided by the `[BITHockeyManager sharedHockeyManager]`:
-
+
+**Objective-C**
+
```objc
[BITHockeyManager sharedHockeyManager].feedbackManager
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().feedbackManager
+```
+
Please check the [documentation](#documentation) of the `BITFeedbackManager` and `BITFeedbackManagerDelegate` classes on more information on how to leverage this feature.
#### 3.8.2 Add the NSPhotoLibraryUsageDescription to your Info.plist.
@@ -602,6 +750,8 @@ When an update is detected, this module will show an alert asking the user if he
By default this module is **NOT** enabled! To enable it use the following code:
+**Objective-C**
+
```objc
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
@@ -610,6 +760,14 @@ By default this module is **NOT** enabled! To enable it use the following code:
[[BITHockeyManager sharedHockeyManager] startManager];
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+BITHockeyManager.shared().isStoreUpdateManagerEnabled = true
+BITHockeyManager.shared().start()
+```
+
When this module is enabled and **NOT** running in an App Store build/environment, it won't do any checks!
Please check the [documentation](#documentation) of the `BITStoreUpdateManager` class on more information on how to leverage this feature and know about its limits.
@@ -625,6 +783,8 @@ This module automatically disables itself when running in an App Store build by
This feature can be disabled manually as follows:
+**Objective-C**
+
```objc
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
@@ -633,6 +793,14 @@ This feature can be disabled manually as follows:
[[BITHockeyManager sharedHockeyManager] startManager];
```
+**Swift**
+
+```swift
+BITHockeyManager.shared().configure(withIdentifier: "APP_IDENTIFIER")
+BITHockeyManager.shared().isUpdateManagerDisabled = true
+BITHockeyManager.shared().start()
+```
+
Please note that the SDK expects your CFBundleVersion values to always increase and never reset to detect a new update.
If you want to see beta analytics, use the beta distribution feature with in-app updates, restrict versions to specific users, or want to know who is actually testing your app, you need to follow the instructions on our guide [Authenticating Users on iOS](http://support.hockeyapp.net/kb/client-integration-ios-mac-os-x/authenticating-users-on-ios)
diff --git a/Documentation/Guides/Set Custom AlertViewHandler.md b/Documentation/Guides/Set Custom AlertViewHandler.md
index b1879f5d19..b11ea780ea 100644
--- a/Documentation/Guides/Set Custom AlertViewHandler.md
+++ b/Documentation/Guides/Set Custom AlertViewHandler.md
@@ -15,59 +15,119 @@ The following example shows how this could be implemented. We'll present a custo
## Example
- @interface BITAppDelegate ()
- @end
-
-
- @implementation BITAppDelegate
-
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- [self.window makeKeyAndVisible];
-
- [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"<>"
- delegate:nil];
-
- // optionally enable logging to get more information about states.
- [BITHockeyManager sharedHockeyManager].debugLogEnabled = YES;
+**Objective-C**
- [[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";
- }
-
- [customAlertView show];
- }];
+```objc
+@interface BITAppDelegate ()
+@end
- [[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
- return YES;
+@implementation BITAppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [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";
}
- - (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;
- }
- }
+ [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;
+ }
+}
+
+@end
+```
+
+**Swift**
+
+```swift
+import UIKit
+import HockeySDK
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate, UIAlertViewDelegate {
+
+ 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"
+ }
+ customAlertView.show()
+ }
+
+ 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)
+ }
+ }
+}
+```
+
- @end