A while ago I became a fan of creating/manipulating the view hierarchy through code. Both because I think is more expressive and forces me to learn more about Cocoa.
But I just wrote a 5 lines of code which would look way more expressive if an IBOulet was used. It finds a subview within a view with a specific tag and sends a message to it. But I could easily create an IBOutlet and do it in one line only.
Because of this, I ask: is creating an IBOutlet too expensive?
P.S.: Let's cut off the "readability over performance" for now. I really want to know the impact of this.
IBOutlet is a marker for Xcode that gets removed by the time the preprocessing step is over. Internally, setting it up boils down to assigning a single pointer to an instance variable that "backs" the IBOutlet property. This pointer is assigned at the time the view is set up, and does not change after that. It is very cheap.
Finding a subview by tag, on the other hand, is a run-time operation that needs to run every time that you are looking for the subview. Usually it is cheap, but it may become considerably more expensive in a view with large number of subviews that have subviews as well.
Therefore, I would definitely go for IBOutlet, because it's a one-time deal, and because it lets you shorten the code from five lines to one.
You have to be able to find out the pros and cons of your current approach. In fact Apple's documentation states:
As with any item of object state, you should be able to justify its inclusion in a class; the more outlets an object has, the more memory it takes up. If there are other ways to obtain a reference to an object, such as finding it through its index position in a matrix, or through its inclusion as a function parameter, or through use of a tag (an assigned numeric identifier), you should do that instead.
I prefer to use IBOutlets in most cases, as (I know that you don't want to hear this) they make the code more readable and of course as #dasblinkenlight pointed out, your traversing of the view hierarchy is performed at runtime and therefore anytime (assuming you do this in viewDidLoad) the view is loaded.
My recommendation: Stick to IBOutlets, unless you have a really really simple view hierarchy and using tags to find your subviews is the best solution.
Related
If we create many IBOutlets from the storyboard/xib to the ViewController/View then will it cause performance overhead? If so how?
See the IBOutlet Definition in Apple Developer.
Here's Outlets documentation link
We can see this
the more outlets an object has, the more memory it takes up.
If there are other ways to obtain a reference to an object,
such as finding it through its index position in a matrix,
or through its inclusion as a function parameter,
or through use of a tag (an assigned numeric identifier),
you should do that instead.
So it will cause performance overhead.
For more details, you can see the documents.
Yes. That's why you should create many storyboards base on your purposes.
For example : Setting Storyboard, Main Storyboard, User Storyboard, Picker Storyboard.
Thinking it over, this feels like a bit of a noob MVC question, but I can't come up with or find a definitive answer so I feel I should ask and get some clarity for myself.
I have a custom view that I created using a xib. It is going to be used in, currently, 4 other places in my app. Each usage has identical functionality, so I'm basically just creating a custom control object that I can reuse multiple times.
My "control object" consists of a UITextField, and two UIButtons.
The functionality I'm looking at implementing is, the first button will bring up a UIPicker and the 2nd button is essentially a done button and will just resignFirstResponder on the UITextField. As previously mentioned, this is consistent everywhere this will be used.
What I'm curious about is, is it ok for me to build this functionality directly into the custom UIView subclass since it is consistent behaviour for all instances of my control object? Or, do I need to create a custom UIViewController subclass to go along with it?
Currently, in my main UIViewController for my app I am creating instances of my custom UIView "control object" and treating them the same as any other control object. If I should actually be creating a custom UIViewController class to go along with it, well, I'll have more questions for another thread as to how I should be doing that (unless someone can direct me to a resource on this)
So far, searching the web has yielded nothing for me and from everything I've seen so far with iOS development in general, I've gotten the vibe that UIViewControllers are really only ever for a main, presentable view (that takes up the entire screen.. I might be missing some terminology for this).
My gut feeling is that no view controller is necessary in the scenario I'm describing, but I'd like to try to get some sort of confirmation, if possible.
There is no silver bullet, so no approach is absolutely right or absolutely wrong. What you describe here is just a view that changes its states. So putting everything in your UIView subclass is completely OK. It also conforms to the KISS principle.
However, as far as I understand, and correct me if I'm wrong, the input of your custom view - the text and the picked value from the picker does not really affects the view itself, but the viewController it's attached to. So you need to pass that input to the hosting viewController. This can be achieved by protocol with a default implementation. So the handling of the input data is written only once, but can be attached to whatever viewController you want.
Based off of everything that you've said, I see no need for another view controller. I can see where the answer could be a little unclear considering that the actions are something that ViewControllers usually handle, but I think you'll be just fine letting your custom view handle this by itself.
If you add more functionality or more complex operations, then perhaps it is time to explore other options but for now I think the single view will be fine.
I would like to know how much memory does a single ViewController take , because when I'm developing some apps I'm still not sure if it is better to create more ViewControllers , or if I should create less ViewControllers and change things in code , instead of UserInterface.
Example of what I mean: Let's say that I have two types of data and I want to see them on presented ViewController, but these two types are almost the same. So should I have only one ViewController and change things in code or I can just create ViewController for every type?
I know that it depends on how much code and how much things are in the UI but let's say that it is a few lines of code and just a very basic ViewController
I have looked into The Role of View Controllers
by Apple but I could not find the answer.
https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/index.html#//apple_ref/doc/uid/TP40007457-CH2-SW1
I know that it's a bit weird , but I'm really curious.
Thanks.
An uninstantiated view controller doesn't use any memory. It's takes a trivial amount of disk space as part of the app, but no memory at runtime until it is created and displayed.
You are currently guilty of premature optimization. Write your code properly so it is easy to write, easy to maintain, and easy to debug. Don't worry about things like memory usage and performance until you have a problem that needs to be addressed.
If you have two different screens with two different types of data, then create two different view controllers.
Once it is working, then run it through Instruments and confirm you have no leaks or reference cycles wasting memory.
The size of extra view controller classes in your code is negligible, so unless you're talking about some extreme number of them, I wouldn't worry about that. The governing principle here is more likely to be DRY. If you've got a bunch of objects that differ in very small ways (e.g. the names on labels, etc.), then perhaps you can create a common protocol to which all of these objects conform, and then you can write a view controller designed for that protocol, rather than any particular object. But if you find yourself adding a bunch of unwieldy if statements and programmatically adding controls, simply to avoid having multiple scenes in your storyboard, then you may have gone too far.
I am displaying a number of cells, whose content is reasonably memory intensive. I have a custom controller that sets up a view to display the content, and updates the UI periodically. However, often UICollectionView asks for a particular cell several times. I want to know how to design (well) a system to re-use the controller + view if I have already created it for a given piece of data. I thought about storing a controller reference in the data object, but don't know if storing UI elements in what is meant to be data is a good idea. Also, if I did this, I would need to monitor retainCount on cell unload, and when it gets to '1', remove it from the data object, which seems a bit hacky. Similarly, a NSDictionary of data->controller pairs in the UICollectionView could also work, and would again require monitoring retainCount, or re-implementing a retain counting mechanism for my particular case. It's doable, but seems clunky.
I'm very new to ios, so it may be I'm approaching this all wrong. Any suggestions are greatly appreciated!
First of all, think if displaying a controller view inside a cell is a good idea. I'm not sure, but since i'm not familiar with your project, it's something only you can tell.
Secondly, You can create your own pool of controllers. When you need a controller to put inside the cell (in cellforIndexPath method), take one from the pool. If the pool is empty, create a new one. The cell shouldn't come with a controller of it's own, put it only in cellForItemMethod.
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.