按下 TableViewCell 中的按钮时,将事件从 API 保存到日历
Posted
技术标签:
【中文标题】按下 TableViewCell 中的按钮时,将事件从 API 保存到日历【英文标题】:Save Event to Calendar from API when Button in TableViewCell is Pressed 【发布时间】:2019-11-18 17:57:35 【问题描述】:我希望在 tableView 的每一行中都有相同的“保存到日历按钮”,并且每个按钮从通过 api 使用可解码的 JSON 导入的 JSON 中打开一个不同的事件。
我需要为每个按钮分配 indexPath.row 以便第一个按钮填充来自第一个 JSON 对象的信息,第二个按钮填充来自第二个 JSON 对象的信息,等等...有一个示例下面的表格视图。我希望每个按钮使用从 api 传递的“标题”将不同的事件保存到用户的日历中。 (传递给您在下面看到的“标题”UILabel 的相同标题。)我还希望“描述”自动填充来自 api 的描述。我已经使用 decodedable 导入了 json 信息。
这是在 viewController 中找到的 cellForRowAt 代码:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as! EventTableViewCell
let item = page!.tradeshows[indexPath.row]
cell.registrationUrl = item.link
cell.eventTitle.text = item.title
cell.eventDate.text = item.tradeshowDescription
cell.addEventToCalendar(title: item.title!, description: item.tradeshowDescription, startDate: NSDate() as Date, endDate: NSDate() as Date)
return cell
我需要上面应用的 JSON 信息(标题:item.title!)和(描述:item.tradeshowDescription),以便在每行中按下“保存到日历”按钮时自动填充信息。我需要分配 indexPath,以便在保存到日历时自动填充事件的信息是每一行的正确信息。
感谢任何建议。
在 TableViewCell 中找到自定义 Xib 单元类代码:
import UIKit
import EventKit
class EventTableViewCell: UITableViewCell
var registrationUrl : URL!
@IBOutlet weak var eventDate: UILabel!
@IBOutlet weak var eventTitle: UILabel!
@IBOutlet weak var saveToCalendarButton: UIButton!
@IBOutlet weak var registerButton: UIButton!
override func awakeFromNib()
super.awakeFromNib()
// Initialization code
selectionStyle = UITableViewCell.SelectionStyle.none
@IBAction func registerButtonPressed(_ sender: Any)
UIApplication.shared.open(registrationUrl)
@IBAction func saveToCalenderButtonPressed(_ sender: Any)
addEventToCalendar(title: "", description: "", startDate: NSDate() as Date, endDate: NSDate() as Date)
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil)
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: (granted, error) in
if (granted) && (error == nil)
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do
try eventStore.save(event, span: .thisEvent)
catch let e as NSError
completion?(false, e)
return
completion?(true, nil)
else
completion?(false, error as NSError?)
)
【问题讨论】:
你为什么要用 [String()] 而不是 [String]() 来创建一个 String() 类型的函数数组, 我不确定应该如何格式化该变量。我在每一行都有一个“保存事件”按钮。我希望当您单击第一行中的“保存事件”按钮时,它将带有标题的事件作为“标题”字符串从第一个 json 对象中的标题保存到用户的日历中。然后,如果您单击第二行中的下一个“保存事件”按钮,它会将第二个 json 对象的标题保存为事件标题。 正如我的评论中所建议的那样,您需要一个字符串数组,即 [String]() 以便您摆脱错误并能够将字符串保存在数组中 请添加addEventTocalendar
的代码,这里是从保存到日历中读取的事件值。
当我使用“[String]()”时,此解决方案给我错误“无法将类型 '()' 的值分配给类型 '[String]”我添加了“addEventToCalender”代码。
【参考方案1】:
重写 cellForRow 方法。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as! EventTableViewCell
let item = page!.tradeshows[indexPath.row]
cell.registrationUrl = item.link
cell.eventTitle.text = item.title
cell.eventDate.text = item.tradeshowDescription
cell.saveToCalendarButton.tag = indexPath.row
cell.saveToCalendarButton.addTarget(self, action: #selector(saveToCalenderButtonPressed(sender:)), for: .touchUpInside)
return cell
然后在 viewController 中你必须编写以下函数。
@IBAction func saveToCalenderButtonPressed(_ sender: Any)
guard let index = (sender as? UIButton).tag else return
let item = eventArray[index]
addEventToCalendar(title: item.title ?? "", description:item.tradeshowDescription, startDate: Date(), endDate: Date()) (granted, error) in
if error == nil
print("success")
else
print("error added to calendar")
并将这个其他功能添加到 viewController。
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: Error?) -> Void)? = nil)
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: (granted, error) in
if (granted) && (error == nil)
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do
try eventStore.save(event, span: .thisEvent)
catch
completion?(false, error)
return
completion?(true, nil)
else
completion?(false, error?)
)
因此您的 viewController 负责将事件添加到日历中。 当用户触摸单元格中的按钮时,您必须获取数组的索引,发送者标记等于单元格的 indexPath.row。
【讨论】:
我无法让 IBAction 函数连接到我的 viewController,因为 IBOulet 在 EventTableViewCell.swift 文件中,如上所示。如果我从该文件中删除它,那么当我尝试在 cellforRowAt 中引用它时,它找不到出口,因为它正在“eventCell”中查找 我说你必须从单元格中删除并将其添加到视图控制器,这样你就可以将目标连接到按钮而不执行操作。因此单元格中的按钮没有@IBAction,您可以在 addTarget 函数中为其添加目标。以上是关于按下 TableViewCell 中的按钮时,将事件从 API 保存到日历的主要内容,如果未能解决你的问题,请参考以下文章
tableviewcell 内的 UIButton 触发单元格而不是按钮 [重复]