首页 文章

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

提问于
浏览
8

我的团队最近发布了一个应用程序,其中发现了这些相对简单的应用程序,因为这是一个问题,即在违规函数中找到一个不良的强制转换或隐式解包的可选设置为nil . 这次虽然我找不到那种东西 . 我最好的猜测是,由于日历错误,可能其中一个 TimeBlock 对象或其属性为零 .

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

Apple SigTrap Definition

如果在运行时遇到意外情况,Swift代码将以此异常类型终止,例如:具有nil值的非可选类型,强制类型转换失败

Crashing Function

/**
    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)
}

Call of Crashing Function

/**
    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))
}

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()

}

TimeBlock Definition

// 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)
    }

}

Crash Report

事件标识符: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异常子类型:undefined线程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 _delegateViewForHeaderIn部分:](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:浮动:reuseViewIfPossible:willDisplay:](UIKit的)8的UIKit 0x000000018cfc6c04 - [_ UITableViewUpdateSupport(私人)_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专用闭包#1在MeetingTableViewController.re中freshTable(:)(MeetingTableViewController.swift:513)15 CallIn 0x0000000102c7aacc部分申请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 0x000000018327ea14 _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.swif) t:18)26 libdyld.dylib 0x00000001832e456c start(libdyld.dylib)

1 回答

  • 0

    Reproduction

    这是由于索引被 Timeblock.startHourTimeblock.endHour 弄为 Int 值造成的 . 在查看我们的用户日历后,我注意到他们所有的 Session 都在午夜结束 .

    因此,对于在下午5点到午夜之间进行的 Session ,我们会发生以下情况 .

    for i in timeblock.startHour...timeblock.endHour 成了 for i in 0...17

    这会给出一个非常准确的错误,告诉我一旦我再现了崩溃,我就无法向后迭代,遗憾的是没有出现在崩溃报告中,这有点误导 .

    Fix

    我们限制了创建 timeblock.endHour 属性的时间,因此第二天的 > 0:00 已更改为 23:59 以防止此情况发生 . 该修复只是将上限应用于 >= 0:00 ,因此在午夜结束的 Session 不会被视为多日 Session .

    未来的重构可能会设置从小时到前一小时结束的所有时间的结束时间,因为从技术上讲,如果您的 Session 在上午11:00结束,您仍然可以免费获得小时 . 我还想在 Timeblock 对象中处理这一切,而不是过滤用于创建它的参数 .

相关问题