How to use an integer from another class? - ios

I am making a multiple choice quiz app. In my main class, I have an integer called "points" that is used to display the current points earned in the quiz view. However, I also want to display the points in the view of another class, which tells the user that his answer is correct.
I know that you can do this if one class is a subclass of the other, but can you do it if they are not related?

One way to do this is to set up points as a global variable. Like so:
In your AppDelegate.h file insert this line after the #end:
extern int points;
In any classes that needed to read/write to points, in the .h files after the #end, add this line:
int points;

I would look into something like Singleton Objects
This link provides a basic example of simple Singleton Objects, which you could use to share a variable between classes.

Related

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.

Any smarter way to define constants in bulk?

I want to have macros for all constant strings in the project, which I am assigned to maintain.
The format of database fields are like #"first_name", #"last_name", etc.
What I want is like follows:
#define kFirstName #"first_name"
#define kLastName #"last_name" // And so on.
Problem: I have over 3500 unique fields with constant strings. I want each one of them to be defined as macro.
Any smarter way to do this. I am thinking of manually copy, paste & edit each one of them.
Tagging as iOS & Objective-C, as the project itself is an iPad Application.
In general, defining constants like this is the way to go on iOS, so you're on the right track.
You surely won't get around typing out each of the fields at least once.
I would recommend either of two approaches:
use multiple .h-files for the definition of all the constants. you can group the header files according to the definitions that they contain (e.g. all fields related to user data in UserDefinitions.h). that way you at least make sure that you don't have to import all the constants everywhere in your code. working with prefixes will also be helpful in this situation, so prefix all the Macros names with the .h-file that they contain, e.g. kUserFirstName so that you you know at first sight where this constant comes from
define all your constants in one (or multiple) property lists. that makes them easy to maintain. only make sure that you don't load the property file each time you use one of the constants, but rather cache the file once its loaded for the first time.
When using Core Data consider using mogenerator which creates constant values for you that you can reference for all of the attribute and relationship names.
the cleanest way is to make a pair of constants files (header and main). Create a new class (inheriting from whatever, NSObject say) call it constants. Delete the #interface and #implementation, so you have an empty header (except for #import Foundation/Foundation.h) and empty main (except for importing the header.)
then declare each in the header like this
extern NSString *const kFirstName;
and implement each (in the .m file) just like this
NSString *const kFirstName = #"Johnny";
make sure the .m file is added to your target, import the header where need be.

Defining global arrays to be shared between ViewControllers

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.

Move from old-fashioned struct to class

I know this could be a noob question but I am a bit stucked here. I usualy makes the following to access app data in different ViewControllers: First I declare a global.h module like this
global.h
typedef struct {
NSString *appName
NSString *appVersion;
bool mode;
} structApp;
extern structApp app;
After that I declare in MainViewController.h the struct so that I can access data
#implementation ViewController
structApp app;
- (void)viewDidLoad
{
app.appVersion = #"v1.02";
}
#end
And then I include "global.h" in every ViewController.h
This way I can access globally. As far I can see this is a good implementation and I have used it in more than 20 apps. Problem starts when this struct grows in size. In those cases I see corrupted memory, nil variables that were previously loaded with data, etc.
There is a better way of making data available in all ViewController? Please give me some examples if you can.
You have two options
Use a singleton class - Refer Objective C Singleton
Declare properties in App delegate - Refer SO
You can access the app delegate from any class using:
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
As you were using extern in your structure, any object updating the same value.
In OOPS, global variables are never said Good, so you need to use a singleton pattern.
Create a singleton/shared class having all those stuffs in your structure and use it.
You should deal with struct only if you deal with primitive data (if you are in a OOP way).
app.appVersion = #"v1.02";
Make your struct pointing on dangling pointer, since you are pointing a data in a function scope (app.appVersion is only holding the pointer, not the data). So you must retain all those object values in order to make it content safe, but i must admit it is still a Q&D approach.
If you need global access to data, you can use a singleton, only if you really need strong encapsulation and control to data.
How to make a singleton
What should my Objective-C singleton look like?
You can use macro too, that way you'll can use constants string without worrying data persistency, since they will always be available into the scope you are dealing with.
If you only want to read the data and you dont need any complex data structure you can also use a settings file like
Settings.h
#define appName #"blabla"
#define appVersion #"1.01"
#define mode 1
In General using struct should work fine. There is nothing wrong with using them. If you observe weird values caused by overlapping memory or illegal re-use of it or so then your problem is somewhere else but not in using structs in principle. The extern statement could lead to such an issue.
A class is not much more than a struct too, from a memory usage perspective. If I were you I would design a class with properties where ever you have members when using a struct. And make use of them in pretty the same way.
For "global variables" I apply a singleton pattern. That is basically a class with a class method (the leading + instead of -) that makes the one and only instance of the class available. Within that method I check if the class (a class internal static reference to the same class) is already available (!= nil) and instantiate it. Sometimes I use the initialize method for that. Initialize is an objective-c typical thing. It is called only once for each class, even subclassed ones, when or before the class is used for the first time. A very good place for instantiating class variables as singletons but not portable to other programming languages.

iOS - Clarifying class and instance methods

I just want to make sure I'm using class methods correctly.
By way of example, let's say I'm creating a game that involves a single map and individual tiles on that map (for instance, 16 x 16 tiles).
Each tile can consist of either a building, tree, road, etc - and this can change throughout the game.
Would I be correct in setting up a Map class with a class method to initialise the map, simply because there will only be one map and I would have no need to instantiate more than one?
Would I also be correct in setting up a Tile class with instance methods to initialise the tiles, because there would be 256 tiles each with their own properties?
Struggling to get my head around it all, any advice would be greatly appreciated.
There are multiple patterns for dealing with this, but basically it boils down to the Map class being a singleton. Some prefer to enforce the singleton-ness of the class by disallowing the creation of multiple instances (for example, by hiding the constructor, or making the constructor throw an exception, etc). In other cases it just suffices to document the Map class as being a singleton and use it as such.
A simple way of dealing with singletons in Objective-C is to create a class method for instantiating it, i.e.:
static Map* defaultMap = nil;
+ (Map*) defaultMap {
if(!defaultMap) defaultMap = [[Map alloc] init];
return defaultMap;
}
Using class methods for the map is probably not such a good idea, just like global variables is something that should usually be reduced to a minimum (though the example above is really a global variable, it will be a lot easier to refactor your code once you have a need for multiple maps).
Map class can be implemented as singleton pattern. Or any other way that limits it to only 1 shared instance.

Resources