Accessing UIButton from another class not working? - ios

I am trying to access my UIButton in my Play class from my CCLayerClass.
The problem is that it is not working!
Here is how I declare it in the Play class:
.h
IBOutlet UIButton *pauseButton;
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
.m
#synthesize pauseButton;
Then in the dealloc:
[pauseButton release];
Also of course I connect it then in Interface builder.
Then in my other class (My CCLayer) class. I try to do this:
Play *play = [[[Play alloc] init] autorelease];
[play.pauseButton setHidden:YES];
The thing is, is that it simply just does not hide the button. Is there any reason for this?
Thanks!
Edit1:
My Play.h
IBOutlet UIButton *pauseButton;
BOOL pauseButtonVisible;
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
#property(readwrite) BOOL pauseButtonVisible;
.m
#synthesize pauseButton;
- (void)setPauseButtonVisible: (BOOL) variableToSet {
pauseButtonVisible = variableToSet;
if(pauseButton)
[pauseButton setHidden: !pauseButtonVisible];
}
- (BOOL) pauseButtonVisible
{
return(pauseButtonVisible);
}
viewWillAppear:
[pauseButton setHidden: !pauseButtonVisible];
I also made sure I connected it in Interface Builder
Then in CCLayerClass I do this:
Play *play = [[[Play alloc] init] autorelease];
if(play.pauseButton == NULL) {
NSLog( #"pause button is NULL");
}
But that NSLog gets called! Why is my pauseButton NULL? I just need to alloc it so it stays alive, is that possible?
Thanks!
play.pauseButtonVisible = YES;

Okay. Hopefully third time is the charm (and after that, I'm giving up cause it's time for me to go to bed).
Here in the .h file, I'm keeping the new pauseButtonVisible BOOL property.
#interface Play : UIViewController
{
BOOL pauseButtonVisible;
IBOutlet UIButton *pauseButton;
}
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
#property(readwrite) BOOL pauseButtonVisible;
#end
But in the .m file, we're doing something a little different:
#interface Play
// here we are rolling our own setters and getters
// instead of #synthesizing...
- (void)setPauseButtonVisible: (BOOL) variableToSet
{
pauseButtonVisible = variableToSet;
if(pauseButton)
[pauseButton setHidden: !pauseButtonVisible];
}
- (BOOL) pauseButtonVisible
{
return(pauseButtonVisible);
}
- (void) viewWillAppear: (BOOL) animated
{
[pauseButton setHidden: !pauseButtonVisible];
[super viewWillAppear: animated];
}
and
Play *play = [[[Play alloc] init] autorelease]; // you should really be using initWithNibName, but anyways
play.pauseButtonVisible = YES;
So now, hopefully pause button will be visible or hidden at the appropriate time for while your code is running.

Related

Passing back info between delegates on ObjectiveC

I need to pass back an NSMutableArray of photos between a CameraSessionView; how store the photos taken from camera on an NSMutableArray, and a TableViewController how uploads this photos to DropBox. I'm using delegates and protocols, but all the ways I tried... fail.
Anyone can help me. I think Im doing some little thing wrong.
I show you some code:
CameraSessionView.h
#class CameraSessionView;
#protocol CameraSessionViewDelegate <NSObject>
#optional
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos;
#end
#property (nonatomic, weak) id <CameraSessionViewDelegate> delegado;
CameraSessionView.m
#property (nonatomic, strong) NSMutableArray* images;
- (void)onTapOkButton{
NSLog(#"Save photos");
if([self.delegado respondsToSelector:#selector(uploadPhotosFromCamera:)])
[self.delegado uploadPhotosFromCamera:_images];
[self onTapDismissButton];
}
PhotosTableViewController.h
#interface PhotosTableViewController : UITableViewController <CameraSessionViewDelegate>
PhotosTableViewController.m
#property (nonatomic, strong) CameraSessionView *camera;
- (void)viewDidLoad
{
_camera = [CameraSessionView new];
[_camera setDelegado:self];
}
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos
{
NSLog(#"UPFC");
for(int x=0; x < [photos count];x++)
{
NSLog(#"UPFC...");
UIImage *foto = [photos objectAtIndex:x];
if (foto.size.height > 1000 || foto.size.width > 1000)
foto = [self imageWithImage:foto scaledToScale:0.15f];
DBMetadata* datos = [TablaSubidas addFile:pathElemento];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSData *data = UIImageJPEGRepresentation(foto, 1.0);
[fileManager createFileAtPath:[self photoPath:datos] contents:data attributes:nil];
[elementosTabla insertObject:datos atIndex:0];
}
[self sincFotos];
[self.tableView reloadData];
}
Only wants that when I press OK button the photos send back to PhotosTableViewController where it would be uploaded to dropbox.
self.delegado on onTapOKButton is always nil.
Looks easy but I cant run it.
I'm so grateful if anyone could help me or recommend me any tutorial...
Thanks!!
Your CameraSessionView instance will be released from memory as soon as viewDidLoad ends. You need to store it in a property in PhotosTableViewController so that it is retained.
Your delegate should also be defined as weak, e.g.
#property (nonatomic,weak) id< CameraSessionViewDelegate >delegado;
Then in your implementation of PhotosTableViewController, you'll need to implement the -(void)uploadPhotosFromCamera:(NSMutableArray*)photos; method.
Also as this method is defined as #optional, you should check if the delegate responds to it before calling it.
if([self.delegado respondsToSelector:#selector(uploadPhotosFromCamera:]){
[self.delegado uploadPhotosFromCamera:_images];
}
This will prevent the app from crashing if the delegate method isn't implemented.
This is working for me. So, you can implement this Directly. Hope, you will get success. Oh! first check without camera activity. Just pass simple array of string to test the delegate
/............*****************
CameraSessionView.h file
/............*****************
#import <UIKit/UIKit.h>
#class CameraSessionView;
#protocol CameraSessionViewDelegate <NSObject>
#optional
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos;
#end
#interface CameraSessionView : UIViewController
#property (nonatomic,weak) id< CameraSessionViewDelegate >delegado;
#end
/............*****************
CameraSessionView.m file
/............*****************
#import "CameraSessionView.h"
#interface CameraSessionView ()
#property (nonatomic, strong) NSMutableArray* images;
#end
#implementation CameraSessionView
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(onTapOkButton)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"OK" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
}
- (void)onTapOkButton{
NSLog(#"Save photos");
_images = [[NSMutableArray alloc]init];
[_images addObject:#"_images1"];
[_images addObject:#"_images2"];
//NSLog(#"from del:%#",_images);
if([self.delegado respondsToSelector:#selector(uploadPhotosFromCamera:)])
[self.delegado uploadPhotosFromCamera:_images];
[self onTapDismissButton];
}
-(void)onTapDismissButton{
[self.view removeFromSuperview];
}
#end
/............*****************
DetailViewController.m file
/.........********
#import "DetailViewController.h"
#import "CameraSessionView.h"
#interface DetailViewController ()<CameraSessionViewDelegate>
#end
#implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
CameraSessionView *Camara= [[CameraSessionView alloc]initWithNibName:#"CameraSessionView" bundle:nil];
[Camara setDelegado:self];
[self.navigationController pushViewController:Camara animated:YES];
}
-(void)uploadPhotosFromCamera:(NSMutableArray*)photos{
NSLog(#"success:%#",photos);
}
#end
If you have to pass data from B View Controller To A view Controller
Create protocol in B View Controller as
#protocol BViewControllerDelegate <NSObject>
-(void)didclickonSubmit:(NSArray*)selected_array;
#end
Create an id, so that you can assign any class as its delegate class.
#property (weak,nonatomic) id<BViewControllerDelegate> delegate;
Call this method in B View Controller on submit button or wherever required.
if (self.delegate && [self.delegate respondsToSelector:#selector(didclickonSubmit:)])
{
[self.delegate didclickonSubmit:myarray];
}
Create an object of B View Controller in View Controller A and assign A as delegate of B
BViewController *b = [[BViewController alloc]init];
b.delegate=self;
Implement required protocol methods of B in A and access the array
-(void)didclickonSubmit:(NSArray*)array
{
NSArray *myarray =[[NSMutableArray alloc]initWithArray:array];
}
now you can use myarray,as u like it..
hit link for sample project
https://www.dropbox.com/s/002om8efpy6fout/passDataToPreviousContoller.zip
Hope it helps..
****EDITED****
u can for sure assign tableViewController as delegate of UIView class.
#protocol BView <NSObject>
-(void) didclickonSubmit:(NSArray*) selected_array;
#end
#interface BView : UIView
#property (weak,nonatomic) id<BView> delegate;
#end
in A i.e. your tableViewController create an object of B and assign your tableview controller as delegate of B .
BView *b=[[BView alloc]init];
b.delegate=self;
Happy Coding..:)

How to get UITextField from inputAccessoryView button click

I have a dynamic number of UITextFields which all have an inputAccessoryView. This is composed of a UIToolbar which has a button on it. When this button is pressed it calls a method, however, within this method I somehow need the ability to access the underlying UITextField.
Please could someone advise how this is possible?
// Create the toolbar controls
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(navigationBarDoneButtonPressed:)];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
// Setup the toolbar
navigationToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(10.0, 0.0, 310.0, 40.0)];
[navigationToolbar setItems:#[flexibleSpace, doneButton]];
// In a UITableView I create a number of cells which contain UITextFields....
// This is the method that gets called when a user presses the done button
- (void)navigationBarDoneButtonPressed:(id)sender
{
NSLog(#"Based on sender I need to access the underlying UITextField.");
}
You can keep track of the currently focused UITextField in a variable, and use that variable in your inputAccesoryView method:
in your .h file: make sure you're conforming to the UITextFieldDelegate protocol:
#interface MyViewController : UIViewController <UITextFieldDelegate>
and add this property:
#property (assign, nonatomic) UITextField *activeTextField;
In your .m file: While creating your dynamic textfields:
...
theTextField.delegate=self;
...
And add these implementations of the UITextFieldDelegate protocol:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
self.activeTextField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
self.activeTextField = nil;
}
And now, in the method invoked by your inputAccesoryView:
- (void)navigationBarDoneButtonPressed:(id)sender{//Just an example
self.activeTextField.text=#"Test";
}
I would create UITableViewCell subclass with delegate, e.g.
MyTextEditTableViewCell.h
#class MyTextEditTableViewCell;
#protocol MyTextEditTableViewCellDelegate <NSObject>
- (void)didDoneButtonPressed:(MyTextEditTableViewCell *)sender;
#end
#interface MyTextEditTableViewCell : UITableViewCell
#property (nonatomic, weak) id<MyTextEditTableViewCellDelegate> delegate;
#property (nonatomic, strong) UITextField *textField;
#end
MyTextEditTableViewCell.m
#implementation MyTextEditTableViewCell
- (void)navigationBarDoneButtonPressed:(id)sender
{
// Call delegate
if (self.delegate)
[self.delegate didDoneButtonPressed:self];
}
#end
Your UIViewController subclass (Or UITableViewController)
...
- (void)didDoneButtonPressed:(MyTextEditTableViewCell *)sender {
UITextField *cellTextField = sender.textField;
// do some stuff with text field
}
Don't forget to set delegate to cell when you will config it.

Possible to use a getter to configure UIButtons an d UIViews in iOS?

I regularly use lazy loading to instantiate custom classes, arrays, etc. The pattern is typically:
#property (strong, nonatomic) Class *class;
...
- (Class *)class
{
if(!_class) _class = [[Class alloc]init];
return _class;
}
Is it possible to use the same pattern to configure UI elements? For example, instead of formatting all my buttons and views in ViewWillAppear, I would like to put the formatting in the getter. For example:
- (UIButton *)button
{
if(!_button) {
_button = [[UIButton alloc]init];
self.button.backgroundColor = [UIColor redColor];
}
return _button;
}
The problem is I am using a storyboard and XCode instantiates the button so asking if it is nill should always return false. So the background will never be changed. If I remove the if-then, then the background will be set every time the getter is accessed which is probably OK but not optimal.
So, how do I use a UI element's getter to configure the element?
If this is really the way you want to do it, just use a BOOL flag. For example:
#interface MyClass() {
BOOL _hasCustomisedButton;
}
#property (strong, nonatomic) UIButton *button;
#end
#implementation MyClass
- (UIButton *)button {
if (_hasCustomisedButton || _button == nil) {
// check for nil button as well in case the nib isn't loaded yet
return _button;
}
[_button setBackgroundColor:[UIColor redColor]];
_hasCustomisedButton = YES;
return _button;
}
#end

Send a Delegate message from UIPopover to Main UIViewController

I'm trying to use a Button in my UIPopover to create a UITextView in my Main UIViewController the code I have looks something like this (PopoverView.h file):
#protocol PopoverDelegate <NSObject>
- (void)buttonAPressed;
#end
#interface PopoverView : UIViewController <UITextViewDelegate> { //<UITextViewDelegate>
id <PopoverDelegate> delegate;
BOOL sendDelegateMessages;
}
#property (nonatomic, retain) id delegate;
#property (nonatomic) BOOL sendDelegateMessages;
#end
Then in my PopoverView.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton * addTB1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
addTB1.frame = CGRectMake(0, 0, 100, 50);
[addTB1 setTitle:#"Textbox One" forState:UIControlStateNormal];
[self.view addSubview:addTB1]; // Do any additional setup after loading the view from its nib.
[addTB1 addTarget:self action:#selector(buttonAPressed)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonAPressed
{
NSLog(#"tapped button one");
if (sendDelegateMessages)
[delegate buttonAPressed];
}
And also in my MainViewController.m :
- (void)buttonAPressed {
NSLog(#"Button Pressed");
UITextView *textfield = [[UITextView alloc] init];
textfield.frame = CGRectMake(50, 30, 100, 100);
textfield.backgroundColor = [UIColor blueColor];
[self.view addSubview:textfield];
}
I'm using a delegate protocol to link the popover and the ViewController but I'm stuck on how I get my BOOL statement to link the -(void)buttonAPressed in the PopoverView and MainViewController so that when I press the button in the Popover a textview appears in the Main VC. How would I go about doing this?
In MainViewController, where you create PopoverView, be sure to set its delegate property otherwise sending messages to delegate in PopoverView will do nothing.
For example, in MainViewController.m:
PopoverView *pov = [[PopoverView alloc] initWithNibName:nil bundle:nil];
pov.delegate = self; // <-- must set this
thePopoverController = [[UIPopoverController alloc] initWithContent...
I am not sure why you need the sendDelegateMessages variable. Even with that bool, you must set the delegate property so PopoverView has an actual object reference to send the messages to.
If you want to make sure the delegate object has implemented the method you're about to call, you can do this instead:
if ([delegate respondsToSelector:#selector(buttonAPressed)])
[delegate buttonAPressed];
Also, the delegate property should be declared using assign (or weak if using ARC) instead of retain (see Why use weak pointer for delegation? for an explanation):
#property (nonatomic, assign) id<PopoverDelegate> delegate;
Another thing is if you're not using ARC, you need to add [textfield release]; at the end of the buttonAPressed method in MainViewController to avoid a memory leak.

UISwitch is not working

First my .h file:
#interface SettingsViewController : UIViewController <UINavigationControllerDelegate>
{
IBOutlet UISwitch *gravaSwitch;
...
}
#property (retain, nonatomic) UISwitch *gravaSwitch;
...
#end
My viewDidload in .m file (it works):
...
// SET SWITCH BUTTON STATE
keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"TrafficApp" accessGroup:nil];
if ( [[keychain objectForKey:(id)kSecAttrAccount] isEqualToString:#"" ] )
[self.gravaSwitch setOn:FALSE];
else [self.gravaSwitch setOn:TRUE];
...
But my switchChanged doesn't work and I don't know why. On IB everything is right connected, it enters in this method but gravaSwitch is always null.
- (IBAction)switchChanged:(id)sender
{
if ( self.gravaSwitch.on )
{
NSLog(#"IF");
[self.gravaSwitch setOn:FALSE animated:YES];
}
else
{
NSLog(#"ELSE");
[self.gravaSwitch setOn:TRUE animated:YES];
}
}
Regards.
I think the error is the following:
#interface SettingsViewController : UIViewController <UINavigationControllerDelegate>
{
UISwitch *gravaSwitch;
...
}
#property (retain, nonatomic) IBOutlet UISwitch *gravaSwitch;
...
#end
IBOutlet placeholder has to be inserted into #property. Change your code and try to connect your outlet again.
Edit:
Try to create your UISwitch programatically. Change your #property as the following:
#property (retain, nonatomic) UISwitch *gravaSwitch;
Leave #synthesize as is. Then in your viewDidLoad method add your UISwitch (by default on property is FALSE):
// Width and height are set to zero but they take the default dimension
UISwitch *yourSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(100, 100, 0, 0)];
// add target and action
mySwitch addTarget:self action:#selector(yourCustomAction:) forControlEvents:UIControlEventValueChanged];
self.gravaSwitch = yourSwitch;
// don't forget because gravaSwitch has already a retain policy
[release yourSwitch];
// add the switch to the view
[self.view addSubview:self.gravaSwitch];
Within the same controller, but outside the viewDidLoad method, add the following method:
- (void)yourCustomAction:(id)sender
{
if ( self.gravaSwitch.on )
{
NSLog(#"IF");
[self.gravaSwitch setOn:FALSE animated:YES];
}
else
{
NSLog(#"ELSE");
[self.gravaSwitch setOn:TRUE animated:YES];
}
}
- (void)dealloc
{
self.gravaSwitch = nil; // remember to dealloc the switch!!
[super dealloc]
}
You could call self.gravaSwitch = nil; also in viewDidUnload method.
As an alternative you can set gravaSwicth to assign policy as follow. In this case you haven't to call self.gravaSwitch = nil; both in dealloc and/or viewDidUnload.
#property (assign, nonatomic) UISwitch *gravaSwitch;
Hope it helps.
Edit 2:
This code works for me. This is the implementation (.m file) for MyViewController.
#synthesize gravaSwitch;
- (void)viewDidLoad
{
[super viewDidLoad];
UISwitch *yourSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(100, 100, 0, 0)];
[yourSwitch addTarget:self action:#selector(yourCustomAction:) forControlEvents:UIControlEventValueChanged];
self.gravaSwitch = yourSwitch;
[yourSwitch release];
[self.view addSubview:self.gravaSwitch];
}
- (void)yourCustomAction:(id)sender
{
if(self.gravaSwitch.on)
{
NSLog(#"on");
}
else
{
NSLog(#"off");
}
}
where gravaSwicth is declared within MyViewController.h as follows:
#interface MyViewController : UIViewController
{
UISwitch *gravaSwitch;
...
}
#property (retain, nonatomic) UISwitch *gravaSwitch;
...
#end
rembember to call self.gravaSwicth = nil in dealloc in MyViewController.m!!
FWIW I had this problem when my UISwitch was in a UITableViewCell, and I put it at the top of the list of subviews in Interface Builder (and therefore beneath the other views in the cell when running). It worked in a develop build but not a production build for who knows what reason. In prod, I would click on the UISwitch and the whole row would blink ask if selected.
So I moved it to the bottom of the list (and therefore above the other views in the cell when running) and then I could click on the UISwitch.
-(IBAction)alarmSwitchToggled:(id)sender
{
if ([switchAlarm isOn]) {
NSLog(#"switch is ON");
}
else
{
NSLog(#"switch is OFF");
}
}
Give proper connections in nib file and dont forget to make it as valuechanged instead of touchupinside

Resources