Features
Freeze detection
A call to LastCrash.applicationInitialized()
must be made after your app is initialized in order to track freeze (application not responding or ANR) errors.
The reason this call to LastCrash.applicationInitialized()
is required is to starting Freeze monitoring only after everything in your app is initialized/loaded so false positives can be avoided.
Masking
All text that isn't part of the app's localization files will be redacted on device to prevent any user or customer PII from being captured. Ensure that all user interface elements are utilizing localization strings to get the most value out of the recorded crash videos.
SwiftUI masking
In order to mask SwiftUI views copy the LastCrashMasking.swift
file into your application.
Add the following overlay to the view you would like to mask:
Image(systemName: "heart.fill")
.imageScale(.large)
.foregroundStyle(.tint)
.overlay(LastCrashMask("MaskedImage"))
Then add the following onPreferenceChange
to the container view detect masked views via preferences and the onDisappear
block to remove the masked views:
View {
VStack {
// content
}.onPreferenceChange(LastCrashMaskPositionKey.self, perform: lastCrashOnPreferenceChange)
.onDisappear {
LastCrash.removeMaskRect("MaskedImage")
}
}
View based masking
Views can be explicitly masked by passing a View object reference or by view id. An important note: it is your responsibility to manage the masked view lifecycle to add and remove masked views as they are shown on the screen.
A best practice is to add masked views in viewWillAppear
of a UIViewController
.
// Mask view by UIView object reference
LastCrash.addMaskView(view)
Masked views should be removed in the viewDidDisappear
of a UIViewController
.
// Remove mask view by UIView object reference
LastCrash.removeMaskView(view)
Rectangle based masking
Sections of the screen can be masked by rectangles relative to the app's container view frame. An important note: it is your responsibility to manage the masked rect lifecycle to add and remove masked rects.
A best practice is to add masked views in viewWillAppear
of a UIViewController
.
// Mask view by rect
LastCrash.addMaskRect(CGRect(0,0,100,100), maskId: "masked_rect")
Masked views should be removed in the viewDidDisappear
of a UIViewController
.
// Remove mask rect
LastCrash.removeMaskRect("masked_rect")
Networking
A call to LastCrash.addNetworkTrackingToDefaultSession()
must be made to track networking errors and get summarized networking statistics including bytes sent/recieveed and response time.
The call to LastCrash.addNetworkTrackingToDefaultSession()
will add support to any usage of the default URLSession URLSession.shared
.
If a custom URLSession
is used then the URLSessionConfiguration
used during creation must have the LastCrashURLProtocol
class configured.
let configuration = URLSessionConfiguration.default
configuration.protocolClasses = [LastCrashURLProtocol.self] + configuration.protocolClasses!
let myURLSession = URLSession(configuration: configuration)
Swift
import LastCrash
...
class AppDelegate: UIResponder, UIApplicationDelegate, LastCrashReportSenderDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
LastCrash.configure("LASTCRASH_API_KEY")
LastCrash.enabledLogging()
LastCrash.setCrashReportSenderDelegate(self)
LastCrash.addNetworkTrackingToDefaultSession()
LastCrash.applicationInitialized()
...
}
func lastCrashReportSenderHandleCrash() {
// logic to handle crash here
LastCrash.sendCrashes()
}
}
Objective-C
AppDelegate.h:
#import <LastCrash/LastCrash.h>
...
@interface AppDelegate : UIResponder <UIApplicationDelegate, LastCrashReportSenderDelegate>
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[LastCrash configure:@"LASTCRASH_API_KEY"];
[LastCrash enabledLogging];
[LastCrash setCrashReportSenderDelegate:self];
[LastCrash addNetworkTrackingToDefaultSession];
[LastCrash applicationInitialized];
...
}
- (void)lastCrashReportSenderHandleCrash {
// logic here to handle crash
[LastCrash sendCrashes];
}
...