Altering the UIButton behaviour by subclassing - ios

I want to create a check box button which will be used throughout my application at many places. The one basic behaviour I wanted for this button was to alternatively changed its state when the button was tapped. So I subclassed this button and wrote the following class. Basically it just adds one extra target method to button in the -awakeFromNib function.
//
// CheckBoxButton.h
// CheckBoxButton
//
// Created by Ankit Srivastava on 11/07/13.
// Copyright (c) 2013. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface CheckBoxButton : UIButton
#end
here is the .m
/
// CheckBoxButton.m
// CheckBoxButton
//
// Created by Ankit Srivastava on 11/07/13.
// Copyright (c) 2013. All rights reserved.
//
#import "CheckBoxButton.h"
#implementation CheckBoxButton
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)awakeFromNib{
[self addTarget:self action:#selector(alterState:) forControlEvents:UIControlEventTouchUpInside];
}
-(void) alterState:(UIButton*)sender {
[self setSelected:!self.isSelected];
}
#end
Now I add the button via xib and just change its base class to CheckBoxButton.
Every thing works fine but I have heard that UIButton should not be subclassed but I couldn't find any documented proof and also I am just adding a method to the button to change its state. So my question is whether this approach is OK..?
Thanks for your inputs.

I've subclassed UIButton several times. It's a class cluster so there are potential issues when doing so, but I have yet to run into any show stoppers.

Related

How to return number keypad in swift [duplicate]

Hi I find some questions like that but they talk about textView, I have ViewController, with scrollView where are 6 textfield and one textView I want a function which makes the keyboard disappear on on done/return button click.I implemented functions resign to first responder, which hide my keyboard when i click outside of scrollView, but that is not exactly i want, because i like to make it disappear on button click too.
THanks for any help
Set up a class that conforms to the UITextFieldDelegate protocol and make the delegate of your text fields an instance of this class. Implement the method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
As follows:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Hi i found it out so the point with textfields is to add this lines at viewdidload:
textFieldOne.returnKeyType = UIReturnKeyDone;
textFieldCislo.delegate = self;
textFieldTwo.returnKeyType = UIReturnKeyDone;
textFieldCislo.delegate = self;
...
And this implement method :
-(BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == textFieldOne) {
[textFieldOne resignFirstResponder];
}
...
}
U can use this method to hide the keyboard by clicking any where in the view
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
After quite a bit of time hunting down something that makes sense, this is what I put together and it worked like a charm.
.h
//
// ViewController.h
// demoKeyboardScrolling
//
// Created by Chris Cantley on 11/14/13.
// Copyright (c) 2013 Chris Cantley. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITextFieldDelegate>
// Connect your text field to this the below property.
#property (weak, nonatomic) IBOutlet UITextField *theTextField;
#end
.m
//
// ViewController.m
// demoKeyboardScrolling
//
// Created by Chris Cantley on 11/14/13.
// Copyright (c) 2013 Chris Cantley. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// _theTextField is the name of the parameter designated in the .h file.
_theTextField.returnKeyType = UIReturnKeyDone;
[_theTextField setDelegate:self];
}
// This part is more dynamic as it closes any text field when pressing return.
// You might want to control every single text field separately but that isn't
// what this code do.
-(void)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
}
#end

Composing iOS Views

I've created a view with a logout button and I'm trying to make that a subview of another view. The logout button view has a xib and a controller associated with the xib.
How do I make it so that this view/controller is a part of my other view?
The way I've done this before is by having a view that draws itself programmatically, drawing that view in the interface builder as part of another view and changing the class for that view. As I want that view to respond to methods, I made it have a protocol and then made the controller it was a subview of implement that.
Is that the only way to do it? Or is there a way such that I have an independent controller for my logout view that I can just 'drop in' into other views, because the drawback of the other method is that every view that wants to use this subview has to implement the protocol, even if that method is going to be the same in every view.
Create a superclass to abstract the logout behavior. Then, each UIViewController that supports the logout should subclass that superclass. In the superclass, provide the method for logout.
This approach will enable you to either simply hook up UIControls in Interface Builder to the common IBAction in the superclass, or alternatively, even add specific customization in the subclass before invoking the superclass method.
Here's one possible example:
LogoutViewController.h
#import <UIKit/UIKit.h>
#interface LogoutViewController : UIViewController
-(void)performLogout;
#end
LogoutViewController.m
#import "LogoutViewController.h"
#interface LogoutViewController ()
#end
#implementation LogoutViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)performLogout
{
//do logout code
}
- (IBAction)logout:(id)sender
{
[self performLogout];
}
#end
SomeOtherViewController.h
#import <UIKit/UIKit.h>
#import "LogoutViewController.h"
#interface SomeOtherViewController : LogoutViewController
#end
SomeOtherViewController.m
#import "SomeOtherViewController.h"
#implementation SomeOtherViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)mySpecificLogoutButtonPressed:(id)sender
{
self.title = #"Good bye";
// do other code specific to logging out from this UIVC
[super performLogout];
}
#end
You can use NSNotificationCenter for this. So you can post the notification on logout button action. You can check the documentation.
Hope this helps.

Hide/Show & Enable/Disable a button ?

I'm quite new at iOS development and I'm facing some trouble with hiding/showing button in my GUI. Because I need some buttons to appear or disappear and to be enabled or disabled. I followed some great tutorials over the net but can not figure out what is going wrong with my code.
Here is my ViewController.h :
/
// ViewController.h
// WeddingVideoBooth
//
// Created by Frédéric Mouza on 15/07/13.
// Copyright (c) 2013 Frédéric Mouza. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController{
IBOutlet UIButton *but_record;
}
#property (nonatomic,retain) IBOutlet UIButton *but_record;
- (IBAction)but_record:(UIButton *)sender;
#end
and my .m file :
//
// ViewController.m
// WeddingVideoBooth
//
// Created by Frédéric Mouza on 15/07/13.
// Copyright (c) 2013 Frédéric Mouza. All rights reserved.
//
#import "ViewController.h"
#import "MobileCoreServices/UTCoreTypes.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize but_record;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
but_record.hidden=YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)but_record:(UIButton *)sender {
but_record.enabled=NO;
}
#end
It's very simple and, to understand, I just would like the button to disable when you click on it... Currently, the button remains the same when you click on it. I also tried to hide it using the property "but_record.hidden=YES" but nothing worked.
Does somebody have an idea, please ?
Thanks again
Add an NSLog() into your but_record to see if the IBAction is actually getting called. It sounds like that is not triggering as you probably didn't link them together in your Interface Builder. And as mentioned above take out the hidden=YES
Ok, just to wrap-up and properly close the question.
It's probably obvious for most of you but when dealing with interface one has to be careful:
if you create a button, link it to the interface, give it properties... and then you copy it Xcode keeps the previous link in the copy and if you create a new link by control+drag in your .h file, the previous link remains and may supersede the new one.
Therefore, to prevent this, you have to remove the existing links from the link tab after you copied a button but before you create a new link.
That worked for me.
Hope this will help,
Fred

NSLog not working when I make a method call in objective c

I'm working on my first ground-up iOS app. I'm sure I'm doing something wrong here, but I can't seem to ferret out the problem.
I have an app with some IBActions in it, which do two things:
1) Outputs some simple text via NSLog (to let me know the action worked) - this works okay (it outputs my text via NSLog)
2) Makes a call to a method in a custom class which should also output an NSLog statement. - this doesn't work (no text output via NSLog)
I'm also struggling a bit with where to create the instances of my classes so that they are accessible elsewhere in my code.
Here's the code:
//
// ViewController.h
// OrcAndPie
//
// Created by me on 4/27/13.
// Copyright (c) 2013 me. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "Player.h"
#import "Orc.h"
#interface ViewController : UIViewController {
// Variables that you want to access globally go here?
Player *wizard;
Orc *grunty;
}
-(IBAction)takePie:(id)sender;
-(IBAction)castFireball:(id)sender;
-(IBAction)attack:(id)sender;
#end
and
//
// ViewController.m
// OrcAndPie
//
// Created by me on 4/27/13.
// Copyright (c) 2013 me. All rights reserved.
//
#import "ViewController.h"
#import "Player.h"
#interface ViewController ()
#end
#implementation ViewController
-(IBAction)takePie:(id)sender{
// Player attempts to take the pie
// If Orc's health is > 0, don't let the player take the pie
// If the Orc's health is <= zero, let the player take the pie
NSLog(#"IBAction - player attempted to take the pie.");
[wizard takePie];
}
-(IBAction)castFireball:(id)sender{
NSLog(#"IBAction - player cast fireball.");
[wizard castFireball];
}
-(IBAction)attack:(id)sender{
NSLog(#"IBAction - player attacked.");
[wizard attackOrc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Player *wizard = [[Player alloc]init];
Orc *grunty = [[Orc alloc]init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
and
//
// Player.h
// OrcAndPie
//
// Created by me on 4/27/13.
// Copyright (c) 2013 me. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface Player : NSObject
#property int maxHealth;
#property int currentHealth;
#property int armorClass;
#property int meleeToHitModifier;
-(void)setHeathBar;
-(void)attackOrc;
-(void)castFireball;
-(void)takePie;
#end
and
//
// Player.m
// OrcAndPie
//
// Created by me on 4/27/13.
// Copyright (c) 2013 me. All rights reserved.
//
#import "Player.h"
#implementation Player
#synthesize maxHealth;
#synthesize currentHealth;
#synthesize armorClass;
#synthesize meleeToHitModifier;
-(void)setHealthBar {
NSLog(#"Player health is 15");
return;
}
-(void)attackOrc {
// roll a d20
// add the "to hit" modifier
// compare the result to the orc's armor class
NSLog(#"Player - Player attached the Orc");
return;
}
-(void)castFireball{
NSLog(#"Player - Player casts Fireball");
return;
}
-(void)takePie{
NSLog(#"Player - Player attempts to take pie");
return;
}
#end
Note: I also have an Orc class defined, but it looks fairly identical to the player class shown.
Thanks in advance for the help!
-- Eddie
Your ViewController.h (which you should call by some more distinctive name, FYI) should look like this:
//
// ViewController.h
// OrcAndPie
//
// Created by me on 4/27/13.
// Copyright (c) 2013 me. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "Player.h"
#import "Orc.h"
#interface ViewController : UIViewController
#property Player *wizard;
#property Orc *grunty;
-(IBAction)takePie:(id)sender;
-(IBAction)castFireball:(id)sender;
-(IBAction)attack:(id)sender;
#end
Then in your ViewController.m, your viewDidLoadMethod should look like:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.wizard = [[Player alloc]init];
self.grunty = [[Orc alloc]init];
}
This should at least ensure you have an instantiated instance of Player that you can call methods on, so your NSLog should be reached.

error: "No visible #interface for 'UIAlertView' declares the selector 'initWithTitle'

I am in the process of reading the O'Reilly book Learning Cocoa with Objective-C 3rd edition.
The O'Reilly website doesn't have a forum for this specific book, and searching for this error returns nothing.
On page 18, I keep getting the following error:
"No visible #interface for 'UIAlertView' declares the selector 'initWithTitle:message:deluge:cancelButtonTitle:otherButton'"
Here's my code:
//
// ViewController.m
// HelloCocoa
//
// Created by ME on 1/14/13.
// Copyright (c) 2013 ME. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)showAlert:(id)sender
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Hello!"
message:#"Hello, World!"
delegate:nil
cancelButtonTitle:#"Close"
otherButtonTitle:nil];
[alert show];
[_helloButton setTitle:#"I was Clicked!" forState:UIControlStateNormal];
}
#end
//
// ViewController.h
// HelloCocoa
//
// Created by ME on 1/14/13.
// Copyright (c) 2013 Andrew DiNatale. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIView *helloButton;
- (IBAction)showAlert:(id)sender;
#end
What's causing this error?
The otherButtonTitles parameter is plural (as in otherButtonTitle*s*).
UIAlertView is a UIKit (iOS) class. Looks like you are trying to use it in a Cocoa project, instead of Cocoa Touch.
I'm one of the authors on this book.
This question has already been correctly answered, but I just wanted to chime in - the answer from CodaFi is correct, the issue was that the method ends with "otherButtonTitles" (with an s), rather than "otherButtonTitle".
I just double-checked page 18 of the book, and it actually looks like the book had it correct!
If you have any other questions about the book, post 'em up here - I'll be floating around, looking for any questions that mention the book. Errata is always welcome!

Resources