可选类型 EKReminder 的值未展开

Value of optional type EKReminder not unwrapped

我正在尝试根据本教程创建提醒,尝试将 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 块中,它检查值因为不是零。因此 appDelegate!.eventStore 在这个块中不是 nil,因此不需要解包(?)。 我也试过设置“!”在这个变量之后,像这样:

appDelegate!.eventStore!

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

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

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

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

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

从外观上看,这更多的是与额外的参数有关,而不是与隐式解包的可选参数有关——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,也可能会抛出错误而不是打印出来。

如果您检查 nil

的可选值
if (appDelegate!.eventStore != nil) {

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

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

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

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

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