delegate = [[UIApplication sharedApplication] delegate]; does not work in init: only viewDidLoad - iphone

I am using a delegate to store data for my app. I have a tabviewcontroller with a navigationviewcontroller as the first view controller. When i set the delegate using
delegate = [[UIApplication sharedApplication] delegate];
the delegate is null outside of the init method.
It however works fine when places in viewDidLoad. Any ideas why this could be?
UPDATE
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
delegate = [[UIApplication sharedApplication] delegate];
}
return self;
}

Is this view controller in your MainWindow.xib file (or whatever the main .xib in your project is called)? If so, the app delegate is likely also created when that file is loaded, and the app delegate probably is nil at time your view controller is created. If your app delegate has a reference to this view controller, have it set itself as the view controller's delegate in -applicationDidFinishLoadin:withOptions:, or just connect the app delegate to the view controller's -delegate outlet in the .xib file.

You shouldn't use -init method. Sometimes it's not being called. Use theese methods for additional initialization:
- (void)viewDidLoad {
[super viewDidLoad];
// do something
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// do something
}

The nib file was calling the initWithCoder method, not init.

Related

How to send data to the RootViewController

Here is my problem:
I have a basic application with a UIViewController embedded in a NavigationController. It is also the RootViewController of the application. From there I have a push segue to a normal UIViewControllerand a second push segue to a UITableViewController with its own UIViewController for the detailed view.
In the root view there is an instance of the class whose purpose is to send message with a define protocol.
In the table view the user will select the type of message he wants to send and in the detail view the content of that particular type of message.
Now the user has specified everything and I want him to push a "send" button. That button must do two things: pop back to the root view and send the user defined message by the protocol class instance.
I can do the pop back just fine with:
[self.navigationController popToRootViewControllerAnimated:true];
but I have no idea how to send the message (a class instance) back to the root view. The application is still fresh so I can completely change the structure if this one is not correct.
The best for me would be to access the protocol class instance from everywhere (I will need it in the other UIViewController) but I am not sure how to do that so that's why I thought of sending the message back to the root view.
If you know how to do one of the two above please give me a hand!
Cheers.
EDIT: Technically the NavigationController is the initial ViewController so I am not really sure who is the RootViewController anymore.
First: You could do: (only works when your view has been added to a the window)
[self.view.window.rootviewcontroller doSomething];
Second option is to define a property on your appDelegate:
#property (nonatomic, strong) UIViewController *root;
And call it through:
AppDelegate *appDelegate= (YourAppDelegateClass *) [[UIApplication sharedApplication] delegate];
[appDelegate.root doSomething];
you can Create an application object and assign the message to it. and use it on your root view controller. if i understood your question correctly this might help.
You could try:
UIApplication *myApp = [UIApplication sharedApplication];
UIWindow *frontWindow = [myApp.windows lastObject];
UIViewController *myRootViewController = frontWindow.rootViewController;
You Can also send Notification whenever you move to root view controller
by adding observer to it.
one way is to use protocol and other way is to pass your root view controller instance to your tableviewcontroller(via view controller) using your custom init method like:
UIViewController.m
- (id)initWithRoot:(id)rootInstance
withNibNameOrNil:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.root = (RootView *)rootInstance;
}
}
RootViewController.m
viewcontrollerInstance = [[viewcontroller alloc] initWithRoot:self withNibNameOrNil:#"viewcontroller"
bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:viewcontrollerInstance animated:YES];
UITableViewController.m
- (id)initWithRoot:(id)rootInstance
withNibNameOrNil:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.root = (RootView *)rootInstance;
}
}
ViewController.m
tableViewInstance = [[tablecontroller alloc] initWithRoot:self withNibNameOrNil:#"tablecontroller"
bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:tableViewInstance animated:YES];
UITableViewController.m
now on table view controller use your root instance(come from view controller) to call the function of root view controller like:
[self.root displayMessage:message];
sorry for the typo. hope this will help.

InitWithNibName returns viewController but view is nil

Other xib's auto-load fine, but not this one.
When I push this viewcontroller, initWithNibName, loadView, viewDidLoad, and viewWillAppear are called fine, but the view (and all self.xxx objects in #interface) are nil in all these methods, and I am left with an empty window under the navigationbar.
SettingsMain *newVC=[[SettingsMain alloc] initWithNibName:#"SettingsMain" bundle:nil];
[self.navigationController pushViewController:newVC animated:YES];
I was wondering if I can force setting self.view to what's in the .xib, in loadView or initWithNibName, so that all the outlets etc are initalized.
The viewcontroller has the standard code,
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
The problem is that when viewDidLoad is fired, self.view is nil.

XIB is not showing / loading the scrollview but the controls added via code inside the viewdidload being shown

I have addded UIScrollView to my xib but it was not showing on to my view controller.
Also in the view did load method, I have added text boxes to the view controller. This is displayed when I push the view, but not the scrollview which I added inside the xib.
I tried to push the view in two ways
Way 1
SubscribedDetailedViewController *aDetailView = [[[SubscribedDetailedViewController alloc]initWithNibName:#"SubscribedDetailedViewController" bundle:nil]autorelease];
[self.navigationController pushViewController:aPoemDetailView animated:YES];
Way 2
SubscribedDetailedViewController *aDetailView = [[[SubscribedDetailedViewController alloc]init]autorelease];
[self.navigationController pushViewController:aPoemDetailView animated:YES];
Also I placed the below code
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
The above function also gets called.
Why the scrollview which I added into the xib is not being displayed? But the controls added via code inside the viewdidload being shown.

Passing data between views isn't working

I've done this many times with code that is exactly the same, but for some reason it isn't working today.
ExampleViewController1 *exampleView = [[ExampleViewController1 alloc] initWithNibName:#"ExampleViewController1" bundle:nil];
[exampleView setProjectName:[[self.projectListArray objectAtIndex:indexPath.row] objectForKey:#"name"]];
NSLog(#"%#", [[self.projectListArray objectAtIndex:indexPath.row] objectForKey:#"name"]);
XAppDelegate.stackController pushViewController:exampleView fromViewController:nil animated:YES]
My NSLog prints out appropriately.
My ExampleViewController1.h file declared like:
#property(nonatomic, strong) NSString *projectName;
I then do this code in ExampleViewController1.m's
-(void)viewDidLoad {
NSLog(#"%#", self.projectName);
self.projectNameLabel.text = self.projectName;
[super viewDidLoad];
}
The results of my NSLogs are curious. The NSLog from my viewDidLoad appears to be getting called before my other one:
2012-04-22 10:59:41.462 StackedViewKit[43799:f803] (null)
2012-04-22 10:59:41.463 StackedViewKit[43799:f803] NewTest
I have confirmed that the (null) value there is from NSLog(#"%#", self.projectName);, but that should be the second NSLog called...I can't figure out why it is coming through first.
Someone requested this code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// random color
self.view.backgroundColor = [UIColor colorWithRed:((float)rand())/RAND_MAX green:((float)rand())/RAND_MAX blue:((float)rand())/RAND_MAX alpha:1.0];
}
return self;
}
As I expected, the problem is that you are trying to access self.view inside the initialization method. So move the line self.view.backgroundColor = ... to the viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", self.projectName);
self.projectNameLabel.text = self.projectName;
self.view.backgroundColor = [UIColor colorWithRed:((float)rand())/RAND_MAX green:((float)rand())/RAND_MAX blue:((float)rand())/RAND_MAX alpha:1.0];
}
In fact, the documentation of the view property says:
If you access this property and its value is currently nil, the view controller automatically calls the loadView method and returns the resulting view.
So when you call self.view in the initialization method, the view controller will have to load the view (from the nib or using the loadView method). And that's why viewDidLoad is called.
viewDidLoad is called before a view controller is displayed for the
first time, not immediately after initWithNibName.
> viewDidLoad method is called after the view controller has loaded its view
hierarchy into memory. This method is called regardless of whether the
view hierarchy was loaded from a nib file or created programmatically
in the loadView method.
> initWithNibName The nib file you specify is not loaded right away. It
is loaded the first time the view controller’s view is accessed. If
you want to perform additional initialization after the nib file is
loaded, override the viewDidLoad method and perform your tasks there.
You can use App delegate to pass the data from one to another, that is another alternate solution.
you do in initWithNibName method itself. or in viewDidAppear.
Your initWithNibName method should be like this as per as #sch comments;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil] //just set it here first and then check
if (self) {
// do something here;
}
return self;
}
We just need to be smart enough to think about what do we need to in constructor and what do we need to at viewDidLoad (once it had loaded into memory)

NSContextManagedObject - Problem Accessing it

I have tab bar navigation application and The problem is that in my root controller I am able to set its NSContextManagedObject to the app delegates...However when I try to do the same on the other controller the application freezes...
This only happens in the ViewDidLoad but thats where I need to set it so I can fetch the data
Im accessing it like this but it works on the RootviewController:
MyAppDelegate appD = (MyAppDelegate)[[UIApplication sharedApplication] delegate];
managedObjectContext = appD.managedObjectContext
Just does not work when I use it on other view controllers
I faced the same problem on my application. And I solved this by adding the following line that configures the managedObjectContext on my application delegate.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
viewController.managedObjectContext=self.managedObjectContext;
}
and on the viewController viewDidLoad you want to use the managedObjectContext:
- (void)viewDidLoad {
[super viewDidLoad];
MyAppDelegate *delegate=[[UIApplication sharedApplication]delegate];
self.managedObjectContext=delegate.managedObjectContext;
}
hope this helps,
Sarah