【问题标题】:Value of optional type EKReminder not unwrapped可选类型 EKReminder 的值未解包
【发布时间】:2015-10-19 08:12:30
【问题描述】:

我正在尝试根据本教程创建提醒,尝试将 Swift 1 更改为 Swift 2 代码:

http://www.techotopia.com/index.php/Using_iOS_8_Event_Kit_and_Swift_to_Create_Date_and_Location_Based_Reminders

我收到错误:可选类型的值未解包。

func createReminder() {

    if (appDelegate!.eventStore != nil) {
        let reminder = EKReminder(eventStore: appDelegate!.eventStore) //value not unwrapped

        reminder.title = reminderText.text
        reminder.calendar =
            appDelegate!.eventStore!.defaultCalendarForNewReminders()
        let date = myDatePicker.date
        let alarm = EKAlarm(absoluteDate: date)

        reminder.addAlarm(alarm)

        var error: NSError?
        appDelegate!.eventStore!.saveReminder(reminder,
            commit: true, error: &error)

        if error != nil {
            print("Reminder failed with error \(error?.localizedDescription)")
        }
    }
}

我了解可选值的概念(在运行时此时不能为变量赋值),我不明白的是我在 if 块内,它检查值是否为 nil。因此 appDelegate!.eventStore 在此块中不是 nil,因此不需要解包 (?)。 我也尝试设置“!”在这个变量之后,像这样:

appDelegate!.eventStore!

但它破坏了其他代码,它给出了围绕此代码的错误:

appDelegate!.eventStore!.saveReminder(reminder,
            commit: true, error: &error)  //extra argumenr 'error' in call 

用 do{}catch{} 语句包围它没有帮助..

【问题讨论】:

    标签: ios iphone swift2 ios9 xcode7


    【解决方案1】:

    从表面上看,这更多是与额外参数有关,而不是与隐式展开的可选参数有关——Apple 已经为 Swift 2 更新了很多 SDK,以避免传入对 NSError 对象的引用和请改用try

    eventStore.saveReminder(reminder, commit: true, error: &error)
    

    变成

    do {
        try eventStore.saveReminder(reminder, commit: true)
    }
    catch error: NSError {
        print(error.localizedDescription)
    }
    

    作为一般规则,我会避免像瘟疫那样隐式展开的可选项——几乎不需要它们,当它们确实存在时,您总是可以创建一个适当的非可选项。试试:

    func createReminder() throws {
    
        guard let eventStore = appDelegate?.eventStore else {
            let error: NSError = NSError(domain: "com.mycompany.myapp", code: 1, userInfo: [
            NSLocalizedDescriptionKey: "Unable to get event store from app delegate"
            ])
            throw error
        }
    
        let reminder = EKReminder(eventStore: eventStore)
    
        reminder.title = reminderText.text
        reminder.calendar = eventStore.defaultCalendarForNewReminders()
        let date = myDatePicker.date
        let alarm = EKAlarm(absoluteDate: date)
    
        reminder.addAlarm(alarm)
    
        try eventStore.saveReminder(reminder, commit: true)
    }
    

    这样你就不会玩隐式展开的选项,eventStore 保证在你使用它时被设置,并且任何调用 createReminder() 可以处理错误是有一个(你可能也会抛出一个错误而不是如果未设置eventStore,则打印出来)。

    【讨论】:

    • 更新为使用 guard 并抛出错误,作为 Swift 2 的更好使用
    【解决方案2】:

    好的,我不确定代码,但我修复了错误,我仍然需要使用 do-try-catch,但像这样:

         do {
                try appDelegate!.eventStore!.saveReminder(reminder, commit: true) 
            } catch {
                print(error)
            }
    

    【讨论】:

      【解决方案3】:

      如果您检查nil 的可选值

      if (appDelegate!.eventStore != nil) {
      

      你必须打开它以防它不是nil

      let reminder = EKReminder(eventStore: appDelegate!.eventStore!)
      

      更合适的方式是使用可选绑定

      if let store = appDelegate!.eventStore {
       let reminder = EKReminder(eventStore: store)
        …
      }
      

      appDelegate 声明为可选的目的是什么?
      AppDelegate 类默认存在于任何应用程序中,并且永远不会是 nil

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-25
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        相关资源
        最近更新 更多