How to handle alternate views within a scene - ios

I am making modifications to an existing iPad application, and I'm having a hard time dealing with really messy scenes in storyboards. Almost every scene in the app consists of multiple views laid one on top of the other, each containing a different set of controls. Depending on the situation or data coming into the scene, some views are hidden, and others are shown.
It takes a LOT of time to decipher such scenes, and even when I figure out what changes I need to make it's terribly difficult to make those changes, and easy to screw up other things.
As an example, the following scene has 3 views that could appear (Start View, End View, Drawer History), depending on the situation, and they are all laid out on top of each other...
This seems like a terrible way to handle this, and I'm having a hard time believing this is standard practice, but I'm not finding much in the way of alternatives. I find very little in the way of questions where people are dealing with this problem, and the tutorials on how to design user interfaces seem to be too simplistic and never deal with scenes that are complex enough to run into this problem.
Unfortunately, this app is my primary introduction to doing user interfaces in iOS, so it has apparently become the default solution in my head. I've tried many tutorials, but they take a long time and don't seem to ever get to a situation that needs such a technique to solve it.
I would hope there would be a solution where each alternate view in the scene could be laid out on its own, and be made to appear within a placeholder view as needed.
What would be a more enlightened / more manageable approach?

That's what you'll get with Storyboards/Nibs/Xibs. I'm not saying coding your UI is better than using interface builder, but it is, at least for me. I believe, as far as I know, there's no other way to handle such multiple layers of views in one view controller in interface builder. I actually used to use interface builder before and that's how I add multiple layers of controls too. Sometimes some views are initially made hidden, but that would probably confused me or the other developer looking at the layout. Sometimes I extend the viewcontroller height to know that there's a view container with a constraint a thousand constant or a negative thousand constant to make it hidden and ready to animate when it's needed to be shown.
There are ways to somehow improve and organize your Storyboards. You can separate modules into different storyboard files; you can use references; avoid segues; and whatnot. It's still an individual or team's preferences.
Some ref:
https://cocoacasts.com/organizing-storyboards-with-storyboard-references
https://medium.com/#stasost/xcode-a-better-way-to-deal-with-storyboards-8b6a8b504c06
EDIT:
I'm thinking you could also layout separate view containers into a separate xibs, and then call them or layout them when needed. But that would add more files to your project.

Related

Storyboards vs. Xibs - iOS9

I know this is a question that has been asked quite a bit, but it's iOS 9 and I still don't have a clear idea about what to do. For starters, here is what I seem to be surmising from all the data available:
Storyboards let you create segues. [I've never been a big fan of this answer because segues are often the least harrowing part of creating the UI layout for me.]
Xibs can let you create multiple top-level views. (Storyboards vs. the old XIB way) [I don't think I've ever used this much, though it seems rather helpful.]
Storyboards - Creating UITableViewCells is easier. [In my opinion, it's cleaner to create xibs for the cells and just invoke them in cellForRowAtIndexPath].
Storyboards can turn into one giant ultramassive file that is hard to edit. [I've seen this happen in practice and it is a big drawback, but at the same time...]
Storyboards let you arrange all your Views in one place with the layout shown as well. [This seems to be a big help for me. But then, over the years I've found doing this in code much easier. Which brings me to my final question.]
What is the performance aspect of both of these two things. My app is essentially the following :
A top level hierarchy of interconnected view controllers, not more than 5.
A large number of disparate, independent view controllers that range from Scroll Views to TableViews to static Imageviews.
Autolayout, size classes, the works.
For each of these view controllers, what is the performance of creating a storyboard for each of them vs. creating a xib for each of them. More importantly, what would be a good way to lay out an app like the one I've mentioned.
You definitely want to use storyboards for laying out view controllers - simply because you get access to topLayoutGuide and bottomLayoutGuide which the XIB editor won't give you.
For other views, it's a matter of preference. I tend to use XIBs for table view cells simply because I tend to reuse them on different screens and prefer to have them in their own files.
I would actually advise against manually writing view code where possible simply because it's much harder to read and work out how views are laid out, especially for developers who didn't write the code originally! For simple, dynamically sized things this can be fine, but if you're trying to lay out view controllers with different constraints depending on the size class it's going to end up a bit of a mess.
Yes, it's a pain to deal with merge conflicts of these files, but with iOS 9 you can split up view controllers into different storyboards a lot more easily using view controller references. Personally I find the inconvenience of merging storyboards/XIBs the lesser evil of having to write everything in code.
It sounds like a Storyboard is the right thing for your current project. However, my experience has been that Xibs and Storyboards are problematic in the real world, for these reasons:
extremely idiosyncratic from developer to developer, so it is tricky to build good storyboards as a team
black boxes, so they require a tremendous amount of knowledge to master (unbelievable amount of hidden behavior). Only the most superficial semantics are covered in the documentation.
internationalization is made much harder by being split up, especially if you have internationalized messages not contained in the Storyboard/Xib.
backwards compatibility breaks annually / deprecation guaranteed over time. This is especially difficult if you try to maintain compatibility with older devices.
As soon as more than two devs started touching our code we rewrote everything to avoid Storyboards and Xibs altogether, and we became much more productive.
If you have to deal with any of those real world situations, I heartily recommend programmatically creating all of your views. There is even an app that makes this easier (and is way more scalable). I have no relationship with this company or product, but it is hands down a better solution.
http://www.paintcodeapp.com/

Should optional views be added by storyboard/xib and then hidden or added programmatically? (Good practices)

I'm starting a new project and I have some doubts about storyboard good practices, specifically about optional hidden views (show only under certain circumstances).
Let's say you have an pdf downloader app, when the user select a download button a UIProgress bar appears and show the download progress. Should this progress bar be included in the storyboard or generated programmatically when the user press the download button?
It's a simple example but what about if there isn't only a UIProgressBar but also multiple hidden (optional) buttons? What if some of the buttons are overlapped? (I know overlapped button is bad design but just for the purpose of exemplify)
Should this ones be hidden or added programmatically? What about performance? Some say it takes more time to parse a Storyboard/Xib than a programmatically build view.
In DonaldKnuth's paper "Structured Programming With GoTo Statements", he wrote: "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."
So, you are trying to solve a performance problem you do not really have (at the moment).
You decision to have a view permanently or temporarily should be based on context of the view usage, not some hearsay performance issues between xib/stb vs programmatic approach, that resembles platform-wars, but otherwise, given how LLVM compiler works today, and what the HW performance of iPhone 4 or higher is, is basically nonsense.
Here's a simple rule. Have all the views in IB, hide or unhide them as necessary, and add/remove a view programatically only if you can give a good reason why.
I understand you instinctive desire to make it right, so instead of trying to manage one milion views in one controller, take a look at the problem that is satirically called Massive View Controller.
Proper decomposition into custom views, separation of concerns, clearly defined responsibilities split into more view controllers, view controller containment, is the answer to to address your concerns.
You want your app first and foremost to work correctly.That you can achieve by having a sound architecture so that you will be able to stay in control. Users will not appreciate that you instantiated some button programatically, because they couldn't care less. But if the app has inconsistent state because your view controller has 7000 lines and is spaghetti hell or is crashing, that is a problem.
if you are planning to use storyboards; would suggest to have view/buttons etc included . you can always hide / unhide the same from the code.
have a thought process and not cluster your view. Have multiple views and make your app look neat

Creating a card based UI in iOS

Im trying to do app with a card based ui, kind of like Jelly. I was wondering the how this would be done. Im thinking by using a collection view but Im not sure. Are there any open source libraries that would make it easier to do this? Thanks.
You're probably not going to be able to accomplish this using out-of-the-box components. I don't think UICollectionView is going to get you very far. You will almost certainly need to roll your own.
I would start by creating a View Controller class for the "cards", instantiate a few of them, add the views as subviews to the main view, and get to the point where you can comfortably push these cards around with your fingers. You will want to read up on animating UIViews, and UIGestureRecognizers. Make sure the momentum is right. Apps like this really really demand highly-tuned physics, otherwise they'll feel awkward.
Once you get to the point where your cards are happily zipping around the screen, it's just a matter of getting them to "sink" into a couple pre-defined positions (focused front-and-center, and resting in a stack down below). You would probably also want to give your view controllers some sort of state that indicates whether they're "active", or not.
Easier said than done, obviously.

How to manage a very large number of IBOutlets in an iOS app

I am trying to write an iPad app with the basic purpose of form filling. I have 5 independent forms that I have designed in Interface Builder with each form having more than 50 UILabels and UITextFields along with a few Segmented controls in a UIScrollView (yes, its a really really long form). These forms need to be locally saved in the app itself which can later be emailed. After designing the forms I realised that creating IBOutlets for such a large number of different controls is going to be tedious and might also hamper the performance of the app. I am also worried about the complexity it will create in managing these outlets.
I am not sure if I have taken the right approach. Can anybody suggest me any alternatives. I am ready to start everything from scratch, all I need is a little guidance towards the right approach to solve this problem. I only need help with managing the input elements, the rest I can manage.
Any and all suggestions are welcome. Thank you very much.
There can be two kinds of UILabels and UITextFields.
1. Static/Fixed text inside.
2. Dynamic text.
You create outlets for dynamic values that changes at runtime. Or if you are implementing some thing from codes.
If you think 50 outlets are difficult to handle, you can create 5 separate controller classes for each forms, resulting in 10 outlets to handle in one controller class.

How does instantiating view controllers inside Xib files lead to code that is difficult to comprehend and debug?

In the introduction to iOS Programming: the Big Nerd Ranch Guide, the authors say that they always create view controllers programmatically, and that instantiating view controllers in Xib files leads to projects that are difficult to comprehend and debug.
What, specifically, makes this problematic? And which difficulties would you encounter?
Are there any specific examples, and how does creating the view controllers in code avoid these problems?
The quote is at Introduction > Style:
We will always create view controllers programmatically. Some
programmers will instantiate view controllers inside XIB file. We've
found this practice leads to projects that are difficult to comprehend
and debug.
They talk about instantiation. If you have two view controllers A,B, you can alloc/init B in A's implementation, or you can drop a reference to B in A's XIB. In both cases, B may be defined in a XIB or not (the Big Ranch book advises to use XIBs for complex view controllers btw).
Anyway, here is the difference:
CitySelectionVC *citySel = [[[CitySelectionVC alloc] initWithCities:self.cities] autorelease];
[self.navigationController pushViewController:citySel animated:TRUE];
vs
citySel.cities = self.cities;
[self.navigationController pushViewController:citySel animated:TRUE];
First case is a explicit instantiation in code. It tells me:
The VC is created now.
It needs the cities to work.
The code in the second block references an outlet instantiated in the XIB. It tells me:
A VC was instantiated at unknown time, with unknown requirements.
I'm passing the cities.
I favor the first style because it is more explicit, and gives me control of the lifespan of the object.
In iOS 5 you can use Storyboards to create transitions and pass information between controllers. See Session 309 of WWDC2011.
For completeness, here is the answer I received from Joe Conway (one of the book's authors) in the Big Nerd Ranch forum:
"When a low memory warning occurs, a view controller's view is trashed
to free up memory. When that view controller's view needs to go back
on the screen, it reloads its XIB file.
If there are controller objects (or really, any non-view objects) in a
XIB file, those also get recreated. Not knowing this can put your
application into an inconsistent state, because a controller that may
have held state (or held references to model objects that held state)
will be destroyed.
It could be argued that everyone should know this and take the
appropriate action to work around this. However, there are a few
problems with that argument: not everyone knows this and even if they
do know this, they are forced to open up XIB files to see the
controller hierarchy AND read through code. This makes things
difficult to maintain."
To my mind, this is less of a black-and-white, right-or-wrong situation, and more a case of personal preference. It's an old debate, as well - the "real programmers do it in code" argument has been around since mainframe days.
Possible advantages of building view controllers in code:
all the aspects of the interface are in one place, so you can figure out exactly what's going on by reading through one file.
it's arguably less complex to create the view, if you regard dragging-and-dropping in a UI builder as complex.
getting fine-grained pixel-perfect control over the UI can be painful in Interface Builder, especially if you're used to the level of layer and layout control from tools like Photoshop.
The counter view:
unless you're experienced or just that way inclined, getting a sense of how a visual interface looks and feels is very difficult from code.
working with end-users and designers on interfaces that are built in code is damn-near impossible.
sometimes it's just quicker to drag and slap controls and nudge them around until it's right.
Ultimately, it's a case of what works for you. I tend to do it both ways, depending on how complex the interface is, how quickly it needs to go together, and (frankly) the mood I'm in at the time...
This is kind of a philosophical question. It's hard for me to imaging getting the look and layout correct if it's all in code. On the other hand, using .xib files means that you have no single place to look to make sure all your outlets are actually hooked up.
Localization is IMO going to be much easier with .xib files, too — you can certainly do this with code, but when buttons change size it can be tricky.
It's very true that:"real programmers do it in code" but I do not see the problems while debugging until or unless you are not focusing on UI issue while debugging. It means to fix the UI issue you have to fix it through the IB and that issue you should not look into while debugging.
The biggest problem that developers face while doing UI through XIB is developing it in team and putting it in SVN. If you get any conflict and you are required to merge both the code, you have to play through the XML. Sometimes it becomes very tough to resolve the conflict in XIB manually. If you do it by coding you can easily make it done (because you know which line is causing what problem, and what to keep and what to remove).
I hope this will help you to decide on what should you keep in XIB and what you need to do by coding.
Apart from (as others have already pointed out) being a false dichotomy, I find the argument misleading:
While it’s true that you now have two places to look for where things may come from, when you are instantiating view controllers in XIBs, as soon as you need two configurations of the same view controller, you can only lose when you’re heading down the “code only” route.
In my personal experience, most of the code-bloat in the projects I saw or worked on came from a reluctance of separating configuration from functionality, i.e. forcibly “doing it in code” instead of “load a XIB with the configuration”.
In the worst projects, dozens of classes could have been avoided easily by simply treating configuration as data — and leading to better, more robust code because it would have been exercised more thoroughly.
So in my opinion, using XIBs even to instantiate other view controllers does not only not deteriorate the maintainability of a code-base, but can help a lot in actually improving it.
There is one single caveat to using XIBs:
You have to talk to each other — there are a few conventions you have to establish within your team, and you have to talk about who puts (or is planing to put) what exactly where and why.
Establishing conventions and talking about architecture, however, are the things you should be doing regardless of project or even programming language if you don’t want to end up with a huge maintenance nightmare…
A few tips for working with XIBs:
When writing view controllers, be liberal with asserts — if you have a precondition that something is there, put an NS(Parameter)Assert in your viewDidLoad and make sure the exception breakpoint is active, that way you’ll find missing connections easily (including those from code!).
Give objects meaningful labels, as the auto-generated names can become unhelpful quickly — when your view hierarchy grows in complexity, you won’t see much in your outline when you have a “View” in a “View”-with-seven-siblings-three-levels-deep-in-another-view or have ten UILabels that will be filled with data dynamically.
Set the editor to perform live autoresizing “Editor > Canvas > Live Autoresizing” most of the time. Only disable it, when you don’t explicitly need it.

Resources