Passing an object between controller Swift - ios

I have a storyboard which start with a login page. And I have a User class like this
class User {
// Properties
var firmCode : String
var firmId : String
var userId : String
// Default Initializer
init() {
self.firmCode = ""
self.firmId = ""
self.userId = ""
}
// Defult Initializer with prams
init(firmCode: String, firmId: String, userId: String) {
self.firmCode = firmCode
self.firmId = firmId
self.userId = userId
}
}
I am generating some values in login page, and I can create my User object with these values.
Now I want to make this object global and use this user object in all scene.
How to pass this object to other scenes? For example I want to pass this values with my object to an embed static table view controller like this
Note: Does it matter, the embed controller has a tab bar controller? I guess I need to use my delegate file?
EDIT:
Now I have created my global object like this:
// test value
let firmId = "Company Id"
// Creating user object without user class declaration
NSUserDefaults.standardUserDefaults().setObject(firmId, forKey: "testFirmId")
And trying to get my object like this:
// Creating user variable in other scene by globally
let getValue : AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey("testFirmId")
// checking
println(getValue!)
AND done, return my value on termanal. All work until here.
But now the value return to me as AnyObject, I need the convert it String to apply like this:
someLabel.text = getValue!

You can use NSUserDefaults for that like you can store your object this way:
NSUserDefaults.standardUserDefaults().setObject(YourObject, forKey: "YouKey")
After that you can access it in any scene like:
let yourObject: AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey("YouKey")
Hope It will help you.
EDIT:
NSUserDefaults is limited in the types it can handle: NSData, NSString, NSNumber, NSDate, NSArray, and NSDictionary. Thus no Swift objects or structs can be saved.
From the Apple NSUserDefaults Docs:
A default object must be a property list, that is, an instance of (or
for collections a combination of instances of): NSData, NSString,
NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any
other type of object, you should typically archive it to create an
instance of NSData.
And if you are using NSUserDefaults then you can directly store your instance like shown below:
NSUserDefaults.standardUserDefaults().setObject(test, forKey: "firmCode")
NSUserDefaults.standardUserDefaults().setObject(test, forKey: "firmId")
NSUserDefaults.standardUserDefaults().setObject(test, forKey: "userId")
You Don't need model class for that.

var user = User()
self.user.firmCode = 1
//Assign value to other variables
//Save User object in NSUserDefaults as like this
User.saveUserObject(user)
//Function For Save User
class func saveUserObject(user : User){
let userKey = "UserData \(user.userID)"
NSUserDefaults.standardUserDefaults().setObject(data, forKey: userKey)
}
//Get User Object from NSUserDefaults
class func getUserObject(userIDValue : NSNumber) -> User? {
let userKey = "UserData \(userIDValue)"
if let data = NSUserDefaults.standardUserDefaults().objectForKey(userKey) as? NSData {
return data as? User
}
return nil
}

Related

How to access Data in multipleviewControllers in Swift?

I will try to explain the scenario as best as I can.
Lets say if viewControllerA tells the model to hold some data(for example data from a json response) and then viewControllerD(or any other viewcontroller) needs the data, how do i access the data from the model. Creating an instance of the model in viewControllerD creates a fresh instance without any data.
Below code explains the scenario.
ViewControllerA
let userdetails = UserDetails(json: self.userDetailsList!)
userdetailsarray.append(userdetails) //a global array
//Model
class UserDetails: NSObject {
var name : String?
var profession : String?
var id: String?
init(json: NSDictionary) {
let name = json["name"] as? String
let profession = json["profession"] as? String
let id = json["id"] as? String
self.name = name
self.profession = profession
self.id = id
super.init()
}
}
Possible Solution I know: Creating a global variable
var userdetailsarray = [UserDetails]
and appending UserDetails(model) into this array and using this array across multiple viewControllers. An alternative solution could be the model class being singleton.
I am looking for a more optimistic solution. Thankyou
If the data is more make it encrypted using NSKeyedArchiever and store it in user defaults. Whenever you required the data you can fetch it from user defaults and un archive it using NSKyedUnarchiever.
Note: This is the best solution only if you want to persist the data.

Save Dictionary into NSUserDefaults Swift

I have a Dictionary and i want to save it to NSUserDefaults(or something else so I can have access to my variables after i have terminated the app) , I found an example:
var saved = NSUserDefaults.standardUserDefaults()
let dict = ["Name": "Paul", "Country": "UK"]
saved.setObject(dict, forKey: "SavedDict")
But when i used it to mine Dictionary it didn't work. (maybe because my dictionary it's a little bit different)
My Dictionary is made like this:
var userDictionary = [Int : Event]()
struct Event {
var sensorName: String
var sensorType: String
var sensorSub: String
}
And i add elements like this:
userDictionary[value] = Event(sensorName: "first", sensorType: "Temp", sensorSub: "Third")
And here is what i tried to do so I can store it.
saved.setObject(userDictionary, forKey: "valueDictionary")
And I get this error:
Cannot convert value of type '[Int : SensorsView.Event]' to expected
argument type 'AnyObject?'
To avoid this error I did this:
self.saved.setObject(self.userDictionary as? AnyObject, forKey: "valueDictionary")
But I can't retrieve what i saved
Unfortunately this question didn't help me after some comments i believe that the goal here is to convert my dictionary to Data (or something else) and after i retrieve it i convert it back to Dictionary
Try to convert the data to NSData and then retrieve like so:
/// Save
NSUserDefaults.standardUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(object), forKey: key)
/// Read
var data = NSUserDefaults.standardUserDefaults().objectForKey(key) as NSData
var object = NSKeyedUnarchiver.unarchiveObjectWithData(data) as [String: String]
What i think is from the link below you will be able to store the Dictionary into NSUserDefaults
Swift NSUserDefaults not saving Dictionary?
or
Saving dictionary into NSUserDefaults may help
I managed to save my custom Dictionary using Realm!
Instead of a struct I use a different class like this:
import RealmSwift
class Sensors : Object {
dynamic var sensorName = ""
dynamic var sensorType = ""
dynamic var sensorSub = ""
}
and then I fill it like this:
var useOfRealm = try! Realm()
var allSensors = useOfRealm.objects(Sensors.self)
var saving = Sensors()
func fillThis() {
try! useOfRealm.write {
saving.sensorName = "something"
saving.sensorType = "something"
saving.sensorSub = "something"
useOfRealm.add(saving)
}
}
Use the function with parameters so you can fill the 'Dictionary' Dynamically.
Use allSensors so you can retrieve everything that you want.

how to don't get a nil value from NSUserDefaults in ViewDidLoad

I have a case where when my viewControler starts in viewDidLoad I have to load some data using NSUserDefaults.standardUserDefaults() which doesn't exist in this monent. This data are saved when I tap send Button in the same viewController and I need this data when I open this viewController again. Now it looks like that:
var orderHistory = [String:String]()
vievDidLoad(){
let userDefault = NSUserDefaults.standardUserDefaults()
let orderHistory = userDefault.objectForKey("orderHistory")
if orderHistory == nil {
self.orderHistory = orderHistory["name":"", "surname":""] as! [String:String]
} else {
self.orderHistory = orderHistory as! [String:String]
{
}// end viewDidLoad
In this moment I recieve an imformation, I have a problem with memory. How should I avoid this situation?
As Leo Dabus said you should try using the ?? nil coalescing operator.
ObjectForKey does not provide a default value because it doesnt know what kind of object it is until you set it the first time. This results in a nil crash if you try to access it value without having it set once.
Compare this to say "boolForKey" where you dont have to do this, because it knows you are dealing with boolean values and therefore defaults to false automatically.
You also dont have to create 2 orderHistory dictionaries, it just makes your code more confusing.
Try this instead
var orderHistory = [String:String]()
vievDidLoad(){
let userDefault = NSUserDefaults.standardUserDefaults()
orderHistory = userDefault.objectForKey("orderHistory") as? [String: String] ?? orderHistory
//than just use the 1 dictionary without the if statements or creating another one.
}// end viewDidLoad
You check if saved data exists (as? [String: String]) and update the dictionary accordingly. If no saved data exists it will use the default values in orderHistory (?? orderHistory), which in your case is an empty dictionary.
This way you dont have to do a nil check, its all done in that one line.
Also try putting your keys into structs or global files so that you avoid typos. I see people not doing this all the time and its really bad practice.
So for example, above your class create a struct
struct Key {
static let orderHistory = "OrderHistory"
}
and use it like so
...objectForKey(Key.orderHistory)
This code makes no sense:
if orderHistory == nil
{
self.orderHistory = orderHistory["name":"", "surname":""] as! [String:String]
}
The if statement guarantees that orderHistory is nil, thereby guaranteeing that the attempt to fetch keys from orderHistory will crash. Actually, that doesn't look like valid Swift. I would expect that line to throw a compiler error.
Are you trying to create a new dictionary?
If so, your code should read like this:
if orderHistory == nil
{
self.orderHistory = ["name":"", "surname":""]
}

How to get method for class in Swift

I have a class:
class myObject: NSObject {
dynamic var objectId : String?
dynamic var name : String?
dynamic var lastName : String?
dynamic var age : String?
}
In my other class I am getting the value of this class's property:
self.myArray.append(myObject.name!)
I can get the value of myObject.name by adding .name but what if there will be hundreds of properties in my myObject class? For that I want to create a method which can return the properties of my class using a variable:
let myVar = "name"
self.myArray.append(myObject.myVar)
It should append the values of property name, but I am getting an error:
value of myObject has no member `myVar`
and I know why I am getting the error.
How can I get access to properties of my class using a variable? Something like :getValue(String) should return that property of my class.
You should also have a look at NSMutableDictionary, here's a quick example which shows how it works
// initialise a dictionary
var dict = NSMutableDictionary(objects: ["first", "second", 42], forKeys: ["String1", "String2", "Int1"])
// add a new attribute
dict.addEntriesFromDictionary(NSDictionary(object: "New thing", forKey: "String3") as [NSObject : AnyObject])
// access the data
let firstString = dict.valueForKey("String1")
let firstInt = dict.valueForKey("Int1")
// update the data
dict.setValue(99, forKey: "Int1")
let newValue = dict.valueForKey("Int1")
I can be wrong, but as I've already said in a comment, it would be better to use Dictionary and store values in it. Also if you want to access some values with a dot-notation, but still be able to get them by string, you can just create a property and override setter and getter
class MyClass {
var properties = [String: AnyObject]()
var someProperty: String? {
get {
return properties["someProperty"] as? String
}
set {
properties["someProperty"] = newValue
}
}
This way you are able to access value of someProperty both by object.someProperty and object.properties["someProperty"]
You can do it making array of object like following
var arrayOfObjects = [myObject]
and then set an objects values
var firstObject:myObject
myObject.name = "Your name"
myObject.age = "Your age"
...
then append first object to arrayOfObjects
arrayOfObject.append(firstObject)
and you can access it
print("First Object's name: \(arrayOfObjects[0].name)")

Saving to User Defaults in Swift

I am currently trying to save an array to the user defaults.
Here is my code:
//where things will be stored
let defaults = NSUserDefaults.standardUserDefaults()
var taskNames = [String]()
var taskPriorities = [Float]()
//this is the function that saves tasks
func saveTask() {
println(taskNames)
println(taskPriorities)
defaults.setObject(taskNames, forKey: "taskName")
defaults.setObject(taskPriorities, forKey: "taskPriorities")
defaults.synchronize()
}
//this is the function that loads tasks
func loadTasks() {
var taskNamesLoad = defaults.dataForKey("taskName")
println(defaults.dataForKey("taskName"))
println(taskNamesLoad)
}
When I call the function to load the data (after saving some data with the other function of course) the output to the Console is nil and there is no data saved in the user defaults. How can I fix this?
You should use arrayForKey or objectForKey instead dataForKey. Because you store the Array object, not NSData.
Like below:
func loadTasks() {
var taskNamesLoad = defaults.arrayForKey("taskName")
println(defaults.arrayForKey("taskName"))
println(taskNamesLoad)
}
If you're going to save to user defaults you need to use plist safe objects. So instead of using Float you need to use NSNumber.

Resources