未解包的可选类型EKReminder的值

时间:2015-10-19 08:12:30

标签: ios iphone swift2 ios9 xcode7

我正在尝试根据本教程创建提醒,尝试将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 {}语句包围它并没有帮助..

3 个答案:

答案 0 :(得分:4)

从外观来看,这更多的是与额外的参数相比而不是隐式展开的可选项 - 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,则抛出错误而不是打印出来。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

如果您检查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