Currently I'm developing an email app and want all links with mailto scheme to be opened via my app, not default Apple's Mail app.
For instance, I have a link like this one
<a href="mailto:email#example.com\>mailto_test</a>
in UIWebView or UITextView (doesn't matter which one, they have similar behavior).
When I longpress this link iOS will show UIAlertController with 3 options:
The first one option, "New Message", will open default Mail app. So my question is how to override this behavior? How can i force this option to launch my own email app?
For those who think it is impossible - take a look at iOS Gmail app. Gmail devs have implemented what I'm asking about, but I don't understand how.
In a text view, link behavior is completely up to you. Give the text view a delegate and implement textView(_:shouldInteractWith:in:interaction:). A long press is the .presentActions interaction. Return false and substitute your own response. You can put up your own .actionSheet alert that looks just like the default one, but does what you want it to.
The solution is to change the default click action of the mail link to the way you want.
Make a UITextView example:
Suppose we have UITextView textView, its attributeString is
<a href="mailto:email#example.com\>mailto_test</a>
and its documentType is html. The code is below:
let textView = UITextView(frame: view.bounds)
textView.frame.origin.y += 100
let attrStr = try! NSAttributedString(
data: "mailto_test".data(using: .utf8, allowLossyConversion: true)!,
options:[.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil)
textView.attributedText = attrStr
view.addSubview(textView)
This the default effect that after pressed the mailto_test text in the screen the native mail app functions waked up. So we add a delegate to the textView to modify the click action.
textView.isEditable = false
textView.dataDetectorTypes = .link
textView.delegate = self
Here is the delegate function to control the specific click action:
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
print(URL)
return false
}
Whenever you pressed the mail link, the functions invoked without calling the native mail app. And the URL is just the mail url.
You are looking for something like this, right? Where you can open your app from anywhere you click email URL.
I can't find the exact answer right now, but you want to add your app as a URL Scheme (Apple documentation)
Edit: more apple documentation
Related
I'm showing a pdf file inside a UIDocumentInteractionController, like this:
let docController = UIDocumentInteractionController(url: documentsURL)
let url = NSURL(string:"itms-books:");
if UIApplication.shared.canOpenURL(url! as URL) {
docController.delegate = self
docController.presentPreview(animated: true)
}
I need to automatically scroll to the last page when the controller is shown, is there a way to do that? I didn't find one. Thanks to anyone who will send help!
I am afraid there is not a straight forward solution for this, even the documentation says it's a UIViewController but Xcode shows it is inherited from NSObject.
I'd recommend either rendering the PDF on a WKWebView or a UIScrollView. This will give you a room to wiggle.
Our users have reported that the the links in our mails are not clickable in Apple's Mail App as they are just recognized as pure texts(underlined blue colored text). But links become clickable when the same mail is forwarded (in quoted text). This problem only occurs in Apple Mail App and not in any other third party mail apps like gmail etc. Any reason or fix for this? Are we missing something that Mail App needs specifically to be mentioned while creating links? Why Links become operational when the same email is forwarded? This happens on all iOS devices (tested on Ipads and Iphones)
Any additional information from our side can be provided on the same, if needed for better clarification.
Thank You
Are you sure you are adding link attribute to your mailTo: link text?
You may want to give it a try while setting mail content attributed text.
let attrText = NSMutableAttributedString.init(string: "Email me")
let mailLink = "mailTo:test#example.com"
let url = NSURL.init(string: mailLink) as NSURL?
attrText.addAttribute(NSAttributedStringKey.link, value: url ?? "", range: NSMakeRange(0, attrText.length))
let documentAttributes = [NSAttributedString.DocumentAttributeKey.documentType : NSAttributedString.DocumentType.html]
do {
let htmlData = try! attrText.data(from: NSMakeRange(0, attrText.length), documentAttributes:documentAttributes)
if let htmlString = String(data:htmlData, encoding:String.Encoding.utf8) {
let messageVC = MFMailComposeViewController()
messageVC.setMessageBody(htmlString, isHTML: true)
}
}
I am developing an iOS application with a button to report an issue using SMS/iMessage. I am using MFMessageComposeViewController to present the message composition interface using the following code (Swift 3):
if(MFMessageComposeViewController.canSendText()){
let controller = MFMessageComposeViewController()
controller.messageComposeDelegate = self
controller.body = "Example Message"
controller.recipients = ["2345678901"]
self.present(controller, animated: true, completion: nil)
}
I have also implemented the MFMessageComposeViewControllerDelegate function to dismiss properly. A standard text message / iMessage sends successfully, but the user does not have the option to attach an image. The buttons for camera, iMessage Apps, etc. are there, but they are disabled and cannot be pressed. How can I enable these buttons (camera, specifically) to allow my users to attach images to messages composed with the app?
The Buttons in Question:
EDIT:
Thanks Abdelahad for the suggestion. I've modified his response to allow multiple recipients and to include a message body. I also updated it to remove the deprecated addingPercentEscapes(using: ) method.
Here is a solution using a url to open the Messages app. NOTE: This takes users out of the app.
let recipients = "2345678901,3456789012" //Phone Numbers
let messageBody = "This is a test"
let sms: String = "sms://open?addresses=\(recipients)&body=\(messageBody)"
let smsEncoded = sms.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)
let url = URL(string: smsEncoded!)
UIApplication.shared.openURL(url!)
But still I would like a solution that does not take the user out of the app. Is this possible? Why would the MFMessageComposeViewController show the buttons without enabling them?
Don't use MFMessageComposeViewController use UIApplication.shared.openURL(url!) but this will takes the user out of the app
var phoneToCall: String = "sms: +201016588557"
var phoneToCallEncoded = phoneToCall.addingPercentEscapes(using: String.Encoding.ascii)
var url = URL(string: phoneToCallEncoded)
UIApplication.shared.openURL(url!)
I currently have a UITextView with Address detection active, this detects any addresses in this field and makes them into a clickable link that opens up Apple Maps with the address as the focus. I really like this functionality but my users would rather have a button to click on instead of the inline link.
With this in mind I have researched into NSDataDetector and managed to get this functionality working for emailing and phone numbers but I am stuck on Addresses. The code I am using to detect the address is below:
let types: NSTextCheckingType = [.Address]
let detector = try! NSDataDetector(types: types.rawValue)
let matches = detector.matchesInString(input, options: [], range: NSMakeRange(0, input.characters.count))
for match in matches {
return NSURL(string: "\((input as NSString).substringWithRange(match.range))")
}
However the NSURL fails to be created, I believe the syntax must be wrong, it works for phone numbers as below:
let types: NSTextCheckingType = [.PhoneNumber]
let detector = try! NSDataDetector(types: types.rawValue)
let matches = detector.matchesInString(input, options: [], range: NSMakeRange(0, input.characters.count))
for match in matches {
return NSURL(string: "telprompt://\((input as NSString).substringWithRange(match.range))")
}
If the address is valid it returns the components of the address(street, city etc.) in the matches object. I was hoping the NSURL could be used with address just like phone numbers but I may be wrong so is there an alternate way I could use the results from the detector and display them on Apple Maps manually?
Or as a side note could I hide the UITextView and trigger the link touch programatically based on a button touch?
Any more information can be provided as needed,
thank you in advance for any help.
I have referred the Apple's Swift Programming Language book, and it is of no help.
var fh = NSFileHandle.fileHandleWithStandardInput()
if let data = fh.availableData
{
var str = NSString(data: data, encoding: NSUTF8StringEncoding)
}
There is more to it than that. Typically in iOS development, you'll have a UITextView become first responder. A responder is an object (event handling object) that can respond to events and handle them. Once you make a UI element become first responder, you can accomplish what you want. From there, the keyboard appears and the user enters something.
Once that's done, you can resign the first responder and look at the text and use it however you want. Some rough code for this process looks like this:
//Create a label
let tv = UITextView(frame: CGRectMake(0, 0, 200, 100))
self.view.addSubView(tv)
//Tell iOS we want this to handle text input
tv.becomeFirstResponder()
//User enters text, tell iOS we're done handling text input events and print input
tv.resignFirstResponder()
println(tv.text)
A good resource for input in iOS: User Input in iOS