i have a loginviewcontroller class that has a button 'login'.
The login class is connected to my mainmenuviewcontroller to a uiview. This i connected as follows
(mainmenuviewcontroller.h)
import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong) IBOutlet UIView *loginView;
#end
(mainmenuviewcontroller.m)
- (void)viewDidLoad
{
[super viewDidLoad];
LogInViewController *logIn = [[LogInViewController alloc] initWithNibName:#"LogInViewController" bundle:nil];
[self.loginView addSubview:logIn.view];
[self.loginView setClipsToBounds:YES];
}
At this point, everything is fine. My loginViewcontroller is showing up niceley inside its own view in my main menu.
When pressing the login button on the loginviewcontroller(showing in a uiview on the main menu), it then calls the method below located in its loginviewcontroller class.
(loginviewcontroller.h)
#import <UIKit/UIKit.h>
#interface LogInViewController : UIViewController
- (IBAction)loginButtonPressed;
#end
(loginviewcontroller.m)
- (IBAction)loginButtonPressed
{
NSLog(#"login Button Pressed");
}
However an exception occurs and i dont know why: i have ensured the touchup inside sent action from the button has the correct name. And i am using Arc. HELP! :)
2013-10-28 13:57:46.367 Headache Mbl[1593:60b] -[NSConcreteMapTable loginButtonPressed]: unrecognized selector sent to instance 0x17d4fa20
2013-10-28 13:57:46.370 Headache Mbl[1593:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMapTable loginButtonPressed]: unrecognized selector sent to instance 0x17d4fa20'
*** First throw call stack:
(0x2de2fe8b 0x385826c7 0x2de337b7 0x2de320b7 0x2dd80e98 0x305ea55f 0x305ea4fb 0x305ea4cb 0x305d60f3 0x305e9f13 0x305e9bdd 0x305e4c09 0x305b9f59 0x305b8747 0x2ddfaf27 0x2ddfa3ef 0x2ddf8bdf 0x2dd63541 0x2dd63323 0x32a742eb 0x3061a1e5 0x60bdd 0x38a7bab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I am still a quite new to this, a possible solution was suggested that the class needs to be a property. How is this done? Thanks
If you have connected the IBoutlet properly,
Make the LogInViewController as a ivar or property. The object loses its value on viewDidLoad's return.
#interface ViewController : UIViewController
{
LogInViewController *logIn;
}
#property (strong) IBOutlet UIView *loginView;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
logIn = [[LogInViewController alloc] initWithNibName:#"LogInViewController" bundle:nil];
[self.loginView addSubview:logIn.view];
[self.loginView setClipsToBounds:YES];
}
when the viewDidLoad ends the logIn object will be released, only his view will survive because you are adding it to the main view controller view, so when you tap the button, will send a message to an object that doesn't exist anymore.
Let me say that it's conceptually wrong what you are trying to do, the login view controller should be added to a hierarchy, presenting it, pushing it, or containing in another view controller, but not creating it just to get his view and add it to another viewcontroller.
LogInViewController *logIn = [[LogInViewController alloc] initWithNibName:#"LogInViewController" bundle:nil];
[self addChildViewController:logIn];
[self.loginView addSubview:logIn.view];
[self.loginView setClipsToBounds:YES];
turns out i needed to add the view as a a child view controller. Once loaded it removes it from memory but still shows it. so its needs to be added as a child.
:)
Related
I don't know how to solve this problem:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ViewController pushViewController:animated:]: unrecognized selector sent to instance 0x8e5fc70'
This problem is connected to screen timeout. After 30 seconds of no activity, my App have to back to the login screen, and if the user come back he have to login again. And this is my code:
AppDelegate.h:
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
AppDelegate.m:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationDidTimeout:) name:kApplicationDidTimeoutNotification object:nil];
return YES;
}
-(void)applicationDidTimeout:(NSNotification *) notif
{
NSLog (#"time exceeded!!");
UIViewController *controller = [[UIStoryboard storyboardWithName:#"Main" bundle:NULL] instantiateViewControllerWithIdentifier:#"mainView"];
[(UINavigationController *)self.window.rootViewController pushViewController:controller animated:YES];
As you can see the problem is in the last line of this code. This part of the code which I used has been taken from:
iOS perform action after period of inactivity (no user interaction)
The pushViewController:animated: method is a method of UINavigationController.
But your root view controller is of type ViewController which is most likely a UIViewController.
You need to change your setup so your main view controller is inside a UINavigationController and you need to make the navigation controller the window's root view controller.
This means in storyboard the rootViewController is a navigationController
Pushing my view controller twice to navigation controller and simulating memory warning, lead to application crash with error: "message sent to deallocated instance"
I'm pushing view controller by pressing on button:
-(void)buttonPressed
{
MyViewCOntroller *vc = [[MyViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
I'm using ARC.
Scenario:
[self buttonPressed];
Press back button in vc.
[self buttonPressed];
Press back button in vc
Simulate memory warning
The crash does not happen if pushing only once.
I tried also to move "vc" to be ivar of parent controller, but the effect is the same...
Maybe this will help, but I'm using custom back button and its selector:
-(void)backButtonPressed
{
[self.navigationController popViewControllerAnimated:YES];
}
create this vc object as class member and check if crash exists
#interface ParentViewController()
{
MyViewCOntroller *vc;
}
#end
#implementation PaintingViewController
-(void)buttonPressed
{
vc = [[MyViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
Found a solution to this. Please see my answer to my other question:
[UINavigationController retain]: message sent to deallocated instance
I have two view controllers. We'll call them listViewController and mapViewController. The listViewController shows first, a user taps a button that shows the mapViewController. The user taps a button on a annotation which is where my problems start.
When the user taps a button on mapViewController, I would like to call a method listViewController and dismiss mapViewController. To do this I am using this code:
mapViewController.m
listViewController* lvc = [[listViewController alloc] initWithNibName:nil bundle:nil];
[lvc getInformation:StringParameter];
[self dismissViewControllerAnimated:YES completion:nil];
However, when executing getInformation it seems that the listViewController class has been dealloc'd because all of the objects that I initialized in the viewDidLoad on listViewController are now nil including self, which just breaks everything.
I assume I'm creating the listViewController object incorrectly in mapViewController. I've tried it with a nil for nibName with the same result.
Ok, Let me clear one thing. On listViewController, you presentViewController a mapViewcontroller right? And you want invoke getInformation of the instance from mapViewController. In the code you're added, you instantiate listViewController again. You have 2 different instance of listViewController.
One option is to use a delegate pattern:
In your MapViewController.h file:
#protocol MapViewControllerDelegate <NSObject>
-(void)dismissMe;
-(void)getInformation:(NSString *)stringParameter;
#end
#interface MapViewController : UIViewController
#property (weak)id <MapViewControllerDelegate> delegate;
#end
In your MapViewController.m file:
-(void)annotationButtonTap:(id)button
{
[self.delegate getInformation:stringParameter];
[self.delegate dismissMe];
}
In your ListViewController.h
#import "MapViewController.h"
#interface ListViewController : UIViewController <MapViewControllerDelegate>
-(void)dismissMe
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)getInformation:(NSString *)stringParameter
{
//do whatever you plan with stringParameter
}
And somewhere in you ListViewController.m file where you create the MapViewController instance:
mapViewController = [[MapViewController alloc] initWithNibName:#"MapViewController" bundle:nil];
mapViewController.delegate = self; //make sure you do this
I am making a login page for an application using Parse.
I get the error "visible #interface for 'UIResponder' declares the selector 'viewDidAppear'"
I also get "visible #interface for 'UIResponder' declares the selector 'presentViewController:animated:present'"
So, in my AppDelegate.m I have:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];//I GET THE ERROR HERE
if (![PFUser currentUser]) { // No user logged in
// Create the log in view controller
PFLogInViewController *logInViewController = [[PFLogInViewController alloc] init];
[logInViewController setDelegate:self]; // Set ourselves as the delegate
// Create the sign up view controller
PFSignUpViewController *signUpViewController = [[PFSignUpViewController alloc] init];
[signUpViewController setDelegate:self]; // Set ourselves as the delegate
// Assign our sign up controller to be displayed from the login controller
[logInViewController setSignUpController:signUpViewController];
// Present the log in view controller
[self presentViewController:logInViewController animated:YES completion:NULL];//I GET THE ERROR HERE
}
}
In my AppDelegate.h:
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
// Implement both delegates
#interface DefaultSettingsViewController :
UIViewController <PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate>
#end
How can I go about fixing this issue?
Your superclass needs to be a UIViewController subclass. In your code, it's a UIResponder subclass.
But I think the reason is that you're putting code that should go in a view controller into the app delegate. Move the viewDidAppear: method to the view controller where it needs to be.
I have two views a levelComplete view and a levelSelector view. What I would like to do is when the levelComplete shows or the ViewDidLoad occurs on that view I would like to send a delegate to the level selector to show a button in the view and then make that button UserInteractionEnabled so then I will then be able to programme that button to do something if its not hidden.
You want to necessarily do it via a delegate. Coz you can do it in a simpler way as well. When you call your secondView, just tell your button to hide. So your modified code to calling the second view controller becomes:
-(IBAction)passdata:(id)sender {
secondview *second = [[secondview alloc] initWithNibName:nil bundle:nil];
self.secondviewData = second;
sender.hidden=YES;
secondviewData.passedValue = textfield.text;
[self presentModalViewController:second animated:YES];
}
And then you can set it to visible when your view loads up again using viewDidLoad. I can tell you how to do it via delegates if you need. Lemme know what works best.
EDIT - Solution by Delegates
Your secondView's Header file will be as follows:
#protocol SecondViewHandlerDelegate <NSObject>
- (void)viewHasBeenLoaded:(BOOL)success;
#end
#interface secondview :UIViewController {
IBOutlet UILabel *label;
NSString *passedValue;
}
#property (nonatomic, retain)NSString *passedValue;
-(IBAction)back:(id)sender;
#end
Then, in the implementation file of secondView(.m), synthesise the delegate first by #synthesize delegate; . After this, in your viewDidLoad of secondView, add the following line:
[[self delegate] viewHasBeenLoaded:YES];
That should be enough for your secondView. Now onto the firstViewController, perform the following steps:
In the header file (.h), import your second view and implement the protocol:
#interface ViewController :UIViewController <SecondViewHandlerDelegate>{
..
..
}
In the implementation file (.m) of your firstViewController, implement this method:
- (void)viewHasBeenLoaded:(BOOL)success
{
NSLog("Delegate Method Called");
[myButton setHidden:YES];
}
And finally, in your code when you call the secondView, add this line:
secondview *second = [[secondview alloc] initWithNibName:nil bundle:nil];
second.delegate = self;
...
That should solve your purpose. I'd appreciate if you could mark the answer as correct as well. Thanks :)