So heres my issue. I assume its a simple one but i just cannot figure out why this is not working.
I need to access Outlets (UITextField, UITableView, UIActivityIndicatorView, etc.) in one class (RootViewController) from a different class (ServiceController).
I have this currently (only showing whats need) :
RootViewController.h
#interface RootViewController : UIViewController{
UITextField *textField;
}
#property (nonatomic, retain) IBOutlet UITextField *textField;
- (void)startService;
#end
RootViewController.m
#implementation RootViewController
#synthesize textField;
- (void)startService{
ServiceController *service = [[ServiceController alloc] init];
[service start];
[service release];
}
#end
ServiceController.h
#class RootViewController;
#interface ServiceController : NSObject{
}
#property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
- (void)start;
#end
ServiceController.m
#import "RootViewController.h"
#implementation ServiceController
#synthesize rootViewController;
- (void)start{
[((RootViewController*)rootViewController).textField setText:#"HELLO !"];
NSLog(#"CALLED !");
}
#end
I do not see why this is not working, i use the same method to do the same thing from the RootViewController to the DetailViewController and it works fine. I checked to see if there were any other declaration in the detail/root controllers to allow that to work but i did not notice any.
PS: everything is being called successfully and "CALLED !" is being logged, just whatever i do to the outlet(s) has no effect.
Your ServiceController needs to have its rootViewController property set. You can either do this in an XIB file or explicitly in code:
myServiceController.rootViewController = myRootViewController;
It looks like you didn't set the rootViewController.
Try adding :
ServiceController *service = [[ServiceController alloc] init];
// set the property here
[service setRootViewController:self];
[service start];
[service release];
Related
I am just learning and trying to put forth some of the knowledge with objective c and cocoa. I have a little program that has a login screen which then displays a main menu. On the main menu view, there is a button that should load a view to be able to add some data to the app. When I click on the button, it doesn't fire the IBAction but throws an error
EXC_BAD_ACCESS [StartMenuViewController performSelector:withObject:]: message sent to deallocated instance 0x6080195e9f90
I know that it is because there is an object that is not instantiated when the message is being sent, but I cannot find out why. Sorry for the code and the novice level here is the main menu view controller StartMenuViewController.m file:
#import "StartMenuViewController.h"
#import "AppDelegate.h"
#import "MasterViewController.h"
#interface StartMenuViewController ()
#end
#implementation StartMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
}
-(IBAction)showStrainView:(id)sender{
AppDelegate *delegate = nil;
delegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
MasterViewController *addStrainView = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[delegate swapView:self.view toView:addStrainView.view];
}
#end
here is the StartMenuViewController.h
#import <Cocoa/Cocoa.h>
#interface StartMenuViewController : NSViewController
#property (weak) IBOutlet NSButton *showStrainViewButton;
#end
Here is the AppDelegate.h
#import <Cocoa/Cocoa.h>
#class loginView, MasterViewController,StartMenuViewController;
#interface AppDelegate : NSObject <NSApplicationDelegate>{
loginView *loginView;
MasterViewController *masterViewController;
}
#property (assign) IBOutlet NSWindow *window;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (strong) loginView *loginView;
#property (strong) MasterViewController *masterViewController;
#property (strong) StartMenuViewController *starMenuViewController;
-(void)swapView:(NSView *)view1 toView:(NSView *)view2;
#end
Here is the AppDelegate.m
#import "AppDelegate.h"
#include "MasterViewController.h"
#import "ScaryBugDoc.h"
#import "Strains.h"
#import "loginView.h"
#interface AppDelegate()
#end
#implementation AppDelegate
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
#synthesize loginView;
#synthesize masterViewController;
#synthesize starMenuViewController;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// 1. Create the master View Controller
self.loginView = [[loginView alloc] initWithNibName:#"loginView" bundle:nil];
// 2. Add the view controller to the Window's content view
[self.window.contentView addSubview:self.loginView.view];
self.loginView.view.frame = ((NSView*)self.window.contentView).bounds;
}
-(void)swapView:(NSView *)view1 toView:(NSView *)view2{
//[view1 removeFromSuperview];
[self.window.contentView addSubview:view2];
view2.frame = ((NSView*)self.window.contentView).bounds;
}
#end
If you need the loginView.h and loginView.m files I can add them as well. I would appreciate any and all help. Thanks in advance
The problem is here:
MasterViewController *addStrainView = [[MasterViewController alloc]initWithNibName:#"MasterViewController" bundle:nil];
[delegate swapView:self.view toView:addStrainView.view];
You don't keep a reference to the MasterViewController so it gets deallocated even though its view is kept around. Now anytime the view tries to access methods from the view controller, things fail.
You should make addStrainView a child view controller of self in the above code so the view controller sticks around as long as its view.
How can I access to ViewController property from another class ?
(the ViewController was created by XCode)
this is code of ViewController.h:
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#interface ViewController : UIViewController{
AppDelegate *appDelegate; //il delegate disponibile per tutta la classe
int numPag; //indice array (sulle pagine html da visualizzare)
NSString *path;
NSURL *baseURL;
NSString *file;
NSString *contentFile;
}
- (IBAction)sottrai:(id)sender;
- (IBAction)aggiungi:(id)sender;
#property (strong, nonatomic) IBOutlet UILabel *valore;
#property (strong, nonatomic) IBOutlet UIWebView *web;
#end
thanks!
[EDIT]
I use Xcode 4.3.2 and the code of AppDelegate.m not find something like:
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
Now, I put in the method didFinishLaunchingWithOptions:(into AppDelegate.m) this code:
viewController = [[UIViewController alloc] initWithNibName:#"ViewController" bundle:nil];
[viewController.web loadHTMLString:contentFile baseURL:baseURL];
adding in the file AppDelegate.h the variable viewController:
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>{
NSArray *pageInItalian;
NSArray *pageInEnglish;
UIViewController *viewController;
}
#property (strong, nonatomic) NSArray *pageInLanguage;
#property (strong, nonatomic) UIWindow *window;
#end
I did it correctly? the error is: Property 'web' not found on object of type 'UIViewController *'
I think this post might answer your question
How can I access variables from another class?
You need to make your variable accessible from foreign classes (with #property and #synthesize) and then your foreign class need to know your instance of ViewController
[EDIT]
In your AppDelegate.m, there must be a line like this one :
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
This is where your ViewController is instantiate. From there, you can access every property of your ViewController.
[EDIT]
You need to add the following at the beginning of your implementation
#implementation ViewController
#synthesize web;
I can't get why I can't set delegate. I'm using UINavigationController to switch between two views. Here is my code
SecondViewProtocol.h
#import <Foundation/Foundation.h>
#protocol SecondViewProtocol <NSObject>
#required
-(void)textFieldDidChange:(NSString *)data;
#end
SecondView.h
#import <UIKit/UIKit.h>
#import "SecondViewProtocol.h"
#interface SecondView : UIViewController
#property (nonatomic, retain) id<SecondViewProtocol>delegate;
#end
SecondView.m
#synthesize delegate = _delegate;
.......
-(IBAction)textFieldReturn:(id)sender
{
[[self delegate] textFieldDidChange:[self.textField text]];
}
.......
I have imported SecondViewProtocol.h in FirstView.h
FirstView.m
....
SecondView *secondView = [[SecondView alloc]init];
secondView.delegate = self;
....
Here I get Assigning to id from incompatible type FirtView.
What is wrong here ?
First of all, delegate property should be declared as assign, not retain. You should never retain delegates.
Second, FirstView should conform to SecondViewProtocol like the following.
#interface FirstView: UIViewController <SecondViewProtocol>
I am trying to improve myself in Objective-C and what I am on about is now modifying and changing and existed project. I did everything I wanted expect one thing. Theres an info button in my program and it doesnt related with .xib file. I tried to remove it but always my main.m gave error like SIGABRT (int retval thing.)
Here is the thing what I want to modify
http://i.stack.imgur.com/ZG51s.png // The picture of my program and info button
I am trying to remove the (i) button on the right-down corner.
Here's my code
This is my RootViewController.h
#import <UIKit/UIKit.h>
#class MainViewController;
#interface RootViewController : UIViewController {
IBOutlet UIButton *infoButton; //Silinecek
MainViewController *mainViewController;
}
#property (nonatomic, retain) MainViewController *mainViewController;
#end
This is my RootViewController.m
#import "RootViewController.h"
#import "MainViewController.h"
#implementation RootViewController
#synthesize mainViewController;
- (void)viewDidLoad {
MainViewController *viewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = viewController;
[viewController release];
[self.view insertSubview:mainViewController.view belowSubview:infoButton];
}
and also I tried to modify my AppDelegate h and m. Here they are ;
#import <UIKit/UIKit.h>
#class RootViewController;
#interface AppDelegate : NSObject <UIApplicationDelegate> {
IBOutlet UIWindow *window;
IBOutlet RootViewController *rootViewController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) RootViewController *rootViewController;
#end
#import "AppDelegate.h"
#import "RootViewController.h"
#implementation AppDelegate
#synthesize window;
#synthesize rootViewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:[rootViewController view]];
//[window makeKeyAndVisible];
}
/*
- (void)dealloc {
[rootViewController release];
[window release];
[super dealloc];
}
*/
What should I do for removing that info button in my View. Thanks for the any tips
And if you are interested in this is the whole algorithm : http://pastebin.com/hHQkQYS6
Do you still have the control linked somewhere in your xib file? It is declared as an IBOutlet control. Usually when I have these controls I will use the GUI link this control in some way (I can't remember what exactly as I have not done Obj-C in a long time). But I would definitely have a look around you xib file (as well as removing [self.view insertSubview:mainViewController.view belowSubview:infoButton];
The exception mentions:
[<RootViewController 0x4b9ab20> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key infoButton.
The call stack shows that it is thrown by UINib. So this is happening during nib load. So check for all objects present, carefully, in the nib and remove the info button
I've got the following method on a GameScreen.m file, with its own declaration - (void) drawNumbers on a GameScreen.h file:
//GameScreen.h
#import <UIKit/UIKit.h>
#interface GameScreen : UIView
{
IBOutlet UIButton *cell00;
}
- (void) drawNumbers;
- (IBAction) onCellClick:(id)sender;
#property (nonatomic, retain) IBOutlet UIButton *cell00;
#end
//GameScreen.m
#import "GameScreen.h"
- (void) drawNumbers
{
//testing if this works, so far it doesn't
[cell00 setTitle:#"Whatever" forState:UIControlStateNormal];
[cell00 setTitle:#"Whatever" forState:UIControlStateHighlighted];
}
I'm trying to call this method from my GameScreenViewController.m file, this way:
//GameScreenViewController.m
#import "GameScreenViewController.h"
#import "GameScreen.h"
...
- (void) viewDidLoad
{
GameScreen *aGameScreen = [[GameScreen alloc] init];
[aGameScreen drawNumbers];
[aGameScreen release];
[super viewDidLoad];
}
This is supposed to change the title of a button in a GameScreen.xib file where GameScreenViewController.m is the viewController and GameScreen class is the event handler where I get all the button clicks, timers running, etc. I am trying to call [drawNumbers] from [viewDidLoad] since I want the title to be changed when the screen is brought up front (screen management is done through the AppDelegate files).
The thing is, if I call drawNumbers instance from inside the same class through
//GameScreen.m
#import GameScreen.h
-(void) onButtonClick:(id)sender
{
//some other code
[self drawNumbers];
}
it works (as to say, nothing wrong with the code implementation or the graphic interface).
I've browsed through Apple Guide and tons of pages on the Internet, but I can't seem to find any light to this. Any further help (including answers as to where exactly find the answer in the ADG) would be really appreciated.
(Edited: here goes the AppDelegate code to flip to the specific view, just in case):
//myAppAppDelegate.h
#import <UIKit/UIKit.h>
#class myAppViewController, GameScreenViewController;
#interface myAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
myAppViewController *viewController;
GameScreenViewController *gameScreenViewController;
}
- (void) flipToGameScreen;
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) GameScreenViewController *gameScreenViewController;
#end
//myAppAppDelegate.m
-(void) flipToGameScreen
{
GameScreenViewController *aGameScreenView = [[GameScreenViewController alloc] initWithNibName: #"GameScreen" bundle:nil];
[self setGameScreenViewController:aGameScreenView];
[aGameScreenView release];
[gameScreenViewController.view.frame = [[UIScreen mainScreen] applicationFrame];
[viewController.view removeFromSuperview];
[self.window addSubview:[gameScreenViewController view]];
}
Since your cell00 is to be set by a NIB it will be nil if you simply do [[GameScreen alloc] init]. It will only be set if the corresponding NIB is loaded (and a connection is actually set up).
If the cell can be accessed in your viewDidLoad, create a property on GameScreen and pass it through the property (or a dedicated initWithCell: or something).
If you have something like an IBOutlet GameScreen *aGameScreen; on your GameScreenViewController (and also established a connection to cell00 in the same NIB) you should access that instead.