Error when using NSUserDefaults - swift

I've been trying for weeks now to save some values in one view controller then access them in another using the NSUserDefaults method. I am using this code:
(to save):
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("Coding Explorer", forKey: "userNameKey")
the last line produces an "expected declaration" error
(to get values):
let defaults = NSUserDefaults.standardUserDefaults()
if let name = defaults.stringForKey("userNameKey")
{
println(name)
}
The first of these lines produces a "incorrect redeclarion of 'defaults'"
second line produces "expected declaration"
third line produces "Consecutive declarions on a line must be seperated by a ;" and "variables used within its own initial value"
Please help me fix this I've tried different lots of code to use NSUserDefaults, and I've tried using the code on separate and the same view controllers.

You may try to use this way..
to save first define a string called for example "firstName":
var firstName : String = "Im Swift"
in viewDidLoad in the first ViewController :
if (NSUserDefaults.standardUserDefaults().stringForKey("firstName") == nil){
NSUserDefaults.standardUserDefaults().setObject(firstName, forKey: "firstName")
}
To retrieve value :
in the viewDidLoad of second ViewController :
if (NSUserDefaults.standardUserDefaults().stringForKey("firstName") != nil){
var x = NSUserDefaults.standardUserDefaults().objectForKey("firstName") as! String
println("\(x)");
}

Related

Accessing Firebase Data inside unique AutoID

This is my first question and I'm still learning Swift/Xcode/Firebase, so I appreciate your patience. I've been stalking StackOverflow and have found a lot of answers to help with various things, but nothing that makes sense for the problem I've been struggling with for 2 days.
I am writing a program that will save a date picked on a previous viewcontroller and a set of user-entered floats from text fields to a Firebase database, and append each data set as a separate entry instead of overwriting the previous data. Using the first block of code below, I've got this problem solved except I can't find a way to do it without using AutoID. This leaves me with a setup like this in Firebase, but with multiple categories and "optionSelected" sections in each category:
program-name
Category 1
optionSelected
L1cggMnqFqaJf1a7UOv
Date: "21-12-2017"
Variable 1 Float: "12345"
Variable 2 Float: "26.51"
L1ciVpLq1yXm5khimQC
Date: "30-12-2017"
Variable 1 Float: "23456"
Variable 2 Float: "35.88"
Code used to save:
func newWithNewVars() {
let myDatabase = Database.database().reference().child("Category 1").child(optionSelected)
let variable1 = textField1.text
let variable2 = textField2.text
let variable1Float = (textField1.text! as NSString).floatValue
let variable2Float = (textField2.text! as NSString).floatValue
let writeArray = ["Date": textPassedOverDate, "Variable 1 Float": variable1Float, "Variable 2 Float": variable2Float]
myDatabase.childByAutoId().setValue(gasArray) {
(error, reference) in
if error != nil {
print(error!)
}
else {
print("Message saved successfully!")
}
}
}
The problem comes with recalling data. Since the AutoID is unique, I can't figure out how to access the data deeper inside for calculations. Specifically, I want to be able to make a new entry, press the save data button, and have it find the most recent entry in the "optionSelected" section so it can do calculations like subtract the older variable 1 from the new variable 1 and such.
Given the above description, layout, and code used above, what code structure would allow me to find the most recent date and access the data inside the AutoID sections for a specific category and "optionSelected"?
Thank you for your help.
The issue you're having is that you're trying to dig deeper but can't as you don't have a hold of that id. You'll want to use the .childAdded in your reference observation when you want to get inside of a list in your JSON tree when you don't have a hold of that id to get inside - this will be called as many times as there are values inside of Category 1 tree:
let reference = Database.database().reference()
reference.child("Category 1").child("optionSelected").observe(.childAdded, with: { (snapshot) in
let uniqueKey = snapshot.key // IF YOU WANT ACCESS TO THAT UNIQUE ID
print(uniqueKey)
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
let date = dictionary["date"] as? String
let variableOne = dictionary["Variable 1 Float"] as? Float
let variableOne = dictionary["Variable 2 Float"] as? Float
}, withCancel: nil)
You may also want to avoid using spaces in your database keys to avoid any problems in the near future. I'd stick with the common lowercased underscore practice e.g. "category_1" or "variable_2_float"

How to pass and get multiple URLQueryItems in Swift?

Ok, I am working in an iMessage app and am trying to parse more than 1 url query item from the selected message here- I have been successful getting/sending just 1 value in a query:
override func willBecomeActive(with conversation: MSConversation) {
// Called when the extension is about to move from the inactive to active state.
// This will happen when the extension is about to present UI.
if(conversation.selectedMessage?.url != nil) //trying to catch error
{
let components = URLComponents(string: (conversation.selectedMessage?.url?.query?.description)!)
//let val = conversation.selectedMessage?.url?.query?.description
if let queryItems = components?.queryItems {
// process the query items here...
let param1 = queryItems.filter({$0.name == "theirScore"}).first
print("***************=> GOT IT ",param1?.value)
}
}
When I just have 1 value, just by printing conversation.selectedMessage?.url?.query?.description I get an optional with that 1 value, which is good. But with multiple I cant find a clean way to get specific values by key.
What is the correct way to parse a URLQueryItem for given keys for iMessage?
When you do conversation.selectedMessage?.url?.query?.description it simply prints out the contents of the query. If you have multiple items then it would appear something like:
item=Item1&part=Part1&story=Story1
You can parse that one manually by splitting the string on "&" and then splitting the contents of the resulting array on "=" to get the individual key value pairs in to a dictionary. Then, you can directly refer to each value by key to get the specific values, something like this:
var dic = [String:String]()
if let txt = url?.query {
let arr = txt.components(separatedBy:"&")
for item in arr {
let arr2 = item.components(separatedBy:"=")
let key = arr2[0]
let val = arr2[1]
dic[key] = val
}
}
print(dic)
The above gives you an easy way to access the values by key. However, that is a bit more verbose. The way you provided in your code, using a filter on the queryItems array, is the more compact solution :) So you already have the easier/compact solution, but if this approach makes better sense to you personally, you can always go this route ...
Also, if the issue is that you have to write the same filtering code multiple times to get a value from the queryItems array, then you can always have a helper method which takes two parameters, the queryItems array and a String parameter (the key) and returns an optional String value (the value matching the key) along the following lines:
func valueFrom(queryItems:[URLQueryItem], key:String) -> String? {
return queryItems.filter({$0.name == key}).first?.value
}
Then your above code would look like:
if let queryItems = components?.queryItems {
// process the query items here...
let param1 = valueFrom(queryItems:queryItems, key:"item")
print("***************=> GOT IT ", param1)
}
You can use iMessageDataKit library. It makes setting and getting data really easy and straightforward like:
let message: MSMessage = MSMessage()
message.md.set(value: 7, forKey: "user_id")
message.md.set(value: "john", forKey: "username")
message.md.set(values: ["joy", "smile"], forKey: "tags")
print(message.md.integer(forKey: "user_id")!)
print(message.md.string(forKey: "username")!)
print(message.md.values(forKey: "tags")!)
(Disclaimer: I'm the author of iMessageDataKit)

Swift - add text to dictionary

While I am trying to add a value to a dictionary, it always fail while I try to set the value from my textField.text. I have a text field, that I want to add to a dictionary, with this code:
var dict = [String:AnyObject]()
dict.updateValue(usernameText.text!, forKey: "key")
print(dict["key"]!)
However, on the print it doesn't show anything. When I am setting the value as "a value" - it prints fine. How come I can't add a text field value?
What type is usernameText ? and are you certain that there is any text in it ?
try adding print(usernameText.text!) to make sure.
I tested with UITextField and could not reproduce the problem when there is text in the .text property.
Try it like this:
dict["key"] = usernameText.text!
Update:
Just tried this code:
var dict = [String:AnyObject]()
dict.updateValue("Foo", forKey: "key")
print(dict["key"]!)
and it prints me as I expected Foo, try the following code, setting non optional value under "key" key:
if let aText = usernameText.text {
dict.updateValue(aText, forKey: "key")
}

Bypassing code on initial run

In my code I need to retrieve a saved array of data to populate student history data. I am using the following line of code - which works great.
returnedArray = UserDefaults.standard().object(forKey: "studentHistoryArray")! as! NSArray as! [[String]]
The problem I have is on the initial (first) run of the program. The array hasn't been created/saved yet so I need to skip this step, but only on the initial run of the program. Is there a way to run this line of code only on the first run of a program?
var defaults = UserDefaults.standard()
let studentHistoryArrayKey = "studentHistoryArray"
var returnedArray = defaults.object(forKey: studentHistoryArrayKey) as? [[String]]
// I don't think that you need to use the intermediary cast to NSArray, but
// I could be wrong.
if returnedArray == nil {
returnedArray = [[String]]()
defaults.setObject(returnedArray, forKey: studentHistoryArrayKey)
}
// Now it's guaranteed to be non-nil, so do whatever you need to do with the array.
As a rule of thumb, if you're using ! as liberally as in your example, something's going to break.

Accessing .recordFields from CKQueryNotification Swift 2

I get the following error on didReceiveRemoteNotifications if I try to simply print this property, like:
let cloudKitNotification = CKNotification(fromRemoteNotificationDictionary: userInfo as! [String : NSObject])
if cloudKitNotification.notificationType == .Query {
let queryNotification = cloudKitNotification as! CKQueryNotification
print(queryNotification.recordFields)
Could not cast value of type '__NSCFDictionary' (0x273119c) to 'CKRecordValue' (0x2763090).
If I print the whole queryNotification, I can see the recordFields inside of it. I've spent the whole day trying to understand that. Any clues?
Xcode 7.3.1