Reputation: 93
Hello I apologize for my ignorance if this is an overdone or overly simple question. I am using SwiftUI and want my page to have multiple buttons that all send emails with different subject and message bodies. Everything currently works although only after the second time I click a button. The first time the subject is my initialized var ("start") regardless of button.
Another small thing, when I click the same button repeatedly it never updates until I click a different one.
Thank you very much, attached is code, I left out my mailcompose swift file as it all works as expected.
import SwiftUI
import MessageUI
import Foundation
struct ContentView: View {
@State var result: Result<MFMailComposeResult, Error>? = nil
@State private var showSheet = false
@State private var subject: String = "start"
@State private var msgBody: String = ""
let numberString = "201-228-0752"
var body: some View {
ZStack{
Color.white.ignoresSafeArea()
VStack{
Image("Icon-1024")
.resizable()
.aspectRatio(contentMode: .fit)
.clipShape(Circle())
.shadow(radius: 10)
.overlay(Circle().stroke(Color.black, lineWidth: 3))
.frame(width: 50, height: 50, alignment: .center)
.padding(.top, 10)
Text("Contact Us")
.foregroundColor(.black)
.fontWeight(.heavy)
.font(.title)
.padding()
Text("Be part of something bigger.")
.foregroundColor(.black)
.fontWeight(.medium)
.font(.system(size: 20))
.padding()
.padding(.bottom, 5)
.multilineTextAlignment(.center)
Spacer()
VStack(spacing: 0){
Button(action: {
self.subject = "General"
self.msgBody = "Hello, I need help."
self.suggestFeature()
}){
HStack {
Spacer()
Text("General help")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 1.00, green: 0.49, blue: 0.51))
Button(action: {
self.subject = "Technical"
self.msgBody = "Hello, I am having technical difficulties"
self.suggestFeature()
}){
HStack {
Spacer()
Text("Technical issues")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 0.81, green: 0.39, blue: 0.40))
Button(action: {
self.subject = "Gender"
self.msgBody = "Hello, I would like to make a gender or sexuality request."
self.suggestFeature()
}){
HStack {
Spacer()
Text("Gender & Sexuality")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 0.62, green: 0.29, blue: 0.30))
Button(action: {
self.subject = "Delete"
self.msgBody = "Hello, I would like to request a delete of my info."
self.suggestFeature()
}){
HStack {
Spacer()
Text("Delete info")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 0.45, green: 0.19, blue: 0.20))
Button(action: {
let telephone = "tel://"
let formattedString = telephone + numberString
guard let url = URL(string: formattedString) else { return }
UIApplication.shared.open(url)
}){
HStack {
Spacer()
(Text("Call ") + Text(Image(systemName: "phone.fill")))
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(.black))
Spacer()
Text("© Copyright Sixish, Inc.")
.padding(.bottom, 30)
.foregroundColor(.gray)
}.sheet(isPresented: $showSheet) {
MailView(result: self.$result, newSubject: self.subject, newMsgBody: self.msgBody)
}
}
}
}
func suggestFeature() {
print("You've got mail")
if MFMailComposeViewController.canSendMail() {
self.showSheet = true
} else {
print("Error sending mail")
// Alert : Unable to send the mail
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Upvotes: 2
Views: 763
Reputation: 52645
This is a classic issue that gets run into a lot with sheet()
on SwiftUI. The gist is that your sheet's content view can get rendered before it actually appears and before the @State variables' changes propagate to it.
The fix is to use sheet(item:)
:
struct Message : Identifiable, Hashable {
var id = UUID()
var subject : String
var body : String
}
struct ContentView: View {
//@State var result: Result<MFMailComposeResult, Error>? = nil
@State private var showSheet = false
@State private var message : Message?
let numberString = "201-228-0752"
var body: some View {
ZStack{
Color.white.ignoresSafeArea()
VStack{
Image("Icon-1024")
.resizable()
.aspectRatio(contentMode: .fit)
.clipShape(Circle())
.shadow(radius: 10)
.overlay(Circle().stroke(Color.black, lineWidth: 3))
.frame(width: 50, height: 50, alignment: .center)
.padding(.top, 10)
Text("Contact Us")
.foregroundColor(.black)
.fontWeight(.heavy)
.font(.title)
.padding()
Text("Be part of something bigger.")
.foregroundColor(.black)
.fontWeight(.medium)
.font(.system(size: 20))
.padding()
.padding(.bottom, 5)
.multilineTextAlignment(.center)
Spacer()
VStack(spacing: 0){
Button(action: {
self.message = Message(subject: "General", body: "Hello, I need help.")
self.suggestFeature()
}){
HStack {
Spacer()
Text("General help")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 1.00, green: 0.49, blue: 0.51))
Button(action: {
self.message = Message(subject: "Technical", body: "Hello, I am having technical difficulties")
self.suggestFeature()
}){
HStack {
Spacer()
Text("Technical issues")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 0.81, green: 0.39, blue: 0.40))
Button(action: {
self.message = Message(subject: "Gender", body: "Hello, I would like to make a gender or sexuality request.")
self.suggestFeature()
}){
HStack {
Spacer()
Text("Gender & Sexuality")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 0.62, green: 0.29, blue: 0.30))
Button(action: {
self.message = Message(subject: "Delete", body: "Hello, I would like to request a delete of my info.")
self.suggestFeature()
}){
HStack {
Spacer()
Text("Delete info")
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(red: 0.45, green: 0.19, blue: 0.20))
Button(action: {
let telephone = "tel://"
let formattedString = telephone + numberString
guard let url = URL(string: formattedString) else { return }
UIApplication.shared.open(url)
}){
HStack {
Spacer()
(Text("Call ") + Text(Image(systemName: "phone.fill")))
.font(.system(size: 25))
.fontWeight(.medium)
.foregroundColor(.white)
.padding(.top, 15)
.padding(.bottom, 15)
Spacer()
}
}
.background(Color(.black))
Spacer()
Text("© Copyright Sixish, Inc.")
.padding(.bottom, 30)
.foregroundColor(.gray)
}.sheet(item: $message) { item in
MailView(message: item)
//your code would probably need to be more like MailView(result: self.$result, newSubject: item.subject, newMsgBody: item.body)
}
}
}
}
func suggestFeature() {
print("You've got mail")
if MFMailComposeViewController.canSendMail() {
self.showSheet = true
} else {
print("Error sending mail")
// Alert : Unable to send the mail
}
}
}
struct MailView : View {
var message : Message
var body: some View {
Text(message.subject)
Text(message.body)
}
}
Note that now, your sheet is displayed if message
has an item it it. Message
is now a struct.
I simplified things a little bit since I didn't have your MailView
container (and I temporarily commented out your result
property), but the concept presented here should get you started doing what you need to do.
Upvotes: 3