iOS: Why does "Turn on Location Services" alert show twice upon startup? - ios

When I have location services disabled, this alert shows up twice. The first time is without the location manager purpose property displayed. Immediately after that (before a button of first alert is touched), it shows again, this time with the purpose property included.
When the second alert is dismissed, the first alert is still there.
This is a little annoying, and I would expect it to be confusing to the users.
What can I do to only show it once, with the purpose property?

I had both a map controller object and a location manager object instantiated in my app delegate.
mapController = [[[MapController alloc] initWithFrame:CGRectMake(0, 0, 0, 0)] retain];
[self restartLocationManager];
However, the location manager purpose property is not set until the location manager is instantiated in this code:
- (void) restartLocationManager {
if (locationManager)
[locationManager release];
locationManager = [[[CLLocationManager alloc] init] retain];
locationManager.purpose = NSLocalizedString(#"Location Service Purpose", nil);
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
}
So this was a clue that something in the initialization of the map was triggering the first alert.
Because I declined to turn location services on in the first alert, the map controller initialized and saw a need to show the alert. The map controller initialization is this (it is part of a singleton, and needs some cleanup in that regard, but ignoring that...):
- (id) initWithFrame:(CGRect)aFrame {
#synchronized(self) {
if (!theMap) {
if (!self) self = [super init];
theMap = [[[MKMapView alloc] initWithFrame:aFrame] retain];
theMap.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
theMap.showsUserLocation = YES;
theMap.delegate = self;
}
return self;
}
Stepping through the code, I saw the second alert show up when the showUserLocation line was executed. I'll have to do a little more testing to narrow it down exactly, but I think I'm on the right track now.

Related

MapView not loading when in subclass of UIView

I created a custom view and I have a map in it, this is how my view is setup.
- (id)initWithFrame:(CGRect)frame withPackage:(AftershipTracking *)package andLocation:(CLLocation *)location
{
if (self = [super initWithFrame:frame]) {
self = [[[NSBundle mainBundle] loadNibNamed:#"SPShareView" owner:nil options:nil] lastObject];
[self setLabelsWithPackage:package];
_dayLabel.text = _dayLabel.text.uppercaseString;
[self setupMapWithPinLocation:location];
}
return self;
}
Inside of the setupMapWithPinLocation I have this.
- (void)setupMapWithPinLocation:(CLLocation *)location
{
_mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, 760, 560)];
_mapView.mapType = MKMapTypeStandard;
_mapView.delegate = self;
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
[annotation setCoordinate:location.coordinate];
[_mapView addAnnotation:annotation];
MKCoordinateRegion region = [_mapView regionThatFits:MKCoordinateRegionMakeWithDistance(location.coordinate , 700, 700)];
region.span.latitudeDelta = 3;
region.span.longitudeDelta = 3;
[_mapView setRegion:region animated:NO];
}
However after creating the view, when I look at it in debug I get a blank map that has not been loaded yet, what would be the correct way to go about implementing this? I added the delegate methods for checking if the MapView loaded and they seem to never get called. Also I do not need the map to be interactive, the map can be turned into an image and that would be good.
Based on the comment:
_mapView is already added in the nib
A NIB isn't a magical code-generation tool, it's data. It's loaded once, then its influence is expended. When it was loaded, whatever its mapView described was added to the NIB. I'll bet you have a map view in your nib that _mapView connects to? That's the one that's displaying.
When you do this:
_mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, 760, 560)];
You:
create a new instance of MKMapView that nobody else knows about;
discard your reference to the map view that is visible on screen.
Whatever you subsequently do to _mapView will have no effect to the one on screen for the same reason that:
int a = 3;
int b = a;
b = 4;
... does not change the value of a. Changing the identity of the object that _mapView points to has no effect on your view hierarchy. Your views are completely unaware that you have done it.
If you have a map view in your NIB that is being created and displaying as you want then there's no reason also to create one programmatically. Delete the line quoted above and leave everything else alone.
(also: it's very odd that you want to call initWithFrame: and then throw away your instance for a NIB-loaded copy, which you decided not to load via -initWithNibName:bundle:; if you're using a NIB then you should just set your basic view properties up in the NIB)

Core data object gets corrupted after calling requestAlwaysAuthorization

I have a problem.
I have a ViewController wherein I have a property that's a subclass of NSManagedObject. In the same viewController, in the viewDidAppear method, I call the new requestAlwaysAuthorization method on a CLLocationManager object because I need to use the GPS. My issue is that after the user has allowed me to use the device location, the core data object (the NSManagedObject) has all nil fields.
I've tested removing my [_locationManager requestAlwaysAuthorization]; line and that results in non-corrupted NSManagedObject but then again I can't use location on iOS8+ if I skip this line!
I'm using the Magical Records library to handle core data but I can't see how that could be a factor here.
Does anybody have any idea what might be going on?
EDIT: code
In the .h file of my viewController (VC) I have
#property (strong, nonatomic) CDMission *mission;
and in the .m file of the same VC I have:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[LocationTracker sharedTracker] wakeUpLocationManager];
}
The important methods in the LocationTracker class look like this:
+ (instancetype)sharedTracker {
static LocationTracker *sharedTracker = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedTracker = [[self alloc] init];
});
return sharedTracker;
}
# pragma mark - Getters and setters
- (CLLocationManager *)locationManager {
if (!_locationManager) {
_locationManager = [[CLLocationManager alloc] init];
if ([_locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[_locationManager requestAlwaysAuthorization];
}
_locationManager.activityType = CLActivityTypeFitness;
_locationManager.pausesLocationUpdatesAutomatically = YES;
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
return _locationManager;
}
- (void)wakeUpLocationManager {
[self locationManager];
}
when I put a break point in viewDidAppear I can see how my CDMission object (that's my NSManagedObject) is fine but when I press a button after allowing location and put a breakpoint in the button's selector I see how my object is messed up.
Second edit:
The CDMission object that is a property in my VC is passed into the VC from another viewcontroller. Thus, there is no core data code relevant to my issue. It's just that the NSManagedObject CDMission becomes corrupted after the user answers the permission question for the location.

GADInterstitial splash dismiss with warning

I want to add GADInterstitial to my iOS game, so everytime the app become active I want to present interestitial. In my AppDelegate.m, in method applicationDidBecomeActive: i call my method
-(void)splashInterstitial{
interestitial = [[GADInterstitial alloc] init];
interestitial.adUnitID = ADMOB_ID;
interestitial.delegate = self;
[interestitial loadAndDisplayRequest:[self createRequest] usingWindow:self.window initialImage:nil];
}
But everytime i close the ad i get warning:
attempt to dismiss modal view controller whose view does not currently appear. self = <GADInterstitialAppController: 0x5d3ed0> modalViewController = <GADWebAppViewController: 0x5d1ca0>
Does anyone got that warning?
I found a solution. Just always check will your initialization and visualization of banner after
viewDidAppear
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
hasLoaded = YES;
[self splashInterstitial];
}

CLLocation speed not displaying on UIView

I am pretty new to iOS coding. I need some help to fix an issue with CLLocation.
I use didUpdateLocations to retrieve location and speed information. I am able to get these details and display using NSLog.
However, I am unable to display it on UIview. How do I fix it?
Below is my code.
I use CoreLocationController to retrieve my location details.
#implementation CoreLocationController
#synthesize locMgr;
#synthesize location;
- (id)init {
self = [super init];
if(self != nil) {
self.locMgr = [[CLLocationManager alloc] init];
self.locMgr.delegate = self;
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
DriveTrapViewController *driveTrapViewController = [[DriveTrapViewController alloc]init];
self.location = [locations lastObject];
//NSLog(#"Speed, %f", self.location.speed);
[driveTrapViewController locationUpdate:(CLLocation *)self.location];
}
I send the retrieved details back to DriveTrapViewController. I am able to display them using NSLog. But self.speedText.text is always NULL and nothing is showing on the screen.
#implementation DriveTrapViewController
#synthesize CLController;
#synthesize speedText = _speedText;
- (void)viewDidLoad {
[super viewDidLoad];
CLController = [[CoreLocationController alloc] init];
CLController.delegate = self;
[CLController.locMgr startUpdatingLocation];
}
- (void)locationUpdate:(CLLocation *)location
{
NSString *speed = [NSString stringWithFormat:#"SPEED: %f", location.speed];
NSLog(#"Speed %#",speed);
self.speedText.text = speed;
}
How do I fix this? Any help is appreciated. Thanks
Every time your locationManager:didUpdateLocations: method is called, it creates a new DriveTrapViewController, which is destroyed as soon as the method finishes. Maybe you should use an ivar for this instead. That way it wouldn't be created and destroyed every time.
Also, both objects seem to be making instances of the other. Instead of a Core Location problem, this is a general architecture-type problem.
I'd suggest that at this stage you should just have a CLLocationManager variable inside your DriveTrapController instead of trying to break it out into a controller of it's own.
Try CLController.locMgr.desiredAccuracy = kCLLocationAccuracyBestForNavigation;. this should include some extra information about the users location, speed, bearing etc...

MTLocation how-to

Hi I just came across MTLocation here: https://github.com/darkseed/MTLocation.
I want to use a locate me button in my app which will be located in navigation bar and when pressed will move the map to current location.
The author proposes to use the code like this:
// Configure Location Manager
[MTLocationManager sharedInstance].locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[MTLocationManager sharedInstance].locationManager.distanceFilter = kCLDistanceFilterNone;
[MTLocationManager sharedInstance].locationManager.headingFilter = 5; // 5 Degrees
// create locate-me item
MTLocateMeBarButtonItem *locateMeItem = [[[MTLocateMeBarButtonItem alloc] initWithLocationStatus:MTLocationStatusIdle] autorelease];
// set delegate that is called when mode of Button changes
locateMeItem.delegate = [MTLocationManager sharedInstance];
// add target-action
[locateMeItem addTarget:self action:#selector(myCustomSelector:) forControlEvents:UIControlEventTouchUpInside];
// disable heading
locateMeItem.headingEnabled = NO;
// create array with ToolbarItems
NSArray *toolbarItems = [NSArray arrayWithObject:locateMeItem];
// set toolbar items
[self.toolbar setItems:toolbarItems animated:NO];
which is great to show a locate me button in toolbar but how can we make this work to show current location through gps? I guess tha we have to implement myCustomSelector method but I do not know how. Any help?
Make sure that you have
self.mapView.showsUserLocation = YES;
And then implement myCustomSelector:, for example like this:
- (void) myCustomSelector:(MTLocateMeBarButtonItem*) button {
[self.mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate];
}
You'll need to take care of a proper functionality at different button modes (whether MTLocateMeBarButton is Idle, or something else), but that should give you a direction.

Resources