Bugfender iOS SDK - Swift
The official iOS SDK code is available at Github Bugfender iOS
Bugfender is a game-changing platform that logs every detail your users experience and feeds the data directly to an easy-to-use web console. Bugfender SDK is multi-platform and available for mobile and web apps, so you can use the same tool for all your apps.
Specifically for iOS developers, Bugfender offers powerful capabilities to remotely monitor and debug any log or error. You can easily reproduce and fix issues using our detailed log viewer and the stack trace of exceptions.
If you don't have a Bugfender account yet, go to Bugfender Signup and come back here.
Supported iOS versions:
- BugfenderSDK 2.0 works for iOS 12.0 and newer.
- For iOS 11.0 support you can use BugfenderSDK 1.12.
- For iOS 10 support you can use BugfenderSDK 1.10.6.
- For iOS 8 support you can use BugfenderSDK 1.8.
Install
Learn How To Install Bugfender iOS SDK in 10'
Watch this simple tutorial and learn how to receive the NSLog logs and crashes form your iOS users.
In order to get started using the Bugfender JavaScript SDK, you will need to load the Bugfender script to the top of your application, before all other scripts. Alternatively, you can also install the SDK via a package manager.
- Swift Package manager
- CocoaPods
- Carthage
- Manual
Please note you will need Xcode 12 or better.
In Xcode go to the target's
General
tab and press on the icon to add a new libraryIn the popover choose
Add Other
and thenAdd Package Dependency...
Paste the GitHub url from the Bugfender iOS repository
https://github.com/bugfender/BugfenderSDK-iOS
in the textfield and pressNext
Leave the first option checked and press
Next
Xcode will download the Bugfender files and you will be prompted with the following menu. Ensure BugfenderSDK is selected and press Finish
Import
SystemConfiguration.framework
,Security.framework
,CoreServices.framework
,CoreGraphics.framework
andlibc++.tbd
as well.
Open a terminal window and navigate to the location of the Xcode project for your app.
If you do not have a Podfile
yet, create one with:
pod init
Add this line to your Podfile
:
pod 'BugfenderSDK', '~> 2.0'
Save the file and run
pod repo update
pod install
This creates an .xcworkspace file for your app. Use this file for all future development on your application.
Please note: make sure to use Cocoapods v1.10.0 or newer for compatibility with Xcode 12. Please note: the 1.8.x versions of the SDK require Swift 5.1 or better, and 1.9.x versions require Swift 5.2 or better.
Use Carthage v0.38.0 or newer for Catalyst and Apple Silicon support (.xcframeworks).
Open a terminal window and navigate to the location of the Xcode project for your app.
Add this line to your Cartfile
:
github "bugfender/BugfenderSDK-iOS" ~>2.0
Save the file and run:
carthage update --use-xcframeworks
Then import the framework into your project:
- Import
Carthage/Build/BugfenderSDK.xcframework
to your Linked Frameworks and Libraries (or drag-n-drop the file to your project). - Make sure to select the option "Embed framework" (or list the framework in
input.xcfilelist
). - Make sure you have
SystemConfiguration.framework
,Security.framework
,CoreServices.framework
,CoreGraphics.framework
andlibc++.tbd
there as well. - Make sure Swift is available in your project. Check that Build Settings -> Always Embed Swift Standard Libraries is set to YES.
Updating from BugfenderSDK prior to 1.8? Starting 1.8.x, BugfenderSDK is now a dynamic framework now and you will need to check the embed option when adding it to your project. Additionally, the Bugfender.swift helper class is not needed anymore and can be safely deleted. 1.8.x versions of the SDK require Swift 5.1 or better.
Starting 1.9.x, versions require Swift 5.2 or better.
- Download the latest xcframework version of our SDK and unzip it.
- Go to your Project > Your Target > General > Frameworks, Libraries, and Embedded Content and drag
BugfenderSDK.xcframework
there. - Make sure to select the option "Embed framework"
- Make sure you have
SystemConfiguration.framework
,Security.framework
,CoreServices.framework
,CoreGraphics.framework
andlibc++.tbd
there as well. - Make sure Swift is available in your project. Check that Build Settings -> Always Embed Swift Standard Libraries is set to YES.
Note if updating from BugfenderSDK prior to 1.8: BugfenderSDK is a dynamic framework now and you will need to check the embed option when adding it to your project. Additionally, the Bugfender.swift helper class is not needed anymore and can be safely deleted.
Please note the 1.8.x versions of the SDK require Swift 5.1 or better, and 1.9.x versions require Swift 5.2 or better.
Configure
Configuring the Bugfender SDK for your iOS application is super easy! If your application uses SwiftUI and doesn't have an AppDelegate, you might need to create one like this:
@main
struct YourAppNameApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// your Bugfender init code here
return true
}
}
In your AppDelegate class:
@_exported import BugfenderSDK
And add the following to application(_:didFinishLaunchingWithOptions:)
:
//Next two lines are usually not required
//But in case you have on-premises or custom data centers, you might need to put your URLs
//Bugfender.setApiURL(URL(string: "https://api.bugfender.com/")!)
//Bugfender.setBaseURL(URL(string: "https://dashboard.bugfender.com")!)
// Activate the remote logger with an App Key.
Bugfender.activateLogger("YOUR_APP_KEY")
Bugfender.enableNSLogLogging() // optional, capture logs printed to console automatically
Bugfender.enableUIEventLogging() // optional, log user interactions automatically
Bugfender.enableCrashReporting() // optional, log crashes automatically
Remember to change YOUR_APP_KEY with the app key of your app. You can get an app key by signing up to Bugfender.
Usage
Send logs
bfprint("Hello world!") // use bfprint() as you would use print()
You may use BFLog
as you would normally use NSLog
.
You may also want to specify a logging level by using the following helper functions:
Bugfender.print(...)
: Default log.Bugfender.warning(...)
: Warning log.Bugfender.error(...)
: Error log.
We also have support for several logging libraries:
Device associated data
Once your application is running on several devices, it will be useful to know which device belongs to whom. You can associate information to a device as if it were a dictionary:
Bugfender.setDeviceString("value", forKey: "key")
This will later on let you search this device by “key” in the Bugfender Dashboard and you can use any of the associated data to filter our your device list.
Send issues
Bugfender allows you to send issues to the server. An issue is similar to a session but they are showed in the issues
section and you can send issues any time from the app, even if the device is not enabled in the system. Issues are useful to keep track of important errors that you can detect in your code.
For sending an issue you can use the following function:
Bugfender.sendIssueReturningUrl(withTitle: "Issue title", text: "Description of the issue")
Collect user feedback
Getting feedback from the final users is one of the most important things for an app developer. Good user feedback allows you detect errors in your app and helps you to understand better your product.
Bugfender provides a feature to easily collect app feedback from final users. It takes only two minutes and a few lines of code to integrate. You can think about the User Feedback as a special kind of Issue, every time your users submit their feedback you will get a new issue in Bugfender.
The easiest way to implement Bugfender User Feedback is using the customizable User Feedback View Controller. It provides a convenient view controller with two text fields, one short for the subject and another bigger for the feedback. Both text fields grow automatically.
Using the default UI
Using the convenient UI provided by Bugfender requires only creating a new View Controller and presenting it modally. All you need is to call the following method and complete the required parameters with the title and placeholders for your UI.
// Instantiate new User Feedback
let nvc = Bugfender.userFeedbackViewController(withTitle: "Navigation bar title",
hint: "Give some instructions to your users",
subjectPlaceholder: "Placeholder for subject textfield",
messagePlaceholder: "Placeholder for message textfield",
sendButtonTitle: "Send",
cancelButtonTitle: "Cancel") { (feedbackSent, url) in
if (feedbackSent) {
// Say thanks!
// url is a direct link to the dashboard
// Use it to create automations or send it to your server
} else {
// User decided to not send feedback
}
}
// Present modally
self.present(nvc, animated: true, completion: nil)
Additionally, if you require more customization you can configure the view controller prior to presenting it.
Please note BFUserFeedbackNavigationController is a subclass of navigation controller. You need to access the view controller using the public property feedbackViewController.
// Access the root view controller.
let feedbackViewController: BFUserFeedbackViewController = nvc.feedbackViewController
// Change the background colors
feedbackViewController.mainBackgroundColor = UIColor.lightGray
feedbackViewController.secondaryBackgroundColor = UIColor.white
// Change the font of the hint text
feedbackViewController.hintFont = UIFont(name: "Avenir", size: 14)!
For a complete list of customizable attributes you can inspect "BFUserFeedbackViewController.h" or read the docs.
Using SwiftUI
Here is an example using the BFUserFeedbackNavigationController
in SwiftUI:
struct SwiftUIView: View {
@State private var showFeedbackScreen = false
var body: some View {
VStack {
Text("Hello World!")
Button("Show Feedback screen") {
showFeedbackScreen = true
}
}.sheet(isPresented: $showFeedbackScreen) {
FeedbackView() { sent, feedbackUrl in
if sent == true,
let url = feedbackUrl{
BFLog("Sent feedback to URL: \(url.absoluteString)")
} else {
BFLog("User rejected to send feedback")
}
}
}.navigationBarTitle(Text("Swift UI Test"))
}
}
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
}
struct FeedbackView: UIViewControllerRepresentable {
typealias UIViewControllerType = BFUserFeedbackNavigationController
let completion: (_ feedbackSent: Bool, _ feedbackUrl: URL?) -> Void
func makeUIViewController(context: Context) -> BFUserFeedbackNavigationController {
BFUserFeedbackNavigationController.userFeedbackViewController(
withTitle: "This title",
hint: "This hint",
subjectPlaceholder: "This subject",
messagePlaceholder: "This message",
sendButtonTitle: "Send",
cancelButtonTitle: "Cancel") { sent, feedbackUrl in
completion(sent, feedbackUrl)
}
}
func updateUIViewController(_ uiViewController: BFUserFeedbackNavigationController, context: Context) {}
}
Using a custom UI
If you need further customization than provided by BFUserFeedbackViewController you can implement your own UI. All you have to do is collect your user feedback as you wish and send it to Bugfender using sendUserFeedback
:
let feedbackUrl = Bugfender.sendUserFeedbackReturningUrl(withSubject: "Title of the feedback", message: "message of the feedback")
The returned URL is a direct link to the Bugfender's dashboard. Use it to create automations or to keep a reference in your servers.
Advanced Usage
Collecting system logs
Automatic os_log
collection
Bugfender can collect os_log
and NSLog
messages from your customers' iOS devices.
To enable the automatic collection, call:
Bugfender.enableNSLogLogging()
Customizing os_log
collection
Bugfender also provides the enableNSLogLogging(withInterceptor:)
function which to enable the log system collection but allows you tu use an interceptor to do an advanced filtering of the messages you want to send to our systems.
First you need to create a class that implements BFLogInterceptor
protocol:
import Foundation
import BugfenderSDK
class CustomLogInterceptor: NSObject, BFLogInterceptor {
func intercept(_ interceptedLog: BFInterceptedLog) -> BFInterceptedLog? {
// Implement your filtering logic here
// For example, only log messages that contain a specific keyword
if interceptedLog.text.contains("ImportantKeyword") {
return interceptedLog
} else {
return nil // Returning nil will block the log entry
}
}
}
Then, in your AppDelegate or the place where you initialize Bugfender, you can enable NSLog logging with your custom interceptor:
import UIKit
import BugfenderSDK
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Activate Bugfender with your app key
Bugfender.activateLogger("YOUR_APP_KEY")
//... other Bugfender options ...
// Create an instance of your custom interceptor
let interceptor = CustomLogInterceptor()
// Enable NSLog interception with your custom interceptor
Bugfender.enableNSLogLogging(withInterceptor: interceptor)
// ... other setup code ...
return true
}
}
Check the signature of BFInteceptedLog to see all the properties you can use.
Having your app decide when to send logs
In some special circumstances you may want to send logs, regardless of the enabled state of the device in the Bugfender console, for example in a custom exception handler. Use forceSendOnce
to force sending the logs once, and use setForceEnabled:
to force it for some period of time.
Manually sending crashes in iOS
If you have your own crash reporting system and need to send crashes, you can do so by calling directly sendCrashWithTitle
[Bugfender sendCrashWithTitle:@"My Crash" text:@"The app crashed on my code"]
Get Session Link
Sometimes you want to integrate Bugfender with a third party tool. For this purpose, the SDK provides a method that returns the URL for the session. You can send it to the third party tool to easily go to the logs of the current session from the other tool.
Bugfender.sessionIdentifierUrl();
Get Device Link
Sometimes you want to integrate Bugfender with a third party tool. For this purpose, the SDK provides a method that returns the URL for the current device. You can send it to the third party tool and easily navigate back to the logs of the device from the other tool.
Bugfender.deviceIdentifierUrl()
Log buffer size
Bugfender keeps up to 5 MB worth of log data in the device. This way Bugfender can work offline, and you can get some log data from the past when enabling a device. You can change that limit with setMaximumLocalStorageSize
.
// Setting maximum cache size to 1 Mb
Bugfender.setMaximumLocalStorageSize(1024*1024)
Automate Symbols Uploading
You can use the Bugfender XCode Script to automatically upload dSYM bundle for symbolicating crashes.
Note: At the moment, Bitcode enabled apps are not supported by the script.
To add the script to XCode:
- Copy the script to your project directory.
- Go to your App settings.
- Select Target from the left.
- Select the Build Settings tab, find Build Options > User Script Sandboxing and set it to No.
- Go to Build Phases.
- Open menu under the
+
sign and select New Run Script Phase. - Under the shell portion of Run Script add a script call:
BUGFENDER_SYMBOLICATION_URL=https://dashboard.bugfender.com/ <path_to_the_script>/upload-symbols.sh YOUR_SIMBOLICATION_TOKEN
- It is also possible to drag & drop it from Finder and XCode will fill in the path.
Remember to change YOUR_SIMBOLICATION_TOKEN with the symbolication token for your app. You can get an app key by signing up to Bugfender.
API Reference
For a complete API Reference you can visit: https://bugfender.github.io/BugfenderSDK-iOS/Classes/Bugfender.html