This is a question about best-practices.
I have an application that uses a standard iOS tab controller.
One of the things that I'd like to do is split the XIB up into separate files. I can achieve this by specifying the 'child' XIB in the 'NIB Name' section for each tab controller. So far, so good.
In this application, I have an object that is used by virtually all of the UIViewControllers (e.g: provides web service calls). Let's call it MyServices.
In the single XIB solution, I can drag an object onto the Objects list, set the type to be 'MyServices'. I can declare in each ViewController an IBOutlet of type MyServices*, and wire the two together. This works nicely.
However, if I move my view out to a separate XIB, any controllers further down the stack that need access to the MyServices object are out of luck, because the object no longer exists within that XIB to perform wiring with.
What I'd expected to be able to do is to declare an 'external object', and wire to that instead. But I can't see how I 'pass' the MyServices Object in the 'parent' XIB as the 'external' object in the child XIB.
Is this just not supported in IB? What is the best alternative?
I could not specify the XIB name in the controller, and perhaps programatically create it at runtime (presumably with some kind of loadFromNib code declaring a dictionary to provide the external object). This does mean that the controller that does this has to be aware of MyServices, even if it doesn't use it directly.
Alternatively, I could have a 'dataProvider' in each UIViewController, so instead of setting the MyServices directly as an IBOutlet, it could do do [dataProvider getServices]. Again, will have to be wired to something that can do that - which limits where XIBs can be broken up. And it feels a bit needlessly verbose..
What's the best practice here?
It looks like with using External Object, you take the object instantiation back into your own hands and you also have to instantiate the NIBs manually. At least that's what I gathered from the answer to How to use a common target object to handle actions/outlets of multiple views?
Can I use Interface Builder to inject dependencies across multiple nibs? asks very similar question to yours, also without a real solution.
In How do I set up a proxy object in the main application NIB? the author also gives up on the idea of using Interface Builder as a dependency injection tool.
So I would guess that we, the Java immigrants, are banging our heads against invisible walls here. The metaphors we use to shape the code in our heads (and the code qualities we've come to value and associate with quality), do not apply to Objective-C, as is. That might be because we are not familiar with Obj-C idioms. Or it might be, that we are dealing with different evolutionary stages of language and community development (for example see the staggering immaturity of TDD practice in Obj-C). I, personally, have not seen much best practices described in Obj-C world in the 9 months that I am seriously dealing with it.
Related
For quite a while I've been looking at objective c examples, watching the Stanford lectures, and playing around with some code to get a hang of creating an iOS app.
However there are a few things that I can't find a good answer on:
How do I properly separate my layers? I understand the MVC structure, and I saw some examples of creating Categories for models to implement business logic. Is that the proper way, by enriching models or should I create dedicated classes (e.g. to authenticate users, extract models from json, group orders)?
How smart should views be? Can I make a view that displays a Contact (by assigning the contact property) or should I create separate properties for all of the Contact fields or should the view request it's information via a delegate call?
I'm using a Storyboard in my application. On my screen I want to
have a navigation bar, and let's say a view that displays orders. On
other screens I want to reuse the order-view.
How can I re-use the order-view's ViewController and View in other ViewControllers?
If I have 4 screens with the same look-and-feel, do I have to simply copy them in the Storyboard? This seems like a pain to main, what if I want to change my background? Or add a button to all of the views? When I create a setup-wizard I don't want to define the look-and-feel for every screen separately.
Coming from a C# background I probably have to get into the objective-c mindset :)
Any help on this would be great.
1) ObjC-Categories will easily distort your understanding of the main problem you're facing. ObjC-Categories are completely unnecessary. You could always approach these extensions by subclassing, object composition, additional methods in the actual model, or some customization in the controller or view. So if you need to format data (e.g. which is present in the model) for display in a view -- that task would often land in the controller. As far as the examples you provide: You may opt for models in simple cases -- as well, any of the examples could merit dedicated class, if complex enough or if it would keep you from redundant implementation. Note that these may be accessory classes, which simply produce a model, or they may be composites of multiple concrete of abstract classes. Not everything needs to land squarely in the definition of M-or-V-or-C. You're free to use many design patterns with ObjC. Think of MVC as the patterns Cocoa typically uses -- you will need to know them, and you will need to know how to subclass and extend these types, but these patterns lose dominance as implementations move away from Cocoa's libraries (e.g. as complexity increases).
2) They can be smart. However, under MVC, you want to focus its implementation on the view/presentation aspect. A view which represents a collection of information could in fact perform some tasks which are typically reserved for the controller -- however, you would generally cede that the implementation were a dedicated MONContactView in doing so. If you go that route, you would generally do so for easy reusability or to achieve a simple interface. Displaying information about a Contact could be very complex - In simple scenarios, these tasks are often handled by the controller. Specifically, a MONAwesomeContactView is likely less complex (e.g. in SLOC) than MONAwesomeContactViewController (unless you have some very special drawing or layout to perform). It would be more common to set the controller's contact, and let the controller push the contact data to the views' fields. Again, in the case of a very specialized subclass -- a view could very well hold its own controllers in some cases.
3a) There's nothing wrong with creating multiple instances of a class.
3b) No need to copy. When duplication is smelled, I push the implementation to actual code -- the programs can apply the look and feel you desire, or add or manipulate the subviews as you desire. Of course, they will not be present in Xcode's NIB editor. There are of course alternate approaches, but this replication often makes me move the implementation to compiled code. Achieving a good balance of both is not so difficult (personally, I do most of my views programmatically, rather than using NIBs).
This is a pretty abstract question and it's not clear what oh mean by 'layers'. Yes, you should create your own classes where appropriate, but categories also give you the option of adding functionality to existing classes. If you can be more specific with the question it'll be easier to provide a better answer.
It's a judgement call. If you want to create a view class that knows how to display an instance of your Contact type, that's fine in my book. If that view knows where Contacts are stored in the app, though, that's not so good.
Remember that the things in a storyboard are objects, not classes. You don't want to try to re-use a view from one scene in another scene -- that'd mean sharing a view between scenes, which really won't work. If you want to use the same order-view in several places, that'd be a good candidate for creating a class. On the other hand, you can set up your storyboard so that several different scenes all transition to the same scene. If you want different parts of your app to modally display a scene that displays an order, for example, you can do that.
I've created my first iPhone app that presents audio tracks of a similar genre in a tableview. The user can play audio tracks using ipod-like controls which streams mp3.
All of my code is in two main classes: RootViewController and CustomCell.
My RootViewControllerClass is massive. I'm assuming it is poor design to stuff almost all of my code in one class?
Initially, I thought it made sense because I only have one View Controller. To practice better coding conventions, I'd like to split up my RootViewController class into smaller, specific classes (assuming this is the correct practice?).
Here are the components of RootViewController that I plan to separate out into individual classes:
DataSource - pulls data from server; modifies and organizes the data for the tableView
TopChartsView - includes buttons in a view to modify the audio tracks(dataSource) by top rated weekly/monthly/all-time
GenreChange - includes buttons in a view to filter the dataSource by genre
AudioPlayerControls - includes buttons in a view that are similar to iPod controls
Am I organizing my classes correctly? It seems to make sense that I organize my classes by function. However, I'm having difficulty grasping how classes should interact with each other in an ideal design.
Do I use protocols and delegation to link my classes together?
Designing iOS apps is mostly about the MVC design pattern, which means that you seperate your model, view and controller. In your case I would put the DataSource logic in a seperate file or files (it's your model). This also makes it easier to reuse the same logic in another view controller in a later point. Maybe you can also subclass your UITableView if lots of code resides there.
Protocols and delegates are a great way to connect your classes and they are very frequently used in a good design. Since you don't have many viewcontrollers in your application (as far as I see), there are not very much opportunities to use them, please correct me if I'm wrong ;)
It's more about object-oriented-programming than especially about iOS and I think, you should get familiar with some concepts of OO-Design (if you really interested), but from my point of view you don't have to. To answer your questions first:
I'm assuming it is poor design to stuff almost all of my code in one class?
Some say so...
Am I organizing my classes correctly?
Hard to tell, by the information you gave.
Do I use protocols and delegation to link my classes together?
Not necessarily.
But: If your code works fine, you are the only one, who works on it, you don't plan to re-use your code as a library or by taking full classes from it (i.e. if you only plan to copy & paste), there is no need to refactoring everything just for the sake of doing it.
Even though: If you want to move forward or if you're planning to write libraries or something, it would be a good idea to learn about OO (sometimes it's even entertaining). Since you're working with objective-c this one from apple's docs could be a good start to learn.
And: If you read a bit about OO-programming and (more important) take the time and to read code of others, you'll know how and when it is useful to organize your own code.
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.
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.
I had a bunch of objects which were responsible for their own construction (get properties from network message, then build). By construction I mean setting frame sizes, colours, that sort of thing, not literal object construction.
The code got really bloated and messy when I started adding conditions to control the building algorithm, so I decided to separate the algorithm to into a "Builder" class, which essentially gets the properties of the object, works out what needs to be done and then applies the changes to the object.
The advantage to having the builder algorithm separate is that I can wrap/decorate it, or override it completely. The object itself doesn't need to worry about how it is built, it just creates a builder and 'decorates' the builder with extra the functionality that it needs to get the job done.
I am quite happy with this approach except for one thing... Because my Builder does not inherit from the object itself (object is large and I want run-time customisation), I have to expose a lot of internal properties of the object.
It's like employing a builder to rebuild your house. He isn't a house himself but he needs access to the internal details, he can't do anything by looking through the windows. I don't want to open my house up to everyone, just the builder.
I know objects are supposed to look after themselves, and in an ideal world my object (house) would build itself, but I am refactoring the build portion of this object only, and I need a way to apply building algorithms dynamically, and I hate opening up my objects with getters and setters just for the sake of the Builder.
I should mention I'm working in Obj-C++ so lack friend classes or internal classes. If the explanation was too abstract I'd be happy to clarify with something a little more concrete. Mostly just looking for ideas or advice about what to do in this kind of situation.
Cheers folks,
Sam
EDIT: is it a good approach to declare a
interface House(StuffTheBuilderNeedsAccessTo)
category inside Builder.h ? That way I suppose I could declare the properties the builder needs and put synthesizers inside House.mm. Nobody would have access to the properties unless they included the Builder header....
That's all I can think of!
I would suggest using Factory pattern to build the object.
You can search for "Factory" on SO and you'll a get a no. of questions related to it.
Also see the Builder pattern.
You might want to consider using a delegate. Add a delegate method (and a protocol for the supported methods) to your class. The objects of the Builder class can be used as delegates.
The delegate can implement methods like calculateFrameSize (which returns a frame size) etc. The returned value of the delegate can be stored as an ivar. This way the implementation details of your class remain hidden. You are just outsourcing part the logic.
There is in fact a design pattern called, suitable enough, Builder which does tries to solve the problem with creating different configurations for a certain class. Check that out. Maybe it can give you some ideas?
But the underlying problem is still there; the builder needs to have access to the properties of the object it is building.
I don't know Obj-C++, so I don't know if this is possible, but this sounds like a problem for Categories. Expose only the necessary methods to your house in the declaration of the house itself, create a category that contains all the private methods you want to keep hidden.
What about the other way around, using multiple inheritance, so your class is also a Builder? That would mean that the bulk of the algorithms could be in the base class, and be extended to fit the neads of you specific House. It is not very beautiful, but it should let you abstract most of the functionality.