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.
Related
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.
I will try to make this question as understandable as possible. I am implementing core data in my app, and I need to access the NSManagedObjectContext from around 10,000 different instances of a class (this class extends UIView). The Core Data stores what is displayed on these instances and the class builds it.
Everything that I have found so far uses View Controllers, of which you only have one instance, so you can just alloc init the VC in AppDelegate, set an #property for NSManagedObjectContext and be on your way. This does not work for my program.
What I want to do is have many instances of my CoreDataHelper class (which I will alloc init in the class that I have around 10,000 instances of, which all have a property pointing to the same NSManagedObjectContext. Is this a possible way to do it or will I have to make my program less flexible by moving all of the code to create the 10,000 different objects to the View Controller?
Sure, just put your NSManagedObjectContext in a singleton and all your instances can access the single class.
It does not matter if you get your managed object context from a singleton or from your app delegate (where presumably you the core data stack is set up by default).
To follow the pattern suggested by Apple with view controllers, do the exact same thing with your views: give them a #property of type NSManagedObjectContext and set it during initialization. Seems straight forward enough.
The advantage of the singleton is that you do not even need the property on your view but can call the singleton instead. But why go there? From your comments I understand that you do not really know how a singleton works. You don't need it. Go with the class property solution.
One more caveat: with your setup, you are seriously braking the MVC architecture by giving the views access to your data. Instead, you should indeed have a view controller do this and then populate your views with the retrieved data. I do not think that there is a compelling reason to deviate from this principle.
I have two or even more view controllers (A and B) which uses the same calculation method. I would guess the best way is to put the calculation method in its own class (lets call it C), define a protocol and thats it. If this is right, how do I know how to address the delegate?
If I alloc/init an object of the class C (the one with the calculatormethod) e.g. in class B I have the object pointer in class B - thats ok. But how do I get the object pointer known in class A or even other classes (i.e. how do I tell those controllers which want to use the delegate (i.e the same calculation method), how to address the delegate once it is alloc/init by class B?
Any help is very much appreciated!
I have two or even more view controllers (A and B) which uses the same calculation method.
Unless this is for calculating view layouts, it probably indicates you've have an MVC violation. View Controllers typically should not calculate anything. Their job is to manage user interaction. Data and calculations belong in the model.
If it is a proper view controller calculation (like managing layout), then you're correct that you want a delegate. "Delegation" is what Cocoa tends to call the Strategy pattern. You move your algorithm into another object and that lets you vary the algorithm without varying the rest of the code.
So in one case you need access to some model object, and in the other you need access to some delegate. In either case, the solutions can be similar. I'll call either situation "C" as you have.
One solution, particularly is you're using a storyboard, is to create "C" in the storyboard and wire it with an IBOutlet. You can create any object you like in a storyboard. Just drag out an "Object" and set its class to the appropriate class. Wire it up just like anything else. (This is a technique that is commonly used for multi-view nib files on OS X, and I had remembered translating over to Storyboards, but it doesn't work for sharing objects across scenes, only within scenes; so it's not as useful on iOS.)
Another solution, particularly for the model, is to implement it as a singleton, or to have a separate singleton (a "model controller") that returns it. You should not use the app delegate for this; use a singleton made expressly for this purpose.
You can create "C" in the application delegate and pass it into the root view controller (this is a proper use of the app delegate, because it's part of global program initialization). The view controllers can pass the object as part of their segues. This is my preferred solutions for passing model objects around.
If it really is a layout calculation delegate, this is probably part of some kind of configuration system (assuming it can change). The current configuration can be treated as a piece of the model, and all the above techniques still work.
If it really is just shared algorithms and doesn't vary, don't forget C functions. There is no rule that you must put all code into methods. Functions are ideal for stateless calculation. Categories can be used this way to, but simple functions have fewer complexities.
What you are saying is that both classes A and B have a common dependency (could be class C or simply a protocol C).
A and B don't need to know anything about how they are instantiated, they just need to know that they will be eventually provided with an instance implementing (protocol) C.
Another important thing is that you probably don't want C to be hold with a strong reference by either A or B.
I would look at which class F could have the responsibility to instantiate A and B.
The responsibility of this class (which could be described as a Factory) could also be to provide instances of A and B with a C instance.
So what I would do: Define a "factory" class that has methods to build instances of A and B.
Each of these methods would also provide with a C instance. This C instance could be a property of the factory class if you want it to be shared (or this factory class could also pick the C instances from a pool of available C instances).
UPDATE: not practical if you are using storyboards to instantiate your controllers. In this case you probably want to go with other given answer or implement your shared computational functions as methods of a singleton class C (see How to pass object between several views in storyboard, iOS Dev for example)
Use a superclass for A and B (and any number of additional controllers) that contains the calculation method. By using a superclass, you don't have to alloc init another class or use delegates, all the subclasses will have access to the method.
Another approach that would be more general would be to implement a category on UIViewController to add the calculation method. This way, any controller that descends from UIViewController (UITableViewController, UICollectionViewController, etc.) would have access to that method.
After Edit:
I see in your comments that your calculations have nothing to do with the controllers, just some sort of algorithm, so a category or subclass of UIViewController is probably not the best way to go. If you want to do it in another class, any controller that needs to use it, can instantiate an instance of that class, set itself as delegate, and get the result back through the delegate method (that is, if you even need a delegate -- if the calculation is fast, then you can just return a result from the method rather than using a delegate). After your controller gets the result back, the instance should be deallocated. You don't have to worry about which controller set the delegate, since each controller creates its own instance of the calculation class, and sets itself as delegate. I use this kind of structure for apps that need to do downloads from a server from multiple controllers. The download class is instantiated, does its work, sends back the result in a delegate method, and then gets deallocated. It only sticks around for as long as it needs to to do its work.
I have a theoretical-practical question. I can't understand how I must do. I have a class let's call them DataManager that manage all plist writing-reading things and I need to get access to plist (i.e. work with that DataManager class) from different UIViewControllers.
I also have one class, I call it ModelManager, that is work with all kind of "utilities classes", include my DataManager. ModelManager works only with one complex UIViewController right now, let's call it MainUIViewController for clearness. And for now, I thought that all calls from UIViewControllers will be comes to ModelManager and from it to end-call classes. But now I'm confused.
Here is an illustration of my architecture:
I'm see different approaches and don't know how to decide and if there is some rules or guides for that. So, here is my choices:
1) I add some interface to ModelManager and from my another UIViewController (not a MainUIViewController) allocate and initialise it.
2) I add some interface to ModelManager and create a property with reference to ModelManager in another UIViewController and when segues performs set this property from MainUIViewController.
3) Work with DataManager itself and allocate and initialise it from another UIViewController
4) Work with DataManager itself and create a property with reference to DataManager in another UIViewController and when segues performs set this property from MainUIViewController.
Which approach is correct?
I know that this is some kind of depends from developer which approach to choose, but I never read and didn't find any tutorial or guide of how to develop multi-class architecture.
Ask me about any circumstance that you want to know.
You can use a singleton or you can instantiate one instance of the class in your app delegate and pass it around to all your view controllers via #propertys on each controller. There's no right answer, it's mostly a matter of preference. I prefer to make my ModelManager/DataManager type classes singletons, but a lot of people are rabidly opposed to singletons. However, if you work with Cocoa for any length of time you'll find that it's full of them (NSUserDefaults, NSFileManager, UIDevice, probably some others I'm forgetting).
Here's a good example on how to create singletons: http://www.galloway.me.uk/tutorials/singleton-classes/
BTW: Once you have your singleton, learn how to use KVO to make your view controllers respond to changes in the model. It's pretty fantastic once you get the hang of it. http://nshipster.com/key-value-observing/
I have a singleton that manages preferences which are loaded from a plist. I use it multiple apps. It contains methods like -(BOOL)boolForKey:(NSString *)key defaultValue:(BOOL)def
So I can get use the class in two different apps, just by supplying different keys, such as in one app: [PreferenceManager boolForKey:#"UseAlternateColors" defaultValue:NO];
But it would be easier to have a method like -(BOOL)useAlternateColors (which just returns the value from the above line) just in that app. So should I add this method to PreferenceManager using a category (and only have the category in the one app) or create subclass like OneAppPreferenceManager?
In this specific example, is it better to subclass or use a category?
Subclassing would have been a better option if you needed to add new data members to the derived PreferenceManager. However, since the backing storage always remains the same, I think that using a category would be preferable in this specific case.
Using a category would let your keep the singleton PreferenceManager unchanged, along with the piece of code that sets it up. If you were to subclass PreferenceManager, you would need to make an additional change to the code that instantiates the singleton, so that it uses the PreferenceManagerSubclass instead of the raw PreferenceManager. With a category, this change would be unnecessary.