英文:
UIActivityViewController - How can I identify selected option and link specific data type to it?
问题
我正在困扰一个问题,这个问题之前也在其他帖子中讨论过(例如 https://stackoverflow.com/questions/14149532/uiactivityviewcontroller-is-there-a-way-to-know-which-activity-was-selected),但在我看来还没有完全解决。
我想根据UIActivityController共享对话框中可以选择的不同选项来共享不同的数据类型:
a)如果选择了“邮件”,“打印”或“消息”,我想分享一个NSAttributedString
b)如果选择了“空投”或“保存到文件”,我想分享数据文件(由临时创建的文件的URL标识)。
我尝试通过以下方式处理:
public func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return [NSAttributedString().self, URL.self] as [Any]
}
public func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
if let activityType = activityType {
switch activityType {
case .airDrop, .copyToPasteboard: return [URL.self] as [Any]
case .mail, .message, .print: return [NSAttributedString().self] as [Any]
default: return [NSAttributedString().self, Array<EKLPosition>.self, URL.self] as [Any]
}
} else {
return [NSAttributedString().self, URL.self] as [Any]
}
}
不幸的是,这不起作用。当我选择例如“邮件”时,生成的电子邮件包含了NSAttributedString(如预期的那样),但也包含了数据文件作为附件。
如果选择“保存到文件”,则会存储一个包含NSAttributedString文本和数据文件的文件。
如果选择“空投”,则只会分享数据文件,正如预期的那样。
因此,我有两个问题:
1)我做错了什么,如何解决这个问题?
2)我如何确定是否选择了“保存到文件”,“保存到Dropbox”等选项,因为在这些情况下,我只想分享数据文件。在UIActivity.ActivityType列表中,我找不到任何标识符。
感谢您的支持。
英文:
I'm struggling with a problem, which was discussed in earlier threads too (e.g. https://stackoverflow.com/questions/14149532/uiactivityviewcontroller-is-there-a-way-to-know-which-activity-was-selected), but in my understanding not fully solved yet.
I want to share different data types based on the different options that can be selected in the share dialogue of the UIActivityController:
a) if "mail", "print" or "message" is selected, I want to share a NSAttributedString
b) if "airdrop", "save to Files" is selected, I want to share data file (identified by an URL to a temporarily created file).
I tried to handle this via:
public func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return [NSAttributedString().self, URL.self] as [Any]
}
public func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
if let activityType = activityType {
switch activityType {
case .airDrop, .copyToPasteboard: return [URL.self] as [Any]
case .mail, .message, .print: return [NSAttributedString().self] as [Any]
default: return [NSAttributedString().self, Array<EKLPosition>.self, URL.self] as [Any]
}
} else {
return [NSAttributedString().self, URL.self] as [Any]
}
}
Unfortunately, this doesn't work. When I select e.g. "mail", the generated e-mail contains the NSAttributedString (as intended) but also the data file as an attachment.
If "Save to Files" is selected, a file with the text of the NSAttributedString and the data file is stored.
If "airdrop" is selected, only the data file is shared as intended.
Hence I have two questions?
- What am I doing wrong and how can I fix this problem?
- How can I identify if "Save to Files", "Save to Dropbox", etc is selected, because in these cases I only want to share the data file too. In the UIActivity.ActivityType list I couldn't find any identifier for it.
Thanks for your support.
答案1
得分: 1
不确定为什么在itemForActivityType
中返回那些类型的数组。你应该返回给定活动类型的项目。
例如:
class MyActivity: NSObject, UIActivityItemSource {
let attributedString: NSAttributedString = ...
let url = ...
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
// 用其中一个作为占位符
url
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
// 返回其中一个项目 - URL或带属性的字符串
if activityType == .copyToPasteboard {
return attributedString
} else {
return url
}
}
}
更一般地说:
class ActivityItemPair: NSObject, UIActivityItemSource {
let item1: Any
let item2: Any
let item1Types: [UIActivity.ActivityType]
let item2Types: [UIActivity.ActivityType]
let defaultItem: Any?
init(item1: Any, item2: Any, item1Types: [UIActivity.ActivityType], item2Types: [UIActivity.ActivityType], defaultItem: Any? = nil) {
self.item1 = item1
self.item2 = item2
self.item1Types = item1Types
self.item2Types = item2Types
self.defaultItem = defaultItem
}
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
defaultItem ?? item1
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
if let activityType = activityType, item1Types.map(\.rawValue).contains(activityType.rawValue) {
return item1
} else if let activityType = activityType, item2Types.map(\.rawValue).contains(activityType.rawValue) {
return item2
} else {
return defaultItem ?? item2
}
}
}
至于如何识别活动类型,你可以在itemForActivityType
中打印活动类型的rawValue
:
print(activityType?.rawValue)
然后,你可以选择"Save to Files"并查看打印出的内容。对于"Save to Files",它是:
com.apple.DocumentManagerUICore.SaveToFiles
你可以使用这个原始值初始化AcitivityType
:
UIActivity.ActivityType("com.apple.DocumentManagerUICore.SaveToFiles")
然后,你可以将这个值传递给ActivityItemPair
中的item1Types
和item2Types
参数。
英文:
Not sure why you are returning those arrays of types in itemForActivityType
. You should be returning the items for the given activity type.
For example:
class MyActivity: NSObject, UIActivityItemSource {
let attributedString: NSAttributedString = ...
let url = ...
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
// use one of the two things as a placeholder
url
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
// return one of the two things - URL or attributed string
if activityType == .copyToPasteboard {
return attributedString
} else {
return url
}
}
}
More generally:
class ActivityItemPair: NSObject, UIActivityItemSource {
let item1: Any
let item2: Any
let item1Types: [UIActivity.ActivityType]
let item2Types: [UIActivity.ActivityType]
let defaultItem: Any?
init(item1: Any, item2: Any, item1Types: [UIActivity.ActivityType], item2Types: [UIActivity.ActivityType], defaultItem: Any? = nil) {
self.item1 = item1
self.item2 = item2
self.item1Types = item1Types
self.item2Types = item2Types
self.defaultItem = defaultItem
}
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
defaultItem ?? item1
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
if let activityType, item1Types.map(\.rawValue).contains(activityType.rawValue) {
return item1
} else if let activityType, item2Types.map(\.rawValue).contains(activityType.rawValue) {
return item2
} else {
return defaultItem ?? item2
}
}
}
As for how you can identify the activity type, you can print the rawValue
of the activity type in itemForActivityType
:
print(activityType?.rawValue)
Then, you can select "Save to Files" and see what gets printed. For "Save to Files", it is:
com.apple.DocumentManagerUICore.SaveToFiles
You can use this raw value to initialise an AcitivityType
too:
UIActivity.ActivityType("com.apple.DocumentManagerUICore.SaveToFiles")
Then you can pass this to the item1Types
and item2Types
parameters in ActivityItemPair
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论