I am using Swift 3 on iOS 10. I am using the UIActivityViewController with subclass of UIActivity with activityType set to mail. When the call to present UIActivityViewController is made I get an error in the debugger which says:
2017-05-26 14:09:27.583 TrialActivityViewControllerMail3[798:21017] -[TrialActivityViewControllerMail3.TSSActivityMail setSourceIsManaged:]: unrecognized selector sent to instance 0x60800026c580
2017-05-26 14:09:27.605 TrialActivityViewControllerMail3[798:21017] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TrialActivityViewControllerMail3.TSSActivityMail setSourceIsManaged:]: unrecognized selector sent to instance 0x60800026c580'
The key message is unrecognized selector sent to instance for selector setSourceIsManaged. That deals with the multithreading system which I don't have control of.
How do I fix this or get around it or find out more about the problem?
In addition to putting my code here, I also put the entire project in a git repository on GitHub. It's a small project intended only to try code to use the UIActivityViewController with a mail activity.
Here's the url:
https://github.com/Shinehah-Gnolaum/TrialActivityViewControllerMail3.git
Here is my code:
let mailItemProvider = TSSMailItemProvider(placeholderItem: textView.text as Any)
let activityItems = [mailItemProvider]
let activityMail = TSSActivityMail()
let applicationActivities = [activityMail]
let activityViewController = UIActivityViewController.init(activityItems: activityItems, applicationActivities: applicationActivities)
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad) {
activityViewController.modalPresentationStyle = UIModalPresentationStyle.popover
activityViewController.preferredContentSize = CGSize(width: 0, height: 0)
activityViewController.popoverPresentationController?.barButtonItem = barButtonItemMore
}
present(activityViewController, animated: true, completion: nil)
Here is TSSActivityMail.swift:
import UIKit
import MessageUI
class TSSActivityMail: UIActivity, MFMailComposeViewControllerDelegate {
var activityItem: Any?
let mailComposeViewController = MFMailComposeViewController()
override init() {
super.init()
}
// Succeed when activityType is remarked out or when it returns nil.
override var activityType: UIActivityType? {
get {
return UIActivityType.mail
}
}
override var activityTitle: String? {
get {
return "Mail"
}
}
override var activityImage: UIImage? {
get {
return UIImage(imageLiteralResourceName: "email.png")
}
}
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
// !!! Perform checks.
return true
}
override func prepare(withActivityItems activityItems: [Any]) {
activityItem = activityItems[0] // $$$ as! String
mailComposeViewController.mailComposeDelegate = self
let filename = "file.txt"
mailComposeViewController.setSubject("subject")
mailComposeViewController.setMessageBody("Message body.", isHTML: false)
let content = activityItem as! String // $$$ ('as! String' was added)
let length = content.lengthOfBytes(using: String.Encoding.utf8)
let outputData = NSData(bytes:content, length: length) as Data
mailComposeViewController.addAttachmentData(outputData, mimeType: "plain", fileName: filename)
}
override class var activityCategory: UIActivityCategory {
get {
return UIActivityCategory.action
}
}
override var activityViewController: UIViewController? {
get {
return mailComposeViewController as UIViewController // $$$ ('as UIViewController' was added)
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
print("TSSActivityMail.mailComposeController(_:_:_:)")
// Check the result or perform other tasks.
print("result.rawValue = \(result.rawValue)")
if let error = error {
print("error.localizedDescription = \(error.localizedDescription)")
self.activityDidFinish(false)
}
else
{
if !(result == MFMailComposeResult.sent) {
self.activityDidFinish(false)
}
else
{
self.activityDidFinish(true)
}
}
}
}
Here is TSSMailItemProvider.swift:
import UIKit
class TSSMailItemProvider: UIActivityItemProvider {
var placeholderItemAny: Any
var localActivityType: UIActivityType?
override init(placeholderItem: Any) {
placeholderItemAny = placeholderItem
super.init(placeholderItem: placeholderItem)
}
override var item: Any {
get {
let itemAny = NSString(string: placeholderItemAny as! String)
localActivityType = UIActivityType.mail
return itemAny
}
}
override var placeholderItem: Any? {
get {
return placeholderItemAny
}
}
override var activityType: UIActivityType? {
get {
return localActivityType
}
}
}