iOS 11 拖放:拖放到标准日历应用程序上



我正在尝试将iOS 11拖放功能集成到Xcode 9测试版的应用程序中。 我对创建一个可以被标准日历应用程序理解的 NSItemProvider 很有趣。我的拖动从 UITableView 开始,因此只实现了单个 dragDelegate 方法。

到目前为止,我已经尝试了以下方法:

let text = "Rendez-vous at (clientName)"
let data = text.data(using: .utf8)
let itemProvider = NSItemProvider()
itemProvider.registerDataRepresentation(forTypeIdentifier: kUTTypeCalendarEvent as String, visibility: .all) { completion in
completion(data, nil)
return nil
}
let dragItem = UIDragItem(itemProvider: itemProvider)

并且还尝试使用类型标识符kUTTypePlainText。没有运气,日历应用程序没有记录掉落。

我找不到任何关于此的官方文档。我希望日历应用程序正在寻找一些标准日历数据,这不仅限于相互通信的标准应用程序。例如,您可以将文本从备忘录应用拖放到日历中以创建事件。

有人知道我可以尝试什么吗?

提前谢谢。

TL;DR:让默认iOS日历应用程序识别符合NSItemProviderWriting协议的自定义对象的秘密要素是"com.apple.ical.ics"类型标识符并将自定义对象导出为iCalendar字符串(vEvent(。


我已经玩了几天了,我终于设法让它工作了!我会尽可能多地分解我的步骤。

  1. 创建一个符合 NSItemProviderWriting 的自定义对象:
    • 为了符合协议,您需要实现 可写类型标识符ForItemProvider 和加载数据(与类型标识符:, forItemProviderCompletionHandler:(。
    • 标识符
    • 数组是可以按保真顺序以最高保真度优先导出的类型标识符的列表。因此,请将自定义类型标识符放在首位,然后将"com.apple.ical.ics"放在后面。
    • 上面提到的loadData函数将尝试查找拖动目标(此方案中的日历应用(支持的标识符,并且你的应用也支持该标识符,并尝试首先获得最高保真度。

例如:

public static var writableTypeIdentifiersForItemProvider: [String] {
return ["com.yourcompany.myEvent", "com.apple.ical.ics"]
}
public func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
switch typeIdentifier {
case "com.yourcompany.myEvent": // Your custom handling goes here
case "com.apple.ical.ics": completionHandler(createVEvent(), nil)
default: completionHandler(nil, YourAppError.someCustomError)
}
return nil
}
  1. 使用自定事件信息创建 iCalendarvEvent字符串:
    • 此步骤与 WWDC 2017 会话 227 中的演示非常相似,他们在演示中为自定义联系人创建vCard字符串。从该会话中签出演示项目。
    • 从本质上讲,日历应用程序支持几种特定类型的类型标识符,iCal格式就是其中之一。因此,您只需要创建一个帮助程序方法,将自定义事件类型转换为 iCalendar 字符串。
    • 我不会详细介绍vEvent,但这里和这里有很多好信息。

这里有一个建议:

private func createVEvent() -> Data? {
let today = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss'Z'"
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
let startDateString = dateFormatter.string(from: startDate)
let endDateString = dateFormatter.string(from: endDate)
let todayString = dateFormatter.string(from: today)
var vCalendarText = "BEGIN:VCALENDARn"
vCalendarText +=    "VERSION:2.0n"
vCalendarText +=    "PRODID:-//Your Company//App Name//ENn"
vCalendarText +=    "BEGIN:VEVENTn"
vCalendarText +=    "UID:(identifier.uuidString)n"
vCalendarText +=    "SUMMARY:(name)n"
vCalendarText +=    "DTSTAMP:(todayString)n"
vCalendarText +=    "DTSTART:(startDateString)n"
vCalendarText +=    "DTEND:(endDateString)n"
vCalendarText +=    "END:VEVENTn"
vCalendarText +=    "END:VCALENDAR"
return vCalendarText.data(using: .utf8)
}

↑ 类似于我之前提到的那个会话演示中的createVCard()函数......

就是这样!这几乎就是您所需要的一切。困难的部分是知道日历应用程序支持的标识符以及如何进行vEvent。感谢 quiker 找到支持的标识符。

最后一个提示:您可以使用这个漂亮的工具验证您的 iCalendar 字符串 这里.

请注意,这只允许删除自定义对象。将事件从日历拖动到您的应用程序是另一回事,但您可以从我的提示中弄清楚。:)

祝您编码愉快!

相关内容

最新更新