How to correctly setup NSNotification and post? - ios

I want to make a singleton Reachability observer for each connection delegate to use,
however I couldn't build it correctly, here is some snippet of code.
MYReachability.m
static MYReachability *sharedInstance;
+ (MYReachability *)sharedInstance
{
if (sharedInstance == NULL) {
sharedInstance = [[MYReachability alloc] init];
}
return sharedInstance;
}
- (void)addReachabilityObserver
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(reachabilityChanged:)
name: kReachabilityChangedNotification
object: nil];
Reachability *reach = [Reachability reachabilityWithHostname: #"www.apple.com"];
[reach startNotifier];
}
- (void) reachabilityChanged: (NSNotification *)notification {
NSLog(#"notification: %#", notification);
Reachability *reach = [notification object];
if( [reach isKindOfClass: [Reachability class]]) {
NetworkStatus status = [reach currentReachabilityStatus];
NSLog(#"reachability status: %u", status);
if (status == NotReachable) {
// Insert your code here
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Cannot connect to server..."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
}
in MYConnectionDelegate.m
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if (error.code) {
// sending notification to viewController
[[MYReachability sharedInstance] addReachabilityObserver];
MYTestClass *myTestClass = [MYTestClass new];
[myTestClass notificationTrigger];
}
}
in MYTestClass.m
- (void)notificationTrigger
{
// All instances of TestClass will be notified
[[NSNotificationCenter defaultCenter]
postNotificationName:kReachabilityChangedNotification
object:self];
}
Rick, Thanks, that works, but here comes another problem,
each time it calls will generates one more notifications into stack...
I made a dealloc in MYReachability.m
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
but previous notification still exists.

You're calling the method notificationTrigger but your test class only has the method notificationTrigger: with a colon, i.e. one parameter.
Change [myTestClass notificationTrigger]; to [myTestClass notificationTrigger:self]; and it should work.
If you only want the notification to show once, remove yourself as an observer once the alert view has been shown, like this:
- (void) reachabilityChanged: (NSNotification *)notification {
NSLog(#"notification: %#", notification);
Reachability *reach = [notification object];
if( [reach isKindOfClass: [Reachability class]]) {
NetworkStatus status = [reach currentReachabilityStatus];
NSLog(#"reachability status: %u", status);
if (status == NotReachable) {
// Insert your code here
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Cannot connect to server..." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
}

In one class:
[[NSNotificationCenter defaultCenter] postNotificationName:#"notifyMe" object:self];
In another class:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(doSomething)
name:#"notifyMe"
object:nil];

Related

Share kit integration into iOS - Dropbox Authentication on button press

I’m trying to adapt the original Sharekit demo app so that it allows me to authenticate dropbox on a single button press (instead of appearing a new view etc. like it does in the demo).
To do this I have wired up a button with the following method as the IBAction (in the initial ViewController it launches into on Storyboard):
-(IBAction)assignDropbox:(id)sender
{
[SHK setRootViewController:self];
Class sharerClass = NSClassFromString(#"SHKDropbox");
BOOL isiOSSharer = [sharerClass isSubclassOfClass:[SHKiOSSharer class]];
if ([sharerClass isServiceAuthorized]) {
if (isiOSSharer) {
[sharerClass getUserInfo];
UIAlertView *iosSharerAlert = [[UIAlertView alloc] initWithTitle:#"iOS Social.framework sharer"
message:#"You can deauthorize this kind of sharer in settings.app, not here. By tapping this button you have refetched user info data only."
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:#"OK", nil];
[iosSharerAlert show];
} else {
[sharerClass logout];
//[self.tableView reloadData];
}
} else {
SHKSharer *sharer = [[sharerClass alloc] init];
[sharer authorize];
if (isiOSSharer) {
UIAlertView *iosSharerAlert = [[UIAlertView alloc] initWithTitle:#"iOS Social.framework sharer"
message:#"You can authorize this kind of sharer in settings.app, not here."
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:#"OK", nil];
[iosSharerAlert show];
}
}
if ([sharerClass isServiceAuthorized]) {
NSLog(#"After Logging in Username: %#", [sharerClass username]);
} else {
NSLog(#"After Logging in Username: %#", [sharerClass username]);
}
}
I’ve added the following notification code ViewDidLoad of the ViewController:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(authDidFinish:)
name:#"SHKAuthDidFinish"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidCancel:)
name:#"SHKSendDidCancel"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidStart:)
name:#"SHKSendDidStartNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidFinish:)
name:#"SHKSendDidFinish"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sendDidFailWithError:)
name:#"SHKSendDidFailWithError"
object:nil];
With the following code within the actual main (to make the notifications actually work - as per setup):
- (void)authDidFinish:(NSNotification*)notification
{
NSDictionary *userInfo = notification.userInfo;
NSNumber *success = [userInfo objectForKey:#"success"];
if (NO == [success boolValue]) {
NSLog(#"authDidFinish: NO");
} else {
NSLog(#"authDidFinish: YES");
NSLog(#"userInfo: %#", userInfo);
}
}
- (void)sendDidCancel:(NSNotification*)notification
{
NSLog(#"sendDidCancel:");
}
- (void)sendDidStart:(NSNotification*)notification
{
NSLog(#"sendDidStart:");
}
- (void)sendDidFinish:(NSNotification*)notification
{
NSLog(#"sendDidFinish:");
}
- (void)sendDidFailWithError:(NSNotification*)notification
{
NSLog(#"sendDidFailWithError:");
}'
It launches the web view in the app, and I can authenticate (I get notifications from dropbox saying another device has logged on), however the save authentication/session code in ‘SHKDropbox.m’ is never called.
Method under:
- (void)restClient:(DBRestClient*)client loadedAccountInfo:(DBAccountInfo*)info
I’ve done a lot of comparison work to see what the differences are between the projects, but can’t see any difference in settings.
Have you got any storyboard/button presses sample code as described above. Or have you got any idea on why this isn’t working on ShareKit?

Notification when WiFi connection available

I need a notification when device has WiFi connection is available or Device get connect via WiFi. I need to do some stuff only when WiFi is available.
I have used following code from Reachability:
BOOL status=true;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
internetReachability = [Reachability reachabilityForInternetConnection];
[internetReachability startNotifier];
NetworkStatus internetNetworkStatus = [internetReachability currentReachabilityStatus];
status = (internetNetworkStatus == ReachableViaWiFi);
But checkNetworkStatus: method not called properly and accurately. So, please guide me to solve this problem.
Any help to solve problem must be appreciated.
I hope it will help you in your problem.
-(void) rechabilityInit
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
self.internetConnectionReach = [Reachability reachabilityForInternetConnection];
self.internetConnectionReach.reachableBlock = ^(Reachability * reachability)
{
NSLog(#"%#", reachability.currentReachabilityString);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
dispatch_async(dispatch_get_main_queue(), ^{
// Do stuff here when WIFI is availble
}];
};
self.internetConnectionReach.unreachableBlock = ^(Reachability * reachability)
{
NSLog(#"%#", reachability.currentReachabilityString);
dispatch_async(dispatch_get_main_queue(), ^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// do some stuff here when WIFI not present
}];
};
[self.internetConnectionReach startNotifier];
}
-(void)reachabilityChanged:(NSNotification*)note
{
Reachability * reach = [note object];
if (reach == self.localWiFiReach)
{
if([reach isReachable])
{
NSString * temp = [NSString stringWithFormat:#"LocalWIFI Notification Says Reachable(%#)", reach.currentReachabilityString];
NSLog(#"%#", temp);
}
else
{
NSString * temp = [NSString stringWithFormat:#"LocalWIFI Notification Says Unreachable(%#)", reach.currentReachabilityString];
NSLog(#"%#", temp);
}
}
}
The following way is help me to solve my problem:
// Use below to any method
// check for internet connection
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
internetReachability = [Reachability reachabilityForInternetConnection];
[internetReachability startNotifier];
-(void) checkNetworkStatus:(NSNotification *)notice {
// called after network status changes
NetworkStatus internetStatus = [internetReachability currentReachabilityStatus];
switch (internetStatus) {
case NotReachable: {
NSLog(#"The internet is down.");
break;
}
case ReachableViaWiFi: {
NSLog(#"The internet is working via WIFI.");
//Remove Observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
//Write your code
break;
}
case ReachableViaWWAN: {
NSLog(#"The internet is working via WWAN.");
break;
}
}
}

When wi-fi is tuned off, status shows NotReachable but when wi-fi turned on again network status still shows NotReachable

I've this scenario, UIViewController => UITableViewController => UITableViewController => UIViewController.
From first UITableViewController, I check internet connection and populate data based on that.
This is what the problem is -
1. At first UITableViewController wi-fi is on so data populated from URL,
2. I turn-off wi-fi and select row and go to second UITableViewController, network status is NotReachable and data is populated from database
3. I turn on wi-fi and select row and go to last UIViewcontroller, here network status is NotReachable whereas it should be ReachableViaWiFi
Am I missing something? Please suggest.
-(void) viewWillAppear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(reachabilityChanged:)
name: kReachabilityChangedNotification
object: nil];
Reachability *reach = [Reachability reachabilityWithHostname: #"www.apple.com"];
[reach startNotifier];
}
- (void) reachabilityChanged: (NSNotification *)notification {
Reachability *reach = [notification object];
if( [reach isKindOfClass: [Reachability class]]) {
NetworkStatus status = [reach currentReachabilityStatus];
switch(status) {
case NotReachable:
{
if (!performedOnce) {
[self processOffline];
performedOnce = YES;
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];
}
break;
default:
{
if (!performedOnce) {
[self retrieveUserListWithUrl];
performedOnce = YES;
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];
}
break;
}
}
}

Reachability + UIAlertView + false-positive

Hey guys i'm having a few problems with Apple's reachability code.
What i've found out is that, even if the device is correctly connected to the internet, initially the reachability code will send out 1 false notification(Networkstatus = NotReachable) followed by a couple of correct notifications (Networkstatus = ReachableViaWiFi).
Therefore, as i am displaying an UIAlertView when i get a "NotReachable" notification, even if the device is connected to the internet, the app still outputs an uialertview informing the user that the device is not connected.
Is there anyway to avoid this inconvenience?
Any help would be really appreciated.
This is my code:
In my .h file:
#property (nonatomic, retain) Reachability *hostReach;
In my .m file:
- (void)viewDidLoad
{
self.hostReach = [Reachability reachabilityWithHostname:#"www.google.com"];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
[_hostReach startNotifier];
NetworkStatus netStatus = [self.hostReach currentReachabilityStatus];
if(netStatus == NotReachable && _alertShowing==NO){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"No internet connection found"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
_alertShowing = YES;
[alert show];
}
...
}
-(void)reachabilityChanged:(NSNotification *)note {
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
NetworkStatus netStatus = [curReach currentReachabilityStatus];
if(netStatus == NotReachable && _alertShowing==NO){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"No internet connection found"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
_alertShowing = YES;
[alert show];
}
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
_alertShowing = NO;
}
Why do you use reachabilityWithHostname:#"www.google.com"? This method checks the reachability of particular host (in your case google.com). And you receive notifications if Google available or not. Google may block you and you will receive NotReachable status.
Try to use:
//reachabilityForInternetConnection- checks whether the default route is available.
// Should be used by applications that do not connect to a particular host
+ (Reachability*) reachabilityForInternetConnection;
And also take a look on methods description here.

iPhone application freeze when out of range from wifi connection?

i have developed a radio application which uses network connection for online streaming, and also i am checking the condition whether network is available or not. if no network connection, it shows an alert "their is no network available" .my code is here
- (void)viewDidLoad
{
[super viewDidLoad];
//checking network reachability statys, this will show one alert view if no network available
Reachability* reachabile = [Reachability reachabilityWithHostName:#"www.apple.com"];
NetworkStatus remoteHostStatus = [reachabile currentReachabilityStatus];
if(remoteHostStatus == NotReachable)
{
NSLog(#"not reachable");
UIAlertView *notReachableAlert1=[[UIAlertView alloc]initWithTitle:#"NO INTERNET CONNECTION" message:#"This Application Need Internet To Run" delegate:self cancelButtonTitle:#"Okay Buddy" otherButtonTitles:nil];
notReachableAlert1.delegate=self;
[notReachableAlert1 show];
[notReachableAlert1 release];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerPlaybackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerLoadStateChanged:) name:MPMoviePlayerLoadStateDidChangeNotification object:player];
// Do any additional setup after loading the view from its nib.
}
also i checked the condition on notifications
-(void) moviePlayerPlaybackStateDidChange:(NSNotification*)notification
{
Reachability* reachabile = [Reachability reachabilityWithHostName:#"www.apple.com"];
NetworkStatus remoteHostStatus = [reachabile currentReachabilityStatus];
NSLog(#"playbackDidChanged");
MPMoviePlayerController *moviePlayer = notification.object;
player=notification.object;
MPMoviePlaybackState playbackState = moviePlayer.playbackState;
if(playbackState == MPMoviePlaybackStateStopped)
{
NSLog(#"MPMoviePlaybackStateStopped");
}
else if(playbackState == MPMoviePlaybackStatePlaying) {
NSLog(#"MPMoviePlaybackStatePlaying");
} else if(playbackState == MPMoviePlaybackStatePaused) {
NSLog(#"MPMoviePlaybackStatePaused");
if(remoteHostStatus == NotReachable)
{
NSLog(#"not reachable");
UIAlertView *notReachableAlert1=[[UIAlertView alloc]initWithTitle:#"NO INTERNET CONNECTION" message:#"This Application Need Internet To Run" delegate:self cancelButtonTitle:#"Okay Buddy" otherButtonTitles:nil];
notReachableAlert1.delegate=self;
[notReachableAlert1 show];
[notReachableAlert1 release];
}
} else if(playbackState == MPMoviePlaybackStateInterrupted)
{
NSLog(#"MPMoviePlaybackStateInterrupted");
if((remoteHostStatus == NotReachable)&&(remoteHostStatus != ReachableViaWiFi))
{
NSLog(#"not reachable");
UIAlertView *notReachableAlert1=[[UIAlertView alloc]initWithTitle:#"NO INTERNET CONNECTION" message:#"This Application Need Internet To Run" delegate:self cancelButtonTitle:#"Okay Buddy" otherButtonTitles:nil];
notReachableAlert1.delegate=self;
[notReachableAlert1 show];
[notReachableAlert1 release];
}
my problem is, when app goes out of range from wifi connection without without 3g and normal data connection, it freezes for some time. and when i came back to range only it goes to active state and shows alert.
is their anything wrong i did with network availability checking?
this is sample u can edit based on ur application
#class Reachability;
#interface urAppDelegate : NSObject <UIApplicationDelegate>
{
Reachability* internetReachable;
Reachability* hostReachable;
BOOL hostActive;
BOOL internetActive;
}
#property (nonatomic, assign) BOOL hostActive;
#property (nonatomic, assign) BOOL internetActive;
#end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.internetActive=NO;
self.hostActive=NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
internetReachable = [[Reachability reachabilityForInternetConnection] retain];
[internetReachable startNotifier];
// check if a pathway to a random host exists
hostReachable = [[Reachability reachabilityWithHostName: #"www.apple.com"] retain];
[hostReachable startNotifier];
// now patiently wait for the notification
[self.window makeKeyAndVisible];
return YES;
}
-(void) checkNetworkStatus:(NSNotification *)notice{
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
NSLog(#"The internet is down.");
self.internetActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(#"The internet is working via WIFI.");
self.internetActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(#"The internet is working via WWAN.");
self.internetActive = YES;
break;
}
}
NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
switch (hostStatus)
{
case NotReachable:
{
NSLog(#"A gateway to the host server is down.");
self.hostActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(#"A gateway to the host server is working via WIFI.");
self.hostActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(#"A gateway to the host server is working via WWAN.");
self.hostActive = YES;
break;
}
}
if (internetActive && hostActive)
{
// Net work Available.......
}
else
{
UIAlertView *netWorkAlert=[[UIAlertView alloc]initWithTitle:#"Network Connection Error" message:#"Please Check Connection" delegate:nil cancelButtonTitle:#"Close" otherButtonTitles:nil, nil];
[netWorkAlert show];
[netWorkAlert release];
}
}

Resources