The cancel button on right top corner after a message composer has been presented is not visible in iOS 11 devices. As shown in the screenshot, cancel button works but is not visible. Once we press on it, the screen dismisses.
I have tried like this:
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Messages(_ sender: UIButton) {
if MFMessageComposeViewController.canSendText() == true {
let recipients:[String] = ["1500"]
let messageController = MFMessageComposeViewController()
messageController.messageComposeDelegate = self
messageController.recipients = recipients
messageController.body = "Your_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)
}
}
Added Messages and MessageUI frameworks and imported in view controller.
Screenshot:
Image:
Related
I am trying to create a drop down menu, that when you press the "Select" button two options drop down. I want these options to be a Timesheet button and Expense report button. I can't get it to work, here is my code.
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var SelectBTN: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func handleSelection(_ sender: UIButton) {
SelectBTN.ForEach { (button) in
UIView.animate(withDuration: 0.3, animations: {
button.isHidden = !button.isHidden
self.view.layoutIfNeeded()
})
}
}
#IBAction func cityTapped(_ sender: UIButton) {
}
#IBAction func ERBTNpressed(_ sender: UIButton) {
self.performSegue(withIdentifier: "ERSegue", sender: self)
}
#IBAction func TSBTNpressed(_ sender: UIButton) {
self.performSegue(withIdentifier: "TSSegue", sender: self)
}
}
You could set a menu as a primary action for a button in viewDidLoad:
SelectBTN.showsMenuAsPrimaryAction = true
SelectBTN.menu = buttonMenu()
In the menu you could add actions:
func buttonMenu() -> UIMenu {
let ERAction = UIAction(title: "Expense report", image: nil) { (_) in
self.performSegue(withIdentifier: "ERSegue", sender: self)
}
let TSAction = UIAction(title: "Timesheet", image: nil) { (_) in
self.performSegue(withIdentifier: "TSSegue", sender: self)
}
return UIMenu(title: "", options: .displayInline, children: [ERAction, TSAction])
}
You could also add images to actions and specify attributes (i.e. .destructive for Delete action)
EDIT: I have decided to change the way my app works, so this problem is solved. Thanks to everyone who helped!
I have a modal controller where when I press a button it dismisses the view. What I want to do is change a variable in another view controller when I dismiss it, is that possible? Or, if this doesn't work, is there a way for me to access the changed variable of another swift file? I will add my code below:
class PopupViewController: UIViewController {
var event = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func dismiss(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func event910(_ sender: Any) {
event = "storyTime"
dismiss(animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! ViewController
vc.event = event
}
}
I want to pass the changed variable "event" to another view controller, how can I do this?
Delegate View Controller is as follows. : -
it is the place where you will send the data to the next swift file
protocol myprotocol {
func anyfunction(_ param1:String)
}
struct mystruct1 {
var delegate:myprotocol?
// where you want tot start the delegate / send the data to the next file
func anymethod(){
delegate.anyfunction(sendTheDataYouWant)
}
}
// it is here you will receive the data
class anyclass:UIViewController ,myprotocol {
let class1 = mystruct1()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
class1.delegate = self
}
func anyfunction(param1:String){
// here Save the data you want
// because this function will be triggered as delegate will be called
}
}
ps:- I reccomend you to read https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
& apple docs
I have a View Controller with a button..
This button calls a "Present as Popover Seague" to a second view controller.
The second view controller has a close button with this function:
#IBAction func exit(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
Now I would like to do something in the first controller, after the second Controller is dismissed.
In the first view controller I tried this functions:
override func viewDidAppear(_ animated: Bool) {
print("viewDidAppear")
}
override func viewWillAppear(_ animated: Bool) {
print("viewWillAppear")
}
but no console log will shown.
Where is my mistake?
FirstViewContorller
import UIKit
class firstVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//ERROR
secondVC.dismissCompletion = {
print("dismissCompletion")
}
}
}
SecondVC (popover)
import UIKit
class secondVC: UIViewController {
var dismissCompletion: (() -> Void)?
// EXIT POPOVER
#IBAction func exit(_ sender: UIButton) {
self.dismiss(animated: true, completion: dismissCompletion)
}
}
The viewDidAppear() method of the main view controller won't be called because of the popover presentation style you use. If you choose to present the second view controller full screen - those methods will fire.
If we're sticking with the popover, the first thing you need to do is in your second view controller, the one that's being presented, add a property for a closure that will be executed upon its dismiss:
class PopoverViewController: UIViewContoller {
var dismissCompletion: (() -> Void)?
#IBAction func exit(_ sender: UIButton) {
self.dismiss(animated: true, completion: dismissCompletion)
}
}
And in your main view controller you define what needs to be done upon the popover's dismiss:
popoverViewContoller.dismissCompletion = {
// do stuff
}
UPDATE:
I assume you've setup the segue in your storyboard. I also assume that in your storyboard you've given the view controllers their respective class names:
This is what your code should look like:
class FirstViewController: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let secondVC = segue.destination as? SecondViewController else {
return
}
secondVC.dismissCompletion = {
print("Popover dismissed")
}
}
}
class SecondViewController: UIViewController {
var dismissCompletion: (() -> Void)?
#IBAction func exit(_ sender: Any) {
dismiss(animated: true, completion: dismissCompletion)
}
}
Please note the classes naming and the way I got the secondVC instance.
This code works and presents email form all filled out and sends the email just fine, just can't get it to dismiss after sending or trying to cancel.
I am sure I am missing something simple.
I also realize I have nothing in place if there is an error but at this point it works and sends email but i cant get it to dismiss
tried several suggestions I found online and there are other ways to do this but I am trying to understand why this is not working so want this way (or close) to work.... xcode 10.2.1
import UIKit
import MessageUI
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func sendEmail(_ sender: Any) {
sendEmail()
}
func sendEmail() {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["xxx#xx.com"])
mail.setSubject("test ")
mail.setPreferredSendingEmailAddress("xxx#jxxx.com")
present(mail, animated: true)
} else {
//show failure alert
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: nil)
}
}
compiles and sends email fine just cant dismiss the controller
All delegate methods should be in class scope , in your current code didFinishWith which should dimiss the mail is nested inside sendEmail
import UIKit
import MessageUI
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func sendEmail(_ sender: Any) {
sendEmail()
}
func sendEmail() {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["xxx#xx.com"])
mail.setSubject("test ")
mail.setPreferredSendingEmailAddress("xxx#jxxx.com")
present(mail, animated: true)
} else {
//show failure alert
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: nil)
}
}
I need to know when the cancel button of the UISearchBar has finished his animation after calling
searchBar.setShowsCancelButton(false, animated: true)
I've tried this
UIView.animateWithDuration(3, animations: {
self.searchBarView.searchBar.showsCancelButton = false
}, completion: {finished in
print(finished)
})
but the completion block gets triggered immediatly, any solution would be appreciated
You can use layoutIfNeeded() to update view in UIView.animateWithDuration(...)
try this code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func touchUpInside(sender: UIButton) {
searchBar.showsCancelButton = !searchBar.showsCancelButton
UIView.animateWithDuration(3, animations: {
self.searchBar.layoutIfNeeded()
}, completion: {finished in
print("Animation finished")
})
}
}
and storyboard: