Custom UIView from Interface Builder - iphone

I'm trying to keep things organized and create hierarchy of views for my app.
So for instance I want to create a custom view to display some text, another custom view to display progress and then use all those views in the main view created with View-Based Application template.
I know how to create it programmatically - you create UIView subclass, implement drawRect method, place an empty UIView in Interface Builder and chance it's Class to my custom class. My problem is that I want to create those custom view's in Interface Builder instead programmatically.
So far I've created UIViewController controller with XIB file and in viewDidLoad method of view controller from the template I create that custom view controller instance and add it's view as a subview of that empty UIView added in Interface Builder (the same you would change Class in programmatic approach).
It works, but it's more of a hack for me and it's hard for me to believe that there isn't a better method where I could add those custom views in interface builder without having to implement viewDidLoad method and create controllers and add their views inside of that method.

This was originally a comment in Ratinho's thread, but grew too large.
Although my own experience concurs with everything mentioned here and above, there are some things that might ease your pain, or at least make things feel a little less hack-ish.
Derive all of your custom UIView classes from a common class, say EmbeddableView. Wrap all of the initWithCoder logic in this base class, using the Class identity (or an overloadable method) to determine the NIB to initialize from. This is still a hack, but your at least formalizing the interface rules and hiding the machinery.
Additionally, you could further enhance your Interface Builder experience by using "micro controller" classes that pair with your custom views to handle their delegate/action methods and bridge the gap with the main UIViewController through it's own delegation protocol. All of this can be wired together using connectors within Interface Builder.
The underlying UIViewController only needs to implement enough functionality to satisfy the "micro controller" delegation pattern.
You already have the details for adding the custom views by changing the class name and handling the nib loading. The "micro controllers" (if used) can just be NSObject derived classes added to the NIB as suggested here.
Although I've done all of these steps in isolated cases, I've never taken it all the way to this sort of formal solution, but with some planning it should be fairly reliable and robust.

For this to work, you have to create a plug-in for Interface Builder that uses your custom control's class. As soon as you create and install your plug-in, you will be able to add by drag and drop, instances of your view onto another window or view in Interface Builder. To learn about creating IB Plugins, see the Interface Builder Plug-In Programming Guide and the chapter on creating your own IB Palette controls from Aaron Hillegass's book, Cocoa Programming for Mac OS X.
Here is the link to the original author of the accepted answer to a similar question.

Maybe i didnt understand u?
you have library in the Interface builder u can move every component u want and place it on your view. (u can add another view by adding UIView and change its class name in the 4th tab).
then u declare vars with IBOutlet and connect them from the 2nd tab of ur file's owners to their components...another question?

Unfortunately, you can't do what you want to do with UIKit. IB Plugins only work for OS X, and Apple explicitly doesn't allow them for use with iOS development. Something to do with them not being static libraries. Who knows, they may change this someday, but I wouldn't hold your breath.

Related

Object structure for creating a "wizard" form view in iOS with multiple input views

I would like to use a single WizardViewController with different inputView subviews. The WizardViewController would share a searchCriteria and pass it along to each new step, with each step adding to the criteria depending on the input for that particular inputView.
The problem I am facing is how to structure my objects/views so that I can reuse WizardViewController accepting different types of input/controls. For example, I've thought of using a WizardViewModel that had members like enum wizardViewModelType (for each type of view), UIView *inputView that corresponds to each type of WizardViewModelType, and creating custom UIView subclasses that correspond to the different possible inputViews that would be needed, connecting outlets as necessary in Interface Builder. The problem is that I believe that going down this road will lead to a lot of inter-class dependencies and basically defeat the purpose of separating the inputView logic from the WizardViewController. Furthermore some of the inputView will require me to grab possible values from a web service, which is something that the ViewModel will have to handle, further breaking the logic. Perhaps I need separate ViewController for each type of input view? Or am I thinking about this in entirely the wrong way?
Normally, the right way to do it is by having a ViewController for each UIView. The logic of your application should not be on the view, but on the viewController, and you can share data by using segues (if on ios 5), and I'm sure that there are other methods for ios 4 or below.
If I wanted to share codes between the UIViewControllers, the way I would do to make a wizard is to embedded it in a navigation controller and push the next viewController on the navigation controller stack.
If you want to share code between view controllers, I don't think you should do it on the view controller class. Basically, I would think of two options to do that:
1) write a base class: the base class should extend the UIViewController and your UIViewControllers could extend this base class.
2) extract the common code into another class (better, if applicable): You create another class that share the common code, and inject it into your view controllers.

Using custom controls with Interface Builder

I have a custom ViewController which allows selection of an image from a grid. The ViewController uses the AQGrid control and is really just a modified version of the samples shipped with AQGrid.
I'm trying to hook it up in InterfaceBuilder, but documentation on how to do this seems sparse. In standard Cocoa apparently I should create an IB plugin to use with IB, but I'm just looking for the quickest option really as there are a few of these custom ViewControllers which I need to hook up (including a rating control). I've also tried dragging the "Object" controller in IB to my tabpage, but it just gets added to the tree outside of the tabcontroller (see screenshot).
As far as I understand your question, you have to add a generic UIViewController to your nib file and then change its class in the Identity inspector to whatever you need as long as it's a subclass of UIViewController.
Use a "Custom View" object and assign the appropriate class in the inspector's info tab. Using Interface Builder plugins isn't really advisable anymore, because Xcode 4 doesn't support them.

MVC when developing in objective-C without using the Interface Builder

What is the correct way of implementing true MVC in Objective-C (Cocoa/iPhone) when the view is NOT created with Interface Builder?
How do I best structure the code and tie the different components of the MVC pattern together when I'm not using the Interface Builder in my project?
Usually when you are trying to create a view without any help from a nib file, you will have to implement that view's controller's loadView method.
So my answer is, any stuff related to V goes to the loadView method in your controller's implementation, any other logic stuff related to C goes to the rest part of your controller's implementation.
It's really a matter of taste : some absolutely think that to one viewController you can have one and only one view so the only manner is to subclass UIView for every view. I totally accept that a viewController manages multiple sub view constituting a screen and I only subclass UIView where it make sense in term of reusability. In fact, I also accept that a viewController use multiple viewControllers to manage different isolated part of the view as does the UINavigationContoller for example.
Usually you create a subclass of the element you want to display. For instance a UITableView which you set in the init method. This way, you're ViewController just dequeues an instance of it

How do I set up several custom UIViewControllers under one central view controller programmatically?

Being new to Xcode and Objective-C I find it hard to get my head around the Interface builder and Objective-C when doing things that are following the basic pattern. I have created a subclass of UIViewController that I want to instantiate several times to make a grid with each row being controlled by an instance of this class. So there will be one root view controller (with navigation etc) that should include/genereate all the instances of the custom sub-viewcontroller.
Now what would be the best way to do this? All examples I can find are about navigation, where one view should replace another, but I want to have all the viewcontrollers visible on the same "page". Do I need to create a nib file for the custom controller at all? I have also been thinking about using the UITableView somehow but inserting my custom viewcontroller in every row.
Any help greatly appreciated!
Apple's documentation recommends using one view controller per screen. It is possible to decompose your interface and use multiple view controllers on one screen if you have a good reason to do it, but Apple hasn't really designed their frameworks to support this, so you'll run into pitfalls if you don't know what you're doing.
In this case, I question whether each row of your grid really needs its own view controller. I find it hard to imagine a case where this would be the best choice, although it's hard to say for sure without knowing more about your app. Some things to consider:
What is your custom controller doing? Is it mostly changing the visual appearance of its corresponding grid row? If so, perhaps it would be more appropriate to subclass the UIView itself.
If this object is really behaving as a controller and not a view, consider implementing it as a subclass of NSObject rather than subclassing UIViewController. The UIViewController for your screen can capture events and delegate them to the appropriate custom controller object, or your custom views can capture their own events and notify their associated controllers of those events directly using a delegate pattern.
If you're sure you have a valid reason to implement these objects as UIViewController subclasses, check out my answer to this question.

Custom UIView built with Interface Builder accessible/positionable via Interface Builder

This shouldn't be this confusing. I have a custom UIView with a bunch on controls on it. UILabels, buttons, etc. I've created this Nib using Interface Builder. I want to be able to position this custom uiview on another UIView using the interface builder.
How do I link my UIView custom class, to the nib? initWithCoder gets called, but I want this class to get loaded from the nib.
Thanks
For this to work, you have to create a plug-in for Interface Builder that uses your custom control's class. As soon as you create and install your plug-in, you will be able to add by drag and drop, instances of your view onto another window or view in Interface Builder. To learn about creating IB Plugins, see the Interface Builder Plug-In Programming Guide and the chapter on creating your own IB Palette controls from Aaron Hillegass's book, Cocoa Programming for Mac OS X.
Here is the link to the original author of the accepted answer to a similar question.
You only need to make a plugin if you want the custom view to draw correctly in the nib you are using it. You can make a custom control and then have it show as a blank rectangle until instantiated during run right now.
How do I get a view in Interface Builder to load a custom view in another nib?
You can insert a UIViewController object using Interface Builder, and then set the UIViewController's "Nib name" property.
I don't know if this messes up your model, but I think it's the only way to do what you're trying to do.
In IB bring up the Identity Inspector tool (Command-4) then select your custom view and in the Class pop-up choose the name of your custom class instead of generic UIView. You may want to connect it to an ivar as well. In your ViewController declare an instance of your custom class with an IBOutlet in front of it. Then go back and bring up the Connections Inspector and connect your view to the ivar by click-dragging from the custom-view's referencing outlet to the File's Owner (which should be an instance of your ViewController) and choosing the ivar name.
When your NIB is loaded it should be creating an object of that type and connecting it to that variable.