How to import ViewController data into email in Swift 3? - xcode

I am VERY new to Swift/xcode and I've built my first app but I'm stuck on one part. I have a button that opens an email and I would like to take the selections from a picker, two date pickers and a text input and import them into the email. I want the user to make their choices and just click send when the email opens. Everything works fine but I can't figure out how to import the data from the app into the email despite searching all over. Any suggestions?
}
func configuredMailComposeViewController() -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(["myemail#myemail.com"])
mailComposerVC.setSubject("EQUIPMENT RESERVATION REQUEST")
mailComposerVC.setMessageBody("test email message", isHTML: false)
return mailComposerVC
}
Basically, I want to replace the "test email message" string with the selections from my date pickers, picker and text input.

I was able to figure this out using the link from Kevin above and the following links:
How to store data from a picker view in a variable when a button is pressed?
Get just the date (no time) from UIDatePicker
The revised code is below and works exactly as I wanted it to:

#IBOutlet weak var StartDate: UIDatePicker!
#IBOutlet weak var EndDate: UIDatePicker!
#IBOutlet weak var HowMany: UITextField!
func configuredMailComposeViewController() -> MFMailComposeViewController {
let chosen = Picker1.selectedRow(inComponent: 0)
let chosenString = words[chosen]
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd"
let stringDate = dateFormatter.string(from: StartDate.date)
let Start = stringDate
let number = HowMany.text
let stringendDate = dateFormatter.string(from: EndDate.date)
let End = stringendDate
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(["myemail#example.com"])
mailComposerVC.setSubject("Email Subject")
mailComposerVC.setMessageBody ("Please reserve \(number ?? "") of
the following **\(chosenString)** from \(Start) to \(End).
Thanks.", isHTML: false)
return mailComposerVC
}

Related

How to use an array to fill the title text

I've created a customized keyboard using UIView. I'm trying to auto-fill the letters using a for loop but with no success.
func initializeSubviews() {
let xibFileName = "keyboardView" // xib extension not included b
let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)![0] as! UIView
self.addSubview(view)
view.frame = self.bounds
setKeyboardText()
}
#IBOutlet var keyboardLetters: [myKeyboardBtn]!
func setKeyboardText() {
let str = "abcdefghijklmnopqrstuvwxyz"
let characterArray = Array(str)
for (Index, key) in keyboardLetters.enumerated() {
key.titleLabel?.text = String(characterArray[Index])
}
// [a,b,c,d,...]
}
what am I doing wrong?
According to Apple
"To set the actual text of the label, use setTitle(_:for:)
(button.titleLabel.text does not let you set the text)."

How to fetch using string in swift

I was just wondering how would I be able to use a searched barcode to fetch using Core Data in Swift. I'm basically passing a barcode to a static func method, but how would I be able to use that to fetch the data from the Core Data?
Here is the barcode when detected:
func barcodeDetected(code: String) {
// Let the user know we've found something.
let alert = UIAlertController(title: "Found a Barcode!", message: code, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Search", style: UIAlertActionStyle.Destructive, handler: { action in
// Remove the spaces.
let trimmedCode = code.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
// EAN or UPC?
// Check for added "0" at beginning of code.
let trimmedCodeString = "\(trimmedCode)"
var trimmedCodeNoZero: String
if trimmedCodeString.hasPrefix("0") && trimmedCodeString.characters.count > 1 {
trimmedCodeNoZero = String(trimmedCodeString.characters.dropFirst())
// Send the doctored barcode
ProductDetailsViewController.searchCode(trimmedCodeNoZero)
} else {
// Send the doctored barcode
ProductDetailsViewController.searchCode(trimmedCodeString)
}
self.navigationController?.popViewControllerAnimated(true)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
My Product Class:
import UIKit
import Foundation
import CoreData
class ProductDetailsViewController: UIViewController, NSFetchedResultsControllerDelegate {
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBAction func addProduct(sender: AnyObject) {
let AppDel = UIApplication.sharedApplication().delegate as? AppDelegate
let context:NSManagedObjectContext = (AppDel?.managedObjectContext)!
let ent = NSEntityDescription.entityForName("Products", inManagedObjectContext: context)
var newProduct = ProductItem(entity: ent!, insertIntoManagedObjectContext: context)
newProduct.title = productLabel.text
//newProduct.price = priceLabel.text
/*context.save(nil)
print(newProduct)
print("Object Saved")*/
}
private(set) var PRODUCT_NAME = ""
private(set) var PRODUCT_PRICE = ""
private var menuItems:[ProductItem] = []
static func searchCode(codeNumber: String) -> String{
let barcodeNumber = codeNumber
return barcodeNumber
}
deinit{
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
productLabel.text = "Scan a Product"
priceLabel.text = ""
NSNotificationCenter.defaultCenter().addObserver(self, selector: "setLabels:", name: "ProductNotification", object: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I already added the items into Core Data successfully and was able to load all items into a table in my app. Now with the barcode scanned I want to be able to just load the products with the barcode and i'm stuck on that part. As you can see my static fun searchCode is receiving the barcode from barcodeDetected but what should I do next to fetch it? Thanks.
EDIT:
Core Data Entity
import Foundation
import CoreData
#objc(ProductItem)
class ProductItem: NSManagedObject{
#NSManaged var barcodeNum:String?
#NSManaged var box_height:NSNumber?
#NSManaged var box_length:NSNumber?
#NSManaged var box_width:NSNumber?
#NSManaged var price:NSNumber?
#NSManaged var sku:String?
#NSManaged var weight:NSNumber?
#NSManaged var title:String?
}
To fetch the correct ProductItem, you need to use a predicate (see the Apple Documentation here). In your case, you could use something like this:
let AppDel = UIApplication.sharedApplication().delegate as? AppDelegate
let context:NSManagedObjectContext = (AppDel?.managedObjectContext)!
let fetchRequest = NSFetchRequest(entityName: "ProductItem")
fetchRequest.predicate = NSPredicate(format: "barcodeNum == %#",codeNumber)
let results = try! context.executeFetchRequest(fetchRequest) as! [ProductItem]
if results.count > 0 { // great, you found (at least one) matching item
let scannedProduct = results[0]
// from here you can access the attributes of the product
// such as title, price, sku, etc.
...
} else { // not found
...
}
Note that I've use try! for brevity, but in practice you should use proper do ... catch syntax and handle any errors.
I'm not clear why you are using a static func in the ProductDetailsViewController; a common approach would be to use the above fetch within your barcodeDetected method, and then to segue to the ProductDetailsViewController passing the relevant ProductItem for display/editing or whatever. Or to display an alert view if the product was not found.

PFLoginViewController´s Twitter, Facebook buttons not working when subclassing

When I subclass PFLoginViewController from Parse so that I can customise UI, both Twitter and Facebook buttons stop working as they used to if I were not subclassing.
This is the class I instantiate my subclass from:
class SettingsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate, MFMailComposeViewControllerDelegate
{
#IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
#IBOutlet weak var tableView: UITableView!
// THIS DOES WORK (without subclassing)
//var loginVC: PFLogInViewController = PFLogInViewController()
var loginVC:LogInViewController {
get{
let livc = LogInViewController()
livc.delegate = self
let suvc = SignUpViewController()
suvc.delegate = self
livc.signUpController? = suvc
return livc
}}
And this is my subclass of PFLogInViewController
class LogInViewController: PFLogInViewController {
static let forgotPassword = "Trouble Signing In?"
override func viewDidLoad() {
super.viewDidLoad()
let lv = self.logInView
self.facebookPermissions = ["public_profile", "email"]
self.fields = [PFLogInFields.UsernameAndPassword, .Facebook, .Twitter, .SignUpButton, .LogInButton, .PasswordForgotten, .DismissButton]
lv?.logo = UIImageView(image: UIImage(named: "myImage"))
lv?.logo?.contentMode = UIViewContentMode.ScaleAspectFit
lv?.emailAsUsername = true
self.view.backgroundColor = UIColor.whiteColor()
}
It might be a bug in Parse´s side, though. Any help would be appreciated!
This is a known issue - it looks like this bug was patched in the GitHub repo (see this commit) but not in the Cocoapod, if that's what you're using. I'm hoping they'll push the changes over soon :)
The reason for the bug in the old code is that the superclass is not updating the target/actions for the buttons when you set which fields you want in viewDidLoad. PFLoginViewController configures the target/actions in its viewDidLoad, but since you're setting the self.fields after calling super.viewDidLoad (which is what you should be doing, since you always call super first :) ), the field target/actions aren't re-updated. In other words, it looks like, the way PFLogInViewController was written, it only works if the fields don't change after its viewDidLoad is called :/. And since the default fields don't include a Facebook button, the Facebook button will never be set up. A simple solution is just to move self.fields =... before super.viewDidLoad().

Swift NSUserNotificationCenter didActivateNotification not working

I'm working on a swift os x application and I'm having trouble understanding the userNoticiation / didActivateNotification structure. I've reviewed the documentation and searched SO but am still stuck. Any guidance on the following code would be much appreciated:
func notify(message: String, callBack: String) {
println(message)
println(callBack)
var notification:NSUserNotification = NSUserNotification()
notification.title = "New Phone Call"
notification.informativeText = message
notification.actionButtonTitle = "Lookup"
notification.hasActionButton = true
var center:NSUserNotificationCenter = NSUserNotificationCenter.defaultUserNotificationCenter()
center.delegate = self
center.scheduleNotification(notification)
}
func notify (center: NSUserNotificationCenter, didActivateNotification notification: NSUserNotification){
center.delegate = self
println("clicked") //this does not print
}
The notification displays exactly as I'd like it to. Clicking the "Lookup" button that I've defined will bring my app to the foreground the first time it is clicked, but the code I'd expect to handle that action does not fire.
Thanks in advance.
Change your second 'func notify' declaration to 'optional func userNotificationCenter'

How do I convert NSOpenPanel.URL to a string?

I was trying to display an open file dialog in OSX via Xcode and Swift.
I then wanted to put the filename in a TextField.
I started with
#IBOutlet weak var lblFileName: NSTextField!
#IBAction func FileOpen(sender: AnyObject) {
var f:NSOpenPanel = NSOpenPanel()
f.title = "open that file"
f.allowsMultipleSelection = false
f.canChooseDirectories = false
f.runModal()
var thefile = f.URLs[0].absoluteString
println(thefile)
//failed: lblFileName.stringValue = thefile
lblFileName.stringValue = "I want this to be the filename!"
}
println(thefile) worked, so it was just an issue with converting the URL
The variable "thefile" wasn't a string and all attempts to cast it failed.
I did get it working so I thought I'd post the answer here as well.
Here's the code that ended up working
note I created a string named mystring and had to use the ? and the ! to get things to work.
If there's an easier/better way please add that in the comments!
#IBOutlet weak var lblFileName: NSTextField!
#IBAction func FileOpen(sender: AnyObject) {
var f:NSOpenPanel = NSOpenPanel()
f.title = "open that file"
f.allowsMultipleSelection = false
f.canChooseDirectories = false
f.runModal()
var thefile = f.URLs[0].absoluteString
println(thefile)
var mystring:String? = thefile
lblFileName.stringValue = mystring!
}

Resources