Custom Objects and Storyboards - ios5

Are Custom Objects (the little orange cubes) still supported when using storyboards?
Details: I was making a sample iOS App using storyboards and I added a custom object mapping a class which only had a button and a method for that button and I started getting strange errors. I removed this custom object and added the button and the method to the view controller class and everything worked as expected; this lead me to believe that something changed in the way custom objects worked when using storyboards, am I correct?

The orange cubes only instantiate objects at wake-up. They're not really meant to add views. For example I use a few orange cubes to instantiate extra UIViewControllers and then I link them to outlets in my parent UIViewController. This gives me a nice clean way to create a number of child UIViewControllers for the parent UIViewController. It was pretty much the same as pre-storyboard IB as well. If you wanted a view, the you would add the view. If you wanted an object you could instantiate it by IB or manually in the UIViewController.
Hope this helps.

Related

Subclassing a UITableViewContoller subclass created using Storyboard

In my application, I thought it would be a good idea to create a subclass of UITableViewContoller (call it GenericTableViewContoller) which has a few prototype cells created in Storyboard that are reused throughout the app.
Now, what I wanted to do was to create a subclass of GenericTableViewContoller (say SpecialTableViewController) that has some other prototype cells created in Storyboard that are used only in SpecialTableViewController.
Thus, I have two scenes in my main storyboard, one for GenericTableViewContoller and one for SpecialTableViewController, each with their own set of prototype cells.
The problem I am running into, is that SpecialTableViewController gets nil prototype cells when I call dequeueReusableCellWithIdentifier: for a cell identifier declared in the GenericTableViewContoller scene. Cells declared in the SpecialTableViewController scene dequeue just fine.
Is this expected behavior (I have a strange suspicion it is)? Do I have to call registerNib:forCellReuseIdentifier: in SpecialTableViewController to actually get them registered from the other scene? Any simple way to get around this?
Is this expected behavior (I have a strange suspicion it is)?
Yeah, this is the expected behavior. The core concept here is that the storyboard is a object-instance designer, not a class designer. For example, you're free to make three scenes, each with the same view controller class, but all with different view layouts.
There isn't an simple way to share prototype table cell layouts between different table view instances short of putting them into their own XIB, and using -registerNib:forCellReuseIdentifier: and manual segues.

Is it necessary to create a separate view class when using MVC?

After watching the Stanford iTunesU CS193p online course I have quick question regarding the correct way to implement an MVC design.
Usually when I do an application I set my view up as part of the controller and add UIButtons, UILabels etc. to that. Essentially the controller and the view become one, unless you count the UIObjects as being the view objects
In one of the early CS193p examples the tutor splits the view off from the controller as a separate object (subclassing UIView), before implementing a protocol and delegate property on the view which the controller object then conforms to.
I am just curious about the practicality of the CS193p design, I can understand that splitting off the view better represents the MVC design paradigm (especially as a teaching aid) but slightly sceptical of its application in real world applications.
Think about the "view" as objects such as UIButton and UIImageView; re-usable components that don't necessarily know anything about the rest of your application. Your view controller is the object responsible for configuring the view objects and managing their state.
There are times when you'll want to subclass UIView, mostly when you need to do custom drawing in drawRect:. You wouldn't subclass UIView to customize behavior though, that's what your view controller is for. For example, you wouldn't subclass UITableView and just to make the table view its own delegate. Instead you'd make your view controller the table view's delegate.
With iOS, the UIView class implements drawing refresh and touch handlers, not the view controller class. If you need drawRect: or touchesBegan:, etc., you will need a separate UIView subclass.
This partially could be because this is how buttons and labels themselves behave as well. They redraw themselves, and delegate processed touches. The view controller doesn't draw their content and track xy locations.
It's not strictly necessary. If you use Interface Builder, most of the reasons why you would build a custom view (breaking UI setup code out of your business code) are taken care of. However, if you want to build custom actions to your view, or setup some properties that you can't quite get at with IB, then it would make sense to split off your view into a separate class.

Custom UIView from Interface Builder

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.

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.

Loading a View from IB

This should be a pretty easy fix, but I haven't figured out from reading the Apple documentation or other SO questions how to do this simple switch from creating my Interface programmatically to using Interface Builder.
I am basing my code around this framework:
http://www.pushplay.net/blog_detail.php?id=27
The only difference is that, where each View is programmatically created (View01.m, View02.m) in ViewDidLoad, I instead want to import from a nib (while still using this framework) for each view (each view has a unique IB design).
Thanks for the help.
Think of IB as an Object Creator and not a code generator. That really helps. What IB does is actually create instances of objects as they are dragged on to the desktop/view/XIB window. It then allows you to start creating various connections (with a control drag on the mouse) from one object to another object. You then instantiate the entire XIB by unarchiving it from your bundle. This is highly automatic and reading up on UIViewController should move you along a bit. Look at:
initWithNibName:bundle:
You basically have two types of connections:
Outlet: This is how you teach one object about the existence of another object. For example, you might have a controller object that needs access to a button. You create an outlet (either in XCode Text Edit in the controller.h file/property area or in IB by adding an outlet) in your controller and then control-click-drag from the outlet to the button.
Actions: This is how you trigger an event on one object to call a method on another object. Actions will have a prototype of:
- (IBAction) someMethod:(id) sender;
I think the ":(id) sender" is optional if your method does not need a link to the object causing the event.
Within IB, you can arrange objects and set various attributes like size, color, position, target/actions, user interactions, Files Owner...
That brings me to files owner. Big concept here. It tends to be the Controller that loads the NIB (OK: I have a custom window controller I have used for over 15 years but Apple has a really good one UIViewController that does all sorts of goodness.) and acts as a proxy in IB. It is not actually instantiated in IB but it will be when you alloc and request it to load the NIB (XIB files are XML files that are turned into NIB files by the compile process)