the best way to get access - ios

I've got one variable and I need this variable during the whole programm. Now code is the next:
.h file
extern RequestParams* newUser;
.m file
RequestParams* newUser;
But it works bad. Information doesn't get to this variable.
What is the best way to solve this problem?
Thank you.

You will have to use NSUserDefault or Singleton to handle the values of varaiables accross various Controllers.
These both are used in such a scenario where you need to maintain and access the variable values across multiple View Controllers. You can opt for either one based on your choice.
NSUserDefault can store multiple key-value pairs that are accessible globally throughout the app. Singleton helps you create a object / variable which is static and hence no other instance of it is created afterwards. Only a single instance is retained throughout the app.
The following links might help you.
Singleton Tutorial
Another Singleton Guide
NSUserDefault Tutorial
Another NSUserDefault Tutorial
Hope this helps !

If you required only in you program then you can create it as singleton
// constants.h
+ (RequestParams*) newUser;
// constants.m
+ (RequestParams*) newUser{
static RequestParams* instance = nil;
if (instance == nil) {
// initiate your instance here;
}
return instance;
}
// you can Use it where you required
[constants newUser];
If you you want to keep to when application is closed then you need to use NSUserDefault to save it.
If this help you then you can accept it as solution.

Related

Using an Array Variable in All Views

In an app that I am working for, I need array variable that can be used in all UIViews. Currently when the array is changed in a view it is stored in the database, and when I need the updated version of the array in the previous view, I use the viewWillAppear method and retrieve the updated array from the database. While going to another view by a segue, I use the passing data by prepareForSegue, but if I use the back button, or just change the screens via tab bar, I use the viewWillAppear and a query.
Is there any way that when the array is created in a view, the data in it will be accessible in all views?
As I've stated in my comment, singletons are generally frowned upon for a myriad of reasons. However, there is much debate on this topic:
What is so bad about singletons?
Having said that, the best way I know to make a variable globally available for the session is by creating a singleton.
struct myArray {
static var data: [Int] = []
}
You could set this singleton up to fetch the records using CoreData and store the current working version in a static variable for quick access.
note: I am really very curious to see some other approaches.
Singleton
Singleton is basically a global variable that you can use them in any views, but some developers experience some bugs and difficulties, use it at your own risk, I recommend this method when you're definite that you will use that data a lot (STILL RISKY), but this method is like goddess of data handling :).
Create a NSObject subclass and call it DataManager.swift (I call it data manager cause it handle data.) as following:
import UIKit
class DataManager: NSObject {
//Store Data Globally
static var someData: NSArray! //This Boolean, you can choose whatever you want.
}
the static is what keep your data live.
Now you can store and receive someData from anywhere like you handle any data type like this.
//Store
DataManager.someData = []
//Receive
print(DataManager.someData)

How to share one array with many view controllers iOS

I value the opinions on this site and wanted to know what you all thought. I have an app that contains an array. This array is used in several view controllers. Currently, I create the array each time one of the view controllers opens up. I don't believe this to be the best thing to do. I have used NSUserDefaults before, and singletons, but am open to any ideas you have, plist, etc. I am looking on making things run quick and efficient.
Also, I wanted the user to be able to rearrange the array. Lets say it starts out in alpha order. But the user finds it better to rearrange it some other way. I know how to do that, rearrange, but I wanted to know where to keep the original array so that the user can than reset the order back to the original alpha order.
So I guess this question is twofold. Where to store the original array, and how best to then access the changed array throughout the app. Thanks very much for your help.
EDIT #1
I want to thank everyone for their comments and answers! This is what, I feel, the community is about. Learning new and different techniques is great. I am going to attempt to try all the answers (to see if I can actually program it) and see which one works the best for me. Once again thanks for this excellent dialogue.
Edit#2
I ended up doing a bit of both, and I would have never done that without all of your comments and answers. I made the array in the app delegate and saved it in user defaults. It wasn't a basic array, it was an array of custom objects so I had to use a bit of NSCoding. It also was not just alpha sorted, so I made one array that could be manipulated. Once again, thanks for all the great insight!
You can create a singleton instance of it in your AppDelegate.
Make an #property for the array in AppDelegate.h, and then import that header into your other viewControllers.
Init and store the array to the appDelegate's array #property in "didLoadWithOptions." You could create custom getters/setters to allow for manipulation. The actual data could come from an external XML, JSON or plist file, but to test you can just hard-code an array in AppDelegate to start with.
Each viewController needs to have a reference to the appDelegate, using the methods described in this answer. You can then access the 1 array as you would any other property,
NSArray *dataInVC = myAppDelegate.singletonArray; (...or using NSMutableArray if you want to add/change/manipulate).
...Alternatively, just have a separate class for your data, and create a singleton version of it so you can more easily refactor later if necessary. Examples of how to do this in this answer
As you are accessing your data from five different places, it will soon become confusing to send data to and fro. A singleton class with public properties storing your arrays would be a good solution to this problem.
In case you want to persist the data to disk, NSUserDefaults would be the better option.
Here's how one would go about using NSUserDefaults to do that. For saving data:
[[NSUserDefaults standardUserDefaults] setObject:originalArray forKey:#"OriginalArray"];
[[NSUserDefaults standardUserDefaults] setObject:modifiedArray forKey:#"ModifiedArray"];
Retrieving data:
NSMutableArray *modifiableArray = [[NSUserDefaults standardUserDefaults] arrayForKey:#"ModifiedArray"].mutableCopy;
Don't forget to save the data to disk with a call to [NSUserDefaults synchronize] at appropriate times.
I'd recommend storing the array in your app delegate. One of the advantages of this solution is that your app delegate is already a singleton.
Create an NSMutableArray property in your app delegate header file. Init and fill the array in the app delegate didFinishLaunchingWithOptions: method.
Access it from anywhere with the following code :
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
// appDelegate.myArray holds your values
Going even further, add this to your Prefix.pch file:
#import "MyAppDelegate.h"
#define appDelegate ((MyAppDelegate *)[UIApplication sharedApplication].delegate)
Then the previous code can be reduced simply to calling appDelegate.myArray from anywhere.
You can create methods that handle sorting and other manipulation on your array in your app delegate implementation. If you declare those methods in the app delegate header file, you can also call them from anywhere in the app with :
[appDelegate doStuff:parameter];

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.

iOS: Singleton class for storage in UITableView app

I got a app that uses navigation controller and tableViews and I want to create a class to do some simple storage of information that stays persistent while navigating through the different views without saving to disk.
I can either create an singleton with only class methods, but in this case I´d need to create
the collection class holding the data as an instance variable (as #properties don´t work with class methods). I only ever see objects declared in properties in iOS, so is this frowned upon?
The class would look something like this
header:
+ (BOOL) addObject: (id) object;
+ (BOOL) removeObject: (id) object;
+ (NSInteger) count;
and privately I´ll have an NSArray for storage
NSArray *cache;
But is this a good way of achieving the task? or would it be possible to have a non-singelton class with instance methods and use that same instance of the class in the different table views? if so, how would I do that?
First, ALL readwrite properties auto-synthesize instance variables (unless you implement BOTH setter AND getter).
Second, if that information is global to the entire (or most of the) App, a singleton is just what you need. You don't need to keep it as a property (or an ivar). It's a singleton, it keeps its own pointer.
If you still want to go with a property, you will have to pass it some how to every VC in your App (prepareForSegue:sender: probably if you're using storyboards).
First figure out what global information you need. Then figure out what objects you already have that have a lifetime consistent with that global information, and which are logically associated with the info. Eg, if you need an array of info to "back up" a UITableView, store the pointer to that array in the table view data source instance.
It is rarely necessary to create a "singleton", and having lots of singletons is usually a sign of poor programming.

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.

Resources