When working on an iPhone project, it can get really messy and many files are created (libraries, view controllers, interfaces...) What's the best way to organize your project files? What group structure do you use? Should I follow the MVC paradigm into groups?
Thanks!
Whatever makes the structure of your application most obvious is the short but ultimately unhelpful answer. I'm not sure that there's a single, correct answer.
As a one data point, here's roughly how I've structured my most complex application:
Application-wide data (model) has its own group
Utility classes/functions get their own group (sometimes nested where they require multiple classes of their own)
I have a UI group for simple views. These classes often also contain the controller
I have a bunch of other groups for series of connected views. For example, I part of my app displays tags and there are two or three views related to this. I group the views, the controllers and, sometimes, the data together
The grouping does not mirror the class structure. My general rule is that I want to have files I'll want to modify at the same time close together.
We normally have a group for view controllers and custom list cells.
In our current project, we also have a group for XMLParsers (we have quite a few of those, thread-born instances to parse incoming messages from the server).
The MVC paradigm is basically moot here - of course, it is one you should follow - but I see XCode's groups as much more than just pandering to MVC in terms of filesystem layout.
Related
I'm working upon a small-scale enterprise database application. It works with such business objects as Vendors, Device types, Devices, Suppliers, Invoices, Departments, Employees etc., so I need to let users view and edit data from all these tables.
My first approach was to create a pair of forms for each type of business object:
a table to view and select an object
an editing form for this type of object
But now I find it hard to maintain all these forms, because e.g. if I want to change the look of all view forms, of course I have to edit each one of them.
So I want to replace all my view forms with a single one "template" form and to call it with some kind of parameters. The problem is, I don't know the right approach to perform it. Maybe there could be some example in some book or somewhere else?
I think the best way is by using Visual Form Inheritance .
Actually we use this kind of programming a lot, it keeps maintenance pretty simple. Stick your base functionality in the parent form, and specific behaviour in the child forms.
I have built an app that does some computation and communication with varying internet resources. I branded my application with its tab bar navigation bar for three corporate clients, the only change was the difference in pictures and coloring. So I created three targets and handled target membership appropriately.
So far, so good. But what if I wanted to customize the whole layout of views or even the navigation of the app for a client? For example, the next client could ask for a navigation controller based interaction instead of a navigation based on a tab bar. Or to add one more label in one view. Or to use a pie chart instead of a bar graph to visualize a certain set of data.
It leads to very ugly code if you put all different targets in one project with all these if/else if/else if/else if/... blocks of code. What if I had 100 clients?
Now here is the question: In my imagination an ideal concept would be if I could make an Xcode project named "Base" that does all the domain specific computations, communications and so on (of course) and has a basic, non-branded UI. This way the code can be easily maintained for all clients in one central repository. Then, for every client, I create a whole new Xcode project, import or reference the "Base" project and when I click on Build without any customization, it already builds me the non-branded, but fully functional app. If a client requests to have a modified layout, I subclass the corresponding view. When hitting the Build button again, it should bring up the "Base" app but the certain subclassed view replaced the standard layout.
Can this idea of a "Base" app with "overriding" the visuals be done elegantly in Xcode?
I did exactly that for a client last year. I had one framework app that used a header shared with the app project. It's almost like a protocol in that the app "commits" to supplying some strings, views, and images. You can start with a fairly simple app project, and as you find you need more variation move code out of the framework into the app. The header was the implementation of a class-methods only class that vended the app specific data.
In my case we had 7 or so apps (all in the store now) yet not a single bit of knowledge in the framework of exactly what app was using it.
As an example in app did launch, the framework might query if a sound should be played and if so ask for that resource - same with images and other variations.
One way to do it would be to create a static library. You could stuff all the commonly used stuff into a static library and then reference it in the other projects.
Maybe most of the stuff lives in the static library and you just have one or two files in your app project. This would work well if there a very minimal amount of changes between applications (ie: just style changes like you mention in your post).
Another technique would be to use generated and template code. The idea would be that you have your boiler-plate code and you run a script that would set up your project and resources based on provided colors, logos, strings, etc.
In the end, you'll likely want to use a combination of the two approaches above based on your requirements.
As I have a complex domain model (DDD) where I need to create a few hundred forms in the user interface, I'm looking for a generator, preferably embedding the apple layout rules, and data binding. This is crucial to get a uniform application appearance.
I would prefer the generating to be of run-time instances (introspection), not static source code.
I do not want to build from a data model, as that doesn't have enough information to create something useable. I have information on grouping, validation, roles and rights, navigation, filtering, actions, workflow so I should be able to do much better layouts.
Even better would be the ability to also generate forms for the iPhone/iPad, using the default navigation.
[Results]
Sensible TableViews looks like the right kind of solution for iPhone. The descriptions are not yet sophisticated enough but provide a good starting point.
Interface Builder will do this for Core Data models if you option-drag parts of (or all of) your data model from the Data Modeler into a window or view in Interface Builder.
When you drop the managed object(s) you dragged, you're given an option to create a Single Item View, a Master/Detail View (with search and detail fields and add/remove buttons), or a Collection View (with box + search field).
I don't know of any third-party solutions to do this from "just any model." It'd be a great tool, but would likely require using an object model to define the entities (like Core Data's Managed Object Model).
Sensible Tableviews Might be able to help you. I haven't used them myself but it looks solid. It also supports generating forms from core data entities.
Maybe Echasoft Reports would work for your problem? (Plugin for Interface Builder that gives you easier reporting capabilities). I saw this demoed at NSConference, and it looks pretty awesome. Commercial, yes, but for 100+ forms it might be worth the money...
I wonder in which cases it would be good to make an NSManagedObjectModel completely programmatically, with NSEntityDescription instances and all this stuff.
I'm that kind of person who prefers to code programmatically, rejecting Interface Builder. But when it comes to Core Data, I have a hard time figuring out why I should kill my time NOT using the nice Xcode Data Modeler tool.
And since data models are stuck to a given state (except when you want to do some ugly migration operations where thinks probably go wrong and users get mad, really mad), I see no big sense in a data model that's made programmatically for the purpose of changing it all the time.
Did I miss something?
I dont think you missed anything. The only reason I can see to create your model programatically would be if the objects you are modeling are themselves dynamic: you could for instance build a coredata entity (or graph of entities) in response to a web service which changed over time, or was selected by the user. However, I think if you had that or a similar use case, you wouldn't need to write this question (and you'd probably solve it a different way anyway)
So, if your application is dealing with resources that are dynamic, as #Andiih mentioned, then this programatic is the only way to do it. I don't know what my core data entities are until runtime, I don't know what the attributes are, or what the data looks like. So, I ask the server to give me the kinds of resources I should support and what their attributes look like. I build the model, the entities, the properties, the relationships - at runtime. I still want to use Core Data because I'm dealing with a lot of data and I need the benefit of efficient memory management with NSFetchedResultsController, etc. I can only do this programmatically.
The trouble is how to handle migration to try and preserve as much of the persistent store as possible, to reduce the size of the networked data payload after the model changes. Right now I blast the whole model and the persistent store if there's a conflict. I haven't yet figured out a way to create an .xcdatamodel from a programmatically generated model, thus I can't yet create a version mapping to do the migration.
Everything is a trade off. Basically, I think IB and the visual Core Data modeler are the right tool if you're building a simple application. You'll need to make the determination when your application becomes large/complex enough that you prefer to have direct control over all aspects of the code.
Regarding Interface Builder, if you have an application with a variety of complex interactions between view controllers, and multiple custom controls, I find code more appropriate.
For Core Data, the question is pretty much the same. Does your project have a defined scope? Can you foresee everything in that scope being done within the visual modeler? If so, it's probably fine. For other projects, where you may be asked to add features on an ongoing basis, perhaps it's better to spend a little more time writing it out so you have more flexibility later.
One other thing to consider, that doesn't get mentioned much, is it's MUCH harder to ask for help with IB or any hybrid visual design/code system. When something does go wrong, or you need help, it's way easier to post your code, than try to explain what's going on in a visual modeler.
In general, there's no reason to build the managed object model in code. There's nothing you can do in code that can't be done in the model editor. There are some fancy tricks you can do in code, however, to work with multiple models. For example, you can merge two models, establishing cross-model relationships between entities in those models at load time (see Cross-model relationships in NSManagedObjectModel from merged models?).
Regarding whether it's a good idea to code or use the graphical editor, I think the balance tips heavily towards the graphical editor in this case. Being able to verify the model by visual inspection instead of (rather convoluted) code is a win. The model can still be verified by unit test, if you desire.
I have one use case that might be valid, what if you load some data from the internet whether it is XML from an RSS Feed or WSDL response, then flatten those responses into a tabular from generating an in memory data table and finally mash it all up into a single coherent data model, then you can create the entities for those in memory data tables and create master/detail relationships. That's one case I think Core Data data model generated programmatically could become handy and a powerful feature.
I've changed models programmatically in unit tests. For example, I wrote a class that is designed to work with Core Data models that have a particular protocol attached. Instead of testing against a random implementation, I mutated the default model by adding one just in the unit tests programmatically, and tested against that test-only model.
I am writing a Catalyst web application that presents some data that does not change in between requests. I want to load this data when the application starts and stick them somewhere so that the relevant controllers can use them. Where should I load this data and where should I store it? At first I tried to load it in the main App.pm file and put them into the application config. This works, but it’s ugly, since the App.pm file gets littered by a lot of loading subs that don’t really belong together:
__PACKAGE__->config(this => load_this());
__PACKAGE__->config(that => load_that());
# et cetera
Then I figured I could load some of the data in the controller that uses them and store them in the controller’s config hash. This is not perfect either, because some of the data is needed in more than one controller.
I also thought I could localize the data to the controller instead of sharing them. This feels nice, because I would have all the code that works with the data more or less on one place. The problem is that the controller would also have to render parts of the resulting page for other controllers – for example if the title page controller wanted to display a list of recent news, it would have to ask the news controller to render the list. This does not seem to be the preferred way of doing things in Catalyst.
How would you solve this?
(The nature of the data: This is a website of a music festival. There is a line-up, a list of sponsors and other simple data pulled from YAML files, because database would be overkill and hard to edit.)
Fundamentally, the data should belong to the Model, which is to say your YAML files should be represented by modules in your application's Model. That's one reason you separate the model from the controllers in the first place: All of your controllers can talk to the same models, without having to replicate their information within themselves.
There's no reason you can't cache the data persistently in these modules, using plain perl data structures or whatever caching technique you like.