How to create UIButton and its #selector in a NSObject - objective-c

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.

Related

Constraint in UIView class crash application

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];

Program a UIButton to change UILabel

I am trying to use Objective-C in iOS Single View app to program a UIButton to change the text in a UILabel. Is there a way to run a function for this to be implemented in my "ViewController.m" file?
Here is my Source Code:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)loadView {
//UIBUTTON
//allocate the view
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
//set the view's background color
self.view.backgroundColor = [UIColor whiteColor];
//create the button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//set the position of the button
button.frame = CGRectMake(50, 280, 280, 50);
//set the font size of the button
button.titleLabel.font = [UIFont systemFontOfSize:40];
//set the text color of the button, before it is pressed
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
//set the text color of the button, while it is pressed
[button setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
//set the button's title
[button setTitle:#"3" forState:UIControlStateNormal];
//listen for clicks
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
//add the button to the view
[self.view addSubview:button];
//UILABEL
UILabel *Question=[ [UILabel alloc] initWithFrame:CGRectMake(10,200,350,60)];
Question.text=#"How many horns does a Triceratops have?";
Question.backgroundColor = [UIColor grayColor];
Question.textColor = [UIColor whiteColor];
Question.font=[UIFont fontWithName:#"Helvetica" size:18 ];
[self.view addSubview:Question];
}
-(void)buttonPressed { }
#end
Is it possible to trigger the change in text in my buttonPressed function? Thanks so much for anybody's help!
The problem is that when you create your label and add it to the interface...
UILabel *Question=[ [UILabel alloc] initWithFrame:CGRectMake(10,200,350,60)];
// ...
[self.view addSubview:Question];
...you didn't keep a reference to it. So now, in buttonPressed, you have no way to talk about the label.
Make a property:
#interface ViewController ()
#property (nonatomic, weak) UILabel* questionLabel;
#end
... and when you create the label, remember to set that property to that label. Now you will be able to access the text of that label later on, in buttonPressed (or anywhere else), through the property.

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?

How to Show and Hide UISearchDisplayController's UISearchBar

I have a button search that located in the right side of the navigation.
This is my code:
UIButton *btnSearch = [UIButton buttonWithType:UIButtonTypeCustom];
btnSearch.frame = CGRectMake(0, 0, 22, 22);
[btnSearch setImage:[UIImage imageNamed:#"search_btn.png"] forState:UIControlStateNormal];
[btnSearch addTarget:self action:#selector(showSearch:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *searchItem = [[UIBarButtonItem alloc] initWithCustomView:_btnSearch];
self.navigationItem.rightBarButtonItems = searchItem ;
This is how it's look.
And I want to display search bar after clicked on the search button, and close it after clicked on cancel and then show the Navigationbar back, but I don't know how to code it.
- (IBAction)showSearch:(id)sender{
???
}
This what I want.
Please help or provide some sample code. I really need it.
Thank for reading.
Add a property UISearchBar *mySearchBar to your viewController as
#property(nonatomic, retain) UISearchBar *mySearchBar;
Conform to UISearchBarDelegate as
#interface HomeViewController () <UISearchBarDelegate>
...
...
#end
Then implement the showSearch method as
-(void)showSearch:(id)sender {
if(!mySearchBar) {
mySearchBar = [[UISearchBar alloc] init];
[mySearchBar setFrame:CGRectMake(0, 0, self.view.frame.size.width, 55)];
[mySearchBar setShowsCancelButton:YES animated:YES];
[self.view addSubview: mySearchBar];
mySearchBar.delegate = self;
self.navigationController.navigationBarHidden = YES;
}else {
searchBar.alpha = 1.0;
self.navigationController.navigationBarHidden = YES;
}
Then implement the search bar delegate method as :
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
self.navigationController.navigationBarHidden = NO;
[mySearchBar setAlpha:0.0];
}
Hope you have got the idea by doing this. Also you can add it directly to navigation controller, itself, if you want & then play with Showing/ hiding the searchBar alone.
You can add it to navigation controller as just initialize the mysearchBar & add it to navigationBar as :
UIBarButtonItem *searchBarItem = [[UIBarButtonItem alloc] initWithCustomView:mySearchBar];
self.navigationItem.rightBarButtonItem = searchBarItem;

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.