Access array from all Swift Files - ios

I have an array stored in a class that downloads its objects from the internet. My class is set up like so:
class StockManager {
var managerStock: [Dictionary<String, String>] {
return downloadStockFromDatabase()
}
...
}
I access the managerStock from other Swift files in my project like so, but it always resorts to re-downloading the stock again no matter if I have used the variable before (ie. recalls the function downloadStockFromDatabase):
let stockManager = StockManager()
print(stockManager.managerStock)
How would I make sure the managerStock only downloads once and I could use it in any of my files?

This is a question of correct software pattern usage. I would suggest:
make StockManager a singleton, so you will always access the same instance of it
initialize it e.g. in the AppDelegate, i.e. make sure it stays alive for the whole runtime
tip: call managerStock lazily, i.e. only when you really need it and not as part of initialization

As ff10 and holex suggested, make your class a singleton. It will look like this:
class StockManager {
static let sharedInstance = StockManager ()
var managerStock: [Dictionary<String, String>] {
return downloadStockFromDatabase()
}
...
}
Then access it using the static sharedInstance property:
print(StockManager.sharedInstance.managerStock)

Related

Ios swift class without instantiate

How do you (if possible) create a class that anything that references it gets the same object?
So, if I had a LoginClass
and I dont want to create a new instance in each file but rather be able to just do
LoginClass.userID
in any file without first creating an instance of it?
It possible. Use singleton:
Stackoverflow question
Tutorial by Ray Wenderlich
You are looking for a Singleton
This is the code
class Login {
static let sharedInstance = Login()
var userID: String?
private init() {}
}
This is how you retrieve the same instance
Login.sharedInstance
And this is how you use it
Login.sharedInstance.userID = "123"
In a different point of your code...
print(Login.sharedInstance.userID) // 123
Creating one instance per application life cycle means you want to implement Singleton pattern. You can implement singleton like this
class LoginManager {
static let sharedInstance = LoginManager()
var userId:String?
var name:String?
}
And now you can use this like
LoginManager.sharedInstance.userId

Save EVObjects with CoreData

I need to save some data with CoreData. Generally thats not a problem at all. The problem is, that the data is created with EVReflection an therefore inherits the class EVObject. To save the gathered data to CoreData they have to also inherit NSManagedObject. The problem is that swift does not allow you to inherit multiple classes. Would appreciate any tips.
class Device : EVObject
{
var channel : [Channel] = [Channel]()
var name : String = ""
var ise_id : Int = 0
var unreach : Bool = false
var sticky_unreach : Bool = false
var config_pending : Bool = false
override internal func propertyMapping() -> [(String?, String?)] {
return [("name", "_name"), ("ise_id", "_ise_id"), ("unreach", "_unreach"), ("sticky_unreach", "_sticky_unreach"), ("config_pending", "_config_pending")]
}
}
You don't have to inherit. You can extend them. Example:
class User : NSManagedObject{
#NSManaged .....
}
//Extension
import EVReflection
extension User : EVReflectable { }
https://github.com/evermeer/EVReflection#extending-existing-objects
Note I'm not aware of EVReflection but I think this answer can generally apply.
Don't use multiple inheritance. Have two separate classes and a mechanism for creating/loading/updating one object from the other. Protocols may allow it to be done in a way that minimises translation boilerplate (possibly using valueForKey(_:) and setValue(_:forKey) if you can know the key names in a safe manner.
It may not even be even be necessary to have an NSManagedObject subclass but just have an instance of NSManagedObject in all your classes that is loaded/created/saved as necessary.
It depends on what functionality you want to use from EVReflection. Since NSManagedObject also has NSObject as it's base class you could use most functions by just setting NSManagedObject as your base class instead of EVObject.
The only thing you have to do is instead of calling EVObject functions directly, you have to implement the code snippets that are in that EVObject method. Almost any function there is just a convenience method that will call the corresponding EVReflection function.
If you have any questions in the future, then please also report this as an issue on GitHub.

How to create Singleton in swift with arguments

I learn the Swift Language and i need to create a manager like a Parse sdk.
For exemple when you initialize your Parse in app you write
Parse.setApplication("...", applicationId:"...")
And later you can write code like this
Parse.doSomething()
The method doSomething() use initial context.
Can you show me in my class should look like? I try some singleton exemple, but a have MyClass.sharedAttribute.doSomething() in case
What you have shown is no indication of singletons whatsoever, it sounds and looks more like a static class with static members and properties:
class MyStatic {
static var appIdA : String?
class func setApplicationId(a : String) {
appIdA = a
}
class func doSomething() {
print(appIdA)
}
}
MyStatic.setApplicationId("blabla")
MyStatic.doSomething() // prints Optional("blabla")
Of course there is the possibility that internally the class is a singleton, but Parse does not seem to be one, just looking at the functions it exposes.
The code comments even state
/*!
The `Parse` class contains static functions that handle global configuration
for the Parse framework.
*/

Accessing singleton object in swift

This is my first time implementing a singleton to share an instance of an object in swift. Everything seems to be working totally fine, except for when I try and add an element to an array (accessing from another class) that lives within my singleton object. It indeed does not append any objects to the array at all. I'm thinking that it's appending onto an array, but not the same instance of the class that I would like it to be (as I only want one and only one instance). However, If I append elements onto the array from the init() of the class, everything works out just fine. Here's some code (I've simplified all the classes to make things more obvious):
File 1:
class Brew: NSObject {
var method = Method()
//Singleton variable
private static var currentBrew: Brew?
//Method to get the current (and only) brew object
static func getCurrentBrew() -> Brew {
if currentBrew == nil {
currentBrew = Brew()
}
return currentBrew!
}
}
struct Method {
var chemex = Device()
init() {
//If I append here - everything works fine
//chemex.instructions.append = (Instruction(title: "Prepare", direction: "Prewet & Heat", time: 3, water: 0))
}
}
struct Device {
var instructions = [Instruction]()
init() {
instructions.append(Instruction(title: "None", direction: "None", time: 1, water: 0, index: 0))
}
File 2: (where I would like to append to the array of instructions)
let brew = Brew.getCurrentBrew() //How i'm accessing the object
//I'm calling this method from viewDidLoad to set up the array
func setupBrewDevices() {
//This is the line that does not actually append to the singleton instance
brew.method.chemex.instructions.append(Instruction(title: "Extraction", direction: "Match water.", time: 8 , water: 25))
Just a side note, I also tried to make a method that would append an instruction onto the array that lives inside of the same class, but that had the same result. Hopefully this is clear enough - I appreciate any help!
Thanks,
Cole
There is a better way to create a singleton instance in Swift.
class Brew: NSObject {
static let currentBrew = Brew()
var method = Method()
}
This is thread-safe and avoids using an optional.
That said, when I tried your code the instructions array ended up with two elements like I would expect ("None") and ("Extraction"). The problem may lie elsewhere in your code.

Using one variable as a reference to another in swift

I keep all of my users data in a User object and access it when I need it, as demonstrated in the example below on line 1. The inconvenience I encounter when using this method of data storing is when I need to edit these objects. Below, I have a Time object which belongs to the current user. Ideally, I would set the current user's times to a variable to make it more manageable, and then edit the times using that variable. The problem is, the time variable doesn't refer to the User.current().times[0] variable. Is there a way of using a variable essentially as a shortcut?
let time = User.current().times[0]
time.name = titleLabel.text
time.start = start
time.end = end
time.save()
User.current().times is of type [Time] which is a subclass of NSObject.
The declaration of the User class as requested with the current() function.
var this_user: User?
class User: NSObject {
var times = [Time]()
class func current() -> User {
if this_user == nil {
this_user = User()
}
return this_user!
}
}
Classes Are Reference Types
Unlike value types, reference types are not copied when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used instead.
Just check User().current().times[0]. Is it a class or only a value? If you make an user object and holds that reference then you can get those.
For more Info see this.
Your code does work. The fault is in your testing procedure.
To prove this, I set up mock versions of your classes at the top level of a file, like this:
var this_user : User?
class Time : NSObject {
var start : String!
}
class User: NSObject {
var times = [Time]()
class func current() -> User {
if this_user == nil {
this_user = User()
}
return this_user!
}
}
Then, elsewhere, I ran this code:
let cur = User.current()
cur.times.append(Time()) // to give us a first Time in times
let time = User.current().times[0]
time.start = "Testing" // so let's see if we can write into it!
println(User.current().times[0].start) // Testing
This proves that when I set time.start it does reflect back into the Time that is in the times array of the current User. Therefore, I conclude that there is something wrong with the way you are testing your code. (Either that, or your description of your objects is inaccurate.)

Resources