Swift 4.0中EKEventStore请求提醒权限时闭包类型转换报错
修复Swift 4中EKEventStore请求提醒权限的类型错误
嘿,这个问题我太熟了!你遇到的核心问题是Swift 4里EKEventStore的权限请求闭包类型发生了变化,再加上代码里几个多余的操作,才导致了类型不匹配的报错。咱们一步步把它修好:
问题根源拆解
- 闭包参数类型不兼容:Swift 3之后,Apple把Objective-C的
NSError统一换成了Swift原生的Error类型。你写的(Bool, NSError?) -> Void和EKEventStoreRequestAccessCompletionHandler要求的(Bool, Error?) -> Void完全不匹配,这是报错的主要原因。 - 多余的强制类型转换:你在闭包后面重复写了两次
as! EKEventStoreRequestAccessCompletionHandler,这完全没必要——只要闭包类型匹配,Swift会自动推断,多写反而会引发类型冲突。 - GCD写法过时:Swift 4里早就不用
dispatch_async(dispatch_get_main_queue())了,现在用DispatchQueue.main.async才是标准写法。
修正后的完整代码
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 别漏了调用父类的生命周期方法! self.eventStore = EKEventStore() self.reminders = [EKReminder]() self.eventStore.requestAccess(to: .reminder) { granted, error in if granted { let predicate = self.eventStore.predicateForReminders(in: nil) self.eventStore.fetchReminders(matching: predicate) { reminders in DispatchQueue.main.async { // 处理reminders为nil的情况,避免可选类型问题 self.reminders = reminders ?? [] self.tableView.reloadData() } } } else { print("The app is not permitted to access reminders, make sure to grant permission in the settings and try again") // 这里其实可以弹个UIAlertController提示用户,比打印日志友好多了 } } }
关键修改点说明
- 把老派的
requestAccessToEntityType(EKEntityType.Reminder)换成Swift 4的语法糖requestAccess(to: .reminder),代码更简洁易读。 - 闭包参数直接写
granted, error就行,Swift会自动推断出它们的类型是Bool和Error?,不用手动声明。 - 删掉那两次多余的
as! EKEventStoreRequestAccessCompletionHandler,类型匹配后完全不需要强制转换。 - 把过时的GCD写法换成
DispatchQueue.main.async,符合Swift 4及以后的规范。 - 给
self.reminders赋值时加了?? [],防止reminders为nil时数组变成可选类型,避免后续可能的崩溃。 - 补充了
super.viewWillAppear(animated)——这是UIViewController生命周期方法的必要操作,之前你的代码漏掉了,可能会导致奇怪的UI问题。
这样改完之后,那个类型转换的错误就会消失,代码也更符合Swift的现代写法,稳定性也更好。
内容的提问来源于stack exchange,提问作者j-s
相关产品推荐
相关产品推荐

