我目前正在xcode项目中测试我的cocoapod,并且在xcode中运行我的应用程序时遇到以下错误。

“线程1:致命错误:展开一个可选值时意外发现为零”

我知道这与展开一个可选值有关,但我不确定是什么问题。有什么想法我做错了吗?

error being thrown when running my app

我已附上我的.swift文件以供参考

import Foundation
import CoreLocation
import UserNotifications

open class Rule {
    public let notificationCenter = UNUserNotificationCenter.current()

    public let action: Action
    public let enabled: Bool
    public let id: String
    public let geofence: Geofence
    public let name: String
    public let trigger: Trigger
    public let locationManager: CLLocationManager = CLLocationManager()


    public init (ruleDict: NSDictionary) {
        self.action = Action(actionDict: ruleDict["action"] as! NSDictionary)
        self.enabled = ruleDict["enabled"] as! Bool
        self.id = ruleDict["id"] as! String
        self.geofence = Geofence(geofenceDict: ruleDict["geofence"] as! NSDictionary)
        self.name = ruleDict["name"] as! String
        self.trigger = Trigger(triggerDict: ruleDict["trigger"] as! NSDictionary)
    }

    open func initGeofence() {
        // do something
        let geofenceRegionCenter = self.geofence.center
        let geofenceRegion = CLCircularRegion(center: geofenceRegionCenter, radius: CLLocationDistance(self.geofence.radiusSize), identifier: self.id)
        geofenceRegion.notifyOnExit = true
        geofenceRegion.notifyOnEntry = true

        locationManager.startMonitoring(for: geofenceRegion)
    }

    open func scheduleNotification() {
        if (self.getActionType() == "notification") {
            let content = UNMutableNotificationContent()
            content.body = self.action.message!

            let center = self.geofence.center
            let region = CLCircularRegion(center: center, radius: self.geofence.radiusSize, identifier: self.id)

            switch self.getTriggerType() {
                case "enters":
                    region.notifyOnEntry = true
                    region.notifyOnExit = false
                case "exits":
                    region.notifyOnEntry = false
                    region.notifyOnExit = true
                case "returns":
                    region.notifyOnEntry = true
                    region.notifyOnExit = false
                default:
                    region.notifyOnEntry = true
                    region.notifyOnExit = false
            }

            let trigger = UNLocationNotificationTrigger(region: region, repeats: true)
            let request = UNNotificationRequest(identifier: self.id, content: content, trigger: trigger)

            notificationCenter.add(request) { (error) in
                if error != nil {
                    print("\(String(describing: error))")  // compiler warning patched
                } else {
                    print("Added notification to center")
                }
            }
        } else {
//            print("Not a notification")
        }

    }

    open func removeNotification() {
        notificationCenter.removePendingNotificationRequests(withIdentifiers: [self.id])
    }

    open func getActionType() -> String {
        return self.action.actionType.rawValue
    }

    open func getTriggerType() -> String {
        return self.trigger.triggerType.rawValue
    }

    open func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        // Play sound and show alert to the user
        print("Showing notification")
        completionHandler([.alert,.sound])
    }

    open func triggerSegue(segueID: String) {
        // TODO: implement
        print("We need to trigger \(segueID)")
    }
}

open class Trigger {
    public enum triggerType: String {
        case enters
        case exits
        case dwells
        case returns
    }

    public let time: Int
    public let triggerType: triggerType

    public init (triggerDict: NSDictionary) { // time is 0 when not a dwell rule
        if let t = triggerDict["time"] as? Int {
            self.time = t
        } else {
            self.time = 0
        }

        let triggerTypeStr = triggerDict["triggerType"] as! String

        switch triggerTypeStr {
            case "enters":
                self.triggerType = .enters
            case "exits":
                self.triggerType = .exits
            case "dwells":
                self.triggerType = .dwells
            case "returns":
                self.triggerType = .returns
            default:
                self.triggerType = .enters
        }
    }
}

open class Geofence {
    public let center: CLLocationCoordinate2D
    public let radiusSize:Double

    public let geofenceType:geofenceType
    public enum geofenceType: String {
        case radius
        case polygon
    }

    public init(geofenceDict: NSDictionary) {
        let centerDict = geofenceDict["center"] as! NSDictionary

        let latStr = centerDict["lat"] as! String
        let lonStr = centerDict["lon"] as! String
        let lat = Double(latStr)!
        let lon = Double(lonStr)!
        self.center = CLLocationCoordinate2DMake(lat, lon)

        let radiusSize = geofenceDict["radiusSize"] as! Double
        self.radiusSize = radiusSize

        let geofenceTypeStr = geofenceDict["geofenceType"] as! String

        switch geofenceTypeStr { // polygon not supported yet
            case "radius":
                self.geofenceType = .radius
            default:
                self.geofenceType = .radius
            }
        }
}

open class Action {
    public let actionType: actionType
    public enum actionType: String {
        case notification
        case segue
        case monitor
        case http
    }

    public var message:String?
    public var segueID:String?

    public init(actionDict: NSDictionary) {
        let actionTypeStr = actionDict["actionType"] as! String

        switch actionTypeStr {
            case "notification":
                self.actionType = .notification
                self.message = (actionDict["message"] as! String)
            case "segue":
                self.actionType = .segue
                self.segueID = (actionDict["segueID"] as! String)
            case "monitor":
                self.actionType = .monitor
            case "http":
                self.actionType = .http
            default:
                self.actionType = .monitor
        }
    }
}

open class NotifyResponse {
    public let triggered:Bool
    public let message:String
    public var action:Action?
    public var httpResponse:NSDictionary?
    public var segueID:String?

    public init(responseDict: NSDictionary) {
        self.triggered = responseDict["triggered"] as! Bool
        self.message = responseDict["message"] as! String
        if (self.triggered) {
            if let actionDict = responseDict["action"] as? NSDictionary {
                self.action = Action(actionDict: actionDict)
                print("Type in constructor: \(self.getActionType())")
                if (self.getActionType() == "segue") {
                    self.segueID = action?.segueID
                }
            } else if let httpResponseDict = responseDict["httpResponse"] as? NSDictionary {
                self.httpResponse = httpResponseDict
            }
        }
    }

    open func getHTTPResponse() -> NSDictionary? {
        return self.httpResponse
    }

    open func getActionType() -> String {
        if let action = self.action {
            return action.actionType.rawValue
        } else {
            return ""
        }
    }
}

最佳答案

Optional value,将允许存储nil值,因此当尝试
  类将其强制转换并找到nil值,这会使您的应用程序崩溃。
  
  类/对象类可以强行完成,在Swift中可以safe一次。您
  已经强制降档,这就是为什么它崩溃的原因。


因此,如下修改您的代码,

 public init (ruleDict: NSDictionary) {
        if ruleDict != nil  {

            if let action =  Action(actionDict: ruleDict["action"] **as?** NSDictionary){
                self.action = action
            }

            if let enabled = ruleDict["enabled"] **as?**  Bool {
                self.enabled = enabled
            }

            if let id = ruleDict["id"] **as?** String {
                self.id = id
            }

            if let geofence = Geofence(geofenceDict: ruleDict["geofence"] **as?** NSDictionary) {
                self.geofence = geofence
            }

            if let name = ruleDict["name"] **as?** String {
                self.name = name
            }

            if let trigger = Trigger(triggerDict: ruleDict["trigger"] **as?** NSDictionary) {
                self.trigger = trigger
            }

        }
    }

08-05 03:15