PDA

View Full Version : Click button = call method in RootViewController - Help - DEADLINE APPROACHING!




mcannell
Dec 23, 2008, 01:04 AM
I have a simple splash screen that displays a picture. Over the picture is a button that says "Continue"

I have the button connected to an IBAction in the implementation file for the nib.

When I press that button I want to call "- (void)loadMainMenuScreen" which is located in the RootViewController.m file.

Someone please let me know how to do something like this (it should be simple)!

Also, please be specific. Too often I read responses that tell what needs to be done but are so vague that the person asking the question has to ask how to do the tip being offered.



mcannell
Dec 23, 2008, 01:25 AM
I thought I had it but I must be on to something....

I added a View Controller to my nib file.
I set its class to RootViewController & voila, the method I want to call is listed in the Actions list.
I right-clicked and dragged a connection to the RootViewController and selected my desired method from the drop down and built the project.

On testing in the Simulator I get an error when I click the button.

Here is the error:

2008-12-23 02:21:46.808 MyAPP[48605:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[CAContextImpl toggleView]: unrecognized selector sent to instance 0x453ac0'

Am I close? Can someone please help ASAP?

mcannell
Dec 23, 2008, 01:38 AM
One step closer....

I forgot to de-link my button FROM the view and relink FROM the RootViewController. As soon as I fixed this connection I don't get the error when I click the button. I get a new error, though. a NON-BOLD error.

Loading program into debugger…
GNU gdb 6.3.50-20050815 (Apple version gdb-960) (Sun May 18 18:38:33 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).
warning: Unable to read symbols from "UIKit" (not yet mapped into memory).
Program loaded.
sharedlibrary apply-load-rules all
Attaching to program: `/Users/MyName/Library/Application Support/iPhone Simulator/User/Applications/012F2C1B-1D49-4CA3-A212-303D3D29F481/MyApp.app/MyApp', process 48873.

The UIKit Framework IS in my project.
I also am importing it into BOTH header files using
#import <UIKit/UIKit.h>

neil.b
Dec 23, 2008, 02:56 AM
I posted a similar question a while back and got two different answere, both of which worked.

1) EXTERN the method you want to call in the RootViewController interface definition.

or (the one I used)

2) In the class that you want to call the RootViewController method from, define an ID that you set to point to the RootViewController when the RootViewController loads;

In the class, I'll call it MyClass for illustration;

//In the interface
ID *RootView;

//In the implementation
@synthesize RootView;

Then in RootViewController, somewhere where it loads/inits;

MyClass.RootView = self;

Then in MyClass, when you want to call the RootViewMethod;

[RootView theMethodName];

neil.b
Dec 23, 2008, 03:11 AM
I think I may have given you a more complicated solution than you need. I should avoid replying to stuff when I've just woken up :)

The UIKit.h warning you're seeing is normal if you're using the iPhone Simulator. Well, I've come to think it is as I see it all the time but it doesn't appear when building for a device.

So, your problem...

Could do with knowing more detail about how you've set up the .xib file. Where is the splash screen and the button - in the same .xib file that contains the RootViewController?

mcannell
Dec 23, 2008, 03:34 AM
I can deal with 4 lines.

I got 2 errors though....

@synthesize RootView;
-->error: no declaration of property 'RootView' found in the interface


SplashScreen.RootView = self;
-->error: 'SplashScreen' undeclared (first use in this function)



I added
#import "SplashScreen.h"

and got a new error:
SplashScreen.RootView = self;
-->error: syntax error before '.' token

mcannell
Dec 23, 2008, 03:44 AM
maybe RootView needs an @property line in the interface file?

mcannell
Dec 23, 2008, 03:51 AM
I also get 2 warnings, one is expected

[RootView myMethod];
-->warning: invalid receiver type 'ID *'
--> warning: no '-myMethod' method found

I added to the top of MyClass.h

#import "RootViewController.h"

And the second warning went away, which makes sense.

neil.b
Dec 23, 2008, 04:06 AM
maybe RootView needs an @property line in the interface file?

Sorry, yes, you'll need @property in the interface.

And you'll need to import SplashScreen.h into the RootViewController.

mcannell
Dec 23, 2008, 04:12 AM
I did the import before because it made sense and I tried the @property too but I got an error because I don't know the syntax.

@property (nonatomic, retain) ID *RootView;
-->error: property 'RootView' with 'retain' attribute must be of object type

I tried copy too

neil.b
Dec 23, 2008, 04:16 AM
I did the import before because it made sense and I tried the @property too but I got an error because I don't know the syntax.

@property (nonatomic, retain) ID *RootView;
-->error: property 'RootView' with 'retain' attribute must be of object type

I tried copy too

Apologies, it should be "id" not "ID".

Edit to clarify: it should be "id RootView" and not "id *RootView". I forgot that with "id" the pointer is implied.

mcannell
Dec 23, 2008, 04:17 AM
This seems to work:

@property (nonatomic, assign) ID *RootView;

but I still have the error in the RootViewController.m

SplashScreen.RootView = self;
-->error: syntax error before '.' token

mcannell
Dec 23, 2008, 04:18 AM
changed to 'id' but still:

- (void)viewDidLoad {
SplashScreen.RootView = self;
-->error: syntax error before '.' token

(...)

}

I am using SplashScreen in place of MyClass because:

@interface SplashScreen : UIView {

(...)

}

neil.b
Dec 23, 2008, 04:23 AM
This seems to work:

@property (nonatomic, assign) ID *RootView;

but I still have the error in the RootViewController.m

SplashScreen.RootView = self;
-->error: syntax error before '.' token

You must have an instance of the SplashScreen view controller defined somewhere in RootViewController?

mcannell
Dec 23, 2008, 04:24 AM
You must have an instance of the SplashScreen view controller defined somewhere in RootViewController?

I have this:

#import "SplashScreen.h"

@implementation RootViewController

(...)

- (void)viewDidLoad {

SplashScreen.RootView = self;

(...)

}


I have only a SplashScreen.h, SplashScreen.m, & SplashScreen.xib
I don't have a specific SplashScreenViewController... files

neil.b
Dec 23, 2008, 04:34 AM
I'm new to this myself but from what I've learned there are a few "rules" that you should stick to until you find your feet at least.

- One View per .nib/.xib.

- For every View you should have a View Controller

On the second point, what that means is that your RootViewController should be thought of as a view controller controller in that it controls your applications various view controllers who in turn control their own views and interactions.

That's quite a simplistic view but I don't find it easy to explain.

mcannell
Dec 23, 2008, 04:43 AM
That's quite a simplistic view but I don't find it easy to explain.

It makes sense.

But what do I put in the SplashScreenViewController.h & .m files to fix this error?

mcannell
Dec 23, 2008, 04:49 AM
I added SplashScreenViewController

@class'd it
declared it
@property'd it

#Imported it
@synthesized it

I still get the syntax error before '.' message

neil.b
Dec 23, 2008, 04:52 AM
It makes sense.

But what do I put in the SplashScreenViewController.h & .m files to fix this error?

Right, well in the RootViewController interface you need a property that is an instance of your SplashScreenViewController, say;

@interface RootViewController : UIViewController {
SplashScreenViewController *splashViewController;
}

@property (nonatomic, retain) IBOutlet SplashScreenViewController *splashViewController;

Then, with the "RootView" property in the SplashScreenViewController definition and not in SplashScreen, in your RootViewController init you can do the;

splashViewController.RootView = self;

mcannell
Dec 23, 2008, 05:07 AM
Builds but I get more warnings... Plus I can't get the button to connect now.

RootViewController.m
splashScreenViewController.RootView = self;
-->warning: passing argument 1 of 'setRootView:' from incompatible pointer type


SplashScreenViewController.m
[RootView loadMainMenuScreen];
-->warning: invalid receiver type 'id *'

For some reason that escapes me, I can NEVER get buttons to work in a ViewController subclass. I can only get them to work in the class files.

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MainViewController 0x454580> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key myButton.'

neil.b
Dec 23, 2008, 05:28 AM
Builds but I get more warnings... Plus I can't get the button to connect now.

RootViewController.m
splashScreenViewController.RootView = self;
-->warning: passing argument 1 of 'setRootView:' from incompatible pointer type


SplashScreenViewController.m
[RootView loadMainMenuScreen];
-->warning: invalid receiver type 'id *'


The "RootView" definition should be "id RootView;"

You'll need to reconfigure your button->action stuff to take into account that you now have a SplashScreenViewController to handle the interaction. Define an action in the SplashScreenViewController and link the button to that then in the implementation of the action call the method in the RootViewController.

It would be too much to type to go through every step but you seem to have the basics.

Without seeing the files/code, it might be best to start again from scratch and build it correctly.

mcannell
Dec 23, 2008, 05:36 AM
You'll need to reconfigure your button->action stuff to take into account that you now have a SplashScreenViewController to handle the interaction. Define an action in the SplashScreenViewController and link the button to that then in the implementation of the action call the method in the RootViewController.


I already did all this but I can't get the button to work... even if it just calls

- (IBAction)continueButton:(id)sender {
NSLog(@"test");
}

Plus I was told by another developer in an email to make it

splashScreenViewController.RootView = self.view;

and that got rid of all my warnings. Now if I can just get the button click to not throw exceptions I think we have it

neil.b
Dec 23, 2008, 05:44 AM
Plus I was told by another developer in an email to make it

splashScreenViewController.RootView = self.view;

and that got rid of all my warnings. Now if I can just get the button click to not throw exceptions I think we have it

Hang on;

splashScreenViewContoller.RootView = self.view

is pointing at the view in RootViewController and not the RootViewController itself, which is wrong. You want it to point to RootViewController as you want to access one of the methods of RootViewController not a method of the view of RootViewController.

mcannell
Dec 23, 2008, 05:56 AM
is pointing at the view in RootViewController and not the RootViewController itself, which is wrong. You want it to point to RootViewController as you want to access one of the methods of RootViewController not a method of the view of RootViewController.

It is pointing to and pointing from the File's Owner... I didn't even have a ViewController in it.

I added a viewController to the xib and set it's class to SplashScreenViewController. Then I connected to button to & from...

It builds, it loads....

When I press the button it is supposed to print "test" in the log but it prints...

Loading program into debugger…
GNU gdb 6.3.50-20050815 (Apple version gdb-960) (Sun May 18 18:38:33 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).
warning: Unable to read symbols from "UIKit" (not yet mapped into memory).
Program loaded.
sharedlibrary apply-load-rules all
Attaching to program: `/Users/MyName/Library/Application Support/iPhone Simulator/User/Applications/6451D117-6621-4652-8933-A4B85A711EE0/MyApp.app/MyApp', process 53454.

So I am back to this....

mcannell
Dec 23, 2008, 06:02 AM
If I build & go and click the button I get that error in the log.

If I build & go then click the big button to exit the app, then click the app icon, and THEN click the button I get this error:

Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x000000000000070b
Crashed Thread: 0

neil.b
Dec 23, 2008, 06:19 AM
I don't know much about your level of experience but, without meaning to offend, I think you need to go back and re-read the basics. I know because I went through the learning pain myself and I see you making the same mistakes I did. :)

You seem to have got yourself tied up in knots and it's difficult to help without seeing all the files and code.

Create a new temp project from scratch and build a simple RootViewController<->ViewController<->View interface.

Actually, create a project with the "Utility Application" template and study it - it uses a RootViewController with two sub ViewControllers to manage views.

mcannell
Dec 23, 2008, 06:23 AM
I'm going to have to.

What I just can't understand is why I can add buttons and they work fine, do what I need, everything....

UNLESS, they are in the ViewController subclass...

That just doesn't make sense to me.


If I do the buttons in the UIView subclass.... all my buttons work fine
If I do the buttons in the UIViewController subclass.... crash & burn

What am I missing?

neil.b
Dec 23, 2008, 06:44 AM
I'm going to have to.

What I just can't understand is why I can add buttons and they work fine, do what I need, everything....

UNLESS, they are in the ViewController subclass...

That just doesn't make sense to me.


If I do the buttons in the UIView subclass.... all my buttons work fine
If I do the buttons in the UIViewController subclass.... crash & burn

What am I missing?

If it's any consolation I went through a similarly frustrating experience. In the end I backed away from the iPhone altogether and worked my way through the basics of Cocoa and Interface Builder. Then once I thought I understood how to use IB a bit better I went back to iPhone.

Anyway :)

So in the xxxxViewControler.xib you;

- added the button(s) to the View
- added the actions(s) to the File's Owner
- connected the buttons(s) to the action(s) in the File's Owner
- then selected "File's Owner" and from the menu File->Write Class Files?

mcannell
Dec 23, 2008, 07:44 PM
I started the entire project over and all my buttons are working, it builds and runs.

When I click the button that is to call the function in the RootViewController class, the button prints in the NSLog that it is being pressed but it doesn't call the method in the other file.

Any ideas?

EDIT:
neil...

can you send me an entire project where you have this working?

I get no errors but it doesn't do anything..

neil.b
Dec 24, 2008, 02:47 AM
I started the entire project over and all my buttons are working, it builds and runs.

When I click the button that is to call the function in the RootViewController class, the button prints in the NSLog that it is being pressed but it doesn't call the method in the other file.

Any ideas?

EDIT:
neil...

can you send me an entire project where you have this working?

I get no errors but it doesn't do anything..

As it's the season of good will, I'll send you a project with it working. :)

Let me just be clear about what you want to see;

a project with a RootViewController and one other ViewController where you press a button in the second ViewController and it calls a method in the RootViewController?

neil.b
Dec 24, 2008, 04:01 AM
I knocked this up for you.

It has a RootViewController (with an orange view) that loads a second UIViewController "SplashScreenViewController". The view of the SplashScreenViewController (light blue) has a button that when pressed, calls a method in the RootViewController which removes the SplashScreenViewController view from the screen.

Have fun :)