UIToolbar Subclassing Doesn't work - ios

I'm trying to subclass a UIToolbar but the code doesn't seem to be working when I add the class to a UIToolbar in Interface Builder. What am I doing wrong here? I'm also looking for adding UIBarbuttonitems etc., this is just a test eg., daniel
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//Customization//
UIImage *ToolbarBackgroundImage;
ToolbarBackgroundImage = [UIImage imageNamed:#"DefaultNavBar"];
[self setBackgroundImage:ToolbarBackgroundImage forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[self setShadowImage:[[UIImage alloc] init] forToolbarPosition:UIToolbarPositionAny];
}
return self;
}
-(void)drawRect:(CGRect)rect {
//do nothing//
}

If you are using a storyboard, you should also implement initWithCoder:.
When a storyboard is being loaded, a decoder is used to create objects defined in the storyboard. initWithCoder: comes from the NSCoding protocol, and is a way for classes to deserialize themselves from coders. You can read about it in detail here.
If you wish to support both nibs and storyboards, there is a method available you can implement in your views, awakeFromNib.

Related

Subclassing an UIButton: custom behaviour on "touchUpInside"

I am subclassing an UIButton which is going to be present in all of my app's ViewControllers, kinda Navigation Button. I would like just to put it to my VC and apply custom class, without any code in ViewController itself. So, the questions:
1. is it possible?
2. I am using this code now in my UIButton custom class. What is wrong?:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addTarget:self action:#selector(didTouchButton) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)didTouchButton {
NSLog(#"YEAH, it works, baby!");
}
UPD: seems that even initWithFrame method is not being called at all.
Loading from the nib I think.The initWithFrame method doesn't work if not called programatically.
Try -awakeFromNib Method
See this question

Why 'NSInternalInconsistencyException' happens when overwrite 'initWithCoder' method

I came across the exception 'NSInternalInconsistencyException' when I write the code below in a viewcontroller which is associated with storyboard:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.view.backgroundColor = [UIColor blackColor];
}
return self;
}
However, if I delete the line 'self.view.backgroundColor = [UIColor blackColor];', there is no problem. I don`t know the reason.
Actually, in the stroyboard I have several controllers, and I want to make a base controller for all the controllers. The purpose is that I want to set a background view(UIView) for them.
I try to add a UIView in the viewDidLoad method of the basecontroller, but the view covers any components that set in the storyboard. I think the reason is that the components on the sub viewcontrollers are initialized in the 'initWithCoder' method before the 'ViewDidLoad' method is called. So I try to add the bgView in the 'initWithCoder' method of the basecontroller, and this led to the problem above.
So I also want to know a right way to achieve my purpose. Thanks!
dont set graphics related properties in init and bring subview to front. Set them from
-(void)awakeFromNib
{
[self.view.superview bringSubviewToFront:self.view];
self.view.backgroundColor = [UIColor blackColor];
}

Change the UITableViewStyle for different iOS versions

I have to tableview designs for ios7/6 - in ios6 I need to implement a tableview grouped style and in ios7 I need a plain one. So In storyboards I change the style to plain and in viewDidLoad of the subclass of UITableViewController I have something like this:
if (!IS_OS_7_OR_LATER) {
self = [[UITableViewController alloc] initWithStyle:UITableViewStyleGrouped];
}
But it doesn't work. I tried to use initWithCoder method but can't get the good result. Any help?
- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)
{
bool isLowerOrEqualToSix = (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1);
if (isLowerOrEqualToSix) { // iOS 6 or lower
[super initWithFrame:frame style:UITableViewStyleGrouped];
} else { // iOS 7 or higher
[super initWithFrame:frame style:UITableViewStylePlain];
}
}
This is what you need.
Try subclassing UITableView, and override this method:
-(id)initWithFrame:(CGRect)frame style:(UITableViewStyle)
{
if (!IS_OS_7_OR_LATER) {
[super initWithFrame:frame style:UITableViewStyleGrouped];
} else
[super initWithFrame:frame style:UITableViewStylePlain];
}
Then, on Interface Builder, set the class of your tableView to be the derived class you just created.
As stated in tableview class reference the style property has to be set at initialization. It cannot be changed after this. In code you would do this with if statement checking ios version and initializing with appropriate style. Using storyboards follow this link How to switch to different Storyboard for iPhone 5?

Should we add UITableView in initializer or layoutsubviews method in iOS?

I am designing a Custom UIView for my app.
The UIView will comprise of below components:
UISearchbar
UITableView
My initialiser is below:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_searchBar = [[UISearchBar alloc]initWithFrame:CGRectZero];
_tableView = [[UITableView alloc]initWithFrame:CGRectZero];
_tableView.dataSource = self;
[super addSubView:_searchBar];
[super addSubView:_tableView];
// Initialization code
}
return self;
}
I am planning to set the frame of the _searchBar and _tableView in layoutsubviews method.
But I think think the way I have added the _tableView to super is wrong. Because the moment the _tableView is added to subview the data source methods of the _tableView will be triggered. And this happens even before the creation of the custom class itself.
Is this a correct design?
Can I add just _tableView alone in layoutSubviews as in below manner?
-(void)layoutSubViews{
//Adjust frame
[_tableView removeFromSuperView];
[self addSubView:_tableView];
}
You shouldn't be assigning the UITableViewDataSource in the view. It should be assigned in the ViewController.
You're right. There is no restriction on it. But your question is about design. Imagine something like this:
#implementation CustomViewController
- (void)loadView {
customView = [[CustomView alloc] initWithFrame:CGRectZero];
customView.tableView.dataSource = self;
customView.tableView.delegate = self;
}
With a ViewController, you can control when you initialize your custom view and control when its tableView loads the data. While you can certainly put all of this code into your customView, you will be running into problems much worse than the one you are asking about now.
You should definitely add it in init, because layout sub-views will get called each time you view will resize and will need to re-layout its sub-views.
Layout subviews method is strictly use as a callback telling you that your view will layout, and is used as an override point for any additional layout you wish to make.
Also, as an additional note, it's not good design adding the view using super.

iOS: Dynamic Creation of UISegmentedControl within UIView

I am wanting to create a custom UIView class that will show a dynamic number of UISegmentedControl objects depending on some input. For example, if a client has 5 products in their cart, the UIView should generate 5 UISegmentedControl objects that I will then link with each item.
The problem I am having is getting this to work in a UIView. Here is what I have done so far. I am successfully able to create a UISegmentedControl object and display it programmatically within my main UIViewController. I don't get any display when adding it to my UIView class. Here is the implementation code for the UIView class:
#import "ajdSegmentView.h"
#implementation ajdSegmentView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSArray *itemArray = [NSArray arrayWithObjects:#"Yes", #"No", nil];
UISegmentedControl *button = [[UISegmentedControl alloc] initWithItems:itemArray];
button.frame = CGRectMake(35,44, 120,44);
button.segmentedControlStyle = UISegmentedControlStylePlain;
button.selectedSegmentIndex = 1;
[self addSubview:button];
}
return self;
}
#end
I created a new UIView object via Storyboard and placed it inside the UIViewController scene. I made sure to set the class from the generic UIView class to my new custom class. I added and outlet for the UIView in my UIViewController class. Here is the code inside the implementation of UIViewController:
#import "ajdViewController.h"
#interface ajdViewController ()
#end
#implementation ajdViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.segmentView = [[ajdSegmentView alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
That's all I have tried. I have been searching through a lot of pages and trying to implement this without asking here, but I seem to be looking in the wrong places.
First you need to check ajdSegmentView is UIVIew or UIViewController. It is fine if it is UIView. If it is type of UIViewController then you need to add this line while adding Segment.
[self.view addSubview:button];
In place of:
[self addSubview:button];
And One more thing You forget to add this View to your main after allocating so You can declare like this:
objajdSegmentView = [[ajdSegmentView alloc] init];
[self.view addSubview:objajdSegmentView.view];
I have just added this thing. i got result like this way.
Hope this will work for you.
You're initializing your custom view using the init method, but your initialization for ajdSegmentView is in your initWithFrame: method (which in your case is not getting called).
So replace:
self.segmentView = [[ajdSegmentView alloc] init];
with:
// Change the frame to what you want
self.segmentView = [[ajdSegmentView alloc] initWithFrame:CGRectMake(0,0,100,40)];
Also don't forget to add your view to the view controller's view also.
[self.view addSubview:self.segmentView];
Unless this view is being created with interface builder, in which case you will need to override initWithCoder: in your ajdSegmentView class.
I'm not familiar with Storyboard though, so maybe I'm missing something, but in a standard scenario what I said above will solve your problem.

Resources