This is Cocoa Touch (et al), iPhone, XCode only.
After completing my first commercial iPhone app, I'm struggling a bit to find a way to start and expand an app from scratch which gives the most linear development (i.e., the least scrapping, re-write or re-organization of code, classes and resources) as app specs change and I learn more (mostly about what Cocoa Touch and other classes and components are designed to be capable of and the limitation of their customization).
So. File, New Project. Blank window based app? Create the controllers I need, with .xib if necessary, so I can localize them and do changes requested by the customer in IB? And then always subclass each class except those extremely unlikely to be customized? (I mean framework classes such as UIButton, CLLocation etc here.)
The question is a generic 'approach' type question, so I'll be happy to listen to handy dev practices you've found paid off. Do you have any tips for which 're-usable components' you've found have become very useful in subsequent projects?
Clients often describe programs in terms of 'first, this screen appears, and then you can click this button and on the new screen you can select... (and so on)' terms. Are there any good guides to go from there to vital early-stage app construction choices, i.e. 'functions-features-visuals description to open-ended-app-architecture'?
For example, in my app I went from NavBar, to Toolbar with items, to Toolbar with two custom subviews in order to accommodate the functions-features-visuals description. Maybe you have also done such a thing and have some advice to offer?
I'm also looking for open-ended approaches to sharing large ("loaded data") objects, or even simple booleans, between controllers and invoking methods in another controller, specifically starting processes such as animation and loading (example: trigger a load from a URL in the second tab viewcontroller after making sure an animation has been started in the first tab viewcontroller), as these two features apply to the app architecture building approach you advocate.
Any handy pointers appreciated. Thanks guys.
Closing this up as there's no single correct answer and was more suitable for the other forum, had I known it existed when I asked :)
If you want to know the method I ended up with, it's basically this:
Window-based blank app
Navigation Controller controls all, whether I need to or not (hide when not used)
Tab Bar Controller if necessary
Connect everything <-- unhelpful, I know.
Set up and check autorotation, it might get added to some view later.
Add one viewcontroller with xib for each view, you never know when they want an extra button somewhere. It's easier to copy code than make the max ultra superdynamic adjustable tableviewcontroller that does all list-navigation, etc.
Re-use a viewcontroller only when just the content differs in it, such as a detail viewcontroller.
Minimize code in each viewcontroller by writing functions and methods and shove them in a shared .m
Everything that's shared ends up in the App delegate, except subclassed stuff.
Modal viewcontrollers are always dynamically created and never have an xib.
Related
I am planning to learn to develop applications using Story Boards. Can anyone please post some advantages and disadvantages while using StoryBoards?
When to use Storyboard and when to use XIBs
What are the benefits of using Storyboards instead of xib files in iOS programming?
iphone-sdk-development
I think these links are helpful and related to your question. Personally, I believe storyboards are better then nibs because they eliminate the need to code your transitions between views (unless you use custom transition with CA), and they have all the capabilities of nib files too.
Hope this helped.
-----------EDIT-----------
Here are some more links I found:
This one speaks about some of the cons of using storyboards.
UIStoryboard on iOS 5: The Good, The Bad, and the 'This Plain Sucks'
This one is mostly about the benefits.
What are the advantages of iOS 5.0 storyboarding over traditional UI layout?
It's mostly cons. Don't use Storyboards. Here's is a list of their problems, copied from iraycd:
Storyboards fail at runtime, not at compile time: You have a typo in a segue name or connected it wrong in your storyboard? It will blow up at runtime. You use a custom UIViewController subclass that doesn't exist anymore in your storyboard? It will blow up at runtime. If you do such things in code, you will catch them early on, during compile time. Update: My new tool StoryboardLint mostly solves this problem.
Storyboards get confusing fast: As your project grows, your storyboard gets increasingly more difficult to navigate. Also, if multiple view controllers have multiple segues to multiple other view controllers, your storyboard quickly starts to look like a bowl of spaghetti and you'll find yourself zooming in and out and scrolling all over the place to find the view controller you are looking for and to find out what segue points where. Update: This problem can mostly be solved by splitting your Storyboard up into multiple Storyboards, as described in this article by Pilky and this article by Robert Brown.
Storyboards make working in a team harder: Because you usually only have one huge storyboard file for your project, having multiple developers regularly making changes to that one file can be a headache: Changes need to be merged and conflicts resolved. When a conflict occurs, it is hard to tell how to resolve it: Xcode generates the storyboard XML file and it was not really designed with the goal in mind that a human would have to read, let alone edit it.
Storyboards make code reviews hard or nearly impossible: Peer code reviews are a great thing to do on your team. However, when you make changes to a storyboard, it is almost impossible to review these changes with a different developer. All you can pull up is a diff of a huge XML file. Deciphering what really changed and if those changes are correct or if they broke something is really hard.
Storyboards hinder code reuse: In my iOS projects, I usually create a class that contains all the colors and fonts and margins and insets that I use throughout the app to give it a consistent look and feel: It's a one line change if I have to adjust any of those values for the whole app. If you set such values in the storyboard, you duplicate them and will need to find every single occurrence when you want to change them. Chances are high that you miss one, because there's no search and replace in storyboards.
Storyboards make you do everything twice: Are you building a universal app that runs both on iPad and on iPhone? When you use storyboards, you will usually have one storyboard for the iPad version and one for the iPhone version. Keeping both in sync requires you to do every UI or app-workflow change in two places. Yay. Update: In iOS 8 and Xcode 6, you can use a single Storyboard for iPhone and iPad.
Storyboards require constant context switches: I find myself working and navigating much faster in code than in storyboards. When your app uses storyboards, you constantly switch your context: "Oh, I want a tap on this table view cell to load a different view controller. I now have to open up the storyboard, find the right view controller, create a new segue to the other view controller (that I also have to find), give the segue a name, remember that name (I can't use constants or variables in storyboards), switch back to code and hope I don't mistype the name of that segue for my prepareForSegue method. How I wish I could just type those 3 lines of code right here where I am!" No, it's not fun. Switching between code and storyboard (and between keyboard and mouse) gets old fast and slows you down.
Storyboards are hard to refactor: When you refactor your code, you have to make sure it still matches what your storyboard expects. When you move things around in your storyboard, you will only find out at runtime if it still works with your code. It feels to me as if I have to keep two worlds in sync. It feels brittle and discourages change in my humble opinion.
Storyboards are not searchable: A project-wide search in Xcode is not really a project-wide search when you use storyboards. They are not included in the search. So when you remove a custom class from your code or rename it, you will have to manually go through the storyboard or look at its raw XML to make sure it is on par with your code changes. No sir, I don't like it. Update: Storyboards are searchable in Xcode 6.
Storyboards are less flexible: In code, you can basically do anything you want! With storyboards you are limited to a subset of what you can do in code. Especially when you want to do some advanced things with animations and transitions you will find yourself "fighting the storyboard" to get it to work.
Storyboards don't let you change the type of special view controllers: You want to change a UITableViewController into a UICollectionViewController? Or into a plain UIViewController? Not possible in a Storyboard. You have to delete the old view controller and create a new one and re-connect all the segues. It's much easier to do such a change in code.
Storyboards add two extra liabilities to your project: (1) The Storyboard Editor tool that generates the storyboard XML and (2) the runtime component that parses the XML and creates UI and controller objects from it. Both parts can have bugs that you can't fix.
Storyboards don't allow you to add a subview to a UIImageView: Who knows why.
Storyboards don't allow you to enable Auto Layout for individual View(-Controller)s: By checking/unchecking the Auto Layout option in a Storyboard, the change is applied to ALL controllers in the Storyboard. (Thanks to Sava Mazăre for this point!)
Storyboards have a higher risk of breaking backwards compatibility: Xcode sometimes changes the Storyboard file format and doesn't guarantee in any way that you will be able to open Storyboard files that you create today a few years or even months from now. (Thanks to thoughtadvances for this point. See the original comment)
It's McDonald's: To say it in Steve Jobs' words about Microsoft: It's McDonald's (video)!
Thank you for reading this.
These are my first steps in the iPhone Ipad app programming.
In order to learn from scratch (and because I know my app would need dynamic views), I decided not to use Interface Builder.
My question is(regarding the fact that I don't use IB): how would one use Views and Controllers?
I think I understand the MVC concept as it is repeated over and over again in the tutorials I follow, but after the "MVC explanation" part, nothing is made to make it clear "on the field" and closer to the real world (Earth being Xcode here).
Worse, sometimes it seems that some tutorials mix these two concepts up and use one word to say the other.
I read around here a lot of questions (and answers of course) based on the matter but I still don't get it. Sometimes it's too generic, sometimes it's too specific (for me at least).
For what I think I understood, the UIView is the static View when the View Controller is the logic which links the View to the data and those 3 concepts must be separated.
This separation, while a bit clearer with the use of Interface Builder seems to get quite blurry when you code everything as it becomes a virtual soup.
Technically, should I create a specific ".h" and ".m" file for each View AND ALSO for each associated Controller?
If I understand the MVC pattern, it's seems that I should but when I follow tutorials (without IB) it is never the case, view and controllers are created and manipulated within the same implementation files.
Any high level (I'm a noob, don't forget) but still applicable explanation of the use and best practices?
Let's say I want to create a simple app with a green view I can swipe to get to a red view.
I know for sure that I would need at least an:
xxxappDelegate.h
xxxappDelegate.m
xxxView.h
xxxView.m
What else?
1)Where should I put the the second view (along with the first one in "xxxView" or should I create another class h and m file?)?
2) What would the controller(s) do, for that kind of application? In which files would they be created and in which files would they be invoked and how would they "control" the related view?
3) Mainly, regarding to MVC pattern and the fact that there would be no IB, how would you organize that app?
I know it's a lot if you go into the details and code but that's not the point here.
Thank you. This - as simple as it seems - would be of a great help and is not as easily found in tutorials as you might think.
I understand the tutorials I read but they are so particular. As soon as I try to create something on my own which is not a "Hello World" screen, I realize that something is missing, logic wise.
Thank you very much for your help.
Sorry, but I can't get past your first paragraph. If you don't use Interface Builder, you are not going to be a successful iOS programmer. It's that simple. The best advice I've ever read about this is in this Aaron Hillegass interview:
Experienced Cocoa programmers put a lot of the smarts of their application in the NIB file. As a result, their project has a lot less code. Programmers who have spent a few years working in Visual Studio get freaked out. They ask me stuff like, "Can I write Cocoa apps without using Interface Builder? I like to see the code. Maybe I can just explicitly create my windows and the views that go on it?"
It is difficult to explain how the NIB file (and a few other scary ideas) create leverage. It is that leverage that enables one guy in his basement to compete with a team of engineers at Microsoft or Adobe. It is like I showed a chain saw to a early American colonist, and he said, "Can I cut down the tree without starting the engine? I don't like the noise. Maybe I can just bang it against the tree?"
Yes, it's hard to generalize after reading specific tutorials, but you will learn. I thought the learning curve was insurmountable when I first started, but if I can become a programmer that gets paid to write Cocoa software, you can too. Just keep reading and practicing. Don't fight the tools--use them.
Early:
In order to learn from scratch (and because I know my app would need
dynamic views), I decided not to use Interface Builder.
Later:
As soon as I try to create something on my own which is not a "Hello
World" screen, I realize that something is missing, logic wise.
I think what is missing logic wise is that you have accepted your assumption that Interface Builder was a crutch and that to learn "from scratch" you had to avoid using it. You are trying to learn the MVC design pattern but you are not willing to use the tools that have been designed to support it.
In Apple's own documentation they discuss the fact that sometimes there is value in having combined roles—Model Controllers and View Controllers—and that is worth reading, as it may explain some of the code examples you're reviewing. But my primary advice would be: before assuming you know better than the people who built the tools, trying using them the way they recommend. It might be an eye-opener.
Additions later:
OK, so to try and actually answer your questions...
1)Where should I put the the second view (along with the first one in
"xxxView" or should I create another class h and m file?)?
If I am understanding correctly and the two views you are thinking of here are the red and the blue displays to the user, you wouldn't have a second view—what you would do, whether in IB or in code—is to have an element in your view on which you changed a colour property... This would be done programmatically whether you were setting up the parent view in IB or in code.
2) What would the controller(s) do, for that kind of application? In
which files would they be created and in which files would they be
invoked and how would they "control" the related view?
There would be a view controller that would implement the gesture support, and would provide a method for changing the colour of the item in the view between blue and red when that swipe gesture was successfully received. I would have a ViewController.h and and ViewController.m. I think if you were implementing the View entirely in code, it would be implemented in the ViewController.m rather than having a separate View.m. (If you were using IB, you would have a ViewController.h, ViewController.m and ViewController.xib, with the latter providing the basic setup of the view elements and layers.)
You would create a ViewController instance in your AppDelegate.
3) Mainly, regarding to MVC pattern and the fact that there would be
no IB, how would you organize that app?
As above.
If you really insist on going without IB (and I agree 100% with SSteve) then in addition to the files you list you will also want to use a UIViewController. Now, it is important to know that you only need to create header and implementation files when you are adding or changing default behavior.
In you case, the view can probably just be a generic UIView, so you wouldn't need the files. What you would do is subclass UIViewController, and put the swipe logic there. In the swipe logic code you would probably just change the background color of the view.
You would instantiate the view controller in the delegate (in this case anyway) and create the view in the view controller's loadView method. That is required since you won't be using IB.
Personally though, I think that IB does a great job of encouraging proper MVC patterns, and if you are just starting then you should go with IB.
In practice you mostly do not make classes for views, unless they need to do custom drawing or display.
For lightweight configuration of views, that is often done in the viewController's viewDidLoad (or I guess in your case loadView) method.
Yes it's a good idea to keep model and view separated, but that's also balanced with the equally good idea to reduce the amount of code that exists. The less code that is written, the fewer bugs you will have.
Since you are just starting out at this point I would absolutely start by using ARC, and using IB - even though I'm sure you're tired of hearing that from everyone, I'll give you an alternate take. Less code means fewer bugs. And the fact that so many experienced developers are telling you to use it should be a giant clue about what a productive path forward is. I mean, are you doing this to build applications or learn every corner of the UIView class?
To speak to your code example, you do not need the UIView custom class. Just create use a UIViewController's main view as a container view, place a UIView inside with the background set to red. On swipe (using a gesture recognizer attached to the container view) call the UIVew method to swap in a new green-background UIView for the existing red view, you can even define the transition style.
Or create a scroll view in the container view, set up the red and green view inside the scroll view, set the content size and enable paging on the scrollview.
Or create a custom UIView class as you had, listen for touch events and slowly adjust two subview positions to follow the drag action.
Or use an OpenGL backed view, and based on the gesture recognizer pan the scene you are observing with two triangles for a green rectangle and two triangles for a red rectangle.
I'm the programmatic guy, and I simply don't want to use Interface Builder. I feel out of control, and besides that my GUI is about 90% custom all the time.
Literally every book does everything in Interface Builder and claims that this is the one and only great way to have real MVC going on.
Example: One of those books mentions that programmatically creating an UINavigationController with an Root View Controller and everything else that belongs in there is a big mess and won't be reusable when porting to the iPad, while doing this in XIB is a clever decision. Then the port to iPad using UISplitViewController will be a simple task.
So when I make iPhone apps and want to port those to the iPad too, what strategies work to reuse as much code as possible? I'd like to learn more about how to separate my code and achieve a better overall architectural design without using Interface Builder.
For those who want to tell me I must go with IB: Again, I do a lot of custom UI where IB is often just in the way. And not to mention all the animations. I really have my reasons. For people who make default UI IB is really fine - but please, I don't want to start a fight for IB vs programmatical UI or default UI vs custom UI! It's all about how to achieve great reusable code when doing everything programmatically, and both have their pros and cons.
Although you did not ask for it, I feel compelled to make the case for why people in general (perhaps not you) should consider IB, and then address the issue of custom components.
I use a lot of animations and custom components. And I love to use IB...
The key is to use IB for its strengths, and then decide what to do with the rest from there. What then are the strongest points of IB? Connections, placement, auto-resizing and customizations.
Connections are linking aspects of views and controllers together. It's faster in IB to drag out a few connections to delegates or references, than it is to write the code that forms the connections. And, it's a quick place to review all links to the UI you are building.
Placement IB also does well at. There's a fair amount of code involved in setting up any GGRect correctly. Not only is it easier to enter and review coordinate and size details in IB, but the tool automatically sizes a lot of elements properly for the container and the control, and offers many guides to help things line up properly - that kind of thing can take a lot of repeated testing to get right.
Related is auto-resizing. Although I don't feel that many screens can actually have auto-reiszing rules that rotate the screen and come out the other side looking just right (I almost always do rotated views as a separate XIB file), there still are a lot of shifts that can occur in the course of running your application that make it really useful to have these defined just right. The best example of this is the enlarged status bar while you are on a call.
Lastly comes customization. This again can be a lot of tedious code to write; try setting up all of the properties on a UILabel manually and it'll have you yearning for quick changes in IB.
With all that said, what is a good approach to custom components? I like to use UIViews in IB screens, with the class type set to a custom UIView that then fills out the display at runtime. But at least IB helps me get composition, placement and auto-resizing just right with minimum fuss, and also wire aspects of that custom view into a controller.
The one thing that would really lend IB to use with custom components is if it would simply let me set values for any simple properties the custom view had - then I could adjust parameters like a corner radius or whatever else I had going on.
I urge you to think on IB a little more, as it's a huge productivity boost when used correctly. There should be nothing about IB that gets in the way, it's there to boost your output.
One book I really liked was Erica Sadun's iPhone Cookbook 1st edition. It did everything programmatically.
Unfortunately the second edition is bloated.
If you reuse lots of your custom UI objects, it would make sense to write a code which
reads a plist (or a more general XML file) specifying how the custom UI objects should be placed / animated
and then creates your custom UI objects accordingly.
It's like writing a mini-xib file format tailored to your UI objects; you can also feel that you're in control of everything, as an added bonus.
There are tons of resources concerning coding on the iPhone. Most of them concern "how do I do X", e.g. "setup a navigation controller", or "download text from a URL". All good and fine.
What I'm more interested in now are the questions that follow the simpler stuff - how to best structure your complex UI, or your app, or the common problems that arise. To illustrate: a book like "Beginning iPhone 3 Development" tells you how to set up a multi viewcontroller app with an top 'switcher' viewcontroller that switches between views owned by other view controllers. Fine, but you're only told how to do that, and nothing about the problems that can follow: for example, if I use their paradigm to switch to a UINavigationViewController, the Navigation bar ends up too low on the screen, because UINavigationViewController expects to be the topmost UIViewController (apparently). Also, delegate methods (e.g. relating to orientation changes) go to the top switcher view controller, not the actual controller responsible for the current view. I have fixes for these things but they feel like hacks which makes me unhappy and makes me feel like I'm missing something.
One productive thing might be to look at some open source iPhone projects (see this question). But aside from that?
Update
To clarify: I suppose what I'm asking about could be summarised as "Recipes and Gotchas for iPhone development". The sort of things that are of interest to developers, but aren't covered in any of the iPhone books etc. that I've seen, such as:
I'm writing an iPad app and want a UISplitViewController presented to the user only some of the time, which Apple seem to be saying I can't do. Is it possible? How?
Apple don't give me a way to stylise my app in a convenient, across the board way (e.g. font tweaks, or colours). How can I approach styling my app?
Memory management isn't made any easier by some of the inconsistencies in UIViewController method names (e.g. viewDidUnload is not the opposite of viewDidLoad, despite the name). Is there a consistent easy way to tidy that up and make view controller memory management less error prone?
How can I consistently and easily test my view controllers for behaving correctly when a memory warning comes in? It's easy to simulate a memory warning in the Simulator, but if the UI I want to test is showing (and is a 'leaf level' view controller), it won't get its view unloaded because it is currently visible.
N.B. I'm not actually asking the above questions here -- I think I have decent answers to them! -- just giving examples of 'good' questions that illustrate this stackoverflow question.
The WWDC talks available on iTunes U (at http://developer.apple.com/videos/wwdc/2010/) have some great information about structuring, especially in the Application Frameworks section.
If you're talking about code, use the Model/View/Controller pattern like in most Web applications:
The model code defines the objects that your program represents. A time tracker app, for example, might have model objects like Task, TimeSlice, and User (especially in a network setting).
The view code is provided for "free" with the iOS SDK, unless you need specialised view code. These are UIImageView, UIButton, etc.
The controller code bridges the 'gap' between the model and view. The controller will change the views to reflect the model selected by the user and facilitate the selection of model objects.
This is the base design pattern for any iPhone app, and it's the one that most will use.
If, on the other hand, you refer to what we in my company call UX (user experience) design, however, you can't beat the Apple HIG guidelines in the Apple iOS SDK documentation set, available online or in Xcode from the Help menu.
The other thing I recommend quite highly is to play around with some test/dummy code. Nothing can top experience. Experimenting with the iOS SDK and getting your hands dirty will allow you to truly learn the best ways to design apps.
Edit:
Also, delegate methods (e.g. relating to orientation changes) go to the top switcher view controller, not the actual controller responsible for the current view.
Can you clarify? In all of the apps I've written, the currently shown view controller receives the orientation change methods. Note that there are two methods. shouldAutorotateToInterfaceOrientation: allows you to decide if the view should rotate, and didRotateFromInterfaceOrientation: allows you to re-layout the view if necessary.
Please go through this link. In this they have explained clearly about design patterns.
http://www.raywenderlich.com/46988/ios-design-patterns
You might want to consider watching videos like the CS193p course from Stanford on iTunes U. They go through the most important parts of iOS development in deep, and give some source code.
As far as I can tell, there isn't a book or resource which deals with the sort of advanced gotchas and recipes that I was looking for. Loads of useful resources exist, but just not addressing the stuff I'm thinking about.
I have been programming with the iPhone SDK for some time now.
I have not been using Interface Builder. This scares me a little. I know that in effect I may be 'fighting the framework' but I do not see it that way.
I find it very easy to just instantiate my UITabBarController in my app delegate, instantiate a UINavigationController, then push and pop view controllers as I go.
Naturally I do not have an extensive knowledge of how to architect an app with XIB files because I have never done so, however I do know the general gist of it, having built some Mac apps in Cocoa using NIBs. So I am not completely ignorant.
My question is whether there is an increase in development time when choosing to lay out UITableViewControllers and UIViewControllers using XIBs rather than programmatically instantiating them and then setting up the ivars.
As I see it, both methods still require you to subclass the view controller for customization which will probably occur for the majority of your views. As well, there are still manual classes required for delegates, and the process of connecting outlets from within the XIB seems comparable to me from setting an ivar.
Or am I missing some other major point?
Thanks!
Code takes much longer to write to configure UIs than IB does.
Plus, you can hand off design to designers and let them tweak the UI.
In the end they both accomplish the same thing. You should use either one depending on the circumstances. Most of the time writing the code to create and position views, and especially maintaining it down the road, will take much longer than using IB. In a simple app for the iPhone though, this might not be true and you'd be just as well off creating everything in code. Basically, you should know how to do both, and pick the path that involves the clearest code and quickest development.
IB shines when you're using it to actually lay out views; even two or three views can be a real hassle to lay out and configure in code. I do tend to use it for tab bar and navigation controllers, and sometimes for subcontrollers (usually only if I think the user is very likely to use it), but that's more just because I'm already there so I find it convenient.
With this new version 3 OS they're announcing next week, I'm hoping Interface Builder gains some of the flexibility it has in Cocoa, where you can add palettes for your own classes and even build up complex non-view data structures (by using custom palettes). We'll have to see, though.
Don't worry too much, IMO Interface Builder is a little over-rated too.
It's definitely useful for getting things up and running quickly, or if you have an app with a lot of screens that are tedious to setup, but you're not missing much.
For the uses you outline just doing things in code is fine, and possibly even a little easier to understand.
Laying out views, or custom cells though... then you get into a ton of font/color/position setting that quickly explodes into a lot of code, hard to maintain and tweak. Much easier to adjust what you want in IB in those cases.