Adding custom controls to Interface Builder (IB) Xcode - objective-c

I did this wonderful tutorial: Photoshop Tutorial For Developers: Creating a Custom UISlider and came away with two questions:
The example above makes every UISlider customized. Can you just subclass UISlider and tweak this code to make it it's own class that can be called upon?
Further, could you make this custom control available in the object explorer within Interface Builder, so you can just drag and drop it on your view like anything else in UIKit?

The docs for CocoaTouch classes will usually indicate if a class is not designed for sub-classing. In the case of UISlider, there's also some instructions for customizing appearance.
Custom Component in Interface Builder
To use a custom component within Interface Builder, its necessary to use the "object" component, and specify the class type to your custom class. Unfortunately this does not render any visual queues, like core UIKit classes.
Your own Plugin
It may be possible to provide a plugin to tweak Xcode, however this is no small undertaking as there are no official docs, so its necessary to search for open-source plugins on GitHub, etc and study the code. Even then, the plugin may break with subsequent version of Xcode.
Recommended Approach
Interface Builder is an amazing technology, however for more complex applications I recommend implementing views in code (override loadView in the VC). Here's some reasons:
Promotes better encapsulation and reuse. You can compose your own components (eg composition vs inheritance) using UIKit components, and provide a custom OO interface to them. Contrast this with lots of IB outlets in a view controller, which leads to poor reuse.
Fat-controllers don't really honor the MVC paradigm.
More flexible and fluent. Not all properties are exposed via IB, so in a complex case, its hard to know where to look. Is that setting in IB or code? Custom fonts, for example.
Xibs are really tricky to merge in a multi-person team.

Related

disadvantages of subclassing ui components

I saw in eclipse articles saying that we can subclass Canvas and Composite.
And they have mentioned some points about subclassing the components.
Is that only applicable to SWT components or are they mentioning general
disadvantages of subclassing all the UI widgets? Please refer the site below.
Writing Your Own Widget
They are saying you should only subclass Canvas and Composite. All other SWT widgets do actually check for subclassing and throw exceptions (although this can be overridden).
As the article says the widgets are generally platform specific so you would have to do an override for each platform. Since the widgets are not designed to be overridden the internal fields and methods are usually not accessible anyway.

When do I need to subclass UIViewController and when can I just instantiate it?

I am learning iOS programming through the Big Nerd Ranch guide by Hillegass and Conway. I’m writing an app of my own as I go through the book, and one of the questions that has been bugging me is exactly when I need to subclass UIViewController (and its ilk) and when I can just instantiate it.
For example, my app consists of generic building blocks: the interface is tabbed, and the tabs lead to a UITableView, a UINavigationController that creates UITableViews, and so on. Following the book’s instructions, I have subclassed UITableViewController to create the table views. However, in creating the UITabBarController that contains all of my app’s content, it seems sufficient to instantiate a UITabBarController and then add a bunch of views to it. (All of this is done in the application:didFinishLaunchingWithOptions: method of my app delegate. Since most of my app consists of simple combinations of basic UI parts, I’m trying to do build the UI programmatically whenever possible.)
I get the impression that what I should be doing is creating a subclass of UIViewController (or UITableViewController or whatever) for every interface in my project. This seems weird to me, since most of these classes would only ever be instantiated once. Am I just misunderstanding how OO should be used in this case? (I have a good amount of programming experience but relatively little has been with OOP.) Should I be creating a subclass for each and every screen that the user will see?
Should I be creating a subclass for each and every screen that the user will see?
If each view requires different logic, yes.
Don't shy away from creating new classes for conceptually separate things. Programmers coming from non-OOP to OOP might feel that a file with only a small amount of code is a waste. Suppress this feeling. Classes are cheap, and help enormously to organise your thinking.
So you have two types of UIViewControllers in iOS. "Container" viewControllers and "Content" viewcontrollers. Both are subclasses of UIViewController but have very different purposes.
The Container type is what the UINavigationController and UITabController are. They are rarely subclassed and typically used as is (in fact, I believe Apple doesn't allow the subclassing of UINavigationController at all). These "Containers" take care of moving "Content" view controller around for you. They do not have much content of their own, beyond adding things like a tab bar or a navigation bar.
The "Content" view controller are the ones you create most of the time. You will rarely be able to use a UIViewController as is, because it will not have any functionality. That is why you subclass them. These are meant to represent a single "screenful" of content. So in effect, every "screen" the user sees should be controlled by a UIViewController subclass.
The UITableViewController is simply a specialized sublass of UIViewController that already contains some methods for managing tables.
The way the UIKit framework was designed was for you to use subclasses of UIViewController to display content and to use out-of-the-box "Container" controllers to facilitate the management of your UIViewController subclasses.
You need a subclass of UIViewController if you want to do any of the following (not an exhaustive list, but some examples)
customize the view hierarchy when the view hierarchy is loaded (in
viewDidLoad)
provide some behaviour as the view controller's views become visible
(or not) (in viewWillAppear:, viewDidAppear:, viewWillDisappear:,
etc.)
clean up after yourself as needed in viewDidUnload
create outlets to views in the hierarchy so you can adjust them as
needed in the above lifecycle methods
My reasoning behind subclassing UIViewController, and other classes is that:
Almost always you must initialize variables and assign values to the instances of classes. You add subviews and set their frames, define actions for the UIViewController instance, etc. If this UIViewController instance is directly from the base class, its initialization should be done outside of it. If this initialization is required at different places for multiple times, you may have to deal with repeated initialization process.
So, you've compiled these processes into a method, making it reusable from wherever this UIViewController instance is used. But where do you want to put it? Don't you think it's much better to put it inside the subclass of UIViewController? Also, you don't even have to come up with specific name for this initialization method. Just override the default -(id)init from the super class.
Though you may think it's suffice to use UIViewController without subclassing it for now, as your project grows, it will be challenged to deal with reusability issues. Take some time to look at your codes. Check if there is too much repetition for such as initializing an object, or assigning values to it. If you are doing same things with an instance of a class in multiple places, compile them into a method to be reused. And as number of such methods grow, you will find the need to use subclass which will contain these relevant methods for the instance.
No matter the size of your project, using classes to distinguish different objects is important. Almost always, the basic essential classification is done by the framework, making it unnecessary to introduce new concept for a class. However, this doesn't mean the framework also knows how your project and its objects can be classified into. By using subclass, you can utilize every benefit the development framework can provide and still keeping the objects in your project to be as unique as possible, based on the purpose you've designed for them.
Well about the UITabBarController you are right. There is no reason for you to subclass anything if the default behavior is sufficient. However once you need to do some custom things you will need to subclass it..
Also, why are you trying to build the GUI programmatically? For the learning curve? There is no real reason not to use InterfaceBuilder, it saves you a lot of time.
You should subclass the UITableViewController in order to get your data in the view, that is how the MVC model works. The default implementation does not offer anything in order to get your data in the view, I don't think they will ever do that in order to make sure that nothing is wasted, their 'connection' to the model object might be different from the one you want and you would end up writing an adapter if your model object is not compatible.
I hope this will help you out a bit.
And merry x-mas.

Xcode programming without usage of Interface Builder

I have a general question for Xcode programming and the usage of the Xcode tools.
I am quite new (4 months) in iOS development and I almost never used the Interface Builder for my purposes. I always created instances programatically. My question is basically if you think i should get used to work with IB or should/can i proceed like i do now?
If you are fine with defining your UI programmatically, then I do not see any issues with that.
Interface Builder allows you to "graphically" define your interface, and this can be an invaluable tool for playing with your UI prototypes, but apart from that there is nothing that you can do in IB that you cannot do programmatically.
In my case, I see that it depends on the kind of UI that I design. When I need a pretty basic UI, the IB is unbeatable for me. On the other hand, when my UI tries to be a bit custom, then I prefer doing everything programmatically.
An interesting point is that you could use IB to design your UI, deciding on sizes and positions of your elements, and the create it programmatically.
Yes you should use IB, basically xcode having IB for ease of development, no need to setting controlls by using coordinates and each time see their visibility by running the app.
just drag and drop and at the time of making the views, you can see hows your screen going to look.
Also using IB is not a typical task so,start development using IB.

Why can't new ObjC classes descend from UIViewController?

So, I've been making iOS apps since the first iPod touch came out, but something has always flabbergasted me; why is the list of new Cocoa Touch classes restricted to subclasses of NSObject, UIView, and UITableView? I routinely make subclasses of UIImageView and UIViewController.
Am I "Doing It Wrong™?" Have I totally misunderstood MVC to the point where I make Controller classes where I shouldn't? What is the philosophical reasoning for requiring classes to never descend from a basic controller class?
What gives you the idea that you aren't supposed to subclass UIViewController? This is directly from the documentation for UIViewController:
In a typical iPhone application, there is usually at least one custom subclass of UIViewController and more often there are several.
The C of MVC is supposed to be the least re-usable part it's whole job is to mediate between M & V. If you find something that is in the C section of your code that you have to copy and paste into several subclasses of a given object or into several projects that code should be moved elsewhere.
If you are just basing this off the fact that there is not a nice popup menu item that says UIViewController, don't worry about it Apple has just not bothered to write a template file for that class yet.
Uhm... maybe it's just me, but I see a UIViewController subclass template when I choose new File.
UIViewController template http://files.me.com/aclark78/obnp83
Like #theMikeSwan says, there simply aren't GUI templates for this when you create a new class in Xcode GUI. But you can always create a new subclass whose parent is initially NSObject. After that, you just go to your code and change the parent class to whatever you like.
So... no, you are not doing it wrong in the sense that you rightly understand that often you want to subclass UIViewController; but yes, you are doing it wrong since you assume you shouldn't do this only because Xcode GUI does not support it :)

How do you display custom UIViews in InterfaceBuilder?

I seem to enjoy designing new UIViews and UIControls that implement their own -drawRect: method. This work well for me, especially when composed using UIViews in Interface Builder.
But composing them in Interface Builder is annoying because they just show up as boring plain rectangles.
It would be great if the views would actually render themselves as the built-in controls do.
Is there any way I can structure my project so that Interface Builder will render my custom views?
In order to do this, you actually have to create a plug-in for Interface Builder that uses your custom class. Once you create and install your plug-in, you will be able to drag and drop instances of your class (your view) onto another window/view/whatever just like any other control. To get started with creating IB Plug-Ins, please see the Interface Builder Plug-In Programming Guide. Also, I recommend taking a look at Aaron Hillegass's book, Cocoa Programming for Mac OS X. As well as being very well written and easy to understand, it has a chapter on creating your own IB Palette controls.
This is achievable by marking your UIView subclass with #IBDesignable. Once you do this, your custom views will render themselves in Interface Builder. You can even add parameters that can be configured by marking them as #IBInspectable. Here's a Swift example:
#IBDesignable class customView: UIView {
#IBInspectable var count: Int = 0
}
There's an article on NSHipster that provides more detail.