This a issue that have took me down since I am not able to solve it although it seems so easy.
The fact is that I have an iOS app, mainly a webview that loads a website, and I need to load different wen page when notification is received. I am implementing push notification and I have managed to get them working. They are received by the app in the App Delegate and then is when the problem starts. I would like to launch the webview with a specific URL but I don't know how to do it. I have tried to get the webview instance and passes the URL to it:
"SomeAppDelegate.h"
#import <UIKit/UIKit.h>
#class BrowserViewController;
#interface SomeAppDelegate : UIResponder <UIApplicationDelegate>
#property(nonatomic, retain) IBOutlet BrowserViewController *viewController;
#property (strong, nonatomic) UIWindow *window;
#end
"SomeAppDelegate.m"
#import "SomeAppDelegate.h"
#import "BrowserViewController.h"
#implementation SomeAppDelegate
#synthesize window = _window;
#synthesize viewController;
.........
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[viewController.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20]];
[self.window addSubview:viewController.webView];
[self.window makeKeyAndVisible];
Another test was to create an instance method within BrowserViewContrller trying to reload from there. I also tried to load story board programatically but when "Is Initial View Controller" is unchecked in storyboard the app crashes just before launch.
I did a lot of googling but I don't understand pretty much how this life cycle works. I will thank any help.
Probably, you should set your viewcontroller as AppDelegate's window.rootViewController in the didFinishLaunching:withOptions: method of your app delegate instead of adding it's webView as window subview - because webView is only loaded after UIViewController's method viewDidLoad got called - that means that your webView might not be loaded when you're trying to reload it with request.
Related
In my AppDelegate I have a property. It is strong and of type custom class(which is a subclass of NSObject). It becomes NULL when the App goes to background. This behaviour is uncertain and could not be reproduced easily (even with Simulate Memory Warning option). It occurs randomly.
My understanding is, when the app goes to background and if some other app needs memory, the app will be terminated. But in this case, the app is not terminated but a specific property becomes null.
I have not implemented didReceiveMemoryWarning in any of my ViewControllers.
Please help me with this.
Edit:
This is the sample of how my AppDelegate looks
AppDelegate.h
#interface AppDelegate : UIResponder
#property (nonatomic, strong) UIWindow *window;
#property (nonatomic, strong) UINavigationController *navigationController;
#property (nonatomic, strong) Person *person;//This is the custom class
#end
AppDelegate.m
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:[UIViewController new]];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
#end
I would suggest you to override your property's setter and add a breakpoint in it. You will see when it has been set to nil.
Setter example:
- (void)setPerson:(Person *)person {
_person = person; // breakpoint on this line
}
You didnt give us more informations and I do not know where do you set your Person object. But you should be sure it is not deleted in somewhere. For exmp: when you assign references to that object, the references can be gone.
Or if you want to keep that instance forever, you can use Keychain or NSUserDefaults.
I don't think some other apps interefere your application allocation & deallocation. I think there is some memory leak in your application life cycle or may be some other object point your Person class weakly then deallocate your object when no-one point it when application goes into background state.
If application terminated, person loose the person object so persist the object and fetch before you use that. for persisting you can use any database or file system like plist or user defaults.
I want to change the value of a label in my default view controller from a different class.
So I start a simple 'Single View Application' iOS project (Xcode5)
This automatically generates a ViewController for me (which I
understand is the root view controller)
I now add a label in my View and connect it to the ViewController (via IBOutlet mechanism)
I call this outlet 'gameStateLabel', so it looks like this in the ViewController.h file
#property (weak, nonatomic) IBOutlet UILabel *gameStateLabel;
Next, I have a completely separate class which has the logic for my code, and based on a condition in the logic I want to change the UIlabel.
So I try to do this from my other class:
Get an instance of the root view controller like this:
UIViewController * uvc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
I think I now have an instance of the rootviewcontroller in uvc and should be able to reach in and change gameStateLabel.
BUT: I CANNOT do this uvc.gameStateLabel simply does not show up as a property even though it is clearly declared as a property and I've added the #synthesize for it also.
Any help will be greatly appreciated - I've been going nuts over this.
(For ref. I'm used to doing something similar on the Mac side where I'd declare a label as a property of the AppDelegate, get the instance of the Appdelegate and simply refer to the label property and change its text]
Here's the ViewController. Note that gameStateLable is a property
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *gameStateLabel;
#end
#implementation ViewController
#synthesize gameStateLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
And here is my class cls1 (which inherits from NSObject)
#import "cls1.h"
#import "ViewController.h"
#implementation cls1
-(void) dummy{
UIViewController * uvc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
// uvc does NOT show gameStateLabel in intellisense, i.e. uvc.gameStateLabel does NOT work
}
Add #import "mainRootVC.h" in you CustomClass.m file
And create object of mainRootVC such like,
mainRootVC *obj = [[mainRootVC alloc] init];
// Now you can access your label by
obj.gameStateLabel...
Do like this...
YourViewController *rootController =[(YourViewController*)[(YourAppDelegate*)
[[UIApplication sharedApplication]delegate] window] rootViewController];
Try the following too:
ViewController *controller = (ViewController*)self.window.rootViewController;
It will return the initial view controller of the main storyboard.
For sending information from a viewController to other viewController you have:
Delegates:Definiton and examples
NSNotificationCenter: Apple Documentation
NSString *label = #"label text";
[[NSNotificationCenter defaultCenter] postNotificationName:NAVIGATETO object:label userInfo:nil];
You can found tons of examples about those two. I recommend you use one of those.
Hope this helps a bit.
OK. I found two issues.
I had copied the code over from my Mac project and modified it. Something seems to have gone wrong.
I retyped the entire function and it solved most of the problem
uvc should be of the type ViewController* - not UIViewController* as I was doing
Thanks everyone for your replies - much appreciated.
This question already has answers here:
iOS - Calling App Delegate method from ViewController
(13 answers)
Closed 6 years ago.
I know there are duplicates of this question but my situation is different here.
When user goes back to the home (void)applicationDidEnterBackground gets invoked from the AppDelegate class. However once user presses home button, I don't want user to see this view controller again, so I have a method named (void)goToBeginning that switches to another view controller. I want to be able to call this method from AppDelegate. I don't really want to use NotificationCenter for this. Also the picked solution here:
Calling view controller method from app delegate
does not work for me as it initialises new object whereas I want to be able to call an object that is already in the view. How can I do that? I am using iOS 7 and XCode 5.
Notification. But you don't want this.
You can get the reference to your that viewController in the AppDelegate. Than call that (void)goToBeginning method in the (void)applicationDidEnterBackground
For example: In your ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.myViewController = self;
}
And in your AppDelegate:
#class MyViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (weak, nonatomic) MyViewController *myViewController;
#end
And in the AppDelegate's implementation:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self.myViewController goToBeginning];
}
The Problem
An IBOutlet is released before I have a chance to use it.
What I Want
I want to access a navigation controller from my app delegate so I can reload a table view.
My Setup
I have:
A Main.xib that's set as my main interface in target settings
An IBOutlet to the navigation controller as an ivar on my app delegate
This IBOutlet hooked up to the correct navigation controller in Main.xib
App Delegate is instantiated in the xib but not set as File's Owner
I'm using ARC, Xcode 4.3.2 and iOS5.1
What I've Tried
Changing deployment target
Putting a break point on dealloc for the navigation controller, app delegate - they're never called
Reading everything I can find on ARC and IBOutlets - nothing seems to contradict what I'm doing
Creating a fresh project with just a the minimum classes required - I see exactly the same problem
Code
KPAppDelegate.h
#interface KPAppDelegate : UIResponder <UIApplicationDelegate> {
IBOutlet KPBrowseExpensesNavigationController *nc;
}
#property (strong) IBOutlet KPBrowseExpensesNavigationController *nc;
KPAppDelegate.m
#implementation KPAppDelegate
#synthesize nc;
-(void)setNc:(KPBrowseExpensesNavigationController *)nc_ {
nc = nc_; // This gets called on view load and nc gets set.
}
...snip...
// This is called about 5 seconds after app startup
-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
// By the time we get here, nc is nil.
UITableViewController *tvc = [[nc viewControllers] objectAtIndex:0];
[[tvc tableView] reloadData];
}
#end
UPDATE
I must be doing something really silly here. Even an incredibly simple project still shows this problem. See link below.
Download a simple test project that shows the problem.
In Window nib, set the FilesOwner Class as UIApplication and then point it's delegate from Outlets to the AppDelegate object. This is what is wrong in your project example.
is your outlet from the Interface Builder set as an KPBrowseExpensesNavigationController type?
If not it is not going to create the connection between your nib and ViewController.
You should set its Custom Class as KPBrowseExpensesNavigationController in the Identity Inspector
I am not sure why you declare it as a property & a non-property. I should do something like this:
#interface KPAppDelegate : UIResponder <UIApplicationDelegate>
#property (nonatomic, strong) IBOutlet KPBrowseExpensesNavigationController *nc;
And in your implementation:
#implementation KPAppDelegate
#synthesize nc = _nc; // So you don't accidentally use nc
...snip...
// This is called about 5 seconds after app startup
-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
// By the time we get here, nc is nil.
UITableViewController *tvc = [[**self.nc** viewControllers] objectAtIndex:0];
[[tvc tableView] reloadData];
}
#end
Hope this helps!
I didn't see where you alloc your nav controller. Just declaring the property won't assign any value to it, so it would be nil. In you -didFinishLaunchingWithOptions in the app delegate, set your alloc/init statement. Everything else looks fine.
KPBrowseExpensesNavigationController *nc = [[KPBrowseExpensesNavigationController alloc] init];
If you have a custom init, you can use that too, but just make sure to set it up before you try and use it.
I'm struggling getting started with the Universal App template in Xcode 4.1. I'm following the basic principles set out by kotancode here. The problem is getting the relevant view controller to load. I will focus on the iPhone part as an example. I create a subclass of UIViewController without a XIB as my "master" view controller class (where shared code will go). I then subclass this to create the iPhone specific UIViewController class called BaseViewController_iPhone, this time with a XIB.
The iPhone specific app delegate the header is set to:
#import "TestAppDelegate.h"
#import "BaseViewController_iPhone.h"
#interface TestAppDelegate_iPhone : TestAppDelegate {
BaseViewController_iPhone *viewController;
}
#property (nonatomic, retain) IBOutlet BaseViewController_iPhone *viewController;
#end
and for the implementation I try to override the applicationdidfinishlaunchingwithoptions method.
#import "TestAppDelegate_iPhone.h"
#implementation TestAppDelegate_iPhone
#synthesize viewController;
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
-(void)dealloc {
[viewController release];
[super dealloc];
}
#end
This doesn't appear to work, it compiles fine and runs, but the new view controller and the corresponding XIB are not displayed (the original main window xib from the template is). I'm sure i'm missing something very simple, but i've spent a long time googling to no avail. Any help gratefully received.
Thank you.
Have you connected the ViewController in the app's delegate's XIB to your "BaseViewController_iPhone *viewController" ?
Are you sure the ViewController in the app's delegate's XIB is of the type BaseViewController?
Is the ViewController loading the correct XIB (check that in the app's delegate's xib)?
Check that and give some feedback.