如何确定我的SIGTrap崩溃的原因?

Dec*_*nna 9 crash crash-reports ios swift

我的团队最近推出了一个应用程序,其中有很多SIGTRAP崩溃.以前我发现这些相对简单,因为它是在一个有问题的功能中发现一个不良的力量施放或一个隐含的未包裹的可选被设置为零的问题.这次虽然我找不到那种东西.我最好的猜测是,TimeBlock由于日历错误,可能其中一个对象或其属性为零.

我们的应用程序是一个会议组织者,在FreeTime,Conflicts和Meeting方面向用户显示他们的原生iOS日历事件TimeBlocks.我可以访问几个崩溃用户的日历.

Apple SigTrap定义

如果在运行时遇到意外情况,则Swift代码将以此异常类型终止,例如:

  • 具有nil值的非可选类型
  • 强制类型转换失败

崩溃功能

    /**
    Updates the conflictHours and meetingHours according to the timeblocks
    it is used as quick light reference to the button
 */
func updateTimeHours(timeblocks : [Timeblock]) {
    for timeblock in timeblocks {
        switch timeblock {
        case is MeetingTimeblock:
            for i in timeblock.startHour...timeblock.endHour {
                self.meetingHours[i] = true
            }
            break
        case is ConflictTimeblock:
            for i in timeblock.startHour...timeblock.endHour {
                self.conflictsHours[i] = true
            }
            break
        default: break
        }
    }
    updateButtonByOffset(offset: self.scrollTimeline.contentOffset.x)
}
Run Code Online (Sandbox Code Playgroud)

召唤崩溃函数

    /**
    This function inits the variables and button layout according to the timeblocks
 */
func handleTimeblocksDependantComponents() {
    buttonLayout()
    guard Scheduler.sharedInstance.timelines.count > SharedGlobals.Calendar.TODAY_INDEX else {
        return
    }
    updateTimeHours(timeblocks : (Scheduler.sharedInstance.timelines[SharedGlobals.Calendar.TODAY_INDEX].timeblocks))
}
Run Code Online (Sandbox Code Playgroud)

SetHeaderHeight

/**
 Adjusts the height of the header depending on whether there are hosted meetings or 
 meeting VIP's or not.
*/
private func setHeaderHeight() {
    self.tableView.tableHeaderView = self.headerView
    let hostedMeetings = OverviewInteractor.getHostedMeetings(dayIndex: SharedGlobals.Calendar.SELECTED_DAY)
    let vips = OverviewInteractor.getVIPS(dayIndex: SharedGlobals.Calendar.SELECTED_DAY)

    self.tableView.beginUpdates()
    if let headerView = self.tableView.tableHeaderView {
        var height = 360.0
        if(vips.count == 0) { height -= 80.0 }
        if(hostedMeetings.count == 0) { height -= 80.0 }
        headerView.frame.size.height = CGFloat(height)
    }
    self.tableView.endUpdates()

}
Run Code Online (Sandbox Code Playgroud)

TimeBlock定义

// The Timeblock parent class. It simply holds a start and end time and provides its own duration. Not to be used as such
public class Timeblock {
    public let startTime: Date
    public let endTime: Date

    /// Returns the hour the Timeblock starts, in current timezone
    public var startHour: Int {
        get {
            return Calendar.current.component(.hour, from: startTime)
        }
    }

    /// Returns the hour the Timeblocks ends, in current timezone
    public var endHour: Int {
        get {
            return Calendar.current.component(.hour, from: endTime)
        }
    }

    /// Returns the minutes the Timeblocks starts
    public var startMinutes: Int {
        get {
            return Calendar.current.component(.minute, from: startTime)
        }
    }

    /// Returns the minutes the Timeblocks ends
    public var endMinutes: Int {
        get {
            return Calendar.current.component(.minute, from: endTime)
        }
    }

    /**
        Initialises the instance with a start and end time
        - Parameters:
            - startTime: The start time of the timeblock
            - endTime: The end time of the timeblock
    */
    public init(startTime: Date, endTime: Date) {
        self.startTime = startTime
        self.endTime = endTime
    }

    /**
        Provides the Timeblock's duration in the form of a DateInterval
        - warning: Only available on iOS 10.0 and up
        - returns: A DateInterval of the duration of the Timeblock
    */
    @available(iOS 10.0, *)
    public func getTimeInterval() -> DateInterval {
        return DateInterval(start: self.startTime, end: self.endTime)
    }

    /**
        Provides the Timeblock's duration in the form of a `Double` (number of seconds)

        - returns: The number of seconds that this Timeblock goes on for
    */
    public func getDuration() -> Double {
        return self.endTime.timeIntervalSince(self.startTime)
    }

}
Run Code Online (Sandbox Code Playgroud)

崩溃报告

事件标识符:98D4F477-C57B-4767-B957-E9EA2E0EE3EA CrashReporter密钥:0000000000000000000000000000000000000000硬件型号:undefined进程:xxxxxxx [784]标识符:
com.xxx.xxx.xx.xxxxxxx版本:4.0.3代码类型:
arm64

日期/时间:Sun Dec 24 2017 09:55:23 GMT + 0000(GMT)发布时间:无效日期操作系统版本:undefined 11.0.3(15A432)报告版本:105

异常类型:SIGTRAP异常子类型:未定义

线程0名称:线程0崩溃:0 CallIn
0x0000000102c224e4专用TimelineHeader.updateTimeHours(timeblocks :)(TimelineHeader.swift:0)1 CallIn 0x0000000102c20af0 TimelineHeader.handleTimeblocksDependantComponents()(TimelineHeader.swift:0)2 CallIn
0x0000000102c7a28c专用MeetingTableViewController.tableView(: viewForHeaderInSection :)(TimelineHeader.swift:78)3 CallIn
0x0000000102c75d54 @objc MeetingTableViewController.tableView(
:viewForHeaderInSection :)(MeetingTableViewController.swift:0)4 UIKit
0x000000018d1157d8 - [UITableView _delegateViewForHeaderInSection:](UIKit)5 UIKit 0x000000018d11def0 96- [UITableView _sectionHeaderView :withFrame:forSection:floating:reuseViewIfPossible:willDisplay:] _ block_invoke(UIKit)6 UIKit 0x000000018cdf1a14 + [UIView(Animation)performWithoutAnimation:](UIKit)7 UIKit 0x000000018d11dc60 - [UITableView _sectionHeaderView:withFrame:forSection:floating:reuseViewIfPossible:willDisplay:] (UIKit)8 UIKit 0x000000018cfc6c04 - [_ UITableViewUpd ateSupport(私人)_setupAnimationsForExistingHeadersAndFooters](UIKit的)9的UIKit 0x000000018cfc1070 - [_ UITableViewUpdateSupport _setupAnimations](UIKit的)10的UIKit 0x000000018cfc0944 - [UITableView的_updateWithItems:updateSupport:](UIKit的)11的UIKit 0x000000018cfa8448 - [UITableView的endCellAnimationsWithContext:](UIKit的)12的UIKit 0x000000018cfa46e4 - [UITableView endUpdates](UIKit)13 CallIn 0x0000000102c761a4 MeetingTableViewController.setHeaderHeight()(MeetingTableViewController.swift:398)14 CallIn
0x0000000102c7a7c8 MeetingTableViewController.refreshTable(
:)中的专用闭包#1(MeetingTableViewController.swift:513)15 CallIn
0x0000000102c7aacc partial申请关闭MeetingTableViewController.refreshTable(_ :)中的#1(MeetingTableViewController.swift:0)16 CallIn
0x0000000102cd17f0 thunk for @callee_owned() - >()(LoginPageViewController.swift:0)17 libdispatch.dylib
0x000000018327ea54 _dispatch_call_block_and_release(libdispatch.dylib)18 libdispatch .dylib
0x000000018327ea 14 _dispatch_client_callout(libdispatch.dylib)19 libdispatch.dylib 0x000000018328b698 _dispatch_main_queue_callback_4CF $ $ VARIANT MP(libdispatch.dylib)20的CoreFoundation 0x00000001838aa544 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE
(的CoreFoundation)21的CoreFoundation 0x00000001838a8120 __CFRunLoopRun(的CoreFoundation)22的CoreFoundation
0x00000001837c7e58 CFRunLoopRunSpecific(的CoreFoundation)23 GraphicsServices 0x0000000185674f84 GSEventRunModal(GraphicsServices) 24 UIKit
0x000000018ce4767c UIApplicationMain(UIKit)25 CallIn
0x0000000102c02c08 main(AppDelegate.swift:18)26 libdyld.dylib
0x00000001832e456c start(libdyld.dylib)

Dec*_*nna 2

再生产

\n\n

这是由于索引被值搞乱了而Timeblock.startHour造成的。查看我们的用户日历后,我注意到他们所有人的会议都在午夜结束。Timeblock.endHourInt

\n\n

因此,对于下午 5 点到午夜之间举行的会议,我们会发生以下情况。

\n\n

for i in timeblock.startHour...timeblock.endHour\n变成\nfor i in 0...17

\n\n

这将给出一个相当精确的错误,告诉我一旦重现崩溃就无法向后迭代,不幸的是,崩溃报告没有出现,这有点误导。

\n\n

使固定

\n\n

我们限制了创建该属性的时间timeblock.endHour,因此> 0:00更改为第二天23:59以防止这种情况发生。修复方法只是应用上限,>= 0:00以便在午夜结束的会议\xe2\x80\x99 不会被视为多日会议。

\n\n

未来的重构可能会将所有在该小时结束的时间设置为前一小时,因为从技术上讲,如果您的会议在上午 11:00 结束,您仍然有这一小时的空闲时间。我还想在Timeblock对象内处理这一切,而不是过滤用于创建它的参数。

\n