Constraint in UIView class crash application - objective-c

I have created a UIView class:
UIViewClass.h
#import <UIKit/UIKit.h>
#interface UIViewClass : UIView
#end
UIViewClass.m
#import "UIViewClass.h"
#implementation UIViewClass
- (instancetype)initWithFrame:(CGRect)frame
{
UIButton *doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[doneBtn addTarget:self action:#selector(doneAction:) forControlEvents:UIControlEventTouchUpInside];
[doneBtn setTitle:#"Done" forState:UIControlStateNormal];
[doneBtn.titleLabel setFont:[UIFont fontWithName:#"AvenirNext-Bold" size:20]];
doneBtn.frame = CGRectMake(0, 0, 75, 40);
doneBtn.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:doneBtn];
[self addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"H:|-180-[doneBtn]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(doneBtn)]];
return self;
}
#end
and I call it
UIViewClass *viewClass = [[UIViewClass alloc] initWithFrame:CGRectMake(0,0,150,150)];
When I try to build it, it built with no errors but when I launch the app, the app crashes. I know that the problem is the constraint because without it, it run smoothly. Can someone tell me what is wrong?

You're not invoking the superclass. Always invoke the superclass (super) initializer first.
Further Reading:
Concepts in Objective-C Programming
Example:
self = [super initWithFrame:frame];

Related

How to create UIButton and its #selector in a NSObject

I'm trying to generate a class that can create a UIButton and take care of what happens when you press the button in any view where the button is located. Here is what I'm doing:
Header File:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface CreateButton : NSObject
- (UIButton *)createButton;
#end
Implementation:
#import "CreateButton.h"
#implementation CreateButton
- (UIButton *)createButton
{
// Instanciate the class
CreateButton *classInstance = [[CreateButton alloc] init];
UIButton *testButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 50.0)];
[testButton setBackgroundColor:[UIColor redColor]];
[testButton addTarget:classInstance action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
return testButton;
}
- (void)buttonClicked:(UIButton *)sender
{
NSLog(#"Clicked");
}
#end
And finally, in the a view controller, I initialize the class and get the button:
CreateButton *create = [[CreateButton alloc] init];
UIButton *testButton = [create createButton];
[self.view addSubview:testButton];
Now everything is ok up to this point and I can see the button, however, nothing happens when I click it. Surprisingly, if I move the buttonClicked: method to my view controller it works just fine. I need to keep all the button wiring inside the NSObject. Any help would be greatly appreciated.
Ok, I solved the problem, interesting.
Implementation file will be modified as:
- (UIButton *)createButton
{
UIButton *testButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 50.0)];
[testButton setBackgroundColor:[UIColor redColor]];
[testButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
return testButton;
}
Then, in the view controller, CreateButton class must be pre-defined in the header file #interface section. Then in the implementation:
create = [[CreateButton alloc] init];
and it works! That would be great if you kindly explains this to me.

UIButton below UITableView cannot be clicked

I have a Table View with APParallaxHeader. This creates a view behind the table, which acts as the header of it. My problem is, that I cannot click anything in this header. I've tried overriding -hitTest of the UITableView, but had no success.
Here is my view controller:
#import "TableViewController.h"
#import "UIScrollView+APParallaxHeader.h"
#implementation TableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
[button setTitle:#"Hello" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor redColor]];
[button addTarget:self action:#selector(ping) forControlEvents:UIControlEventTouchUpInside];
[self.tableView addParallaxWithView:button andHeight:320];
}
- (void)ping
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
#end
EDIT:
My further investigation shows, that the problem can be reduced to a simple UIButton below a UITableView. How can you get the tap events with the button?

customize uibarbuttonitem without uiappearance

Is there a way to customize ALL uibarbuttonitems to have a background image without using UIApperance? Unfortunately our codebase has some limitations and we're not able to use UIAppearance so I'm looking for an alternative.
Thanks in advance.
Edit: I was able to do this by subclassing UIBarButtonItem and it works for most of my buttons...but I'm wondering specifically how to do it with default buttons like UITableView edit buttons and UINavigationController backbuttons.
Thanks!
You also can make subclass like this. First i go to make subclass of UIBarButtonItem. My CustomBarButtonItem.h should be like this.
#interface CustomBarButtonItem : UIBarButtonItem
+ (CustomBarButtonItem *)sharedInstance;
- (UIBarButtonItem *)backButtonwithTarget:(id)target andAction:(SEL)action;
#end
then inside my CustomBarButtonItem.m should like this.
#implementation CustomBarButtonItem
static CustomBarButtonItem * _sharedInstance = nil;
+ (CustomBarButtonItem *)sharedInstance
{
if (_sharedInstance != nil)
{
return _sharedInstance;
}
_sharedInstance = [[CustomBarButtonItem alloc] init];
return _sharedInstance;
}
- (UIBarButtonItem *)backButtonwithTarget:(id)target andAction:(SEL)action
{
UIImage *backImage = [UIImage imageNamed:#"back_btn_normal.png"];
UIImage *backPressed = [UIImage imageNamed:#"back_btn_hilight.png"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[backButton setBackgroundImage:backImage forState:UIControlStateNormal];
[backButton setBackgroundImage:backPressed forState:UIControlStateHighlighted];
const CGFloat BarButtonOffset = 5.0f;
[backButton setFrame:CGRectMake(BarButtonOffset, 0, backImage.size.width, backImage.size.height)];
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, backImage.size.width, backImage.size.height)];
[containerView addSubview:backButton];
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:containerView];
return item;
}
#end
Then where ever you want to make custom NavigationItem (Button in the NavigationBar) you can put the code below for me it custom.
- (void)viewDidLoad
{
self.navigationItem.leftBarButtonItem = [[CustomBarButtonItem sharedInstance] backButtonwithTarget:self andAction:#selector(searchButtonTapped:)];
}
All of my code are working fine. Hopefully it will help you.
you can do something like this. just copied it out of my project.
_leftBarButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:[self imageButton]]
style:UIBarButtonItemStyleBordered
target:self
action:#selector(showLeftViewController)];
[navController.navigationBar.topItem setLeftBarButtonItem:_leftBarButton];
To do this: create category on UINavigationBar and override method drawRect
#implementation UINavigationBar (CustomBackground)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"background"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
This code allows you to change background for all UINavigationBar in a project.

IBOutletCollection and initializing Custom Class Instance

I am using the MHRotaryKnob Class and having trouble configuring it so that multiple outlets have the same default settings. It is no problem to get it working with one instance using IBOutlet, but now it is looking for the properties of the MHRotaryKnob class in NSArray.
How exactly do I define rotaryKnob in the implementation so that the settings are relayed to all controls hooked up to IBOutletCollection? The properties in the implementation are defined in MHRotaryKnob.m but now the compiler is looking for it in NSArray.
ViewController.h
#import <UIKit/UIKit.h>
#import "MHRotaryKnob.h"
#interface CBViewController : UIViewController
#property (nonatomic, retain) IBOutletCollection (MHRotaryKnob) NSArray *rotaryKnob;
ViewController.m
#import "ViewController.h"
#import "MHRotaryKnob.h"
#implementation CBViewController;
#synthesize rotaryKnob;
- (void)viewDidLoad
{
[super viewDidLoad];
rotaryKnob.interactionStyle = MHRotaryKnobInteractionStyleSliderVertical;
rotaryKnob.scalingFactor = 1.5f;
rotaryKnob.defaultValue = rotaryKnob.value;
rotaryKnob.resetsToDefault = YES;
rotaryKnob.backgroundColor = [UIColor whiteColor];
rotaryKnob.backgroundImage = [UIImage imageNamed:#"knob_passive.png"];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_passive.png"] forState:UIControlStateNormal];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_highlighted.png"] forState:UIControlStateHighlighted];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"Knob Disabled.png"] forState:UIControlStateDisabled];
rotaryKnob.knobImageCenter = CGPointMake(35.0f, 32.0f);
[rotaryKnob addTarget:self action:#selector(rotaryKnobDidChange) forControlEvents:UIControlEventValueChanged];
An IBOutletCollection is a collection hence why it is backed by an NSArray in this case.
So it might help to rename the ivar to rotaryKnobs to make this fact clear and then use it like this
for (MHRotaryKnob *rotaryKnob in self.rotaryKnobs) {
rotaryKnob.interactionStyle = MHRotaryKnobInteractionStyleSliderVertical;
rotaryKnob.scalingFactor = 1.5f;
rotaryKnob.defaultValue = rotaryKnob.value;
rotaryKnob.resetsToDefault = YES;
rotaryKnob.backgroundColor = [UIColor whiteColor];
rotaryKnob.backgroundImage = [UIImage imageNamed:#"knob_passive.png"];
rotaryKnob.knobImageCenter = CGPointMake(35.0f, 32.0f);
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_passive.png"] forState:UIControlStateNormal];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"knob_highlighted.png"] forState:UIControlStateHighlighted];
[rotaryKnob setKnobImage:[UIImage imageNamed:#"Knob Disabled.png"] forState:UIControlStateDisabled];
[rotaryKnob addTarget:self action:#selector(rotaryKnobDidChange) forControlEvents:UIControlEventValueChanged];
}

iOS subclassing UIControl not responding

im doing a test for subclassing uiControl, but it is not working yet,
here my code:
MainVC.m::
- (void)viewDidLoad
{
[super viewDidLoad];
TesteaContol *tt = [[[TesteaContol alloc]initWithFrame:CGRectMake(20, 20, 80, 30)]autorelease];
[tt addTarget:self action:#selector(ttActiono:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:tt];
}
- (void)ttActiono:(TesteaContol*)message
{
NSLog(#"proyection");
}
TesteaContol.h
#interface TesteaContol : UIControl
TesteaControl.m
#import "TesteaContol.h"
#implementation TesteaContol
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSLog(#"cao");
UIButton *vacas = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[vacas setTitle:#"pingus" forState:UIControlStateNormal]; ;
vacas.titleLabel.textColor = [UIColor blackColor];
vacas.frame = CGRectMake(0, 0, 80, 40);
[vacas addTarget:self action:#selector(vacasPressed:) forControlEvents:UIControlStateNormal];
[self addSubview:vacas];
}
return self;
}
- (void) vacasPressed:(id) sender
{
NSLog(#"vacanio");
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
so I am testing with a uiButton, i see the button, but is not responding to the touches,
what im i missing?
thanks!
There is a problem here:
[vacas addTarget:self action:#selector(vacasPressed:)
forControlEvents:UIControlStateNormal];
The "forControlEvents" part should be of type UIControlEvents which UIControlStateNormal is not. For a regular button, you want to replace UIControlStateNormal with UIControlEventTouchUpInside:
[vacas addTarget:self action:#selector(vacasPressed:)
forControlEvents:UIControlEventTouchUpInside];