An open API service indexing awesome lists of open source software.

https://github.com/bugsplat-git/bugsplat-apple

BugSplat crash reporting support for macOS and iOS
https://github.com/bugsplat-git/bugsplat-apple

Last synced: 8 months ago
JSON representation

BugSplat crash reporting support for macOS and iOS

Awesome Lists containing this project

README

          

[![bugsplat-github-banner-basic-outline](https://user-images.githubusercontent.com/20464226/149019306-3186103c-5315-4dad-a499-4fd1df408475.png)](https://bugsplat.com)

#

BugSplat

### **

Crash and error reporting built for busy developers.
**


Follow @bugsplatco on Bluesky
Join BugSplat on Discord


## Introduction 👋

The BugSplat.xcframework enables posting crash reports from iOS, macOS, and Mac Catalyst applications to BugSplat. Visit [bugsplat.com](https://www.bugsplat.com) for more information and to sign up for an account.

## Requirements 📋

- BugSplat for iOS supports iOS 13 and later.
- BugSplat for macOS supports macOS 10.13 and later.

## Integration 🏗️

The BugSplat crash reporting SDK can be integrated into your project via the following methods:
- Using Swift Package Manager
- Manually adding xcframeworks

### Swift Package Manager (SPM)

Add the following URL to your project's `Additional Package Dependencies`:

```sh
https://github.com/BugSplat-Git/bugsplat-apple
```

### Manually Add xcframeworks

To manually integrate BugSplat into your Xcode project, three xcframeworks (BugSplat.xcframework, HockeySDK.xcframework, and CrashReporter.xcframework) need to be added and configured within Xcode.

1. Download the latest released xcframeworks (BugSplat.xcframework.zip, HockeySDK.xcframework.zip, and CrashReporter.xcframework.zip) from the [Releases](https://github.com/BugSPlat-Git/bugsplat-apple/releases) page. Each zip will contain the corresponding xcframework.
2. Unzip each archive.
3. In Xcode, select your app target, then go to the General tab, scroll down to Framework, Libraries, and Embedded Content, then click the "+" and navigate to where you unzipped the three archives in step 2. Select BugSplat.xcframework, HockeySDK.xcframework, and CrashReporter.xcframework, then tap the "Add" button. Once added, select Embed & Sign for each xcframework.

## Usage 🧑‍💻

### Configuration

BugSplat requires a few Xcode configuration steps to integrate the xcframework with your BugSplat account.

Add the following case-sensitive key to your app's `Info.plist`, replacing `DATABASE_NAME` with your customer-specific BugSplat database name.

```xml
BugSplatDatabase
DATABASE_NAME
```

> [!NOTE]
> For macOS apps, you must enable Outgoing network connections (client) in the Signing & Capabilities of the Target.

### Symbol Upload

To symbolicate crash reports, you must upload your app's `dSYM` files to the BugSplat server. There are scripts to help with this.

Download BugSplat's cross-platform tool, [symbol-upload-macos](https://docs.bugsplat.com/education/faq/how-to-upload-symbol-files-with-symbol-upload) for Apple Silicon by entering the following command in your terminal.

```sh
curl -sL -O "https://app.bugsplat.com/download/symbol-upload-macos"
```

Alternatively, you can download the Intel version via the following command.

```sh
curl -sL -O "https://app.bugsplat.com/download/symbol-upload-macos-intel"
```

Make `symbol-upload-macos` executable

```sh
chmod +x symbol-upload-macos
```

Several options exist to integrate `symbol-upload-macos` into the app build process.

- Create an Xcode build-phase script to upload dSYM files after every build. See example script [Symbol_Upload_Examples/Build-Phase-symbol-upload.sh](Symbol_Upload_Examples/Build-Phase-symbol-upload.sh)

- Create an Xcode Archive post-action script in the target's Build Scheme to upload dSYM files after the app is archived and ready for submission to TestFlight or the App Store. See example script [Symbol_Upload_Examples/Archive-post-action-upload.sh](Symbol_Upload_Examples/Archive-post-action-upload.sh)
- Manually upload an `xcarchive` or `dSYM` file generated by Xcode via BugSplat's [Versions](https://app.bugsplat.com/v2/versions) page.

> [!NOTE]
> For the build-phase script to create dSYM files, change Build Settings `DEBUG_INFORMATION_FORMAT` from `DWARF` to `DWARF with dSYM File`. See inline notes within each script for modifications to Xcode Build Settings required for each script to work.

Please refer to our [documentation](https://docs.bugsplat.com/education/faq/how-to-upload-symbol-files-with-symbol-upload) to learn more about how to use `symbol-upload-macos`.

### Initialization

Several iOS and macOS test app examples are included within the [Example_Apps](Example_Apps) folder to show how simple and quickly BugSplat can be integrated into an app and ready to submit crash reports.

You can instantiate BugSplat by following the language-specific examples below.

#### Swift (UIKit)

```swift
import BugSplat

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize BugSplat
BugSplat.shared().delegate = self
BugSplat.shared().autoSubmitCrashReport = false
BugSplat.shared().start()

return true
}
}

extension AppDelegate: BugSplatDelegate {
// MARK: BugSplatDelegate
func bugSplatWillSendCrashReport(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatWillSendCrashReportsAlways(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatDidFinishSendingCrashReport(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatWillCancelSendingCrashReport(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatWillShowSubmitCrashReportAlert(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplat(_ bugSplat: BugSplat, didFailWithError error: Error) {
print("\(#file) - \(#function)")
}
}
```

#### Swift (SwiftUI)

```swift
import BugSplat

@main
struct BugSplatTestSwiftUIApp: App {
private let bugSplat = BugSplatInitializer()

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

@objc class BugSplatInitializer: NSObject, BugSplatDelegate {
override init() {
super.init()
BugSplat.shared().delegate = self
BugSplat.shared().autoSubmitCrashReport = false
BugSplat.shared().start()
}

// MARK: BugSplatDelegate
func bugSplatWillSendCrashReport(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatWillSendCrashReportsAlways(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatDidFinishSendingCrashReport(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatWillCancelSendingCrashReport(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplatWillShowSubmitCrashReportAlert(_ bugSplat: BugSplat) {
print("\(#file) - \(#function)")
}

func bugSplat(_ bugSplat: BugSplat, didFailWithError error: Error) {
print("\(#file) - \(#function)")
}
}
```

#### Obj-C

```objc
#import "BugSplatMac/BugSplatMac.h"

@interface AppDelegate ()
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Initialize BugSplat
[[BugSplat shared] setDelegate:self];
[[BugSplat shared] setAutoSubmitCrashReport:NO];
[[BugSplat shared] start];
}

#pragma mark - BugSplatDelegate

- (void)bugSplatWillSendCrashReport:(BugSplat *)bugSplat {
NSLog(@"bugSplatWillSendCrashReport called");
}

- (void)bugSplatWillSendCrashReportsAlways:(BugSplat *)bugSplat {
NSLog(@"bugSplatWillSendCrashReportsAlways called");
}

- (void)bugSplatDidFinishSendingCrashReport:(BugSplat *)bugSplat {
NSLog(@"bugSplatDidFinishSendingCrashReport called");
}

- (void)bugSplatWillCancelSendingCrashReport:(BugSplat *)bugSplat {
NSLog(@"bugSplatWillCancelSendingCrashReport called");
}

- (void)bugSplatWillShowSubmitCrashReportAlert:(BugSplat *)bugSplat {
NSLog(@"bugSplatWillShowSubmitCrashReportAlert called");
}

- (void)bugSplat:(BugSplat *)bugSplat didFailWithError:(NSError *)error {
NSLog(@"bugSplat:didFailWithError: %@", [error localizedDescription]);
}
```

### Attributes

BugSplat supports custom attributes that can be added to a crash report. These attributes are searchable in the BugSplat dashboard.

```swift
BugSplat.shared().setValue("Value of Attribute", forAttribute: "AttributeName")
```

```objc
[[BugSplat shared] setValue:@"Value of Attribute" forAttribute:@"AttributeName"];
```

It is important to understand how attributes are set, as well as if and when attributes will be included in a crash report.

Attributes and their associated values are programmatically set at any time while an app is running. Attributes are unique `NSString` keys so there can only be one attribute of a given name in any given set of attributes. Every time BugSplat's `setValue:forAttribute:` API is called, this attribute/value pair will be added to a `NSDictionary` and persisted to `NSUserDefaults`. If the app session terminates due to a crash, the persisted attributes are handled as follows:

1. Upon first launch after a crash and when BugSplat.shared is being initialized, any persisted attributes are loaded into memory.
2. Next, the persisted NSDictionary holding the attributes within NSUserDefaults is erased.
3. Next, if a crash occurred in the last app session prior to this app session, any attributes that were just loaded into memory from the persisted attributes will be added to the crash report as an attachment (see iOS API limitation notes about a single attachment).
4. Finally, the dictionary in memory holding the prior app session attributes is erased.

Put another way, attributes and their values are only valid for the lifetime of the app session and are only used in a crash report if the crash occurs during that app session. Any attributes set in the prior app session will be attached to the crash report that is processed during the next launch of the app. If the app terminates normally, any attributes persisted during the prior `normal` app session will be erased during the next app launch.

Please take a look at the framework-specific [sample applications](#sample-applications-) for more examples showing how to use attributes.

### Crash Reporter Customization

There are several ways to customize your BugSplat crash reporter.

#### Custom Banner Image

- BugSplat for macOS provides the ability to configure a custom image to be displayed in the crash reporter UI for branding purposes. The image view dimensions are 440x110 and will scale down proportionately. There are 2 ways developers can provide an image:

1. Set the image property directly on BugSplat
2. Provide an image named `bugsplat-logo` in the main app bundle or asset catalog

#### User Details

- BugSplat for macOS provides the ability for the user to provide a name and email when submitting a crash report. To provide the name and email, set `askUserDetails` to `NO` to prevent the name and email fields from displaying in the crash reporter UI. Defaults to `YES`.

#### Auto Submit

- By default, BugSplat will auto-submit crash reports for iOS and prompt the end user to submit a crash report for macOS. This default can be changed using a BugSplat property autoSubmitCrashReport. Set `autoSubmitCrashReport` to `YES` in order to send crash reports to the server automatically without presenting the crash reporter dialogue.

#### Persist User Details

- BugSplat for macOS provides the ability to persist the user name and email entered in a crash reporter UI. Set `persistUserDetails` to `YES` to save and restore the user's name and email when presenting the crash reporter dialogue. Defaults to `NO`.

#### Expiration Time

- Set `expirationTimeInterval` to a desired value (in seconds) whereby if the difference in time between when the crash occurred and the next launch is greater than the set expiration time, auto-send the report without presenting the crash reporter dialogue. Defaults to `-1`, which represents no expiration.

#### Attachments

Bugsplat supports uploading attachments with crash reports. There's a delegate method provided by `BugSplatDelegate` that can be implemented to provide attachments to be uploaded. Currently, iOS supports only one attachment with crash reports. See additional iOS attachment limitation when using Attributes.

#### Bitcode

Bitcode was introduced by Apple to allow apps sent to the App Store to be recompiled by Apple itself and apply the latest optimization. Bitcode has now been officially deprecated by Apple and should be removed or disabled. If Bitcode is enabled, the symbols generated for your app in the store will be different than the ones from your own build system. We recommend that you disable bitcode in order for BugSplat to reliably symbolicate crash reports. Disabling bitcode significantly simplifies symbols management and currently doesn't have any known downsides for iOS apps.

#### Localization

For macOS, the BugSplat crash dialogue can be localized and supports eight languages out of the box.

1. English
2. Finnish
3. French
4. German
5. Italian
6. Japanese
7. Norwegian
8. Swedish

Additional languages may be supported by adding the language bundle and strings file to `BugSplat.xcframework/macos-arm64_x86_64/BugSplatMac.framework/Versions/A/Frameworks/HockeySDK.framework/Resources/`

## Sample Applications 🧑‍🏫

`Example_Apps` includes several iOS and macOS BugSplat Test apps. Integrating BugSpat only requires the xcframework and a few lines of code.

1. Clone the [bugsplat-apple repo](https://github.com/BugSplat-Git/bugsplat-apple).

1. Open an example Xcode project from `Example_Apps`. For iOS, set the destination to be your iOS device. After running from Xcode, stop the process and relaunch from the iOS device directly.

1. Once the app launches, click the "crash" button when prompted.

1. Relaunch the app on the iOS device. At this point, a crash report should be submitted to bugsplat.com

1. Visit BugSplat's [Crashes](https://app.bugsplat.com/v2/crashes) page. When prompted for credentials, enter user `fred@bugsplat.com` and password `Flintstone`. The crash you posted from BugSplatTester should be at the top of the list of crashes.

1. Click the "Crash ID" link to view more details about your crash.

## Contributing 🤝

BugSplat is an open-source project, and we welcome contributions from the community. To configure a development environment, follow the instructions below.

### Building

Clone this repository and all of the dependencies into a new `BugSplat` folder.

```sh
mkdir BugSplat
cd BugSplat
git clone https://github.com/BugSplat-Git/bugsplat-apple
git clone https://github.com/BugSplat-Git/HockeySDK-Mac
git clone https://github.com/BugSplat-Git/HockeySDK-iOS
git clone https://github.com/BugSplat-Git/plCrashReporter
```

Next, in the prescribed order, build each repo. If an error occurs in a specific repo, it
must be resolved before you can move to the next repo. This process was verified with
a specific Apple Developer account for code signing. A different Apple Developer account
requires adjusting the code signing within a given project.

1. Build PlCrashReporter

```sh
cd plcrashreporter
./makeXCFramework.sh
...
xcframework successfully written out to: .../BugSplat/plcrashreporter/xcframeworks/CrashReporter.xcframework
```

2. Build HockeySDK-Mac

```sh
cd HockeySDK-Mac
./makeXCFramework.sh
...
xcframework successfully written out to: .../BugSplat/HockeySDK-Mac/xcframeworks/HockeySDK-macOS.xcframework
```

3. Build HockeySDK-iOS

```sh
cd HockeySDK-iOS
./makeXCFramework.sh
...
xcframework successfully written out to: .../BugSplat/HockeySDK-iOS/xcframeworks/HockeySDK.xcframework
```

4. Build bugsplat-apple

```sh
cd bugsplat-apple
./makeXCFramework.sh
...
xcframework successfully written out to: .../BugSplat/bugsplat-apple/xcframeworks/BugSplat.xcframework
```

If all goes smoothly, `BugSplat.xcframework` will be the result in the xcframeworks folder
of the bugsplat-apple repo.

### Releasing

To release a new version of BugSplat.xcframework, push a new tag to the `main` branch. The [release](.github/workflows/release.yml) workflow will build the xcframework, update `Package.swift`, and publish the zipped archive to the [Releases](https://github.com/BugSplat-Git/bugsplat-apple/releases) page.