Defining global arrays to be shared between ViewControllers - ios

I'm trying to get my head around how to do this and can't figure it out. I want to have a group of NSMutableArrays that are shared between a number of views and are used for a few different data sets that are the same. So I have one called events one called times and so on. They are used multiple times with different sets of data but the data is always of the same type.
What I want to do is to make these globally accessible but there are 2 things I'm struggling with regarding that.
How do I make them globally accessible?
How do I initialise them in each class so that the data can be set in that class?
Ive been looking over a few things on here and what I have at the moment is a class called Football where they are defined in a method called DefineArrays. Is this the right way to approach this problem? Then how do I call that method from another class?

There are 2 ways...
Create a reference class.
Get access to the ViewController instance you have them declared in.

Related

Pass Data,Share global variable,Singleton?

I have a UITabbarController with three UINavigationControllers.And each navigation controllers has a UITableViewController as rootViewController. It's a typical design in many apps.Now I want to share a object between these three UITableViewController in their UINavigationControllers.I have the following ideas:
In UITabbarViewController, I can declare a property,maybe 'strong'.Each UITableViewController can access to the object useself.tabbarcontroller.object
Create a singleton that keeps this object. But it may cause singleton abuse.Some topic advise use dependency injection to avoid the abuse.But it seems it could not satisfy my requirement.
Make the object a global variable.I really do not want to take this method.
I prefer to use method 1. Any ideas about the data passing?
If you need to pass it to the ViewController just like an Android intent extra then i would go for method 1.
If you need to store it and access it multiple times from various classes then i would go for method 2 or 3, maybe 2 is more clear.
Hope this helps.

How to incorporate information from Different Classes

In Swift, I am trying to build a simple app that runs the card game war. There are two view controllers, one for normal gameplay and one in case of a tie. So, in my code, I have two different classes, one called mainScene and one called tieScene. To store which cards the player has and which cards the enemy has, I use two arrays named playerArray and enemy Array. If a tie occurs, I segue from mainScene to tieScene. How do I incorporate the information for playerArray and enemyArray from class mainScene, and use these values in class tieScene?
One thing I tried was subclassing tieScene as part of mainScene as follows:
class tieScene: mainScene {...}
This allowed me to use the playerArray and enemyArray in class tieScene. However, the option to connect tieScene to my second view controller in Interface Builder was not there when I subclassed tieScene.
So, I have two questions:
Did I subclass tieScene wrong and is that why I couldn't connect tieScene in my interface builder?
Besides subclassing, how can I use the information from one class in another class?
This is OOP 101 stuff.
Subclassing does not share information.
Cars and trucks are both motor vehicles
Sedans and coupes are both subclasses of car. Say both have a radio with a radio station property.
If I change the radio station in my sedan instance, that does not mean you can query the radio station in your coupe and find out what station I'm listening to.
Separate objects are completely separate from each other, and have their own instance variables.
You can either set up a link between your two objects and define a protocol to communicate between them, or if you want to save global app state information then maybe you need a data container singleton. See this thread I created for a discussion of the different options:
How do you share data between view controllers and other objects in Swift?
I don't think you're understanding what a subclass is.. If you're subclassing, then that just means that the child class has the same properties as the super class, so it will have the arrays but they are not persisted.
There are a couple of things you can use, the easiest would be to simply create the arrays in your tie view, then when you create a new tie view, set the arrays. Or create a method to setup the tie view with the arrays(initWithEnemyArray.....)
You should not be using subclassing like this, subclassing is not used to share information, that is a misuse of what object orientation is about. It would not work because when your program runs you will have a separate instance of type tieScene and another instance of mainScene. Therefore you will have two separate instances of the data, not one instance which is shared. You should consider making a model class and storing your data there. Read about MVC.
Regarding OOP and inheritance, make sure you understand the difference between a class and an instance of a class. You are mixed up thinking an instance and a class are the same thing, they are not.

Passing Arrays/Objects between ViewControllers in Swift

Following on from this question: Is there a reason that Swift array assignment is inconsistent (neither a reference nor a deep copy)? -
I have been playing with passing objects in Swift and noticed some strange results.
To clarify the kind of behaviour i'm used to (prior to Swift) would be that of Objective C.
To give an example in one of my Applications (written in Obj C) I have the concept of a 'notification list'. - really just an array of custom objects.
In that App I often pass my global array of 'notifications' to various viewControllers which provide a UI to update the list.
When I pass the global array to a child viewController I assign it to a local array variable in the recipient object. Then, simply by updating/changing the local array these changes are reflected in the global array on the rootViewController. I understand this behaviour is implicit in Objective C as objects as passed by reference, but this is really handy and I have been trying to replicate this behaviour in Swift.
However whilst I have been rewriting my App in Swift I've hit a wall.
I first tried to pass a Swift array of strings (not NSMutableArray) from the rootViewController to a child viewController (as described above).
Here is the behaviour when passing in the array of Strings the child viewController:
I Pass in:
[Bill, Bob, Jack] and then assign this passed array to a local array for local modification,
Then I append the String “Frank” to the local array
The results are:
Local array = [Bill, Bob, Jack, Frank]
Global array = [Bill, Bob, Jack]
No changes to the local array are reflected back to the global array. - The SAME result occurs for a change of element (without changing the length of the array.)
I have also tried the above experiment with a more real world example - passing in an array of my custom 'notification' objects to a child viewController. The SAME result occurs with none of the changes to the locally assigned array of custom objects being reflected to the original global array that was passed in.
This behaviour is not desirable to me, I assume the best practice here is to use delegate protocols to pass the modified array (or whatever object) back to the parent object and then to manually update the global array?? - if so this creates quite an extra workload over the Objective C style behaviour.
Finally I did try the inout keyword, which effectively lets you directly modify the function parameter var thats passed to the destination object.
Changes are reflected back to the global array (or object) However the problem is, if the input parameter is assigned to a local variable (to edit outside of scope of the init function) changes to the local variable are still not reflected in global scope.
I hope the above makes sense - It's really stifling my productivity with Swift.
Am I missing something or is this schizophrenic behaviour expected?
If so what is best practice on passing modified data back, delegates?
The linked question provides the answer - it is for performance.
The behaviour may not be desirable for you, but I would say that relying on side-effects from calling methods to modify parameters is the behaviour that is not considered desirable - particularly in a multi-threaded, multi-core environment where data structures can be corrupted.
A design that relies on side-effects is flawed, in my opinion.
If functions need to modify the "global" then they should either return the new value, or if that isn't possible then you should wrap your array inside an object and provide appropriate functions to manipulate the data values.
Swift blurs the lines between intrinsic and object somewhat with arrays, which makes it a little confusing - in Objective-C an NSMutableArray is an object so it always passed by reference.
For notifying other objects that the data has changed you can use an observer pattern. The typical delegate pattern only has a single registered delegate - With an observer pattern you can have multiple registered observers.
You can do this through NSNotificationCenter or an array of "delegates". The former has the advantage of decoupling the code more than delegation
Why don't you create a Model class that contains the array as a var. Add methods to the Model class to manipulate the array and store the new instance in the property. Create a single instance of the Model class at startup and pass it to the view controllers. They all access the array through the Model or through methods in the Model class. The behavior of Swift (where it copies the array on change of size) will be hidden from all of the view controllers.

How to set values to a class without creating an instance of class?

Currently I have 2 ViewController files I want to share common data between, however I want to have a class called GlobalVariables store all of the variables throughout my code. In one of the ViewController files, I want to set the value of a variable (I have created a setVariable method in the GlobalVariables.m file) and from the ViewController, I want to call this method so it sets the variable. How can I do this without creating an instance of GlobalVariables as any changes I make to the instance will not carry over when I create another instance of GlobalVariables in my second ViewController file?
Use singleton Design Pattern. It’s an extremely powerful way to share data between different parts of code without having to pass the data around manually. And also it will always be a single instance through out the Application life cycle
Please check this link:
Singleton Class
Define your varible in AppDelegate. AppDelegate is a Singleton class.
And access that variable where you want.
It's unclear what you mean by "set values to a class". There are 3 kinds of variables in Objective-C: global variables, instance variables, and local variables. Local variables are not relevant. If you con't want to create an instance, then instance variables are out. So then you want global variables. They can be set and accessed by any function or method.

Confusion over running methods on Class Method instances of objects

So I'm getting myself into a confusion over where my data's going and where it's stored in my application. It's not a specific question so hopefully someone can provide a generalised answer.
I need to pass some data around between a few UIViewController instances, and I'm currently doing that with a singleton object called my dataManager. This class has one method, a class method, called + (LCDataManager *) sharedDataManager, and that method basically checks if whether the sharedDataManager already exists, if so, return it, if not, create it and set up its variables. This means that I can refer to that class anywhere I like, access and modify its variables anywhere I like, from across multiple classes.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Second question: what if I want to put an instance method in that class, and call it from within the class method? Let's say my sharedDataManager needs to call a method to grab some objects one of its variables (an array), and put them in another array, then send that back out again. I can't do that, can I? What's the way around that? If I make an instance of that class (rather than using the shared instance), I lose the ability to use that instance across multiple viewControllers.
I'm hideously confused, and it seems like it's not the problem I'm making it. Appreciate any guidance, and preferably not that "Read the Apple documentation" stuff – they write as if you already know what you're doing, and frankly I don't yet.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Your design is perfectly MVC compliant.
Second question: what if I want to put an instance method in that class, and call it from within the class method?
you can surely define an instance method and call it like this:
[[MyModelClass sharedModel] myInstanceMethod];
indeed, [MyModelClass sharedModel] will give you an instance of MyModelClass (which should be guaranted to be unique being it a singleton).
If you want to call the instance method from the sharedModel class method, you could also do that, because sharedModel owns a reference to your singleton, so it can send messages to it.
is this the correct / best / most appropriate means of passing data around like this?
There's nothing wrong with only having a single instance of LCDataManager, but using the Singleton pattern has potential problems. An alternative is to just initialize one LCDataManger and to pass it around to wherever it's needed.
what if I want to put an instance method in that class, and call it from within the class method?
The accessor + (LCDataManager *) sharedDataManager should only return the instance. I guess what you want is something like
+ (LCDataManager *)preparedDataManager {
LCDataManager *shared = [self sharedDataManager];
[shared doSomeInstanceMagic];
return shared;
}
- (void)doSomeInstanceMagic {
// magic!
// grab some objects one of its variables (an array),
// and put them in another array
}
Matthijs Hollemans has an excellent three-part tutorial on his blog about the correct way to make your view controllers talk to each other:
Part 1
Part 2
Part 3
there is no problem with this development architecture, and it is the must used (I think) in the iOS development. In the book IOS Programming: The Big Nerd Ranch Guide they call it Model View Controller Store.
Regarding your second question, yes, you can declare instance methods and call then from your sharedDataManager. What is not usual is creating other instances of a singleton class, but it is possible.

Resources