Move from old-fashioned struct to class - ios

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.

Related

How to avoid the global state in Swift

I been reading about avoiding the mutable state, and how the singleton pattern is bad for having a global state.
I see few answers about Dependency injection http://www.objc.io/issue-13/singletons.html, but I can not find how to solve this basic approach:
How maintain the user data arround the app?, the solution is to pass the user information from the one view (where is requested by webservice) through the views by parameter to the seven push view (where is needed again) ?
there is a better way?, or the singleton pattern is sometimes necessary?
I use a singleton to represent my Engine class in Swift. It is initialized once on launch and contains static class variables stored in a struct. Works fine for me.
class Engine{
struct properties{
static var resourceManager:ResourceManager!;
...
}
init(){
properties.resourceManager = ResourceManager();
}
In another class I can then call
Engine.properties.resourceManager

iOS / Objective-C Meta Class and Category

I understand a class is actually an object / typedef of struct (objc_class*).
Each class has a "backing" meta class, which in turns has a isa pointer pointing to the meta class of NSObject.
And NSObjectbasically has a isa pointer pointing back to itself.
And we could get a hold of the meta class via this line:
objc_getMetaClass("<CLASS_NAME>");
I hope my understanding of meta class is not off here so far (please correct me if it is).
My questions are:
1.)
When would we need to deal with meta class? Could you please cite an
example / a scenario in code when we might need to?
2.)
Background:
I was thinking freely about third party libraries and how they are structured.
Usually they provide you with a class method and return you a class and all other methods are private / "hidden". And most of the time, while they can be subclassed but since we do not know the init method, it would be of no use to subclass.
And suddenly I began thinking about Objective-C Category and thus leading me to think of Objective-C meta class.
And this leads to my question #2:
Is it possible to break this structure by making use of Objective-C
Category and / or with the use of meta class (by grabbing a hold of
it and insert a class method straight there in the meta class)? Or
even look up the name of their instance methods that are private?
My intention here is not to "break" anything, I am just very curious as to how "unbreakable" these third party libraries are structured and if their structures cannot be "broken" via the use of Category and Meta Class.
#Leo Natan:
1.)
What is method_*()?
2.)
For the love of Objective-C Runtime:
Could you cite an example implementation-swizzling an instance method, let say,
(I am not sure if this method is a good example, for we could override it in the first place)
NSArray's -count instance method (let’s make it so that it returns always count 100, for example)
3.)
So in theory all classes (including all third party libraries) can be break (broken)? Other words, there is no way to create a „call-only-this-class-method-or-you-cannot-use-me“ API / library?
Thanks a lot.
The meta class is useful when wishing to view, add or modify class methods and class-level information.
For example,
IMP myIMP = imp_implementationWithBlock(^(id _self, NSString *string) {
NSLog(#"Hello %#", string);
});
Class cls = objc_getMetaClass("NSString");
class_addMethod(cls, #selector(test:), myIMP, "v#:#");
[NSString test:#"lala"];
To get instance methods, you use class_copyMethodList() on the class returned by class method on an object or NSClassFromString(). You will get an array of all the instance methods defined by the class (but not of its superclass!). You can then use the various method_*() methods to retrieve information and possibly even modify these methods (like implementation swizzling).
You can call class_copyMethodList() on the meta class to get all the class methods defined.
To address your "Leo" questions,
1.
Please read the Objective C Runtime Reference. You can find a section of method_ functions dealing with Method structs.
2.
See tutorial on implementation swizzling.
3.
Using Objective C, everything is available to the runtime. It goes without saying, that with great power comes great responsibility. The Objective C runtime is very powerful. These swizzles are very dangerous and usually not recommended.

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.

iOS: Adding class method to the application delegate?

Is ok if I add class methods that I need over all my project in the application delegate?
and then I import the delegate in the current UIViewController and I invoke the method: [MyAppDelegate classMethod];
Is a good approach ?
thanks
I set up an APP_DELEGATE macro that is defined as:
#define APP_DELEGATE ((AppDelegate *)[[UIApplication sharedApplication] delegate])
... so when I need to use it, I just code:
[APP_DELEGATE someInstanceMethod];
So yes, I use instance methods instead (for simplicity). Just define this macro in your AppDelegate.h and include it wherever you need it.
I think it should be fine, but I would only do it if it a) makes sense, and b) is truly the only place for that method. I'd think long and hard about whether that functionality belongs in the delegate or in some other singleton or shared class.
I would say that it's an acceptable approach but I would not recommend it. It depends on what the methods you are taking about do. For example, if you want to be able to access your data model from everywhere in your app, it's better to use a singleton, so that you separate the model completely from the rest of the app.
it's depending upon ur app needs or context.
if u r going to access class variables then u can choose class methods to create.
but u cannot access the instance variables.
but my choice is instance method which will operate on both class variable and instance variable.
The difference between class methods and instance methods are
Class methods
Operate on Class variables (they can not access instance variables)
Do not require an object to be instantiated to be applied
Sometimes can be a code smell (some people who are new to OOP use as a crutch to do Structured Programming in an OO enviroment)
Instance methods
Operate on instances variables and class variables
Must have an instanciated object to operate on

iOS sharing 'global data' across view controllers

I have been using app delegate as a "global bucket" to share data between various view controllers. Typically I do something like this:
My_AppDelegate *appDelegate = (My_AppDelegate *)[[UIApplication sharedApplication] delegate];
And then, I would stick data into the appDelegate, and pick up data from the appDelegate with another view controller. Somehow, this seems clumsy and inappropriate (although it does work).
Is there a better way? Can I set-up a "listener" on some kind of a global sharing area, if somebody sticks a data element in there, another object would get a 'call-back' to let it know that somebody has data ready for it?
In Java we used to do this with Observer/Observable class - maybe there is something like this, or better in iOS?
A cleaner, although not necessarily different, way to do this is to create a singleton class, e.g. AppData, which you can access in a variety of ways, and which would be available to all your other classes. It has the benefit of separating your app-specific stuff from the app delegate stuff. You might define the class this way:
#interface AppData : NSObject
// Perhaps you'll declare some class methods here...
#end
A common thing I do is define class methods on such a class to access, for example, settings values, or app-specific constants or other singleton objects. There are a lot of possibilities.
In the end, you can get a lot done with just class methods, that you would call something like [AppData theMethod]. Just remember there's no self to access inside a class method.
Taking it one step further, you can define ivars for the AppData class, and then manage a singleton instance of AppData. Use a class method, e.g. +sharedInstance, to get a handle to the singleton on which you could then call mehods. For example, [[AppData sharedInstance] someMethod:myArgument]. Your implementation of +sharedInstance can be where you manage the actual creation of the singleton, which the method ultimately returns.
I am not sure if I'd call this approach a "best practice", but I've found this pattern quite handy.

Resources