iOS Pass data, singleton, extern or via protocols? - ios

Hy all,
I am really stuck at data passing in my iOS app.
First i have a class with TabBarController and inside another two ViewController.
It's a container view with a daily and weekly calendar views.
And i wanted to store the downloaded data in an NSDictionary with dates, so the calendar don't have to reload the data any time (only if the user force refresh).
So, should i store this data in an "extern NSDictionary" in the Container view?
Or should i create a SingletonClass and store the Dictionary there?
But will the SingletonClass released after the container view get released?
Or should i store the NSDictionary in the container view and then use methods via protocols to access the Dic? But how?
I checked a lot of tutorials and examples but i still don't know how to do it properly.
Thank you

You could store it inside the tabBarController and access it inside of the tabBar viewController instances, but I think you might be best off by just storing it inside of the NSUserDefaults..That way you can easily grab it from anywhere in your application without grabbing the tabBar instance.
I'd personally recommend creating a Singleton class that implements your NSUserDefaults like so (although you can just write and read directly to it if you'd like):
//DefaultsSingleton.h
#interface DefaultsSingleton : NSObject
{
}
+(DefaultsSingleton*) sharedDefaultsSingleton;
#property(atomic,assign)NSDictionary *yourDictionary;
//DefaultsSingleton.m
#implementation DefaultsSingleton
SYNTHESIZE_SINGLETON_FOR_CLASS(DefaultsSingleton)
-(NSDictionary *) yourDictionary
{
return[ [NSUserDefaults standardUserDefaults] dictionaryForKey:#"your_dictionary"];
}
-(void) setYourDictionary:(NSDictionary *)yourDictionary
{
[[NSUserDefaults standardUserDefaults] setValuesForKeysWithDictionary:yourDictionary];
}
Then just import this singleton file to wherever you want to access it and you can init new dictionaries with the values of it and create mutable copies, and then override the saved value whereever you'd like. Oh and you should also import Matt Gallagher's awesome SynthesizeSingleton class. http://www.cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html

Related

Most appropriate approach for saving item to array at same time its added

I've got an array of elements that needs to be saved to file whenever an item is added/removed from it.
Rather than having some sort of manager type class do this, i.e. in pseudo code:
- (void) SomeManager:addItem(Item*) item {
[someArray addObject: item];
save someArray to file;
I'd rather for example do something like derive a custom class from a mutable array and override addObject to additionally save it to file (probably using NSCoding/NSKeyedArchiver).
Its not recommended to inherit from NSMutableArray, so wondering what are suggestions for the most appropriate and simplest way to achieve this?
The app using this array is a mixture of Swift and Obj-C so the solution needs to be bridgeable between both.
I don't have a preference if any class declarations/implementations are done in Swift or Obj-C.
You can make a class and call it DataHolder, DataContainer, DataStore etc.
#interface DataStore : NSObject
- (NSArray*)data;
- (void) add:(id)object toIndex:(NSUInteger)index;
- (void) removeFromIndex:(NSUInteger)index;
- (id) getAtIndex:(NSUInteger)index;
#end
Put your data inside it and manage it with functions. Maybe you can init with data and keep data private. So you can restrict manipulating data except functions.
- (void) initWithData:(NSArray *)data

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)

the best way to get access

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.

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 control data flow between ViewControllers

I'll start by saying I'm new to Objective-C and iPhone but I have history in C++, Java, AS3, ...
I'm trying to build some sort of RSS Reader, and I have an array for all my feeds. How is the best approach to save new feeds to this array? I have a navigation based project, and I have an add button which pushes a viewController on top to enter new feed URL.
But how do I save this back to the array in my other ViewController? Do I need to research more into SQLLite? Or set some delegates? Or Core Data?
I prefer the singleton method myself but Apple recommends dependency injection i.e. passing a data model object from view controller to view controller as needed.
If you look at a Core Data utilizing template navigation project in Xcode, you can see how this works. The managedObject context is the data model and it is initialized and held by the app delegate. You can then access it two ways:
(1) Since the Application instances itself is a singleton, you can ask it for its delegate and then ask the delegate for its managedObjectContest property. So, in a view controller you would have a property managedObjectContext with a custom getter defined like:
(NSManagedObjectContext *) managedObjectContext{
if (managedObjectContext !=nil){
return managedObjectContext;
}
// this is basically applicationObject.delegate.managedObjectContext
self.managedObjectContext=[[[NSApplication sharedApplication] delegate] managedObjectContext];
return managedObjectContext
}
(2) Alternatively, whenever a view opens another view, it just sets the next view's managedObjectContext property to it's own. So that every view opens with a context. This is useful if you actually have multiple data objects for some reason.
If your just using an array or a custom data model class just substitute its name for the managedObjectContext in the code above.
Check out this question. I recommend using a singleton class and creating some listener pattern to signal when the data has changed (or just reload, always, before your view becomes visible).
You might want to store your feed items in memory by using the a singleton
Something similar to what is being used: Singleton shared data source in Objective-C

Resources