CLLocation Region Monitoring behaves differently in iOS 5.1 and iOS 6 - ios5

UPDATE: I am looking for a workaround to this problem in iOS5.1. Currently, I have evidence that this issue in fact is known. However, I think it is related to an updated xcode rather than iOS5.1 actually region monitoring not working.
The simple code below behaves differently between iOS5 and iOS6. It works as expected in iOS6.
But in iOS5, the didEnterRegion callback is only triggered the first time the region is entered. If you exit the region, then re-enter the region, it will not be triggered. If you close and restart the app, entering the region will not trigger the callback.
The difference in behavior was seen on the iOS5 and iOS6 simulators. The broken iOS5 behavior was seen on an iPhone 4S with iOS5. Xcode 4.6 was used. CoreLocation framework was added properly, and locMan is a property of the AppDelegate. A clean new project was created for this test.
Can someone please find a workaround to this problem? The fix needs to use region monitoring, not active location updating.
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) CLLocationManager *locMan;
#end
// AppDelegate implementation file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
/// LocationManager
self.locMan = [[CLLocationManager alloc] init];
self.locMan.delegate = self;
CLLocationCoordinate2D coordinates = CLLocationCoordinate2DMake(40.0, 40.0);
CLLocationDistance distance = 100.0;
CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:coordinates radius:distance identifier:#"hello"];
[self.locMan startMonitoringForRegion:region];
[self.window makeKeyAndVisible];
return YES;
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(#"didEnterRegion");
}

After leaving this question open for a week, I feel that I've enough evidence that region monitoring is broken in iOS5.1. Time to close out the question.

Related

GEO-reminders launching app

I am thinking about an app which would use the GEO-reminders (those added in iOS5,Remind me at a Location when I leave/arrive ). But I need using this feature (in fact, only using the location) to get the current location and compare it with the defined location by my app and check whether it's the same loc or it isn't. If the current and defined location are the same, launch my app.
Is this possible?
I hope you to understand my objective.
Thanks in advance
While you will be able to monitor your location from the background, keep in mind, it will not automatically launch your app. You can use something like local notifications to prompt the user to open the app. But launching from the background automatically is not an option. At least not an App Store approved option.
The check for current region and defined region are done automatically when you set a region to monitor. The best place to start is by reading the docs for CLLocationManagerDelegate, especially startMonitoringForRegion:. The thing you want to do is called "Geofencing". You can also find more information in the Location Awareness guide.
As 'm new to iPhone Development i don't know how to programmatically lunch an app but i can help you out with the trigger on arriving on predefined location. here is the code.
1: import CoreLocation.framework
2: in viewController.h file place below code
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#end
3: inviewController.m
#import "ViewController.h"
#interface ViewController (){
CLLocationManager *locationManager;
CLRegion *mexicoBoundary;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
CLLocationCoordinate2D regionCords ;
//19.432608,-99.133208 lat, lon for mexico city
regionCords=CLLocationCoordinate2DMake(19.432608,-99.133208);
//5000 below, is in meters-radius
mexicoBoundary =
[[CLRegion alloc]initCircularRegionWithCenter:regionCords
radius:5000.0
identifier:#"mexico_Day"];
[locationManager startMonitoringForRegion:mexicoBoundary];
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(#"%#: %#", #"region entered", region.identifier);
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(#"%#: %#", #"region exited", region.identifier);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

No interaction with Facebook iOS SDK dialog after switching to thread?

I'm playing around a little bit with the Facebook iOS SDK.
I have a TabBar App (with MainWindow.xib) and I successfully integrated the Facebook SDK.
The problem is that non of the Facebook pop up dialogs are responding to my user interactions.
For example. I want to post something in the wall. The Facebook SDK opens a dialog but if i try to interacte with the dialog it doesn't happen anything.
The log tells me: [Switching to process 2365 thread 0x12d07]
How can I fix it?
I'm using the simulator.
The important code int the AppDelegate looks like that, it's actually more or less the same like on developer.facebook.com:
Thank you a lot.
// AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate, FBSessionDelegate, FBDialogDelegate> {
Facebook *facebook;
}
#property (nonatomic, retain) Facebook *facebook;
#property (strong, nonatomic) IBOutlet UIWindow *window;
#property (strong, nonatomic) IBOutlet UITabBarController *tabBarController;
// AppDelegate.m
#implementation AppDelegate
#synthesize facebook;
#synthesize window = _window;
#synthesize tabBarController = _tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
facebook = [[Facebook alloc] initWithAppId:#"APP_ID" andDelegate:self];
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
#end
Kind regards.
You need a method that posts to a feed, like the one below
-(void)postToFeed
{
MyAppAppDelegate *sharedAppDelegate = (MyAppAppDelegate *)[[UIApplication sharedApplication] delegate];
[sharedAppDelegate.facebook dialog:#"feed" andParams:params andDelegate:self];
}
I just hit this same problem. The problem for me was that my UIApplication keyWindow had userInteractionEnabled = NO. So not having that extra UIWindow present fixed it for me (more below).
I found this code in FBDialog.m
- (void)showWebView {
UIWindow* window = [UIApplication sharedApplication].keyWindow;
if (!window) {
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}
_modalBackgroundView.frame = window.frame;
[_modalBackgroundView addSubview:self];
[window addSubview:_modalBackgroundView];
....
so it's going to add the dialog to the keyWindow. I only had one window, so I thought. It turns out SVProgressHUD will create a new window with user interaction disabled and make it the key window (makes sense).
I'm guessing other HUD style things do this to. I was only showing the HUD while some prep work was done, so by the time I can show the dialog, I can remove it anyway. So that was my fix.
I dug this up by calling
NSLog(#"%#", [[UIApplication sharedApplication] windows]);
NSLog(#"%#", [UIApplication sharedApplication].keyWindow);
right before I was about to show the dialog and noticed
I had two UIWindow's
the key one's userInteractionEnabled was set to NO
Hope that helps.

Trying to make my iphone app universal. Navigation Controller keeps saying Unbalanced calls

have been trying couple of hours now to make my iphone app universal. The mission was successful but have a strange problem. The navigation controller keeps pushing things without even pushing anything. The app doesn't crash but it gives me a message in the console
nested push animation can result in corrupted navigation bar
2012-02-06 10:52:07.701 ##$%^^$[54755:207] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2012-02-06 10:52:07.704 !##$%^$%#[54755:207] Unbalanced calls to begin/end appearance transitions for <searchEditViewController: 0xc652150>.
and here is how i've set app the whole thing :
![navigation screen shot][1]
here is my code in the AppDelegate_iphone.h
#import <UIKit/UIKit.h>
#import "iPhoneView.h"
#import "AboutUsViewController.h"
#import "FavoritesViewController.h"
#class iPhoneView;
#interface AppDelegate_iPhone : NSObject <UIApplicationDelegate> {
UITabBarController *tabBarController;
UINavigationController *homeNavigationController;
UINavigationController *favouritesNavigationController;
AboutUsViewController *aboutUsViewController;
iPhoneView * search;
FavoritesViewController *favoritesViewController;
UIWindow *window;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet iPhoneView *search;
#property (nonatomic, retain) FavoritesViewController *favoritesViewController;
#end
and here is on my AppDelegate.m file
#import "AppDelegate_iPhone.h"
#import "iPhoneView.h"
#implementation AppDelegate_iPhone
#synthesize window,search,favoritesViewController;
#pragma mark -
#pragma mark Application lifecycle
- (void)applicationDidFinishLaunching:(UIApplication *)application
{ tabBarController = [[UITabBarController alloc] init];
homeNavigationController = [[UINavigationController alloc] init];
search = [[iPhoneView alloc] init];
[homeNavigationController pushViewController:search animated:NO];
favouritesNavigationController = [[UINavigationController alloc] init];
favoritesViewController = [[FavoritesViewController alloc]init];
[favouritesNavigationController pushViewController:favoritesViewController animated:NO];
aboutUsViewController =[[AboutUsViewController alloc] init];
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:#"επικοινωνία" image:[UIImage imageNamed:#"aboutus"] tag:0];
aboutUsViewController.tabBarItem = item;
[item release];
UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:#"αγαπημένα" image:[UIImage imageNamed:#"favorites"] tag:0];
favouritesNavigationController.tabBarItem = item2;
[item2 release];
NSArray *tabBarControllerCollection = [NSArray arrayWithObjects:homeNavigationController,favouritesNavigationController,aboutUsViewController,nil];
[tabBarController setViewControllers:tabBarControllerCollection animated:NO];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
- (void)applicationWillResignActive:(UIApplication *)application {
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
/*
Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application {
/*
Called when the application is about to terminate.
See also applicationDidEnterBackground:.
*/
}
#pragma mark -
#pragma mark Memory management
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
/*
Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
*/
}
- (void)dealloc {
[tabBarController release];
[search release];
[favoritesViewController release];
[favouritesNavigationController release];
[aboutUsViewController release];
[window release];
[super dealloc];
}
#end
OK solved had connected the button 2 times with the same action in IB. Took me 48hours to figure it out!

iOS Significant Location Change Only Works When Device is Awake

I am trying to write an app in iOS for the iPhone 4 using significant location change that fires a local notification each time the location delegate receives a location update. My code is posted below. I resign the app and close it out of the background. As long as the phone is awake (the screen is lit up), the application works well, firing the notifications, but when I put the phone to sleep (the screen is black), I no longer receive notifications until I wake the phone up by pressing the home button, receiving a text, etc. Then the notification is fired. What do I need to do in order for location updates to register even when the device is asleep? Thanks in advance.
SigLoc.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface SigLocViewController : UIViewController <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
#property (nonatomic, retain) CLLocationManager *locationManager;
#end
SigLoc.m
#import "SigLocViewController.h"
#implementation SigLocViewController
#synthesize locationManager;
- (void)viewDidLoad {
self.locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startMonitoringSignificantLocationChanges];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
UIApplication *app = [UIApplication sharedApplication];
UILocalNotification *alarm = [[[NSClassFromString(#"UILocalNotification") alloc] init] autorelease];
if (alarm) {
alarm.fireDate = nil;
alarm.repeatInterval = 0;
alarm.alertBody = #"Location Update";
alarm.soundName = UILocalNotificationDefaultSoundName;
alarm.hasAction = NO;
[app presentLocalNotificationNow:alarm];
}
}
My guess is your view is not active when your app goes into the background, so it has no way to get the notifications. I would assign your app delegate as a location manager delegate, and then pass the callbacks to your SigLoc location manager delegate.
I had a similar issue trying to receive the callbacks, which didn't resolve until I moved the location manager delegate to my app delegate. I would start there and work your way back to your method.

does the accelerometer work for the iphone/ipad simulator?

From what I can tell, my app should be firing accelerometer events while Im using the iPad simulator in XCode, but its not.
I have googled around and it somewhat seems that the accelerometer is not implemented in the simulator, is this correct? If so, why on earth would they have a "Hardware->Shake Gesture" menu option?
My code is as follows:
.h file:
#interface MyViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate, UIAccelerometerDelegate>{
UIAccelerometer *accelerometer;
//...other stuff
}
#property (nonatomic, retain) UIAccelerometer *accelerometer;
#end
then the .m file:
#implementation MyViewController
#synthesize accelerometer;
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
NSLog(#"%#", [NSString stringWithFormat:#"%#%f", #"X: ", acceleration.x]);
NSLog(#"%#", [NSString stringWithFormat:#"%#%f", #"Y: ", acceleration.y]);
NSLog(#"%#", [NSString stringWithFormat:#"%#%f", #"Z: ", acceleration.z]);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.accelerometer = [UIAccelerometer sharedAccelerometer];
self.accelerometer.updateInterval = .1;
self.accelerometer.delegate = self;
}
#end
Does this look right?
There's no accelerator in the simulator.
The "Hardware → Shake Gesture" is generated by directly sending a UIEvent to the active application.
Although Shake Gesture is implemented using the accelerator on the device, conceptually they are two different kind of user input — the gesture is an event, the acceleration is continuous variation. Thus the Shake Gesture menu item exists for the apps which only use such gesture (e.g. Shake to Undo) but do not need to know the exact acceleration vector.
Accelerometer does not work on iPhone/iPod Simulator. Neither "Hardware->Shake Gesture" use accelerometer nor the orientation change of safari on simulator.