iOS 11 拖放:在标准日历应用程序上拖放
iOS 11 drag & drop: dropping on standard Calendar app
我正在尝试将 iOS 11 拖放功能集成到 Xcode 9 beta 的应用程序中。
我对创建标准日历应用程序可以理解的 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
)。
我已经研究了几天,终于成功了!我会尽量分解我的步骤。
- 创建一个符合NSItemProviderWriting的自定义对象:
- 要符合协议,您需要实施
writableTypeIdentifiersForItemProvider
和 loadData(withTypeIdentifier:,
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
}
- 使用您的自定义事件信息创建一个 iCalendar
vEvent
字符串:
- 此步骤与 WWDC 2017 Session 227 中的演示非常相似,他们在其中为自定义联系人创建了一个
vCard
字符串。从该会话中检出演示项目。
- 基本上,日历应用程序支持几种特定类型的类型标识符,iCal 格式就是其中之一。因此,您只需要制作一个辅助方法,将您的自定义事件类型转换为 iCalendar 字符串。
- 我不会在
vEvent
上详细介绍,但是有很多有用的信息 here and here。
这里有一个建议:
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:VCALENDAR\n"
vCalendarText += "VERSION:2.0\n"
vCalendarText += "PRODID:-//Your Company//App Name//EN\n"
vCalendarText += "BEGIN:VEVENT\n"
vCalendarText += "UID:\(identifier.uuidString)\n"
vCalendarText += "SUMMARY:\(name)\n"
vCalendarText += "DTSTAMP:\(todayString)\n"
vCalendarText += "DTSTART:\(startDateString)\n"
vCalendarText += "DTEND:\(endDateString)\n"
vCalendarText += "END:VEVENT\n"
vCalendarText += "END:VCALENDAR"
return vCalendarText.data(using: .utf8)
}
↑ 类似于我之前提到的会话演示中的 createVCard()
函数……
就是这样!这几乎就是您所需要的。困难的部分是知道日历应用程序支持什么标识符以及如何制作 vEvent
。感谢 quiker 找到支持的标识符。
最后一个提示:您可以使用 this nifty tool here.
验证您的 iCalendar 字符串
请注意,这只允许 删除 您的自定义对象。 将事件从日历拖 到您的应用程序是另一回事,但您可以从我的提示中找出答案。 :)
编码愉快!
我正在尝试将 iOS 11 拖放功能集成到 Xcode 9 beta 的应用程序中。 我对创建标准日历应用程序可以理解的 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
)。
我已经研究了几天,终于成功了!我会尽量分解我的步骤。
- 创建一个符合NSItemProviderWriting的自定义对象:
- 要符合协议,您需要实施 writableTypeIdentifiersForItemProvider 和 loadData(withTypeIdentifier:, 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
}
- 使用您的自定义事件信息创建一个 iCalendar
vEvent
字符串:- 此步骤与 WWDC 2017 Session 227 中的演示非常相似,他们在其中为自定义联系人创建了一个
vCard
字符串。从该会话中检出演示项目。 - 基本上,日历应用程序支持几种特定类型的类型标识符,iCal 格式就是其中之一。因此,您只需要制作一个辅助方法,将您的自定义事件类型转换为 iCalendar 字符串。
- 我不会在
vEvent
上详细介绍,但是有很多有用的信息 here and here。
- 此步骤与 WWDC 2017 Session 227 中的演示非常相似,他们在其中为自定义联系人创建了一个
这里有一个建议:
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:VCALENDAR\n"
vCalendarText += "VERSION:2.0\n"
vCalendarText += "PRODID:-//Your Company//App Name//EN\n"
vCalendarText += "BEGIN:VEVENT\n"
vCalendarText += "UID:\(identifier.uuidString)\n"
vCalendarText += "SUMMARY:\(name)\n"
vCalendarText += "DTSTAMP:\(todayString)\n"
vCalendarText += "DTSTART:\(startDateString)\n"
vCalendarText += "DTEND:\(endDateString)\n"
vCalendarText += "END:VEVENT\n"
vCalendarText += "END:VCALENDAR"
return vCalendarText.data(using: .utf8)
}
↑ 类似于我之前提到的会话演示中的 createVCard()
函数……
就是这样!这几乎就是您所需要的。困难的部分是知道日历应用程序支持什么标识符以及如何制作 vEvent
。感谢 quiker 找到支持的标识符。
最后一个提示:您可以使用 this nifty tool here.
验证您的 iCalendar 字符串请注意,这只允许 删除 您的自定义对象。 将事件从日历拖 到您的应用程序是另一回事,但您可以从我的提示中找出答案。 :)
编码愉快!