UIActivityViewController – 我如何识别所选选项并将特定数据类型链接到它?

huangapple go评论81阅读模式
英文:

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) -&gt; Any {
    return [NSAttributedString().self, URL.self] as [Any]
}

public func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -&gt; 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&lt;EKLPosition&gt;.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?

  1. What am I doing wrong and how can I fix this problem?
  2. 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中的item1Typesitem2Types参数。

英文:

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) -&gt; Any {
        // use one of the two things as a placeholder
        url
    }
    
    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -&gt; 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) -&gt; Any {
        defaultItem ?? item1
    }
    
    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -&gt; 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(&quot;com.apple.DocumentManagerUICore.SaveToFiles&quot;)

Then you can pass this to the item1Types and item2Types parameters in ActivityItemPair.

huangapple
  • 本文由 发表于 2023年7月13日 20:00:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76679139.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定