I need to create a custom UI component that will satisfy the following:
it will contain a composition of UIViews, Labels, Button and a TableView.
it should be possible to instantiate it programatically - or - placing a UIView in nib editor and change the class in the inspector to my custom component class. (and it would the maintain/keep the main frame values from placed UIView)
I already started experimenting with it, I chose the UIView but it doesn't handle the ..cellForRow... cell method. On the other hand, if I use a UIViewController, then my class change in the inspector doesn't work and the app crashes.
Which one should I choose - UIView, UIviewController or NSObject?
I would go for UIViewController or UITableViewController, since you said you are having a tableView in it. If you do a UIViewController, you would probably have to include another UITableViewController inside it, using addChildViewController, as explained here
I believe the reason why your app is crashing is that you you changed your class superclass from UIView to UIViewController, but in the Interface Builder you still just have a UIView object. You need to change it to a UIViewController in the Interface Builder, and select your class as the File Owner.
If you intend this to be a stand-alone component, with all of the logic contained within the control, then I would base it on a UIViewController, like Apple does with the MFMailComposeViewController. If you want it to be strictly a view, with no built-in logic of its own, but instead delegates that logic, then use a UIView and delegate the table view methods to the controller that is using it.
Related
UPDATE
I solved this question, in the sense, that I got what I wanted on some levels of Do Not Repeat Yourself, see here:
Using the same property name/reference for Outlets in a base class and potential bugs
But I still want to leave this question up as someone might share some uses of base classes and protocols that might provide more elegant solutions then what I came up with.
I have a super class called UITabBarTopLevelViewController, it inherits from UIViewController. I then have some UIViewControllers that I want to inherit from the base class UITabBarTopLevelViewController.
What I want the child classes to do is implement a UINavigationItem property, that is part of a UINavigationBar and the UINavigationBar is in the super UIView for each UIViewController: UITabBarTopLevelViewController. I could, for example, in UIViewController , add the following:
#IBOutlet weak var uiNavItemTitle: UINavigationItem!
Of course the UINavigationItem exists in the Story Board because I dragged a UINavigationBar onto the UIViewController.
But, what I rather do, is ensure implementation of a property called uiNavItemTitle, and its type UINavigationItem, and then also access the property in my base class: UITabBarTopLevelViewController.
If I create a Protocol and inherit from that in my base class UITabBarTopLevelViewController that doesn't seem like the right direction as the property, uiNavItemTitle: UINavigationItem doesn't exist there, its in the child UIViewController that inherits from UITabBarTopLevelViewController.
If, for each child UIViewController I have the following class definition:
class ChildViewController: UITabBarTopLevelViewController, MyProtocol
This kind of works as the MyProtocol can enforce a property to be implemented in ChildViewController but then every ChildViewController has to remember to inherit the UITabBarTopLevelViewController base class and the MyProtocol protocol and that also does not give me a way to access the property uiNavItemTitle: UINavigationItem in my base class UITabBarTopLevelViewController.
My goal is that I want to set the same logo in 5 Views and all 5 Views have a UINavigationBar and a UINavigationItem and I am setting the UINavigationItem.titleView.
I would like to set the logo in one place for all 5 views and enforce the 5 views using a Base class and or Protocol to implement the uiNavItemTitle: UINavigationItem, as well as ensure that the uiNavItemTitle: UINavigationItem property exists at runtime and is accessible to the base class UITabBarTopLevelViewController.
Perhaps I am just over thinking it and I need to handle this in each of the views. I already did create a function that can be called from all 5 views and that function creates the UIImageView logo I need, so that simplifies my code.
I also could create a Custom UI Component but I feel like I need to inherit from UIView for my Custom UI Component as inheriting from UINavigationBar will not give me runtime access to UINavigationItem to set the titleView to my logo. UINavigationBar has no viewDidLoad. And if my Custom UI Component is a UIView it will need height settings and what I want is the UINavigationBar "default" height like it is when I drag into a UIView in the Xcode Story Board.
I feel like I am getting an easy height conforming header across different IPhone devices, using a UINavigationBar and if I use a UIView as the super view containing the UINavigationBar in a Custom UI Component, I will be playing height guessing games of some kind across different iPhone devices or have unexpected height results in certain resolution screens. Not to mention that I will have to resize my super view below a UIView Custom UI Component and I think Swift automatically fits the super view below the UINavigationBar.
I am writing a simple app with custom storyboards for iPhone and iPad. I have a generic viewcontroller class from which my custom iPhone and iPad viewcontrollers inherit. Outlets and IBActions in my storyboards are mostly wired up to the generic viewController class and everything works well.
Now for stylistic reasons I decided to make my iPhone's viewcontroller be a UITableViewController and it can no longer inherit from my generic viewcontroller. I've been googling and searching this site and see advice which says I should write a category and use this in my custom classes.
I have never done this, but I looked at the documentation and understand the concept, but once I move my code into a category, how would I be able to link my storyboard's outlets and actions (ctrl-drag from storyboard) to the methods which are now moved out of my custom viewcontroller classes? Usually I would for example ctrl-drag from a switch in the storyboard to an existing IBAction method in my generic viewController, but these methods will now be inherited and not showing my my custom classes to drag to.
I am just a hobbyist and newb, so I apologize if this question is too basic.
You can use UIViewController with UITableView instead of UITableViewController.
1.In storyboard, get a new UIViewController and linking with your custom viewcontroller class.After that,put an UITableView into that UIViewController and linking with that class using (ctrl-drag from storyboard) called mTableView
2.In that class you should implement <UITabBarControllerDelegate,UITableViewDataSource>.
Use mTableView instead of self.tableView just like in UITableViewController.
I am having issues making UILabels and IBAction buttons in custom classes. Xcode seems to not want me to do it. They way I'm trying to do it is through interface builder (storyboard). I have no issue clicking and dragging to make IBOutlets and IBActions using the main View Controller but when I click and drag over to connect them in a custom class it does nothing. Am I only able to make these in the View Controller? I've attached a pic of me trying to drag over to connect my button in the custom class and you can see that nothing pops up. So basically, Are labels, buttons, text fields etc, for the View Controller class only? Thanks for any feedback.
Within interface builder, you will need to make sure your view controller is using your custom class by opening utilities view on the RHS of the IB, selecting the third icon along (please see picture below) and enter your custom class name in the space provided.
Your custom class will need to be a subclass of UIViewController though, like the picture below, not an NSObject for example.
I'm referring to this line within your .h file ...
#interface MyCustomClassViewController : UIViewController
Your custom class needs to match the UI object you are connecting it with. For example if you had UIView object, your custom class would need to be a subclass of UIView, a UINavigationViewController object, a subclass of UINavigationController etc etc.
I hope this helps.
Select your view controller in the stoyboard and go to the identity inspector, make sure the name there is your custom class name.
I have 30+ viewcontroller in my project, and there is a behavior to be added in 28 of them.
When a button is clicked if 10 second not passed in that viewcontroller, I need to present a alertview sliding from top. (I have already implemented this behaviour for one of them)
But my question is, how can I inherit this behavior in a proper way for all of these viewcontrollers?
Googling this, but cannot find relavent solutions.
If all of your view controllers that need this functionality are subclasses of UIViewController, i.e. not UITableViewController or another subclass of UIViewController, you can create a subclass of UIViewController, say ButtonClickAlertViewController (or whatever makes sense) that implements the functionality you need to replicate. Then have all of the classes that need this functionality subclass your ButtonClickAlertViewController class instead of UIViewController.
You may need to take into account how this specific functionality integrates into each of your individual view controller classes. For example, you may need a method in your ButtonClickAlertViewController class that signals a button has been clicked in order to check your timer and possibly display an alert. In each of your classes that subclass ButtonClickAlertViewController, you might need to call this method in each of the IBAction methods that your button click actions call.
Subclass UIViewController and add your desired behavior for all view controllers and then subclass your existing view controllers from the viewController with the desired behavior.
Inheritance chain:
UIViewController -> ViewControllerWithBehaviorForAll ->
YouExistingViewlContollersWhichNeedTheBehavior
I have a flow issue in my iOS app from my subclassed UIView to its parent UIViewController.
Basically, I have a nib called preferences. It contains two sliders, two labels, and another UIView that will display a shape dictated by the two scroll bars (Stroke and opacity). I successfully painted the subclassed ui to the screen by setting the custom class of the UIView to a separate UIView we'll call subView. I have setters/getters for the scroll bars and they print out their values. How do i let the uiview class (pointed at the ui nib object) to update and redraw since it isn't referenced in the parent preferences class? I tried syntax like this:
[code]
IBOutlet SubClassUIView *subclassUI
[/code]
to no effect. It seems best to point a custom class at the UIView.
Any suggestions and advice would be much appreciated.
TL;DR can't modify subclassed uiview from "parent" uiviewcontroller
Sorry folks, i figured it out.
In addition to passing in a custom class that shares the same type as the IBOutlet (such as a UIView),
there MUST be a link referencing every object in in the .xib to its parent. In this case, the parent UIViewController needed a reference from the custom class ui to a IBOutlet UI. From there, some simple casting from generic and boring UIView to the custom class's unique methods makes for a complete flow.