I've got a fairly intricate IOS application with icons, tables, text fields, etc spanning across over 20 different view controllers. I built the entire application in portrait mode, and have of course realized that things look screwy when in landscape.
For the really simple screens I've had little issues using autolayout's constraints to accommodate any orientation changes. However, when there are multiple (5+) items on the screen I've found it incredibly hard to use constraints to manage everything. In fact some views look like they need the entire layout transformed to flow well.
Is there a better alternative to constraints? My only other thought is to make duplicate views, one for portrait and one for landscape. Then I can just switch on the deviceOrientationChange listener.
You can always switch off constraints by selecting the xib/storyboard file and unchecking Use Autolayout. To do this only for the more complicated views, I think breaking out into separate xibs is feasible.
Also, sometimes landscape really calls for a complete rearrangement of the view (or even adding / hiding certain elements). You should not shy away from defining separate views for this, with or without xib documents.
Related
I'm not very good with Constraints, so basically, my idea is to place all the objects on the View Controller manually for every screen size (iPhone 4, 5, 6, iPad, etc).
Is it possible?
Can I place all of them in one View Controller, or will I have to create a new View Controller for each screen size?
It is possible and you can do it in a single ViewController for each screen size. In Interface Builder if you open a ViewController or any other UI element, on the Attributes Inspector you can see small + signs next to most properties, using which you can add screen size specific properties. Using this approach you can manually create different sizings/font sizes/label texts, etc. for each screen size.
However, I would really recommend learning how to use Autolayout. It is one of the most powerful features of iOSs UI design and working on a large project with a complex UI you will pretty soon regret not learning how to use it. In the long-term it definitely saves you a lot of time and effort. With all the different screen sizes Apple has introduced in the past years, handling them manually is a real pain.
Been trying to find some tips on suggested approach for this and not having much luck.
All I'm looking for is to know what is the best approach to handle custom layouts for portrait/landscape modes.
I've seen some posts say in the storyboard add 2 views to the same ViewController and show/hide based on orientation change while some people suggest to use a totally separate ViewController for each orientation.
Which of this is the preferred method. I'm just starting my application, So I'd rather go for the widely accepted method than have to deal with complications later on.
Apple documentation still keeps talking about nib files and not storyboards in this aspect, so not being of much help.
My main focus is performance (I'm fine with having to code stuff instead of depend on the graphical interface for it). separate ViewControllers seem to keep the code in a clean way however if that involves populating views / clearing them every time orientation changes, seems kind of expensive(not sure if it is relevant).
Also if each scene in the application has 2 layouts then managing them I'm not sure how much of a pain it's going to be when the application grows big.
Please point me in a suitable approach for my case,
am not concerned about backwards compatibility. Just worried about the latest Xcode and ios6 if it matters for the decision
Thanks
I would say this really depends on the level of customization of the UI in portrait vs landscape. A large number of implementations I have done can be handled by either autoresizing/autolayout when switching orientation, or simply moving the elements yourself when the UI is rotated and the callbacks are fired. Moving the elements around should not be an expensive operation at all as it is a very common occurrence (again this depends on the complexity of your UI though).
I have a NavigationController that stacks UIViewcontrollers that have UITableView among other UI elmeents. The tables I use are actually custom tables that use custom cell views. With this arrangement those tables don't show scrollbars of any kind even though I have configured in IB the Shows Vertical Scrollers to show them.
I've tried several ways of debugging this without success. If I print to console the value of this property (showsVerticalScrollers), it prints 1, so the property is properly set, and no, my table is not wider than its parent view, actually it's way more narrow than its parent view.
Are there reasons why a table won't show it's scrolls?... btw, this happens in iOS5 running in simulator. I'm using xcode 4.2 with SLeopard. I don't have access to an iPad to test it in the hardware but other tables I have in the same project, show their scroll bars without a problem.
EDIT
thanks for the answer... I did one last test and found that one of the causes for not showing a scrollbar is the number of elements shown in the table, when they fit in it without the need to actually scroll. Say if you have a table with 1 row and the vertical size of the table is too big for just one row?, then iOS won't show the scrollbar when bouncing.
It's hard to provide a possible solution without seeing any code, but the advice I can offer is to update your code to the bare minimum needed code to implement a UITableView and see if scrolling works, if it does, add in functionality in small increments, testing the scrolling with each new code addition till you reach the point that scrolling breaks. Incremental testing in this fashion helps to avoid issues like this where you are unable to effectively debug your application.
I want to decide if it is better to use XIBs or to designs my views completely using code.
So far I have read that when you design your views on interface builder they are pre-built, so even if they use more memory the user feels everything is faster.
People say doing everything using code is harder but I find it to be just as easy, so I want to know if anyone has experienced some real speed gains when using nibs.
What have been your experiences, advice, etc?
Thanks!
You should be able to do both -- there are times when building a view programmatically is better/easier, and times when using a .xib is better/easier. Even if you only ever do things one way, you'll run into code that does it the other, and you'll need to be able to deal with that.
If you don't know how to use IB, then building your views in code is certainly easier. That is why you should learn to use IB. Once you understand IB, it's way, way faster to put together most of the view-based UI your app will likely need. IB helps you line things up, center objects, align base lines, connect controls to their targets and actions, etc. I think it's safe to say that everyone who uses IB effectively experiences "real speed gains when using nibs."
You should know how to use both. Performance differences between the two are negligible and should not be the reason that you choose one or the other.
Many people who are new to iOS development have the misconception that nibs (.xib files) are inferior to programmatically creating your UI and that if you use IB you're not a good iOS developer. That view is 100% wrong. IB is created by Apple and in use by Apple's developers to create their own Mac OS X and iOS apps. If IB (as a tool) is good enough to be used by some of the best developers in the world, it's probably good enough for most of us.
In practice I have found that a combination of the two usually fits the bill.
In my own apps I find that .xibs are great for laying out the basics of your views quickly and they allow you to iterate very quickly while giving you a preview of what your view will look like. It's also much easier to use auto layout in a .xib file.
Then when you need to do more advanced things like add fancy animations or move views around that is what IBOutlets are for. Anything that you put into a nib can be referenced through an IBOutlet. This allows you do then programmatically make your view come to life.
Lastly, you should fully understand what a nib (.xib) is doing automagically for you. You should understand what happens when a .xib's objects are unfrozen. There are many resources on the internet to understand .xib files better.
Also, learn how to use .xibs in an encapsulated way. For example, .xibs are crazy useful for things like prototype cells and they allow you to keep your code base modular (much more so than storyboards). Also, you will require less UI code in your view controllers.
Lastly, I always say that people should think of IB/.xibs like jQuery. It's going to save you a lot of time but the best developers still know how to do everything in javascript if they have to.
Good luck and have fun!
TL;DR version
Performance is not a consideration when deciding to use .xibs or not.
Use .xibs because they give you a preview of the view you are creating and they allow you to quickly iterate
In practice most apps will use a combination of both. You will programmatically add animations or move views around but the .xibs will be a starting point
Understand fully what happens when the objects in a .xib are unfrozen
You'll be more productive but be sure you fully understand what is happening behind the scenes.
I would always use XIB files unless there was a reason not to. This allows your views to be maintained easily in the future.
Some reasons for creating the views programmatically might be:
A control needs to be resized,
repositioned or otherwise altered
depending on something else
Controls
need to be added or removed
dynamically
There may be more reasons but there are not too many.
If you programmatically create views when there is no need you make it a lot more difficult for other developers to try to figure out what the view will look like and to change it.
If you build your views programmatically, you have control over the loading of elements. e.g. you could use lazy loading, and load secondary buttons, subviews, etc. a fraction of a second after the more important elements, allowing the key parts of the UI to come up faster. You could even animate some elements into position.
If you use IB, you get guides as to proper element spacings and positioning, but you could always copy the coordinates from IB into code if you aren't changing the design that often.
For simple UI elements, you will end up with more lines of code to maintain if you create them programatically.
IB and NIBs do a lot to optimise loading/unloading of views, but it is largely oriented to minimising memory usage vs. perceived speed for the user. For example, lazy loading if anything might make the app UI slightly slower, but it should make memory usage lower. This in turn could make overall app performance better on a large application, and is very much encouraged, but it's difficult to define "performance" in a narrow way. It's also difficult to say when you should or should not use IB - there will be some times you're much better off doing it in code.
One often overlooked element to the IB or not debate is development speed, especially if you have multiple developers. On a larger team/project you'll probably have some developer(s) who specialise more in the infrastructure, business logic etc. of the app and some developer(s) who specialise more in the UI. In this case, use of IB will make it easier for them to work independently, which should make overall development more efficient.
I view IB as a core part of the development platform for iOS development. It's not the right solution in every situation but not knowing how to use IB will be a real limiting factor.
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.