Xcode, adding my image view to mail composer in app - swift

I am hoping someone can help me with something I've not done before. which is attach an image from a image view and put it into my email in app. i have all other fields working correctly I just cannot add my image.
thanks in advance for help
class SecondViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet var imageView: UIImageView!
func showMailComposer() {
guard MFMailComposeViewController.canSendMail() else {
return
}
let composer = MFMailComposeViewController()
composer.mailComposeDelegate = self
composer.setToRecipients(["LJDNSGKJNDGJ"])
composer.setSubject("JSABFKASJ")
composer.setMessageBody("hbdfnjbqeashfbnwdlskm", isHTML: false)
//I would like to know how to connect the "#IBOutlet var imageView: UIImageView!" to the composer. here ? and this would then present the image in the email.
)
present(composer, animated: true)

func mailButtonPress() {
if let image = imageView!.image {
composeMail(with:image)
} else {
print("image is nil")
}
}
func composeMail(with image:UIImage) {
let mailComposeVC = MFMailComposeViewController()
mailComposeVC.addAttachmentData(image.jpegData(compressionQuality: CGFloat(1.0))!, mimeType: "image/jpeg", fileName: "test.jpeg")
mailComposeVC.setSubject("Email Subject")
mailComposeVC.setMessageBody("<html><body><p>This is your message</p></body></html>", isHTML: true)
self.present(mailComposeVC, animated: true, completion: nil)
}

Related

Trying to switch which photo pops up depending on button clicked Xcode

I am making an app that will display a random quote from a stoic philosopher. Right now, I am stuck on trying to make the correct picture pop up. (User clicks on a Button with the philosopher's name on it, and then a new view pops up with an image of the philosopher and a random quote by him).
class ViewController: UIViewController {
var allQuotes = [String]()
var pictures = [String]()
#IBOutlet var Epictetus: UIButton!
#IBOutlet var Seneca: UIButton!
#IBOutlet var MarcusAurelius: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Create a constant fm and assign it the value returned by FileManager.default (built in system type)
let fm = FileManager.default
// Declares a new constant called path that sets the resource path of ours apps buddle.
// A bundle is a directory containing our compiled program and all our assets
let path = Bundle.main.resourcePath!
// items array will be a constant collection of the names of all the files found in the directory of our app
let items = try! fm.contentsOfDirectory(atPath: path)
// create a loop to go through all of our items...
for item in items {
if item.hasSuffix("jpg"){
pictures.append(item)
}
}
print(pictures)
title = "Stoicism"
if let stoicQuotesURL = Bundle.main.url(forResource: "quotes", withExtension: "txt"){
if let stoicQuotes = try? String(contentsOf: stoicQuotesURL) {
allQuotes = stoicQuotes.components(separatedBy: "\n\n")
}
}
}
#IBAction func buttonTapped(_ sender: UIButton) {
if sender.tag == 0 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[0]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 1 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[1]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 2 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[2]
navigationController?.pushViewController(vc, animated: true)
}
}
}
}
That's the code for my main viewController.
import UIKit
class PictureViewController: UIViewController {
#IBOutlet var picture: UIImageView!
#IBOutlet var imageView: UIImageView!
var selectedImage: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if let imageToLoad = selectedImage {
imageView.image = UIImage(named: imageToLoad)
}
}
override func viewWillAppear(_ animated: Bool) {
// doing it for the parent class
super.viewWillAppear(animated)
// if its a nav Cont then it will hide bars on tap...
}
// now make sure it turns off when you go back to the main screen
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
That's the code for the viewController that has the imageView. Right now, the image that's popping up is always the preset (Marcus Aurelius), even though my code looks correct to me. Obviously it isn't (also, I've already debugged and ensured through print statements that the jpg files add to the pictures array correctly).
Any help would be appreciated.
First of all, this code is really silly:
#IBAction func buttonTapped(_ sender: UIButton) {
if sender.tag == 0 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[0]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 1 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[1]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 2 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[2]
navigationController?.pushViewController(vc, animated: true)
}
}
}
Do you see that everything in those lines is identical except for the numbers? So make the number a variable:
#IBAction func buttonTapped(_ sender: UIButton) {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
print(sender.tag)
vc.selectedImage = pictures[sender.tag]
navigationController?.pushViewController(vc, animated: true)
}
}
See how much shorter and clearer that is? Okay, I've also added a print statement. This will print the tag to the console. You need to make sure that your buttons do have the right tags. If they do, your code should work.

UIButton does not bring up MFMailViewController

I'm having an error with a bit of code. I am new to this and I am trying to teach myself. I am finding most of my answers online but can't seem to find anything about this particular issue. I want to send an email within the app but anytime I press the email button, the MFMailViewController does not come up. It is like my UIButton isn't working. But I know I have it as an IBAction. Here is my code so far. Any help is much appreciated.
import UIKit
import MessageUI
class RequestService: UIViewController,MFMailComposeViewControllerDelegate {
#IBOutlet weak var CustomerName: UITextField!
#IBOutlet weak var emailButton: UIButton!
#IBAction func sendEmail(_ sender: UIButton) {
if !MFMailComposeViewController.canSendMail() {
print("Mail services are not available")
let ComposeVC = MFMailComposeViewController()
ComposeVC.mailComposeDelegate = self
ComposeVC.setToRecipients(["jwelch#ussunsolar.com"])
ComposeVC.setSubject("New Support Ticket")
ComposeVC.setMessageBody(CustomerName.text!, isHTML: false)
self.present(ComposeVC, animated: true, completion: nil)
}
func mailComposeController(controller: MFMailComposeViewController,didFinishWithResult result:MFMailComposeResult, error: NSError?) {
// Check the result or perform other tasks.
// Dismiss the mail compose view controller.
controller.dismiss(animated: true, completion: nil)
}
}
}
You made an error in the syntax in your sendMail function. The code you posted will only open the view controller if the device can't send mail. Change it to this:
#IBAction func sendEmail(_ sender: UIButton) {
if !MFMailComposeViewController.canSendMail() {
print("Mail services are not available")
return
}
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
composeVC.setToRecipients(["jwelch#ussunsolar.com"])
composeVC.setSubject("New Support Ticket")
composeVC.setMessageBody(CustomerName.text!, isHTML: false)
self.present(composeVC, animated: true, completion: nil)
}
You only attempt to display the mail controller if the device can't send email. That's backwards.
#IBAction func sendEmail(_ sender: UIButton) {
if MFMailComposeViewController.canSendMail() {
print("Mail services are not available")
let ComposeVC = MFMailComposeViewController()
ComposeVC.mailComposeDelegate = self
ComposeVC.setToRecipients(["jwelch#ussunsolar.com"])
ComposeVC.setSubject("New Support Ticket")
ComposeVC.setMessageBody(CustomerName.text!, isHTML: false)
self.present(ComposeVC, animated: true, completion: nil)
}
}
func mailComposeController(controller: MFMailComposeViewController,didFinishWithResult result:MFMailComposeResult, error: NSError?) {
// Check the result or perform other tasks.
// Dismiss the mail compose view controller.
controller.dismiss(animated: true, completion: nil)
}
And you need the delegate method outside of the other method.

Taking a picture and passing it to a different UIViewController Swift 3.0

I'm trying to take an image in my app so I can save it to my device and pass it to the next view controller to be previewed. The way I see people doing this is storing the image they take in a uiimage. Then during prepareforsegue they set the uiimage variable in the destination view controller to the photo you took in the previous view controller. From there in the dest view controller I see people displaying the image as follows : imageName.image = imageVariable . When I pass the variable to the destination view controller and try to display it in the next view controller it appears as a nil value. Where am I going wrong?
First ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ToDetailPage" {
let nextScene = segue.destination as! PostDetailPageViewController
nextScene.itemImage = self.image
// nextScene?.myimg.image = self.image
}
}
#IBAction func TakePhotoButtonClicked(_ sender: AnyObject) {
if let videoConnection = sessionOutput.connection(withMediaType: AVMediaTypeVideo){
sessionOutput.captureStillImageAsynchronously(from: videoConnection, completionHandler: {
buffer, error in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
self.image = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(UIImage(data: imageData!)!, nil, nil, nil)
})
}
}
Second ViewController:
var itemImage: UIImage!
#IBOutlet weak var myimg: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.categories.dataSource = self;
self.categories.delegate = self;
setUpMap()
myimg.image = itemImage
}
You need to push viewController inside the block. Actually what is happening in this code the completion block is called after prepareForSegue. So your image is always 'nil'.
Try to push the viewController like this:
if let videoConnection = sessionOutput.connection(withMediaType: AVMediaTypeVideo){
sessionOutput.captureStillImageAsynchronously(from: videoConnection, completionHandler: {
buffer, error in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
self.image = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(UIImage(data: imageData!)!, nil, nil, nil)
// push view controller here
let destinationVC = SecondViewController()
destinationVC.image = self.image
self.navigationController.pushViewController(destinationVC, animated: true)
})
}
Hope it will help you.. Happy Coding!!

swift - dismissing mail view controller from Sprite Kit

I am trying to add a send email button to a Sprite Kit game. I can get the email dialog to show up. But if I hit cancel, the app will crash or do nothing. If I hit send, the email will send, but the dialog stays. I cannot get the mailComposeController function to fire...please help!
Code:
import Foundation
import UIKit
import MessageUI
class MailViewController: UIViewController, MFMailComposeViewControllerDelegate {
let systemVersion = UIDevice.currentDevice().systemVersion
let devicemodel = UIDevice.currentDevice().model
let appVersion = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as! String
let appBuild = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as! String
let myrootview2 = UIApplication.sharedApplication().keyWindow?.rootViewController
let mailComposerVC = MFMailComposeViewController()
override func viewDidLoad() {
super.viewDidLoad()
}
func sendEmailButtonTapped(sender: AnyObject) {
let mailComposeViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.view.window?.rootViewController = mailComposerVC
print("This is the rootview2: \(myrootview2)")
myrootview2!.presentViewController(mailComposeViewController, animated: true, completion: nil)
} else {
self.showSendMailErrorAlert()
}
}
func configuredMailComposeViewController() -> MFMailComposeViewController {
var msgbody: String
mailComposerVC.mailComposeDelegate = self
msgbody = "\n\nDevice: \(devicemodel)\niOS Version: \(systemVersion)\nApp Version: \(appVersion)\nApp Build Number: \(appBuild)\n"
mailComposerVC.setToRecipients(["test1#test.com"])
mailComposerVC.setSubject("test subject")
mailComposerVC.setMessageBody(msgbody, isHTML: false)
//print(mailComposerVC)
return mailComposerVC
}
func showSendMailErrorAlert() {
let sendMailErrorAlert = UIAlertView(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", delegate: self, cancelButtonTitle: "OK")
sendMailErrorAlert.show()
}
// THIS DOESN'T GET CALLED WHEN SENDING OR CANCELLING EMAIL!
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
let test1 = result.rawValue
print(test1)
print(controller)
print(self)
print(myrootview2)
}
The issue is you are making the mailVC as the root view, you have to present it on your view like given below
#IBAction func sendEmailButtonTapped(sender: AnyObject) {
let mailComposeViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.presentViewController(mailComposeViewController, animated: true, completion: nil)
} else {
self.showSendMailErrorAlert()
}
}
 func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
controller.dismissViewControllerAnimated(true, completion: nil)
}

Can't find fatal error: unexpectedly found nil while unwrapping an Optional value [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
It was working last night, but when I run my code, now I am receiving a:
fatal error: unexpectedly found nil while unwrapping an Optional value.
Can someone help me locate this error?
import UIKit
class UserRegistration: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextFieldDelegate {
//USER REGISTRATION FORM
//Activity Indicator
var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
//Error
func displayAlert(title:String, error:String){
//create Alert
var alert = UIAlertController(title: title, message: error, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
//User Profile Picture Selection
var profileImage = UIImage()
var isThereImage = false
#IBOutlet var uploadProfilePictureButton: UIButton!
#IBAction func uploadProfilePicture(sender: AnyObject) {
//Settings needed for image upload
var image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.PhotoLibrary //can use '.camera' to access camera
image.allowsEditing = true
//Select image. FYI Completion is a function that happens when viewcontroller is presented
self.presentViewController(image, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
//Store image in local variable to be resized later
profileImage = image
println("Image is selected")
//Manually Close View Controller
self.dismissViewControllerAnimated(true, completion: nil)
//Remove button title
uploadProfilePictureButton.setTitle("", forState: .Normal)
//Display Image
uploadProfilePictureButton.setBackgroundImage(image, forState: .Normal)
//Set isThereImage Boolean
isThereImage = true
}
//---------------------------------------
//User Input Information
#IBOutlet var userEmailAddress: UITextField!
#IBOutlet var userPasswordOne: UITextField!
#IBOutlet var userPasswordTwo: UITextField!
#IBOutlet var passwordConfirmationMatch: UILabel!
var confirmedPassword = Bool()
//---------------------------------------
//Submit User Input to Database
#IBAction func userRegistration(sender: AnyObject) {
var error = ""
//Verify if User Exist and Passwords Match
if userEmailAddress.text == "" || userPasswordOne.text == "" || confirmedPassword == false {
error = "Please enter an email address and password, or make sure your passwords match."
println("Registration had an error")
}
if error != "" {
displayAlert("Error in Registration", error: error)
} else {
//Sign Up User
var user = PFUser()
//Resize Profile Picture
let size = CGSizeApplyAffineTransform(profileImage.size, CGAffineTransformMakeScale(0.5, 0.5))
let hasAlpha = true
let scale: CGFloat = 0.0 // Automatically use scale factor of main screen
UIGraphicsBeginImageContextWithOptions(size, !hasAlpha, scale)
profileImage.drawInRect(CGRect(origin: CGPointZero, size: size))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//User Information
user.password = userPasswordTwo.text
user.email = userEmailAddress.text
user.username = userEmailAddress.text
if isThereImage == false {
displayAlert("Please upload a picture for your profile.", error: error)
}else if isThereImage == true {
var imageData = UIImagePNGRepresentation(scaledImage)
var imageFile = PFFile(name: userEmailAddress.text + ".png", data:imageData)
user.setObject(imageFile, forKey: "userProfileImage")
}
user.setObject("", forKey: "firstName")
user.setObject("", forKey: "lastName")
user.setObject("", forKey: "userLocation")
//Insert Activity Indicator here
activityIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 50, 50))
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.sharedApplication().beginIgnoringInteractionEvents()
//-------------------------------
user.signUpInBackgroundWithBlock {
(succeeded: Bool!, signupError: NSError!) -> Void in
//Stop activity indicator whether there is an error or not
self.activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
if signupError == nil {
// Hooray! Let them use the app now.
println("Registration Completed")
} else {
//Keep this here!
if let errorString = signupError.userInfo?["error"] as? NSString{
error = errorString
} else {
error = "Please try again later."
}
self.displayAlert("Could not Sign Up", error: error)
println(signupError)
}
}
}
//Print Confirmation to Cortana
}
//---------------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
passwordConfirmationMatch.hidden = true
//UITextField Delegate
self.userEmailAddress.delegate = self
self.userPasswordOne.delegate = self
self.userPasswordTwo.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Password Matching Function
func passwordCheck() {
if userPasswordTwo.text == userPasswordOne.text {
passwordConfirmationMatch.hidden = false
confirmedPassword = true
println("Password match")
} else {
passwordConfirmationMatch.hidden = true
confirmedPassword = false
println("Passwords don't match")
}
}
//Handle Keyboard
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
passwordCheck()
}
func textFieldShouldReturn(textField: UITextField!) -> Bool {
userEmailAddress.resignFirstResponder()
userPasswordOne.resignFirstResponder()
userPasswordTwo.resignFirstResponder()
passwordCheck()
return true
}
}
The error you get indicates that one of your variables that has been declared as optional was nil when your code tried to access it.
Do you get any more info from the error? Like the name of the variable for example? If not, use some breakpoints to find the culprit and make sure it is not nil when the time to use it comes.