Holtrod
Holtrod

Reputation: 115

How Do I Recover a Stack Trace in Swift?

How do I recover the stack trace in Swift, so that I can find out which method was the last one called before a crash?

What I want to replicate in Swift is this method in C#:

public static Assembly GetComponentInInvocationDegree(int invocationDegree)
    {
        if (invocationDegree < 0) throw new ArgumentOutOfRangeException("Cannot set out of range value: invocation degree must be greater than or equal to zero");

        var stackInvocacion = new StackTrace().GetFrames();
        if (invocationDegree > 0)
        {
            int invokingAssemblyIndex = 0;
            string currentDegreeComponentName;
            try
            {
                for (int currentDegree = 0; currentDegree < invocationDegree; currentDegree++)
                {
                    currentDegreeComponentName = stackInvocacion[invokingAssemblyIndex].GetMethod().ReflectedType.Assembly.GetName().Name;
                    while (stackInvocacion[invokingAssemblyIndex].GetMethod().ReflectedType.Assembly.GetName().Name == currentDegreeComponentName) invokingAssemblyIndex++;                        
                }
            }
            catch (Exception ex) { throw new InvalidOperationException(string.Format("Cannot get component in invocation degree: invocation degree {0} does not exist", invocationDegree), ex); }

            return stackInvocacion[invokingAssemblyIndex].GetMethod().ReflectedType.Assembly;
        }

        return stackInvocacion[0].GetMethod().ReflectedType.Assembly;
    }

Upvotes: 8

Views: 5882

Answers (2)

SwiftArchitect
SwiftArchitect

Reputation: 48514

In many cases, you could use a try/catch mechanism.

do {
    try ... // risky business goes here
} catch let error as NSError {
    print("Error: \(error.domain)")
    println(NSThread.callStackSymbols())
}     

Swift errors have no such thing as stack-trace yet (if will ever), and even Xcode can show stack-trace only if the error is un-handled by our code (and gets caught by Xcode directly instead).

Alternativly, your custom Error's constructor can store the stack-trace for later use, but in most cases errors are not custom, where you can't alter error's constructor (like errors of 3rd-party library).

Exception breakpoint

If you just want to debug, without need to upload stack-trace to server, then Xcode's "Exception breakpoint" feature can help, like:

  • First place a normal-breakpoint near the failing logic.

  • Wait until Xcode pauses App on that line, enable Xcode's feature:

  • Finally, resume App, and wait untill exception is thrown.

Images are old, nowadays you see "Swift error breakpoint" or something like that as well (beside "Add Exception Breakpoint" option).

Upvotes: 7

david euler
david euler

Reputation: 824

In swift 3 and above, you can do it like this:

do {
    //....
}
catch {
    print("error occurred")
    print(Thread.callStackSymbols)
}

Upvotes: 3

Related Questions