I am currently working on an iPhone App with XCode 5.1.1. I'm only getting started with apps but things went pretty well until I recently hit a wall I can't figure out how to overcome.
On the first Viewcontroller that is shown I have two buttons to switch between languages. However everytime this viewcontroller is shown the buttons seem to be automatically "clicked" that is the functions that the buttons trigger are executed. I will attach the code from the .h and .m files here:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
NSString *settingsTitle;
NSString *gerBtn;
NSString *engBtn;
}
#property (strong, nonatomic) IBOutlet UIButton *english;
#property (strong, nonatomic) IBOutlet UIButton *german;
#property (strong, nonatomic) IBOutlet UIButton *settings;
- (IBAction)setEnglish:(UIButton *)sender;
- (IBAction)setGerman:(UIButton *)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewWillAppear:(BOOL)animated
{
if([[NSUserDefaults standardUserDefaults] boolForKey:#"englishEnabled"]){
[_settings setTitle:#"Settings" forState:UIControlStateNormal];
} else {
[_settings setTitle:#"Einstellungen" forState:UIControlStateNormal];
}
NSLog(#"%hhd", [[NSUserDefaults standardUserDefaults] boolForKey:#"englishEnabled"]);
[super viewWillAppear:animated];
}
- (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)setEnglish:(UIButton *)sender {
NSLog(#"setEnglishClicked");
[self enLangChange];
}
- (IBAction)setGerman:(UIButton *)sender {
NSLog(#"setGermanClicked");
[self deLangChange];
}
- (void) enLangChange
{
[[NSUserDefaults standardUserDefaults] setBool:true forKey:#"englishEnabled"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void) deLangChange
{
[[NSUserDefaults standardUserDefaults] setBool:false forKey:#"englishEnabled"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#end
Now everytime I navigate to this viewcontroller also when I start the app it will log "setEnglishClicked" and "setGermanClicked" and always set the BOOL false for the key englishEnabled.
I've tried everything from deleting the buttons and putting them back in, even starting the whole project new from scratch but it always acted the same. The strange thing is that the other two buttons in this view for "Start" and "Settings" are not "clicked". It would help a ton if somebody could advice me what I'm doing wrong!
Best Regards!
J
(IBAction) is actually defined to (void) in UINibDeclarations.h.
Therefor, the methods - (IBAction)setEnglish:(UIButton *)sender and - (IBAction)setGerman:(UIButton *)sender are setters and are called when your view controller appears.
Rename them, for example to - (IBAction)didPressEnglishButton:(UIButton*)sender and it should work.
Related
I am building an ANE which will start a new View which contains a label and button. I was successful in adding view as bundle and view controller in my .a file.
I am starting my view as a subview. And later when I click button, it should do some stuffs and change the label text. I can display the view using below code but my button click event is not working.
--- Code to start view ---
My ViewController class name is 'VideoViewController' and bundle containing xib name is 'ViewBundle.bundle'
UIApplication *app = [UIApplication sharedApplication];
UIViewController *myViewController;
NSBundle * mainBundle = [NSBundle mainBundle];
NSString * pathToMyBundle = [mainBundle pathForResource:#"ViewBundle" ofType:#"bundle"];
NSAssert(pathToMyBundle, #"bundle not found", nil);
NSBundle *bundle = [NSBundle bundleWithPath:pathToMyBundle];
myViewController = [[VideoViewController alloc] initWithNibName:nil bundle:bundle];
[app.keyWindow addSubview:myViewController.view];
--- VideoViewController.h ---
#import <UIKit/UIKit.h>
#interface VideoViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *textLabel;
#property (strong, nonatomic) IBOutlet UIButton *clickBtn;
- (IBAction)BtnTapped:(id)sender;
- (IBAction)BtnTappped:(UIButton *)sender;
#end
--- VideoViewController.m ---
#import "VideoViewController.h"
#interface VideoViewController ()
#end
#implementation VideoViewController
#pragma mark - UIViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self logMessage:#"From did load"];
[_clickBtn setUserInteractionEnabled:YES];
[_clickBtn setTitle:#"Click Here" forState:UIControlStateNormal]; // button text changes here
}
#pragma mark - Public
- (IBAction)BtnTapped:(id)sender {
[_textLabel setText:#"Btn Tapped"];
}
- (IBAction)BtnTappped:(UIButton *)sender {
[_textLabel setText:#"Btn Tappped"];
}
#pragma mark - Private
- (void)logMessage:(NSString *)msg {
NSLog(#"%#", msg);
[_textLabel setText:msg];
}
#end
I tried to give touch event programmatically, but still button click event doesn't work.
Can anyone please help to sort out this issue?
Please check your clickButton is on its superView
Issue was with view initialisation. Replace [app.keyWindow addSubview:myViewController.view]; with
[app.keyWindow.rootViewController presentViewController:myViewController animated:false completion:nil]; solved my issue.
Hey I converted my project to ARC automatically and the only thing I had to fix was that Xcode changed array that had a size of [8] to [4] (still don't know what was going on there)
However, I now realized I got another problem: every time I hit a button in my Popup, the app crashed if it is linked to an IBAction. If I remove the reference to the header and main file, the button is clickable, but as soon as i assign it to a method (even if the method is empty), the whole app jut freezes/crashes.
This is how I initiate my popup:
PopUpViewController *popViewController =
[[PopUpViewController alloc] initWithNibName:#"PopUpViewController" bundle:nil];
[popViewController setTitle:#"This is a popup view"];
[popViewController showInView:self.view
animated:YES];
popViewController.view.center=self.view.center;
Pretty basic stuff, I ripped it off a tutorial I found online. My header is this:
#interface PopUpViewController : UIViewController
- (IBAction)baa:(id)sender;
#property (strong, nonatomic) UIButton *ba; // I was trying to add those buttons as properties here
#property (strong, nonatomic) IBOutlet UIButton *kl; //but no luck whatsoever
#property (strong, nonatomic) IBOutlet UIView *popUpView;
#property (strong, nonatomic) IBOutlet UIView *ppp;
- (IBAction)openSomething:(id)sender;
- (IBAction)openYoutube:(id)sender;
- (IBAction)openFacebook:(id)sender;
- (void)showInView:(UIView *)aView animated:(BOOL)animated;
#end
And my main
#import "PopUpViewController.h"
#interface PopUpViewController ()
#end
#implementation PopUpViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)showAnimate
{
// not important for this question
}
- (void)removeAnimate
{
// shortened
}
- (IBAction)baa:(id)sender{
// NSLog(#"asd"); I commented it out, but even an empty method kills the app
// only if I leave a button unassigned to any method, the app "survives" a button click
}
- (IBAction)openSomething:(id)sender
{
// [[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.test.de"]];
}
- (IBAction)openYoutube:(id)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.youtube.com/"]];
}
- (IBAction)openFacebook:(id)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.facebook.com/"]];
}
- (void) doSomething{
// also tried an empty method with a "new" name over here to eliminate any caching errors, no luck
}
- (IBAction)closePopup:(id)sender {
[self removeAnimate];
}
- (void)showInView:(UIView *)aView animated:(BOOL)animated
{
[aView addSubview:self.view];
if (animated) {
[self showAnimate];
}
}
- (void)viewDidLoad
{
self.view.backgroundColor=[[UIColor blackColor] colorWithAlphaComponent:.0];
self.popUpView.layer.cornerRadius = 5;
self.popUpView.layer.shadowOpacity = 1.0;
self.popUpView.layer.shadowOffset = CGSizeMake(0.2f, 0.2f);
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
Any ideas what I could do different? I referenced everything to everything else possible now and I don't even know how it looked before anymore, but I somehow think it has something to do with the referencing.
Thanks a lot in advance, Alex
I was able to figure out on my own:
In the header of my main ViewController I added
#property (strong, nonatomic) PopUpViewController *popViewController;
Which still fired the crash. But then I adjusted the popup "opening" block to
_popViewController =
[[PopUpViewController alloc] initWithNibName:#"PopUpViewController" bundle:nil];
[_popViewController setTitle:#"This is a popup view"];
[_popViewController showInView:self.view
animated:YES];
_popViewController.view.center=self.view.center;
(added the underscores) and now it's working perfectly again.
Actually I am curious why it worked before but I am not going to investigate this any further.
UPDATE Just resetted al Simulators Data and now it works fine.
I'll appreciate any help :)
My app writes data to a Data.plist file in a subfolder of Documents.
I added an NSLog to find out the path so I can check it. I finded and the plist is good.
I tried it in a iPad Air. Another page has a "Load" button for loading the plist data and placing it in a textfield. In the iPad Air the info is loaded totally fine.
BUT! I tried it in an iPad 2. And the 2 strings are not loaded. The keys and objects are:
proyectName string example
revisarCimiento bool 1
tipoCodigoEsfuerzosAdmisibles string Canada
tipoUnidadMamposteria string Block
mamposteriaConfinada bool 0
When the data is loaded, the proyect name doesn't depend on the plist.
The bools are fine but the other 2 strings are not loaded.
Here is the code
.h
//
// factoresCombinacionesCargaViewController.h
// calcMurosLosas
//
// Created by Brian Matus on 15/12/14.
// Copyright (c) 2014 Matus. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface factoresCombinacionesCargaViewController : UIViewController <UITextFieldDelegate>
- (IBAction)loadData:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *proyectName;
#property (weak, nonatomic) IBOutlet UITextField *levels;
#property (weak, nonatomic) IBOutlet UITextField *revisarCimiento;
#property (weak, nonatomic) IBOutlet UITextField *tipoCodigoEsfuerzosAdmisibles;
#property (weak, nonatomic) IBOutlet UITextField *tipoUnidadMamposteria;
#property (weak, nonatomic) IBOutlet UITextField *mamposteriaConfinada;
+ (void)proyectPath:(NSString *)theString;
#end
.m
#import "factoresCombinacionesCargaViewController.h"
#import "infoGeneralViewController.h"
#interface factoresCombinacionesCargaViewController ()
#end
NSString *proyectPath;
#implementation factoresCombinacionesCargaViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (IBAction)loadData:(id)sender {
[infoGeneralViewController getProyectNameFromPlist]; //This calls a method that returns a string tho the proyectPath method below.
[self performSelector:#selector(setLabels) withObject:nil afterDelay:0.1];
}
+ (void)proyectPath:(NSString *)theString {
proyectPath = theString;
}
-(void)setLabels {
NSMutableDictionary *plist = [NSMutableDictionary dictionaryWithContentsOfFile:[proyectPath stringByAppendingPathComponent:#"Data.plist"]];
_proyectName.text = [proyectPath lastPathComponent];
int leves = [[plist objectForKey:#"numeroNiveles"] integerValue];
_levels.text = [NSString stringWithFormat:#"%d", leves];
bool revisarCimiento = [[plist objectForKey:#"revisarCimiento"] boolValue];
_revisarCimiento.text = [NSString stringWithFormat:#"%s", revisarCimiento ? "Si" : "No"];
_tipoCodigoEsfuerzosAdmisibles.text = [plist objectForKey:#"tipoCodigoEsfuerzosAdmisibles"];
_tipoUnidadMamposteria.text = [plist objectForKey:#"tipoUnidadMamposteria"];
bool mamposteriaConfinada = [[plist objectForKey:#"mamposteriaConfinada"]boolValue];
_mamposteriaConfinada.text = [NSString stringWithFormat:#"%s", mamposteriaConfinada ? "Si" : "No"];
}
#end
I don't why in the iPad Air the strings are loaded fine but in the iPad 2 not.
Thanks for your attention.
i am in initial phase of development and i want to make sure i am in right direction with regards to memory management.
i have a view controller named LayoutViewController with xib.I have a custom ui-subclass with its xib named LayoutContainerView which basically contains a scrollview. I am using LayoutContainerView in LayoutViewController xib by IBOutlet.
I have an another UIView subclassed, which contains a view with background image, some labels and a transparent button with same frame as of viw.I am adding this custom controll in LayoutContainerView's scrollview.
my view controller .h looks like this:
#import <UIKit/UIKit.h>
#protocol LayoutVcRemovedProtocol;
extern const char* MyConstantKey;
#interface LayoutViewController : UIViewController
// public properties
#property (nonatomic, copy) NSString *databasePath;
#property (nonatomic, weak) id<LayoutVcRemovedProtocol> layoutVcRemovedProtocolDelegate;
#end
#protocol LayoutVcRemovedProtocol<NSObject>
-(void) layoutVcRemovedProtocolMethod;
#end
=========================
**some of relevant code of **implementation** file looks like this:**
//private stuffs goes here
const char* MyConstantKey = "MyConstantKey";
#interface LayoutViewController () <UIActionSheetDelegate, UIAlertViewDelegate>
#property(nonatomic, weak) IBOutlet LayoutContainerView *layoutContainerView;
#property(nonatomic, weak) IBOutlet UIButton *backbutton;
#property(nonatomic, weak) IBOutlet UILabel *layoutNameLabel;
#property (nonatomic, strong) UIView *baseView;
#property (nonatomic, strong) NSMutableArray *layoutModelArray;
-(IBAction)backButtonPressed;
#end
#implementation LayoutViewController
//my viewDidLoad and viewWillAppear look like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self adjustLayoutContainerFrameAndSetDataBasePath];
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.layoutNameLabel.text = [Utils getLayoutName];
[self getLatestData];
}
-(void) getLatestData
{
[self setUpDataSource];
[self setUpComponentsOnLayoutScreen];
}
#pragma mark - datasource method
-(void)setUpDataSource
{`
self.layoutModelArray = (NSMutableArray *)[LAYOUTMODULE getAllLayoutData];
}`
-(void)setUpComponentsOnLayoutScreen
{`
for (int i = 0; i < self.layoutModelArray.count; i++)
{
Layout *layout = [self.layoutModelArray objectAtIndex:i];
[self drawViewWithLayoutObject:layout];
}
[self.layoutContainerView.scrollView adjustContentSize];
}
this is what i am trying to manage memory:
-(void) cleanLayoutModelArray
{
if (self.layoutModelArray != nil && self.layoutModelArray.count >0)
{
[self.layoutModelArray removeAllObjects];
}
}
-(void) cleanComponents
{
[self.layoutContainerView.scrollView.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
}
//user events
-(void) placeOrderForLayout:(Layout *)layout
{
[DELEGATE showLandscapeLoading];
//web service COMMUNICATION HERE here
OrderModule *oModule = [OrderModule sharedModule];
NSDictionary *requestDictionary = [NSDictionary dictionaryWithObjectsAndKeys:oModule.currentOrder.mOrderId,#"order_id",oModule.currentOrder.mPosId,#"pos_id",[Utils currentDate],#"book_date", layout.componentId, #"component_id", nil];
BOOL status = [LAYOUTMODULE placeComponentOrderThroughAPI:requestDictionary];
if (status == TRUE)
{
[self performCleanUp];
[self getLatestData];
}
[DELEGATE stopLandscapeLoading];
}
help me or any suggestion for:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
what ever i try in memoryWarningDelegate view controller becomes black screen.
You've got a lot of #properties marked 'weak' in your code - when you mark things as weak, that means that something else is keeping track of whether it should still exist. Here you're doing it with IBOutlet items, which your controller should be keeping track, so they should be marked 'strong,' not weak. I'd review all your usage of 'weak' in this. Also refer to Apple's excellent doc on memory management. ARC will be handling most of your memory management for you. Usually, the only thing you need to do in didReceiveMemoryWarning, is to set to nil anything that's a large object, say a video or webpage you can reload if the user needs it again. Often, there's not much that you can free up at this time in your typical view. Note also that iOS devices have a fairly substantial memory footprint these days, so you should not worry about small data structures remaining resident in memory as long as they have the potential to be needed again. If you're having out of memory issues, I'd run with instruments and check for leaks.
Can anyone help me to understand what is going wrong with my function below pls?
I'm fairly new to native IOS dev.
I wanted to implement a side panel into our app using this tutorial (http://www.appcoda.com/ios-programming-sidebar-navigation-menu/).
All that works fine and is straightforward enough - but I wanted to trigger the reveal functionality via a standard button rather than a dynamic button in the header - to suit our design..
The original code is as follows -
#import "SWRevealViewController.h"
// Change button color
_sidebarButton.tintColor = [UIColor colorWithWhite:0.96f alpha:0.2f];
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
_sidebarButton.target = self.revealViewController;
_sidebarButton.action = #selector(revealToggle:);
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
to replicate that functionality triggered by a button I added the following to the .h file -
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
#property (weak, nonatomic) IBOutlet UIButton *revealLeftBtn;
- (IBAction)btnClickRevealL:(id)sender;
and the following in my .m file
- (IBAction)btnClickRevealL:(id)sender {
[self.revealViewController];
[#selector(revealToggle:)];
}
I get the error 'suspected identifier' for the above lines - I dont understand how the functions triggered with the previous method and not with the above - can anyone help?
Cheers
for reference this is the entire .M file -
#import "MainViewController.h"
#import "SWRevealViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"";
// Change button color
_sidebarButton.tintColor = [UIColor colorWithWhite:0.96f alpha:0.2f];
[self.navigationController.navigationBar setTranslucent:TRUE];
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnClickRevealL:(id)sender {
[self.revealViewController];
[#selector(revealToggle:)];
}
#end
This line:
(IBAction)btnClickRevealL:(id)sender {
[self.revealViewController];
[#selector(revealToggle:)];
}
Does nothing.
I guess this is what you want to do:
[self.revealViewController revealToggle:sender];
When you set the target and the action of a button, you set which class is doing the action (target) and what method is called (action).
that's the equivalent of doing [target action]
- (IBAction)logInBtnClicked:(id)sender {
//Remove WhiteSpace from start of uitextfield
self.emailIdTxtFldRef.text = [self.emailIdTxtFldRef.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
self.passwordTxtFldRef.text = [self.passwordTxtFldRef.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
if ([self.emailIdTxtFldRef.text isEqualToString:#""]||[self.passwordTxtFldRef.text isEqualToString:#""]) {
[self showMessage:#"All fields are mandatory" withTitle:#"Error"];
}else{
SWRevealViewController *revealVC = [self.storyboard instantiateViewControllerWithIdentifier:#"swRevealViewContoller"];
revealVC.delegate=self;
[[UIApplication sharedApplication]keyWindow].rootViewController = revealVC;
}
}