I'm working on an exiting iOS app (called Mazin in the App store, if anyone is interested) and I'm trying to rework the code to avoid using the Application Delegate or a singleton for sharing information/methods. In particular I have the following to share across certain views and controllers:
CoreData objects like NSManagedObjectConttext and related custom methods for interacting with the data
State properties used in several places like currentMazeType, gameMode, and soundIsMuted along with a few widely used utility methods particular to the game
Views and methods used to display information used commonly throughout the app (e.g., an ActivityIndicator and methods to show/hide it on a given view)
In general, several views and ViewControllers need access to various subsets of this information and I need a mechanism to share the information and methods "globally" across these objects. Some of this sharing is for convenience (e.g., every time I want to display a basic activity indicator, I just call a common "startActivityIndicator" method) but some are required (e.g., changing gameMode changes it "globally" and several views/controllers need to access the common mode info).
What sort of patterns would work best for this requirement? I have my own solution in mind, and I'll post it below for your consideration/comments.
Thanks!
Solution I am considering:
I plan to create a few "utility" classes (e.g. GameDataUtil, AppStateUtil, GadgetsUtil) that each encapsulate a proper subset of the "global" information and/or methods. Each View or ViewController that needs to access the common info/methods in a utility will have an appropriate property of that given type (e.g., a view that can make a sound needs access to the AppStateUtil so it can determine if sounds are currently muted).
The ApplicationDelegate will be the only class that generates single instances of the "utility" classes and will pass those instances to the appropriate objects that get loaded from its Nib (in applicationDidFinishLaunching). Those views/controllers will have to pass all necessary information to any of their members that they may load programmatically (which could get hairy--class A may need a GagetsUtil in order to pass it to an instance of class B even though class A never uses the utility directly).
This is sort of like injecting dependencies from the application delegate down (since I don't have the utility of an Dependency Injection Container).
Now, I have thought about creating an uber-utility (e.g., ConfigUtil) that would hold one property for each of the other utilities. The AppDelegate would create a single instance of the uber-utility (setting it up with instances of the other utilities it creates). The AppDelegate would pass the uber-utility instance to anyone who needs access to any of the basic utilities. Each basic utility would still encapsulate a sub-set of the common data/methods, but by putting one of each into an uber-utility and passing it around, I don't have to keep up with which utility is needed by which class (not only for its own use but also to pass to any of its member objects).
NSNotification would be a step away from that model, and is typically easy to implement.
If many things know of and refer to mutable global data right now... it will take time to undo that.
Update
I remembered that I had written a more detailed response to a similar scenario here at SO.
Related
I'm currently developing an app using Parse and I'd like to start abstracting their SDK as I don't know if and when I'm going to replace their backend with another by other provider or by ours.
Another motivation is separating issues: all my apps code will use the same framework while I can just update the framework for any backend specifics.
I've started by creating some generic classes to replace their main classes. This generic classes define a protocol that each adapter must implement. Then I'd have a Parse adapter that would forward the calls to the Parse SDK.
Some problems I can predict is that this will require a lot of different classes. In some cases, e.g. Parse, they also have classes for dealing with Facebook. Or that the architecture in some parts can be so different that there'll be no common ground to allow something like this.
I've actually never went so far with Stackmob as I am with Parse so I guess the first versions will share Parse's own architecture.
What are the best practices for something like this?
Is there something like this out there? I've already searched without success but
maybe I'm looking in the wrong direction;
Should I stick with the Parse SDK just making sure that the code using
it is well identified and contained?
I'm the Developer Evangelist at Applicasa.
We've built a cool set of tools for mobile app developers, part of which includes offering a BaaS service that takes a bit different approach compared to Parse, StackMob, and others. I think it provides a helpful perspective for tackling the problem of abstracting away from third-party SDK APIs in a way that would allow you to replace backends by other providers or your own.
/disclaimer
Is there something like this out there? I've already searched without success but maybe I'm looking in the wrong direction
While there are other BaaS providers out there that provide similar and differentiating features, I'm not aware of a product out there that completely abstracts away third-party providers in an agnostic manner.
What are the best practices for something like this?
I think you already show to be on a solid footing for getting started in the right direction.
First, you're correct in predicting that you'll end up with a number of different classes that encapsulate objects and required functionality in a backend-agnostic way. The number, of course, will depend on what kind of abstraction and encapsulation you're going after. The approach you outline also sounds like the way I'd begin such a project, as well—creating classes for all the objects my application would need to interact with, and implementing custom methods on those classes (or a base class they all extend) that would do the actual work of interacting with a backend provider.
So, if I was building an app that, for example, had a Foo, Bar, and Baz object, I'd create those classes as part of my internal API, with all necessary functionality required by my app. All app logic and functional operations would only interact with those classes, and all app logic and functionality would be data backend-agnostic (meaning no internal functionality could depend on a data backend, but the object classes would provide a consistent interface that allowed operations to be performed, while keeping data handling methods private).
Then, I'd likely make each class inherit from a BaseObject class, which would include the methods that actually talked to a data backend (provider-based or my own custom remote backend). The BaseObject class might have methods like saveObject, getById:, getObjects (with some appropriate parameters for performing object filtering/searching). Then, when I want to replace my backend data service in the future, I'd only have to focus on updating the BaseObject class methods that handle data interaction, while all my app logic & functionality is tied to the Foo, Bar, and Baz classes, and doesn't actually care how get/save/update/delete operations work behind the scenes.
Now, to keep things as easy on myself as possible, I'd build out my BaaS schema to match internal object class names (where, depending on the BaaS requirements, I could use either an isKindOfClass: or NSStringFromClass: call). This means that if I was using Parse, I'd want to make my save method get the NSStringFromClass: of the class name to perform data actions. If I was using a service like Applicasa, which generates a custom SDK of native objects for data interactions, I'd want to base custom data actions on isKindOfClass: results. If I wanted even more flexibility than that (perhaps to allow multiple backend providers to be used, or some other complex requirement), I'd make all the child classes tell BaseObject exactly what schema name to use for data operations through some kind of custom method, like getSchemaName. I'd probably define it as a BaseObject method that would return the class name as a string by default, but then implement on child classes to customize further. So, the inside of a BaseObject save method might look something like this:
- (BOOL) save {
// call backend-specific method for saving an object
BaasProviderObject *objectToSave = [BaasProviderObject
objectWithClassName:[self getSchemaName]];
// Transfer all object properties to BaasProviderObject properties
// Implement however it makes the most sense for BaasProvider
// After you've set all calling object properties to BaasProviderObject
// key-value pairs or object properties, you call the BaasProvider's save
[objectToSave save];
// Return a BOOL value to indicate actual success/failure
return YES; // you'll want this to come from BaaS
}
Then in, say, the Foo class, I might implement getSchemaName like so:
- (NSString) getSchemaName {
// Return a custom NSString for BaasProvider schema
return #"dbFoo";
}
I hope that makes sense.
Should I stick with the Parse SDK just making sure that the code using it is well identified and contained?
Making an internal abstraction like this will be a fair amount of work up front, but it will inevitably offer a lot of flexibility to implement as you wish. You can implement CoreData, reject CoreData, and do whatever you'd like really. There are definite advantages to building internal app logic/functionality in a data-agnostic way, even if it's to allow yourself the ease of trying out another BaaS in, say, a custom branch of your app code to see how you like another provider (or to give you an easy route to working with developing your own data solution).
I hope that helps.
I'm the Platform Evangelist at StackMob and thought I'd chime in on this question. We built our iOS SDK with a Core Data interface. You'll use regular Core Data and we've overridden the NSIncremental Store to persist to StackMob instead of SQLLite.
You can checkout an example of the Core Data code.
http://developer.stackmob.com/tutorials/ios/Create-an-Object
If you want see what methods are being leveraged by Core Data to communicate with StackMob.
http://developer.stackmob.com/tutorials/ios/Lower-Level-CRUD-API
In my application, I have to display image files as a list in tableview, present them in full size and as multiple thumbnails. Hence basically I developed three seperate classes to handle these three views. Now to perform any file operations, I can think of two approaches:
Create appdelegate objects for all these classes, handle them accordingly. When one operation on a photo file is performed in one class, all other classes are notified using NSNotification, keeping the obeserver as Appdelegate object.
Create locally objects for these classes as and when required and assign delegates for performing file operations from one class to other by calling relevant methods.
However, I was not able to judge Which approach would be better in terms of memory usage and performance? Thanks in advance.
Using a one-to-one relationship with direct messaging is the simpler relationship and means of communication/messaging. Favor the delegate callback -- Number 2.
It is also easy to make this design bidirectional -- if the view goes offscreen, you could perform a cancellation. If the load fails, it is easier to inform the controller.
NSNotifications are comparably heavyweight. Not necessary.
Storing a bunch of stuff in a singleton (app delegate) can result in several unnecessarily retained objects. If your program is concurrent, then that can add even more complexity. There's no need for any of this complexity or introduction of mutable global state, and there is no reason presented whereby the objects should have a much larger scope of access and lifetime.
You can optimize for specific needs beyond that, but I don't see any at this time.
It depends a lot on the code and how you are structuring your app. I general use delegates in the following situation:
Where the delegate object exists before and after the main object that needs it. In other words the main object does not need to worry about the lifecycle of it's delegate.
Where the relationship between an object and it's delegate object is a strict one to one. In other words only one delegate object needs to interact with the main object. I have seen situations where delegates are swapped in and out and I would not recommend such code.
Where the main object needs information from the delegate.
I would use notifications where:
Multiple objects need to know of about things happening in another class.
Where the main class does not need to interact with the other classes or even know they exist.
Which ever you choose I would not have more than one file management object for each image. The simple reason being that having multiple means you need to ensure that they all have the same state and therefore are communicating with each other. Otherwise bugs will creep in.
I have a new project, kind of a board game, and I'm using a storyboard which has multiple view controllers in it - the game simply moves from one view to the next with the player making various decisions and then loops back.
I have an object which holds information about the player (along with a couple of methods) - the score etc. I obviously only need one instance of this object and as I want each View Controller to access the same instance, should it be a singleton? I've never used them before and I've read they're often over-used, so I just want to check if this is the correct way to do this from the start. Many thanks.
What you have described is the Model for your application, holding the game data and core logic. Is there any reason to make this a singleton rather than passing it between your controllers?!
I would assume one controller calls the next and so can pass this information across?! We use singletons for services and the like but not for model data, it's not really the point of them in our experience.
I personally have nothing against singletons, as long as you don't use too many of them in one project. While other people might recommend you use some other mediation for this project, I say go for it—this is exactly what you'd use a singleton for.
Singleton's can be be bad if you are developing a library component, a large server project, or for unit testing. But since you are doing an iphone game don't fret about it, it'll will be easier and faster just to use a singleton.
If you are worried about unit testing, since objetive-c is latebound and singletons are made with factory methods instead of constructors it's not hard to changeout the singleton for your unit test anyway.
I’m fairly new to OO. If I have two classes A and B that need to exchange data, or call each other’s methods, I need to be able to access an instance of class B from class A. Should I maintain the address of the instance object in a global variable? Should I appoint a (singleton) master class, and make (pointers to) instances of A and B properties of the master class? (AppDelegate comes to mind.)
Is there a straightforward by-the-book way to implement this? Somehow I‘m missing some "best practice" here. I’ve looked through Apple's examples, but didn't find an answer.
EDIT: Since I'm fairly new to MVC design patterns, my question is essentially "Who creates who"?
We're talking about an Audio Player here. 1. When the user selects a song, the UI displays its waveform by creating a viewController which creates the appropriate view. 2. When the user hits play, the UI displays a timeline while the song is playing by overlaying a new view over the waveform. Now, the latter view needs some info from the waveform display viewController. Right now, I'm storing a pointer to the viewController in an instance variable of my appDelegate. This works, but feels extremely strange.
Should I outsource the info that is needed by both classes to some third entity that every class can access easily?
Classes aren't simply departments of code. They are templates for the creation of objects, which you should think of as actors in your program, doing things within their areas of responsibility (which you define—you decide what each object does) and interacting with each other.
While you can handle a class as you would an object, classes generally do not talk to each other. Most of the time, you will create and use instances of the classes—which is what we normally mean by “objects”—and have those talking to each other. One object sends another a message, telling the receiver to do something or changing one of the receiver's properties. These messages are the interactions between your program's objects.
Those weird expressions in the square brackets are message expressions. Nearly everything you'll do with a class or object will involve one or more messages. You can send messages to classes the same as to objects, and classes can send messages just as objects can.
In Cocoa and Cocoa Touch, you typically have model objects, view objects, controller objects, data objects (such as NSString, NS/UIImage, and NSURL), and helper objects (such as NSFileManager). The classes you'll write for your application will mainly be model, view, and controller objects (MVC). The model represents (models) what the user will see themselves manipulating; the view displays the model to the user; the controller implements logic and makes sure the model gets saved to and loaded from persistent storage.
For more information, see Object-Oriented Programming in Objective-C and the Cocoa Fundamentals Guide.
Since I'm fairly new to MVC design patterns, my question is essentially "Who creates who"?
Controllers create and load the model, and load the views, and pass the model to the view for display. Certain controllers may also create other controllers.
It's good to keep a straightforward tree-like graph of ownership from a single root of your program—typically the application object—down through controllers to leaf objects in the models and views. If two objects own each other, that's a problem. If an object is not owned by anything outside of its own class (a singleton), that's usually a problem as well—a sign you need to think some more about where that code belongs. (Helper objects are the main exception; most of those are singletons. Again, see NSFileManager for an example. But they are few and far between.)
Further situation analysis require more information. At first place you should more specify the relation between classes and what exactly do you mean by exchanging data.
Singletons should be generally avoided. If you want to exchange information it is usually sufficient to provide for example instance of the class A to the instance of the class B by some method or constructor. The instance of B is then capable of calling public methods (and accessing public properties) of the instance of A.
A little bit of "best practices" can be learn by searching up "Design Patterns".
You should decide if one class can be an object of another class (encapsulation), or if one class can inherit from the other class (inheritance). If neither of these is an option, then maybe you could make one class (or some of its members) static?
Thanks for your contributions. Additionally, I found information on this page very useful. It lays out MCV considerations for cocoa in a hands-on way and practical language.
For example, I have window (non-document model) - it has a controller associated with it. Within this window, I have a list and an add button. Clicking the add button brings up another "detail" window / dialog (with an associated controller) that allows the user to enter the detail information, click ok, and then have the item propagated back to the original window's list. Obviously, I would have an underlying model object that holds a collection of these entities (let's call the singular entity an Entity for reference).
Conceivably, I have just one main window, so I would likely have only one collection of entities. I could stash it in the main window's controller – but then how do I pass it to the detail window? I mean, I probably don't want to be passing this collection around - difficult to read / maintain / multithread. I could pass a reference to the parent controller and use it to access the collection, but that seems to smell as well. I could stash it in the appDelegate and then access it as a "global" variable via [[NSApplication sharedApplication] delegate] - that seems a little excessive, considering an app delegate doesn't really have anything to do with the model. Another global variable style could be an option - I could make the Entity class have a singleton factory for the collection and class methods to access the collection. This seems like a bigger abuse than the appDelegate - especially considering the Entity object and the collection of said entities are two separate concerns. I could create an EntityCollection class that has a singleton factory method and then object methods for interaction with the collection (or split into a true factory class and collection class for a little bit more OO goodness and easy replacement for test objects). If I was using the NSDocument model, I guess I could stash it there, but that's not much different than stashing it in the application delegate (although the NSDocument itself does seemingly represent the model in some fashion).
I've spent quite a bit of time lately on the server side, so I haven't had to deal with the client-side much, and when I have, I just brute forced a solution. In the end, there are a billion ways to skin this cat, and it just seems like none of them are terribly clean or pretty. What is the generally accepted Cocoa programmer's way of doing this? Or, better yet, what is the optimum way to do this?
I think your conceptual problem is that you're thinking of the interface as the core of the application and the data model as something you have to find a place to cram somewhere.
This is backwards. The data model is the core of the program and everything else is grafted onto the data model. The model should encapsulate all the logical operations that can be performed on the data. An interface, GUI or otherwise, merely sends messages to the data model requesting certain actions.
Starting with this concept, it's easy to see that having the data model universally accessible is not sloppy design. Since the model contains all the logic for altering the data, you can have an arbitrarily large number of interfaces accessing it without the data becoming muddled or code complicated because the model changes the data only according to its own internal rules.
The best way to accomplish universal access is to create a singleton producing class and then put the header for the class in the application prefix headers. That way, any object in the app can access the data model.
Edit01:
Let me clarify the important difference between a naked global variable and a globally accessible class encapsulated data model.
Historically, we viewed global variables as bad design because they were just raw variables. Any part of the code could alter them at will. This nakedness led to obvious problems has you had to continuously guard against some stray fragment of code altering the global and then bringing the app down.
However, in a class based global, the global variable is encapsulated and protected by the logic implemented by the encapsulating class. This encapsulation means that while any stray fragment of code may attempt to alter the global variable inside the class, it can only do so if the encapsulating class permits the alteration. The automatic validation reduces the complexity of the code because all the validation logic resides in one single class instead of being spread out all over the app in any random place that data might be manipulated.
Instead of creating a weak point as in the case of a naked global variable, you create strong and universal validation and management of the data. If you find a problem with the data management, you only have to fix it in one place. Once you have a properly configured data model, the rest of the app becomes ridiculously easy to write.
My initial reaction would be to use a "modal delegate," a lot like NSAlerts do. You'd create your detail window by passing a reference to a delegate, which the detail window would message when it is done creating the object. The delegate—which would probably be the controller for the main window—could then handle the "done editing" message and add the object to the collection. I'd tend to not want to pass the collection around directly.
I support the EntityCollection class. If you have a list of objects, that list should be managed outside a specific controller, in my opinion.
I use the singleton method where the class itself manages it's own collections, setup and teardown. I find this separates the database/storage functionality from the controllers and keeps things clean. It's nice and easy to just call [Object objects] and have it return a reference to my list of objects.