My application can open PDF-files. So I registered it for PDF-files. When I open a PDF-file from the mail-app my application get called and the following function is called:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let rect = app.keyWindow?.rootViewController?.view.bounds
viewController.view.backgroundColor = UIColor.red
let picker = UIPickerView(frame: CGRect(x: 0, y: 100, width: (rect?.width)!, height: (rect?.height)! / 3))
picker.delegate = self
picker.dataSource = self
viewController.view.addSubview(picker)
let okButton = UIButton(frame: CGRect(x: 0, y: 100 + ((rect?.height)! / 3), width: ((rect?.width)! / 2) - 20, height: 30))
okButton.setTitle("Ok", for: .normal)
okButton.addTarget(self, action: #selector(AppDelegate.endApp), for: .touchUpInside)
viewController.view.addSubview(okButton)
app.keyWindow?.rootViewController?.present(viewController, animated: true, completion: nil)
return true
}
This works! If the user click on the ok Button I want to go back to the mail-app. How can I do this? I read, that apple don't allow you to switch between apps. But whatsApp is doing this.
I tried it with removing the viewController:
viewController.view.removeFromSuperview()
But then I only get a black screen.
The only way to launch other applications is by using their URL schemes, the only way to open mail is by using the mailto: scheme, which will always open the compose view.
let email = "foo#bar.com"
let url = URL(string: "mailto:\(email)")
UIApplication.sharedApplication().openURL(url)
Edit: this answer might help you
This will not help you to go back to mail app viewController.view.removeFromSuperview()
It will just remove views from your viewcontroler and black color window is showing.
There is no way to get back to mail-app even if you use openURL.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"mailto:"]];
This will open email composer, but practically you will not be able to get back to mail app.
Swift
let url = URL(string: "mailto:\abc#xyz.com")
UIApplication.sharedApplication().openURL(url)
This will open email composer with sender as abc#xyz.com.
If you want to attach file and send it through email composer, then make like below code.
import UIKit
import MessageUI
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
#IBAction func launchEmail(sender: AnyObject) {
var emailTitle = "EmailTitle"
var messageBody = "Email BodyFeature request or bug report?"
var toRecipents = ["abc#xyz.com"]
var mc: MFMailComposeViewController = MFMailComposeViewController()
mc.mailComposeDelegate = self
mc.setSubject(emailTitle)
mc.setMessageBody(messageBody, isHTML: false)
mc.setToRecipients(toRecipents)
self.presentViewController(mc, animated: true, completion: nil)
}
func mailComposeController(controller:MFMailComposeViewController, didFinishWithResult result:MFMailComposeResult, error:NSError) {
switch result {
case MFMailComposeResultCancelled:
print("Mail cancelled")
case MFMailComposeResultSaved:
print("Mail saved")
case MFMailComposeResultSent:
print("Mail sent")
case MFMailComposeResultFailed:
print("Mail sent failure: \(error?.localizedDescription)")
default:
break
}
self.dismissViewControllerAnimated(true, completion: nil)
}
}
I made it with the following code:
viewController.dismiss(animated: false, completion: nil)
let mailURL = NSURL(string: "message://")!
if UIApplication.shared.canOpenURL(mailURL as URL) {
UIApplication.shared.openURL(mailURL as URL)
}
Thats good enough for me.
thank you #Jeremy your link helped me!
Related
I have what I believe is a unique problem. I am having trouble getting my email window to dismiss. I am using Xcode 8.
The email dismisses correctly the first time I open it, but if I open it again it won't. If I press "Cancel" it does not give me the option to "Delete Draft". If I press "Send" the email is sent, but the window does not dismiss.
My code is below. The mailComposeController gets called correctly the first time, but it never gets called a second time. Does anyone have any ideas about what I am missing?
let mail = MFMailComposeViewController()
func sendEmail(body: String, subject: String) {
if MFMailComposeViewController.canSendMail() {
mail.mailComposeDelegate = self
mail.setSubject(subject)
mail.setMessageBody("\(body)", isHTML: false)
if let data = (body as NSString).data(using: String.Encoding.utf8.rawValue){
//Attach File
mail.addAttachmentData(data, mimeType: "text/plain", fileName: "data.txt")
}
present(mail, animated: true)
} else {
// show failure alert
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: nil)
}
You need to create a new MFMailComposeViewController each time. Moving your mail declaration inside sendEmail works…
func sendEmail(body: String, subject: String) {
if MFMailComposeViewController.canSendMail() {
// Create a new MFMailComposeViewController…
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setSubject(subject)
mail.setMessageBody("\(body)", isHTML: false)
if let data = (body as NSString).data(using: String.Encoding.utf8.rawValue){
//Attach File
mail.addAttachmentData(data, mimeType: "text/plain", fileName: "data.txt")
}
present(mail, animated: true)
} else {
// show failure alert
}
}
As to why…?
I'm trying to develop an app, that take a number from a variable then open in "Messages" app with (1500) in the field To: and the variable value in Text Messages field like this
I tried this answer how to open an URL in Swift3 and Swift: How to open a new app when uibutton is tapped but i didn't figure out the URL for Messages app
what should I use? Big thanks.
use this
if MFMessageComposeViewController.canSendText() == true{
let recipients:[String] = ["1500"]
var messageController = MFMessageComposeViewController()
//messageController.messageComposeDelegate = self // implement delegate if you want
messageController.recipients = recipients
messageController.body = "Your_text"
self.present(messageController, animated: true, completion: nil)
}
You need to import "MessageUI" to your class and use the below code.
func sendMessages() {
if MFMessageComposeViewController.canSendText() == true {
let recipients:[String] = ["9895249619"]
let messageController = MFMessageComposeViewController()
messageController.messageComposeDelegate = self
messageController.recipients = recipients
messageController.body = "Your_message_text"
self.present(messageController, animated: true, completion: nil)
} else {
//handle text messaging not available
}
}
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
controller.dismiss(animated: true, completion: nil)
}
This is the code I have now, taken from an answer to a similar question.
#IBAction func GoogleButton(sender: AnyObject) {
if let url = NSURL(string: "www.google.com"){
UIApplication.sharedApplication().openURL(url)
}
}
The button is called Google Button and its text is www.google.com
How do I make it open the link when I press it?
What your code shows is the action that would occur once the button is tapped, rather than the actual button. You need to connect your button to that action.
(I've renamed the action because GoogleButton is not a good name for an action)
In code:
override func viewDidLoad() {
super.viewDidLoad()
googleButton.addTarget(self, action: "didTapGoogle", forControlEvents: .TouchUpInside)
}
#IBAction func didTapGoogle(sender: AnyObject) {
UIApplication.sharedApplication().openURL(NSURL(string: "http://www.google.com")!)
}
In IB:
Edit: in Swift 3, the code for opening a link in safari has changed. Use UIApplication.shared().openURL(URL(string: "http://www.stackoverflow.com")!) instead.
Edit: in Swift 4
UIApplication.shared.openURL(URL(string: "http://www.stackoverflow.com")!)
The string you are supplying for the NSURL does not include the protocol information. openURL uses the protocol to decide which app to open the URL.
Adding "http://" to your string will allow iOS to open Safari.
#IBAction func GoogleButton(sender: AnyObject) {
if let url = NSURL(string: "http://www.google.com"){
UIApplication.sharedApplication().openURL(url)
}
}
if let url = URL(string: "your URL") {
if #available(iOS 10, *){
UIApplication.shared.open(url)
}else{
UIApplication.shared.openURL(url)
}
}
as openUrl method is deprecated in iOS 10, here is solution for iOS 10
let settingsUrl = NSURL(string:UIApplicationOpenSettingsURLString) as! URL
UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
In Swift 4
if let url = URL(string: "http://yourURL") {
UIApplication.shared.open(url, options: [:])
}
if iOS 9 or higher it's better to use SafariServices, so your user will not leave your app.
import SafariServices
let svc = SFSafariViewController(url: url)
present(svc, animated: true, completion: nil)
For Swift 3.0:
if let url = URL(string: strURlToOpen) {
UIApplication.shared.openURL(url)
}
This code works with Xcode 11
if let url = URL(string: "http://www.google.com") {
UIApplication.shared.open(url, options: [:])
}
The code that you have should open the link just fine. I believe, that you probably just copy-pasted this code fragment into your code. The problem is that the UI component (button) in the interface (in storyboard, most likely) is not connected to the code. So the system doesn't know, that when you press the button, it should call this code.
In order to explain this fact to the system, open the storyboard file, where your Google Button is located, then in assistant editor open the file, where your func GoogleButton code fragment is located. Right-click on the button, and drag the line to the code fragment.
If you create this button programmatically, you should add target for some event, for instance, UITouchUpInside. There are plenty of examples on the web, so it shouldn't be a problem :)
UPDATE: As others noted already, you should also add a protocol to the link ("http://" or "https://"). It will do nothing otherwise.
For Swift3 , below code is working fine
#IBAction func Button(_ sender: Any) {
UIApplication.shared.open(urlStore1, options: [:], completionHandler: nil)
}
Actually You Can Use It Like This In Your Action Button Works For Swift 5 :
guard let settingsUrl = URL(string:"https://yourLink.com") else {
return
}
UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
}
// How to open a URL in Safari
import SafariServices \\ import
#IBAction func google(_ sender: Any)
{
if let url = URL(string: "https://www.google.com")
{
let safariVC = SFSafariViewController(url: url)
present(safariVC, animated: true, completion: nil)
}
}
I made this way:
I imported SafariServices
import SafariServices
First step: I defined a button just above viewDidLoad:
let myButton = UIButton()
Second step: I called a function inside viewDidLoad:
func setupMyButton() {
view.addSubview(myButton)
myButton.configuration = .plain()
myButton.configuration?.cornerStyle = .capsule
myButton.configuration?.title = "Go to Google"
myButton.addTarget(self, action: #selector(selector), for: .touchUpInside)
myButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
myButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
myButton.widthAnchor.constraint(equalToConstant: 200),
myButton.heightAnchor.constraint(equalToConstant: 50),
])
}
Third step: At the bottom of the scope, I called an #objc func to use as selector. (Outside viewDidLoad)
#objc func selector() {
if let url = URL(string: "https://www.google.com")
{
let safariVC = SFSafariViewController(url: url)
present(safariVC, animated: true, completion: nil)
}
}
And I did not forget to call my func at the beginning of the viewDidLoad:
setupMyButton()
A dude named PRAVEEN BHATI helped me at the third step.
Hope this helps.
I am creating an app, and I have a banner which promotes my other app. This is my code:
var barsButton : UIButton = UIButton(frame: CGRectMake((self.view.bounds.width / 2) - 51, self.view.bounds.height - 100, 102, 30))
barsButton.setImage(UIImage(named: "Bars Icon 2.png"), forState: .Normal)
barsButton.addTarget(self, action: "openBarsLink", forControlEvents: UIControlEvents.TouchUpInside)
func openBarsLink() {
var barsLink : String = "itms-apps:https://itunes.apple.com/app/bars/id706081574?mt=8"
UIApplication.sharedApplication().openURL(NSURL.URLWithString(barsLink))
}
However, when the user presses the button, it just takes them to the App Store, and not the specific page for my app. What am I doing wrong?
You have too many protocols in your URL. Get rid of https: so the URL reads
itms-apps://itunes.apple.com/app/bars/id706081574
Just by following older answers I couldn't make it work, so here I post my complete solution:
if let url = NSURL(string: "itms-apps://itunes.apple.com/app/id1234567890"),
UIApplication.shared.canOpenURL(url) {
UIApplication.shared.openURL(url)
}
}
Use just the short "itms://".
For Swift 3 this is the snippet:
UIApplication.shared.openURL(URL(string: "itms://itunes.apple.com/app/id" + appStoreAppID)!)
I hope this helps someone.
Cheers.
P.S. #Eric Aya was ahead of the time :)
I had this problem but this code just works on the phone not simulator. So check this code:
if let url = URL(string: "itms-apps://itunes.apple.com/app/id" + APP_ID ),
UIApplication.shared.canOpenURL(url){
UIApplication.shared.openURL(url)
}else{
//Just check it on phone not simulator!
print("Can not open")
}
As openURL is deprecated from iOS 10 use below code:
UIApplication.shared.open((URL(string: "itms://itunes.apple.com/app/" + appStoreAppID)!), options:[:], completionHandler: nil)
Simply you can use these functions in a utility struct to goto app page in app store also you can goto rate app view directly:
static func gotoApp(appID: String, completion: ((_ success: Bool)->())? = nil) {
let appUrl = "itms-apps://itunes.apple.com/app/id\(appID)"
gotoURL(string: appUrl, completion: completion)
}
static func rateApp(appId: String, completion: ((_ success: Bool)->())? = nil) {
//let appUrl = "itms-apps://itunes.apple.com/app/" + appId
let appUrl = "https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=\(appId)&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8"
//TODO: use &action=write-review for opening review directly
print("app review URL: ", appUrl)
gotoURL(string: appUrl, completion: completion)
}
static func gotoURL(string: String, completion: ((_ success: Bool)->())? = nil) {
print("gotoURL: ", string)
guard let url = URL(string: string) else {
print("gotoURL: invalid url", string)
completion?(false)
return
}
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler: completion)
} else {
completion?(UIApplication.shared.openURL(url))
}
}
Swift 3 - XCode 8.2.1
UIApplication.shared.openURL(URL(string: "itms-apps://itunes.apple.com/app/id" + appStoreAppID)!)
Link you are trying to open is not valid - remove https: schema from it (or itms: - but I suggest first option, to avoid redirects)
I use this and it works.
let locale: String = Locale.current.regionCode ?? "US"
UIApplication.shared.open(URL(string: "https://apps.apple.com/\(locale)/developer/{developer-name}/{idXXXXXXXXXX}")!, options: [:], completionHandler: nil)
I want to use swift to implement in-app email. When I click the button, the email window pops up. However, I am unable to send my email. Moreover, after I click cancel-delete draft, I cannot go back to the original screen.
import UIkit
import MessageUI
class Information : UIViewController, MFMailComposeViewControllerDelegate{
var myMail: MFMailComposeViewController!
#IBAction func sendReport(sender : AnyObject) {
if(MFMailComposeViewController.canSendMail()){
myMail = MFMailComposeViewController()
//myMail.mailComposeDelegate
// set the subject
myMail.setSubject("My report")
//To recipients
var toRecipients = ["lipeilin#gatech.edu"]
myMail.setToRecipients(toRecipients)
//CC recipients
var ccRecipients = ["tzhang85#gatech.edu"]
myMail.setCcRecipients(ccRecipients)
//CC recipients
var bccRecipients = ["tzhang85#gatech.edu"]
myMail.setBccRecipients(ccRecipients)
//Add some text to the message body
var sentfrom = "Email sent from my app"
myMail.setMessageBody(sentfrom, isHTML: true)
//Include an attachment
var image = UIImage(named: "Gimme.png")
var imageData = UIImageJPEGRepresentation(image, 1.0)
myMail.addAttachmentData(imageData, mimeType: "image/jped", fileName: "image")
//Display the view controller
self.presentViewController(myMail, animated: true, completion: nil)
}
else{
var alert = UIAlertController(title: "Alert", message: "Your device cannot send emails", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
func mailComposeController(controller: MFMailComposeViewController!,
didFinishWithResult result: MFMailComposeResult,
error: NSError!){
switch(result.value){
case MFMailComposeResultSent.value:
println("Email sent")
default:
println("Whoops")
}
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Since you haven't set the current view controller as the mailComposeDelegate of myMail, the mailComposeController:didFinishWithResult method isn't being called. After you init myMail, make sure to add:
myMail.mailComposeDelegate = self
and you'll be good to go
In case anyone is looking for a non MFMailCompose option, here's what I did to send using Gmail's SMTP servers.
Download a zip of this repo: https://github.com/jetseven/skpsmtpmessage
Drag and drop the files under SMTPLibrary into your XCode project
Create a new header file - MyApp-Briding-Header.h
Replace new header file with this:
#import "Base64Transcoder.h"
#import "HSK_CFUtilities.h"
#import "NSData+Base64Additions.h"
#import "NSStream+SKPSMTPExtensions.h"
#import "SKPSMTPMessage.h"
Go to Project(Targets > MyApp on the left)/Build Settings/Swift Compiler - Code Generation
Add path to header file under Objective-C Briding Header -> Debug (i.e. MyApp/MyApp-Bridging-Header.h
Go to Project/Build Phases/Compile Sources
Select all .m files and click enter. Type -fno-objc-arc and hit enter.
Use this code to send email:
var mail = SKPSMTPMessage()
mail.fromEmail = "fromemail#gmail.com"
mail.toEmail = "tomail#gmail.com"
mail.requiresAuth = true
mail.login = "fromemail#gmail.com"
mail.pass = "password"
mail.subject = "test subject"
mail.wantsSecure = true
mail.relayHost = "smtp.gmail.com"
mail.relayPorts = [587]
var parts: NSDictionary = [
"kSKPSMTPPartContentTypeKey": "text/plain; charset=UTF-8",
"kSKPSMTPPartMessageKey": "test message",
]
mail.parts = [parts]
mail.send()
Hope it helps someone. I didn't want to use the MFMailCompose option because I didn't want to have to prompt the user.
This is how I have composed my email with attached PDF file document.
Just to test this example you need to drag and drop a sample PDF named "All_about_tax.pdf"
#IBAction func sendEmail(sender: UIButton)
{
//Check to see the device can send email.
if( MFMailComposeViewController.canSendMail() )
{
print("Can send email.")
let mailComposer = MFMailComposeViewController()
mailComposer.mailComposeDelegate = self
//Set to recipients
mailComposer.setToRecipients(["your email id here"])
//Set the subject
mailComposer.setSubject("Tax info document pdf")
//set mail body
mailComposer.setMessageBody("This is what they sound like.", isHTML: true)
if let filePath = NSBundle.mainBundle().pathForResource("All_about_tax", ofType: "pdf")
{
print("File path loaded.")
if let fileData = NSData(contentsOfFile: filePath)
{
print("File data loaded.")
mailComposer.addAttachmentData(fileData, mimeType: "application/pdf", fileName: "All_about_tax.pdf")
}
}
//this will compose and present mail to user
self.presentViewController(mailComposer, animated: true, completion: nil)
}
else
{
print("email is not supported")
}
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?)
{
self.dismissViewControllerAnimated(true, completion: nil)
}