I would like to refresh a UIWebView whenever my app comes to the foreground. All I really have in my ViewController.m is a method that checks for internet access (hasInternet) and viewDidLoad.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize webview;
-(BOOL)hasInternet{
Reachability *reach = [Reachability reachabilityWithHostName:#"www.google.com"];
NetworkStatus internetStats = [reach currentReachabilityStatus];
if (internetStats == NotReachable) {
UIAlertView *alertOne = [[UIAlertView alloc] initWithTitle:#"You're not connected to the internet." message:#"Please connect to the internet and restart the app." delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alertOne show];
}
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self hasInternet];
[webView loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://warm-chamber-7399.herokuapp.com/"]] ];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Any advice on how to enable this functionality? Does it go in AppDelegate or do I create another method within ViewController.m?
You should register a UIApplicationWillEnterForegroundNotification in your ViewController's viewDidLoad method and whenever app comes back from background you can do whatever you want to do in the method registered for notification. ViewController's viewWillAppear or viewDidAppear won't be called when app comes back from background to foreground.
-(void)viewDidLoad{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doYourStuff)
name:UIApplicationWillEnterForegroundNotification object:nil];
}
-(void)doYourStuff{
[webview reload];
}
Don't forget to unregister the notification you are registered for.
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Note if you register your viewController for UIApplicationDidBecomeActiveNotification then your method would be called everytime your app becomes active, It would not be appropriate to register for this notification.
Register for the UIApplicationDidBecomeActiveNotification or the UIApplicationWillEnterForegroundNotification.
Related
Alright, so I've been toying around with this for a couple days now and I haven't gotten this to work, looking to you for help!
Basically I want to "Unlock" a feature once an IAP is done. I've got the IAP code to work, but I want to change the button "sendMail" ('disabled' in Interface Builder) so that the user can interact with it.
//InputViewController.h
#import "IAPStore.h"
#interface InputViewController : UIViewController <MFMailComposeViewControllerDelegate, UIAlertViewDelegate>
#property(strong,nonatomic)IBOutlet UIButton *sendMail;
-(void)enableMail;
....
#end
//InputViewController.m
#import "InputViewController.h"
#import "IAPStore.h"
-(void)enableMail
{
[_sendMail setEnabled:YES];
NSLog(#"Unlocking Button");
}
//IAPStore.h
#import "InputViewController.h"
#interface IAPHelper : NSObject <UIAlertViewDelegate>
-(void)purchaseComplete;
...
#end
//IAPStore.m
#import "InputViewController.h"
-(void)purchaseComplete
{
UIAlertView *purchased = [[UIAlertView alloc]initWithTitle:#"In-App Purchase" message:#"Purchase complete! Thank you!" delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
GROWInputViewController *viewController = [[GROWInputViewController alloc] init];
[viewController enableMail];
[purchased show];
NSLog(#"button enabled");
}
So it prints out too the log but nothing is changed on the other view controller, but nothing is changed, any idea to what I'm doing wrong?
You could use NSNotificationCenter
In the viewDidLoad: method of InputViewController.m add this line of code:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(enableMail) name:#"purchaseCompleteNotification" object:nil];
And in the purchaseComplete method of IAPStore.m, replace this:
GROWInputViewController *viewController = [[GROWInputViewController alloc] init];
[viewController enableMail];
with this:
[[NSNotificationCenter defaultCenter] postNotificationName:#"purchaseCompleteNotification" object:nil];
This will cause a notification to be posted when the purchase is complete. Meanwhile, InputViewController has an 'observer' that is set to call your 'enableMail' method when that notification is posted.
Also, you'll want to add this method to your InputViewController.m, so that he is removed as an observer when deallocated.
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"purchaseCompleteNotification" object:nil];
}
I like to show the latest Push Notification in a label in my main StoryBoard I use this code to display the alert message in my AppDelegate.m:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSDictionary *test =(NSDictionary *)[userInfo objectForKey:#"aps"];
NSString *alertString =(NSString *) [test objectForKey:#"alert"];
NSLog(#"String recieved: %#",alertString);
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateActive) {
UIAlertView *alertmessage=[[UIAlertView alloc]initWithTitle:#"Geier"
message:alertString delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertmessage show];
AudioServicesPlaySystemSound(1002);
}
}
i tried this in my ViewController.m file latestpush.text = #"%#",alertString; but it doesn't work.
Can someone help me?
Thanks:)
You need to make the text available to the view controller.
You could do this by sending a custom NSNotification with the alert message, from inside application:didReceiveRemoteNotification:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"PushAlertNotification"
object:self
userInfo:#{#"alertString":alertString}];
In your view controller's viewDidLoad method, register as an observer:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateStoryboard:)
name:#"PushAlertNotification"
object:nil];
and create the updateStoryboard: method in the view controller:
- (void) updateStoryboard:(NSNotification *) notification {
self.latestpush.text = notification.userInfo[#"alertString"];
}
An alternative solution is to create a property in your AppDelegate that takes in the ViewController as an observer.
AppDelegate.h (change ViewController to the actual type of your VC).
#property (nonatomic, weak) ViewController *observer;
Inside the ViewController create a method that accepts the NSString and have that method update your Storyboard.
ViewController.m
-(void)updateStoryboard(NSString *alertString) {
self.latestpush.text = alertString;
}
Also, in your ViewContoller's viewDidLoad method, register yourself with the appDelegate:
- (void)viewDidLoad {
[super viewDidLoad];
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
delegate.observer = self;
}
Call updateStoryboard inside your application:didReceiveRemoteNotification: method:
[self.observer updateStoryboard:alertString];
I have a selector to show UIAlertView asking user if want to retry upload images after NotificationCenter post a notification with observename.
[[NSNotificationCenter defaultCenter] postNotificationName:kNOTIFICATION_PHOTOS_UPLOAD_RETRY object:nil];
But because of the notification received more than one, so will show as many as notifications received. Is there a best practice to show alert view only once?
Yeah, you can do something like:
#interface MyClass
{
UIAlertView *_myAlertView;
}
#end
#implementation MyClass
...
- (void)myNotificationSelector:(NSNotification *)notification
{
if (!_myAlertView) {
_myAlertView = [[UIAlertView alloc] init ...]
_myAlertView.delegate = self;
[_myAlertView show];
}
}
...
#end
and in the UIAlertViewDelegate handlers, just release and set _myAlertView to NO.
I'm trying to present a Modal View Controller when the app enters in foreground.. These are my files:
AppDelegate.m :
#import "AppDelegate.h"
#import "MainViewController.h"
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[self.window makeKeyAndVisible];
MainViewController * vc = [[MainViewController alloc]init];
[vc myMethodHere];
}
MainViewController.h :
//[..]
-(void) myMethodHere;
MainViewController.m :
-(void)myMethodHere{
NSLog(#"myMethodHere Activated.");
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
[self presentModalViewController:tweetViewController animated:YES];
}
NSLog(#"myMethodHere Activated.") works.. so I can't understand why "presentModalViewController" doesn't! What should I edit/add? Maybe a delay? Thanks for your help..
p.s. I know my english sucks.. Forgive me :)
I wouldn't rely on the methods in your app delegate for this (even though it seems like the obvious solution) because it creates unnecessary coupling between your application delegate and the view controller. Instead, you can have MainViewController listen for the UIApplicationDidBecomeActive notification, and present the tweet composer view controller in response to this notification.
First, register for the notification in -viewDidLoad.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMethodHere) name:UIApplicationDidBecomeActiveNotification object:nil];
}
Now, when this notification is received when your app returns from the background, myMethodHere will be invoked.
Lastly, remember to remove yourself as an observer when the view unloads.
- (void)viewDidUnload
{
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
I'm using AsyncSocket to connect to a server from my iPhone App. In the delegate that received data from the server, I post a notification that would tell the tableView's delegate to trigger a reloadData on the tableView:
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData*)data withTag:(long)tag {
[[NSNotificationCenter defaultCenter] postNotificationName:#"PEERSTATUSCHANGED" object:self];
[sock readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0];
}
and on the viewController:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(peerStatusDidChange:) name:#"PEERSTATUSCHANGED" object:nil];
}
return self;
}
- (void)peerStatusDidChange:(NSNotification *)notification {
NSLog(#"NOTIFICATION RECEIVED");
}
Now, this doesn't work at all. The notification is posed but not recognized by the ViewController. However, when I do the same thing in applicationDidFinishLaunching:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
protocol = [[XBBProtocol alloc] init];
SourceListViewController *sourceListVC = [[[SourceListViewController alloc] initWithNibName:#"SourceListViewController" bundle:nil] autorelease];
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:sourceListVC] autorelease];
[[NSNotificationCenter defaultCenter] postNotificationName:#"PEERSTATUSCHANGED" object:self];
[protocol connectToServer];
// Override point for customization after application launch
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
I got the notification received in viewController.
Anyone knows why? does it have something to do with delegate methods of AsyncSocket being in different thread?
Thanks in advance.
One possibility is that your initWithNibName:bundle: method is not actually being called. If you instantiate the view controller in a NIB (rather than in code), then it calls initWithCoder: instead.
A quick way to check is to put a breakpoint in initWithNibName:bundle:.
Try putting the method that sends the notification in a different method, and call it with "performSelectorOnMainThread". It's very likely your network code is getting called in a background thread and thus when the notification fires, it informs the table view on the same thread...
You can't make UI calls on anything but the main thread.