I want to know the current time when the app is being terminated. Using this time, I want to do some calculation and store. How can I do this?
In Your AppDelegate.swift store time in user default in the following method and use them later
func applicationWillTerminate(_ application: UIApplication) {
let date = Date()
let df = DateFormatter()
df.dateFormat = "HH:mm:ss a"
let stringTime = df.string(from: date) // 11:35:59 AM
UserDefaults.standard.set(stringTime, forKey: "TerminatedTime")
}
Related
Trying to create a countdown timer, but I can't get past this error:
Cannot invoke 'dateComponents' with an argument list of type '(NSCalendar.Unit.Type, from: NSData, to: Date?)'
my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var TimerLable: UILabel!
let formatter = DateFormatter()
let userCleander = Calendar.current;
let CalenderComponent : NSCalendar.Unit = [
NSCalendar.Unit.year,
NSCalendar.Unit.month,
NSCalendar.Unit.day,
NSCalendar.Unit.hour
]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func printTime()
{
formatter.dateFormat = "dd/MM/yy hh:mm a"
let StartTime = NSData()
let EndTime = formatter.date(from: "10/08/19 12:00 a")
let TimeDifference = userCleander.dateComponents(NSCalendar.Unit, from: StartTime, to: EndTime)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The main issue which causes the error is just a typo. StartTime is supposed to be NSDate not NSData.
Basically don't use NS... classes if there is a Swift native counterpart (Calendar, Date etc).
The Swift 3+ code is
let formatter = DateFormatter()
let userCalendar = Calendar.current
let calendarComponents : Set<Calendar.Component> = [ .year, .month, .day, .hour]
func printTime()
{
formatter.dateFormat = "dd/MM/yy hh:mm a"
let startTime = Date()
let endTime = formatter.date(from: "10/08/19 12:00 am")!
let timeDifference = userCalendar.dateComponents(calendarComponents, from: startTime, to: endTime)
}
Two notes:
According to the naming guidelines variable names start with a lowercase letter
The date format does not match the date string and the created date needs to be unwrapped.
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
}
I'm struggling with updating a value stored in an entity that has a "one-to-many" relationship with another entity.
My project is a budgeting app. Using NSFetchedResultsController, I can successfully add a transaction (which populates in the table) and delete transactions which the FRC automatically saves.
I have an entity that stores the transactions with attributes "name" and "amount", and I have a separate entity with one attribute "theDate" (NSDate) that stores the date of the transaction.
The reason it is separate is because I believed this would organizationally make it simpler-many transactions can occur on the same date.
In the below I create the entities and store the values after creating a new transaction, then set the relationship:
#IBAction func done(segue: UIStoryboardSegue) {
let addTransactionVC = segue.sourceViewController as! AddTransaction
let newTrans = addTransactionVC.newTransaction
let date = addTransactionVC.datePicker.date
// Create Entities
let entity = NSEntityDescription.entityForName("DailyTransactions", inManagedObjectContext: self.managedContext)
let relatedEntity = NSEntityDescription.entityForName("TransDates", inManagedObjectContext: self.managedContext)
// Initialize Record
let record = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: self.managedContext)
let recordDate = NSManagedObject(entity: relatedEntity!, insertIntoManagedObjectContext: self.managedContext)
// Is new transaction being created or an old one being edited?
if !addTransactionVC.isEditingTransaction {
// Populate Record
record.setValue(newTrans.name, forKey: "transName")
record.setValue(newTrans.amount, forKey: "transAmount")
recordDate.setValue(date, forKey: "theDate")
// Create Relationship of Date to Transaction
record.setValue(recordDate, forKey: "date")
} else {
// If user was editing a transaction:
let updatedObject = addTransactionVC.managedObject
let newDate = addTransactionVC.datePicker.date
// How do I change the date associated with this transaction?
updatedObject.setValue(newTrans.name, forKey: "transName")
updatedObject.setValue(newTrans.amount, forKey: "transAmount")
// This line was meant to access the attribute in the "date" relationship:
updatedObject.setValue(newDate, forKey: "date")
Everything above else works fine. After else triggers if the cell (transaction) was selected to be edited. This line: updatedObject.setValue(newDate, forKey: "date") was meant to simply update the "theDate" attribute of the TransDates entity ("date" is the name of the relationship). But I see now why that won't work.
So I tried this in the else statement:
let fetchRequestDates = NSFetchRequest(entityName: "TransDates")
do {
let dateObjects = try self.managedContext.executeFetchRequest(fetchRequestDates) as! [TransDates]
for dateObject in dateObjects {
// These 2 lines were to test that a date was being returned:
let tempDate = dateObject.theDate as! NSDate
print("dateObject is:\n\(String(tempDate))")
if dateObject.valueForKey("theDate") as! NSDate == newDate {
updatedObject.setValue(dateObject, forKey: "date")
break
}
}
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
I thought the above would simply return an array of all the TransDates objects and if a match was found (b/w what's in the array and the new NSDate) the updatedObject would get added to it, otherwise I would add some code to create the newDate as a new NSManagedObject, etc.
However when executing if dateObject.valueForKey("theDate") as! NSDate == newDate { this happens: "fatal error: unexpectedly found nil while unwrapping an Optional value".
My two questions:
In terms of what I'm trying to accomplish-update/change a date that's associated with a transaction (if the date already exists and contains other transactions, this transaction just moves over to join them), is this the best way to do it?
Do I have the purpose/functionality of relationships all wrong?
Sorry for this long-winded question, but I've been stuck here for days. So thanks in advance!
The reason you are getting this error is because you are trying to force unwrap a nil value. You should instead use an if let statement:
if let date dateObject.valueForKey("theDate") as? NSDate {
if date == newDate {
...
}
}
My main issue is one of saving and retrieving data outside of Core Data.
I am looking to save 1 variable with persistent data.
The routine crashes after second button press.
override func viewDidLoad() {
super.viewDidLoad()
var amy="2"
NSUserDefaults.standardUserDefaults().setObject((amy), forKey: "ggpass")
}
#IBAction func pass(sender: AnyObject) {
// Retrieve the original Variable
NSUserDefaults.standardUserDefaults().synchronize()
var aname5 = (NSUserDefaults.standardUserDefaults().objectForKey("ggpass"))! as String
gpass = (aname5.toInt())!
gpass=gpass+1
///Save Data
NSUserDefaults.standardUserDefaults().setObject((gpass), forKey: "ggpass")
}
You are creating the NSUserDefaults as a string, reading it assuming it's a string, and then writing it back as a number - that won't work. You need to either stick to numbers for your values, or strings. Here's a version sticking to strings - a bit clumsy, but closest to your existing code:
#IBAction func pass(sender: AnyObject) {
var aname5 = NSUserDefaults.standardUserDefaults().objectForKey("ggpass") as? String
if let gpass = aname5?.toInt() {
NSUserDefaults.standardUserDefaults().setObject("\(gpass+1)", forKey: "ggpass")
}
}
Note that you don't need the synchronize() call in iOS8 or Yosemite, see http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/.
Retrive the original value of amy by using this code:
amy = NSUserDefaults.standardUserDefaults().integerForKey("ggpass")
Then assign its value to aname5.
var aname5 = amy
Your code now looks like:
#IBAction func pass(sender: AnyObject) {
amy = NSUserDefaults.standardUserDefaults().integerForKey("ggpass")
var aname5 = amy
gpass = (aname5.toInt())!
gpass++
///Save Data
NSUserDefaults.standardUserDefaults().setObject((gpass), forKey: "ggpass")
}
I'm trying to update a progress bar with the progress of loading a load of values into CoreData. However, whenever I try to call an update on my progressView component, I get a fatal error stating that "unexpectedly found nil while unwrapping an Optional value".
The interesting thing is that this happens even if I put 'self.progressView.progress = 0.5' in the delegate method of my program - indicating that it's the progressView component it can't find rather than an issue with the value. A quick check with println also confirms the value does exist and so isn't nil. Note that if I put the 'self.progressView.progress = 0.5' statement under a function connected directly to a button, it works fine so it must be some sort of issue with the command being called from the delegate.
Can anyone work out what I'm doing wrong here? Thanks for your help.
Delegate method:
class ViewControllerUpdate: UIViewController, NSURLSessionDelegate, NSURLSessionDownloadDelegate, saveUpdate {
[....]
func updateStatus(status: String, progress: Float?) {
if let percentProgress = progress? {
self.progressView.progress = 0.5
}
//println(progress) - NOTE THIS IS CORRECTLY POPULATED WITH THE APPROPRIATE VALUE
}
Calling class:
protocol saveUpdate {
func updateStatus(status:String, progress:Float?)
}
class sqlPullSave {
let classtoUpdate: saveUpdate = ViewControllerUpdate()
func saveTSVtoSQL(fromFile: NSURL) -> Int {
//Load up the information into a Dictionary (tsv)
//let tsvURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(fromFileName, ofType: fromFileExtension)!)
let tsvURL: NSURL = fromFile
let tab = NSCharacterSet(charactersInString: "\t")
let tsv = CSV(contentsOfURL: tsvURL, separator: tab)
//let defResult: AnyObject = tsv.rows[0]["Name"]!
//let tryagain:String = AnyObjecttoString(tsv.rows[1]["Name"]!)
//load the data into the SQLite database...
dispatch_async(dispatch_get_main_queue()) {
for a in 0..<tsv.rows.count {
self.SQLsaveLine(self.AnyObjecttoString(tsv.rows[a]["Name"]!),
name_l: "",
desc: self.AnyObjecttoString(tsv.rows[a]["1"]!),
jobTitle: self.AnyObjecttoString(tsv.rows[a]["2"]!),
extn: self.AnyObjecttoString(tsv.rows[a]["3"]!)
// update status
var percentComplete: Float = (Float(a) / Float(tsv.rows.count))
self.classtoUpdate.self.updateStatus("SQLload", progress: percentComplete)
}
}
return 0
}