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
Related
I have two storyboards and each one has its own respective view controller but I need to change the appearance of the second storyboard based on the button pressed in the first view controller.
In the first view controller I have:
// First view controller .h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface FirstViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIButton *LevelOneButton; // tag 0
#property (strong, nonatomic) IBOutlet UIButton *LevelTwoButton; // tag 1
-(IBAction)selectLevel:(UIButton *)sender; // both buttons connected to this method
#property (assign, nonatomic) int levelSelect;
#end
then in the first .m file:
//FirstViewController.m
-(IBAction)selectLevel:(UIButton *)sender {
if (sender.tag == 0) {
_levelSelect = 0;
}
if (sender.tag == 1) {
_levelSelect = 1;
}
}
This code works fine but the problem occurs in the secondViewController that I have. When I try and access the levelSelect property in the SecondViewController I get the errors "Property 'levelSelect' not found on object of type 'FirstViewController'" or "Unexpected identifier levelSelect" or something among those lines. I've tried every single thing I could think of and every question I found on StackOverflow relating to this but none have fixed the problem. Anyone know what I'm doing wrong?
You should be setting the property on the second view controller as you're pushing or segueing.
So in your first view controller it should look something like this:
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIButton *levelOne;
#property (strong, nonatomic) IBOutlet UIButton *levelTwo;
#property (assign, nonatomic) int selectedLevel;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.levelOne.tag = 1;
self.levelTwo.tag = 2;
}
- (IBAction)selectLevel:(UIButton *)sender
{
if (sender.tag == 1) {
self.selectedLevel = 1;
} else {
self.selectedLevel = 2;
}
[self performSegueWithIdentifier:#"pushToSecond" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SecondViewController *dest = segue.destinationViewController;
dest.levelSelect = self.selectedLevel;
}
#end
Now, when viewDidLoad gets called on the SecondViewController that property will be set and you can use it. Like so:
#import "SecondViewController.h"
#interface SecondViewController ()
#property (strong, nonatomic) IBOutlet UILabel *levelLabel;
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.levelLabel.text = [#(self.levelSelect) stringValue];
}
#end
Quick Edit, if you're not using segues you can do the same thing by pushing manually. Would look something like:
- (IBAction)selectLevel:(UIButton *)sender
{
if (sender.tag == 1) {
self.selectedLevel = 1;
} else {
self.selectedLevel = 2;
}
SecondViewController *secondVC = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"second"];
secondVC.levelSelect = self.selectedLevel;
[self.navigationController pushViewController:secondVC animated:YES];
}
Writing my first iphone app through this tutorial--I have a custom UIView with the method showDie and I have two UIView elements on my storyboard that I've hooked up to my ViewController. However, both the UIView elements have the error message "No visible #interface for 'UIView' declares the selector 'showDie'. I think that's because the UIViews aren't subclassing XYZDieView, but when I control-clicked from my Storyboard, only UIView appeared in the dropdown--no XYZDieView. I tried just changing the text manually in the ViewController.h, but that didn't work (I didn't think it would). Am I on the right track? How do I use my subclass? (xcode 5)
XYZDieView.m
-(void)showDie:(int)num
{
if (self.dieImage == nil){
self.dieImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 90, 90)];
[self addSubview:self.dieImage];
}
NSString *fileName = [NSString stringWithFormat:#"dice%d.png", num];
self.dieImage.image = [UIImage imageNamed:fileName];
}
XYZViewController.h
#import <UIKit/UIKit.h>
#import "XYZDieView.h"
#interface XYZViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *sumLabel;
#property (strong, nonatomic) IBOutlet UIButton *rollButton;
#property (strong, nonatomic) IBOutlet UIView *leftDieView;
#property (strong, nonatomic) IBOutlet UIView *rightDieView;
#end
XYZViewController.m
#import "XYZViewController.h"
#import "XYZDiceDataController.h"
#interface XYZViewController ()
#end
#implementation XYZViewController
- (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)rollButtonClicked:(UIButton *)sender {
XYZDiceDataController *diceDataController = [[XYZDiceDataController alloc] init];
int roll = [diceDataController getDiceRoll];
int roll2 = [diceDataController getDiceRoll];
[self.leftDieView showDie:roll];
[self.rightDieView showDie:roll2];
int sum = roll + roll2;
NSString *sumText = [NSString stringWithFormat:#"Sum is %i", sum];
self.sumLabel.text = sumText;
}
#end
Yes you're right, the problem is subclassing. In order to have a view conform to a subclass in the interface builder you need to
Click on the UIView in your storyboard
Open the right inspector panel
Click on the third tab for identity inspector
Add your class
Then try to connect it to your ViewController again.
Edit: Afterwards you may need to cast XYZDieView myView = (XYZDieView*)leftDieView;
Im building an app that calls different subviews and lay them over in a main view controller (http://imgur.com/p6l9Oac)
when ever the user clicks a button on the bottom part of the screen (lets call it sliding menu!) the view behind it will disappear and new one will show up.
one of the subviews is Settings , which it have some switches to enable/disable some of the buttons.
in the SettingsViewController.
Ive set a protocol:
#protocol SettingsViewControllerDelegate <NSObject>
#required
-(void)hideCountdownView;
-(void)showCountdownView;
#end
and the interface contains:
#interface SettingsHubViewController : UIViewController
#property (weak, nonatomic) IBOutlet UISwitch *enableCountdown;
#property (nonatomic, assign) id <SettingsViewControllerDelegate> delegate;
#property (weak, nonatomic) IBOutlet UIView *mainView;
#end
and in the Implementation:
- (IBAction)switchAction:(id)sender {
if (!self.enableCountdown.on) {
NSLog(#"The view is Hidden");
[_delegate hideCountdownView];
} else if (self.enableCountdown.on) {
NSLog(#"The view is Shown");
[_delegate showCountdownView];
}
}
You can see i used _delegate to use the show and hide functions, I used NSLog to make sure that Im calling the functions correctly.
in the MainViewController
#import "SettingsHubViewController.h"
#interface MainViewController () <SettingsViewControllerDelegate>
#property (nonatomic, strong) SettingsHubViewController * settingsViewController;
and the Implementation
#implementation MainViewController
-(void)showCountdownView {
self.slidingMainMenuViewController.countdownView.hidden = NO;
NSLog(#"Showing Countdown");
}
-(void)hideCountdownView {
self.slidingMainMenuViewController.countdownView.hidden = YES;
NSLog(#"Hiding Countdown");
}
-(void)viewDidLoad {
[super viewDidLoad];
self.settingsViewController.delegate = self;
self.slidingMainMenuViewController.delegate = self;
}
the problem is that the NSLogs above is not being called at all, can any one help me ?
Thanks
UPDATE: Since i have more that 20 different views that needs to be called, i created this method
- (UIView *) getPresentedMenu:(NSString *) menuIdentifer withMenuTag:(int) menuTag withAViewController:(UIViewController*) menuViewController andMenuDelegate:(id) menuDelegate {
menuViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:Nil] instantiateViewControllerWithIdentifier:menuIdentifer];
menuViewController.view.tag = menuTag;
if (self.viewBeingCalledBySwipe == NO) {
menuViewController.view.frame = CGRectMake(0, menuViewController.view.frame.size.height, menuViewController.view.frame.size.width, menuViewController.view.frame.size.height);
} else if (self.isItRightSwipe == YES) {
menuViewController.view.frame = CGRectMake(-menuViewController.view.frame.size.width, 0, menuViewController.view.frame.size.width, menuViewController.view.frame.size.height);
} else if (self.isItRightSwipe == NO) {
menuViewController.view.frame = CGRectMake(menuViewController.view.frame.size.width, 0, menuViewController.view.frame.size.width, menuViewController.view.frame.size.height);
}
[self.view addSubview:menuViewController.view];
[self addChildViewController:menuViewController];
[menuViewController didMoveToParentViewController:self];
UIView *view = menuViewController.view;
return view;
}
So when ever i need a certain view controller, i just call this function
self.childView = [self getPresentedMenu:#"Settings" withMenuTag:SETTINGS_TAG withAViewController:self.settingsViewController andMenuDelegate:self.settingsViewController.delegate];
but this method is not assigning the delegate
If settingsViewController is an IBOutlet, you have to add IBOutlet to it's declaration and connect it using the storyboard or xib.
#property (nonatomic, strong) IBOutlet SettingsHubViewController * settingsViewController;
But if it's not an Outlet, you have to allocate it before set it's delegate.
self.settingsViewController = [[SettingsHubViewController alloc] init];
self.settingsViewController.delegate = self;
You should also verify that your - (IBAction)switchAction:(id)sender IBAction is correctly connected in the storyboard or xib.
When you initialize your SettingsViewController, make sure that you do it using the storyboard method and not [[SettingsViewController alloc] init].
First set a Storyboard ID directly in your storyboard view:
Then use this to settingsViewController:
self.settingsViewController = [[UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:NULL] instantiateViewControllerWithIdentifier:#"SettingsViewController"];
Replace MainStoryboard_iPhone with your Storyboard name.
Hope that helps!
// If u are using View controller
SettingsHubViewController *settingVC = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"yourStoryBoardIdentifier"];
settingVC.delegate = self;
// If u are using XIB load the NIB after that set the settingVC.delegate = self;
its working for me (I created OverLay view and loaded in main class)
i have my button, created from storyboard:
#property (weak, nonatomic) IBOutlet UIButton *plusOneBtnPoisonTwo;
with its method:
- (IBAction)plusOnePlayerTwoPoison:(id)sender;
then I check device rotation and set new position:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// NSLog(#"%d", toInterfaceOrientation);
if(!UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){
self.plusOneBtnPoisonTwo.center = CGPointMake(284, 406);
}
}
the button moves in the new position, but the method plusOnePlayerTwoPoison is no more triggered...
Any Idea?
Thanks.
Try using this instead. Its just a guess that it may resolve your problem.
#property (retain, nonatomic) IBOutlet UIButton *plusOneBtnPoisonTwo; //change to retain
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//add button action manually by code
[plusOneBtnPoisonTwo addTarget:self action:#selector(plusOnePlayerTwoPoison:) forControlEvents:UIControlEventTouchDown];
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// NSLog(#"%d", toInterfaceOrientation);
if(!UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){
[plusOneBtnPoisonTwo setFrame:CGRectMake(284, 406,50,100)];
}
}
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.