I am trying to set the Date() the very first time an App is opened. This will be set in UserDefaults.
I used register() to save the date in UserDefault. The problem is.. this value seems to be saving on every launch, which defeats the purpose of UserDefaults.register.
Here is my code:
let initialOpen: NSDictionary = ["FirstOpen" : Date()]
UserDefaults.standard.register(defaults: initialOpen as! [String : AnyObject])
let firstOpenDate = UserDefaults.standard.value(forKey: "FirstOpen")
print("First Opened: \(firstOpenDate)")
I am calling this within didFinishLaunchingWithOptions.
How can I record the time that the App is launched for the first time in UserDefaults?
There's no need for register(defaults:).
Don't use value(forKey:) to read data from UserDefaults.
All you need to do is first check if the date has been set, if not, set it.
if let firstOpen = UserDefaults.standard.object(forKey: "FirstOpen") as? Date {
print("The app was first opened on \(firstOpen)")
} else {
// This is the first launch
UserDefaults.standard.set(Date(), forKey: "FirstOpen")
}
Related
I am using a child added observer to check if a user gets a new notification while using my app...
func newLikeNotificationObserver() {
notifHandle = Database.database().reference().child("notifications").child(FirebaseDatabase.system.CURRENT_USER_ID).observe(DataEventType.childAdded, with: { (snapshot) in
if !snapshot.exists() {
print("ERROR")
return
}
let id = snapshot.key
print(id)
if let dict = snapshot.value as? Dictionary<String, Any> {
print("ADDED TO LIST")
let notif = Notifications(notifID: id, data: dict)
self.notifications.insert(notif, at: 0)
self.collectionView.reloadData()
}
})
}
The strange issue that I am having is that despite no data being written to my database for when a user likes his/her own posts, the observer is triggered and a Notification is inserted to the array containing the actual user notifications. When I print out the notif-ID to see if I can find it in my DB, its no-where to be found. Can anybody see were I may have gone wrong?
Also, I am removing the observer in the deinit method and adding it in viewdidload(). Thanks in advance
The correct place to put event observers is in viewDidAppear and remove them in viewWillDisappear.
I think its likely that a previous observer is not being removed and is returning bad data. restart the computer and see if it occurs on the initial running of the app, or only on subsequent launches
I have tried an answer which doesn't work: Swift Saving user NSUser Defaults.
My problem is that i want to save : var myDict = [Int:String]() permanently using NSUser defaults.
My code is :
let userDefaults = NSUserDefaults.standardUserDefaults()
#IBAction func AddOneWord(sender: AnyObject) {
if newWord.text != "" {
myDict.updateValue(newWord.text!, forKey: 1)
self.Word1Dictionnary.text = myDict[1]
userDefaults.setValue(myDict, forKey: "1")
userDefaults.synchronize()
}
}
The problem is that I have this error when clicking on the button on my app (which is running) : Thread 1 : Signal SIGABRT.
NSUserDefaults can only store property-list objects. As noted in the Property List Programming Guide:
And although NSDictionary and CFDictionary objects allow their keys to be objects of any type, if the keys are not string objects, the collections are not property-list objects.
You cannot store an [Int: String] in NSUserDefaults. The key must be a string.
Hello I am currently doing a project where the user types something in a textfield, and presses a button, where whatever the user types in the textfield appears as part of the alertbody of a notification.
To do this I save the textfield.text as a variable and then use string interpolation to include it into the alertbody.
The problem is that the time in which I fire the notifications change every week, so I have to make new notifications. And I still want to use whatever the user typed into the textfield. But since the textfield.text was saved inside a function, I do not think that it will be stored outside the function.
This is what my code looks like so far
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(604800, target: self,selector:Selector("repeater"), userInfo: nil, repeats: true)
}
savedtext:String!
#IBAction func setNotification{
textfield.text = savedtext
//set notifications and other stuff here
}
//outside the function savedtext should not have the textfield's info
func repeater{
//setting notification
}
Sorry if my question is a bit difficult to understand
Any help is appreciated
I'd use NSUserDefaults here, it will persist your data in a key-value map, even after the user or system kills the app. The code would look like this
let ALERT_MESSAGE_KEY : String = "myAlertMsgKey"
#IBAction func setNotification{
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setValue(textfield.text , forKey: ALERT_MESSAGE_KEY)
NSUserDefaults.standardUserDefaults().synchronize()
//set notifications and other stuff here
}
and in repeater function:
func repeater {
let defaults = NSUserDefaults.standardUserDefaults()
let alertMessage = defaults.valueForKey(ALERT_MESSAGE_KEY) as? String ?? "No message saved"
}
You could also use Core Data for this, but it would be an overkill for something so simple
I want to create a global NSDate in my app, because I want to save the date of the first time ever the app has been opened in this variable. I wrote
"var LaunchDate = NSDate()" before the declaration of the main class of the first view controller, and in the viewdidload, if it is the first time the app is opened, it saves the date into the global variable LaunchDate. But everytime I open the app, it saves the current date because of "var LaunchDate = NSDate()".
I didn't find a solution, do you have any idea to declare a global date without that he gives the current date please?
You could use NSUserDefaults to store the value.
The code checks if a value exists.
If yes it reads the value, if no it writes the current date.
var launchDate : NSDate!
let defaults = NSUserDefaults.standardUserDefaults()
if let dateOfFirstLaunch = defaults.objectForKey("dateOfFirstLaunch") as? NSDate {
launchDate = dateOfFirstLaunch
} else {
let currentDate = NSDate()
defaults.setObject(currentDate, forKey:"dateOfFirstLaunch")
launchDate = currentDate
}
Global variables are variables that are defined outside of any
function, method, closure, or type context
struct globalDate
{
static var LaunchDate = NSDate()
}
In swift if you encapsulate the variable in struct, you can access that in any classes.
Document
Global Variable
Try this:
override func viewDidLoad() {
var LaunchDate: NSDate
// when you want to set the value for it:
LaunchDate = NSDate()
}
The Proble, is that NSDate() which you tried to do is a function, which gets back a value of the current date.
I would use the Singleton Pattern with NSUserDefaults.
The code should be something like this
import Foundation
class UserDefaults {
static let sharedInstance = UserDefaults()
var launchDate: NSDate? {
get {
return NSUserDefaults.standardUserDefaults().objectForKey("launch_date") as? NSDate
}
set {
NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: "launch_date")
}
}
}
Access it using this code
UserDefaults.sharedInstance.launchDate
Iv'e got 2 ViewControllers, In the first one the user get the points and the high score label.
In the second ViewController, the code calculates if the user has broke the old high score, if yes - it changes, of course. BUT! when I quit the app and start playing again, the high score label show my last score and not the highest score.
Here is my code:
First ViewController:
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
defaults.synchronize()
highScore.text = String(stringInterpolationSegment: oldScore)
Second ViewController:
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
if score > oldScore {
defaults.setInteger(score, forKey: "oldScore")
defaults.synchronize()
var money = defaults.valueForKey("oldScore") as! Int
oldScore = money
} else {
defaults.setInteger(oldScore, forKey: "oldScore")
defaults.synchronize()
var money = defaults.valueForKey("oldScore") as! Int
oldScore = money
}
I also got var oldScore = Int() in the view controller code but outside the class of the view controller.
In addition, I have a "Switch" button that starts with state of "ON". But sometimes me/the user want to change it to off, how can I save it to be the user's choice after I quit the app and relaunch?
First of all check if NSUserDefault for oldScore is set. If it is not set only then initialise the oldScore, otherwise don't. Just fetch the value of oldScore and compare it with the new score and set the value accordingly
if (NSUserDefaults.standardUserDefaults().objectForKey(oldScore) == nil) {
oldScore = Int()
}
In your Second View Controller, first of all put NSUserDefault's oldScore's value into a variable and then check if it is equal to your Score. If it is only then set it like this :
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
var oldScoreCheck = defaults.valueForKey("oldScore") as! Int
if score > oldScoreCheck {
defaults.setInteger(score, forKey: "oldScore")
defaults.synchronize()
}
In your first view controller make the following change.
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
if defaults.integerForKey("oldScore") != nil
{
highScore.text = defaults.integerForKey("oldScore")
}
else
{
highScore.text = 0
}
There might be some changes required dependent on the variable type of highScore.
Hope this might be helpful.
According Apple's documentation you should register all default values before using them.
In AppDelegate in application:didFinishLaunchingWithOptions: add this code to register the key oldScore to have a reliable default value. A key switchState is also registered for the mentioned "Switch" button.
let defaults = NSUserDefaults.standardUserDefaults()
let defaultValues = ["oldScore" : 0, "switchState" : "ON"]
defaults.registerDefaults(defaultValues)
In the first view controller retrieve the high score value. If no value has been ever written to disk, the registered default value (0) is taken. You could read the value for the "Switch" button respectively.
let defaults = NSUserDefaults.standardUserDefaults()
let oldScore = defaults.integerForKey("oldScore")
let buttonState = defaults.stringForKey("switchState")
highScore.text = "\(oldScore)"
In the second view controller save the high score if changed
let defaults = NSUserDefaults.standardUserDefaults()
let oldScore = defaults.integerForKey("oldScore")
if score > oldScore {
defaults.setInteger(score, forKey: "oldScore")
defaults.synchronize()
oldScore = score
}