Home > Enterprise >  Objective C - How to call UI-process from non-UI class
Objective C - How to call UI-process from non-UI class

Time:12-09

I'm new to iOS so I could miss some basic concepts.

I'm trying to get the user position in iOS. I guess the problem could be related to the dispatch_async. I don't get errors during compilation but only the init function is called and the locationManager never gives an update.

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
 
@interface LocationC: UIViewController <CLLocationManagerDelegate> {
    CLLocationManager *locationManager;
}
 
@end
 
@implementation LocationC
 
- (instancetype) init {
    self = [super init];
    if (self) {
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        locationManager.distanceFilter = kCLDistanceFilterNone;
        locationManager.desiredAccuracy = kCLLocationAccuracyBest;
          
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
            [locationManager requestWhenInUseAuthorization];
        [locationManager startMonitoringSignificantLocationChanges];
        [locationManager startUpdatingLocation];
    }
    return self;
}
 
 //never called
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSLog(@"test")
}
@end
 
 
class LocationCollector : public claid::Module
{
    public:   
        void initialize()
        {
                dispatch_async(dispatch_get_global_queue(
                     DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
                //Background Thread   
                dispatch_async(dispatch_get_main_queue(), ^(void){
                    //Run UI Updates
                    LocationC *example = [[LocationC alloc] init];
                });
            });   
        }
};

CodePudding user response:

There might be a scenario in which the authorization status is not "Granted" when you call startMonitoring...

If the user sees the page for the first time and and location permission hasn't been authorized yet, requestWhenInUseAuthorization will display the dialogue, but you need to implement locationManager(_:didChangeAuthorization:) in order to know when the status has changed.

See this article: https://developer.apple.com/documentation/corelocation/cllocationmanager/1620562-requestwheninuseauthorization

It says: After the user makes a selection and determines the status, the location manager delivers the results to the delegate's locationManager(_:didChangeAuthorization:) method.

-- Update --

After another look, you should store a reference to the example instance, or else it would dealloc from memory before any location update is received. A UIViewController instance should be presented or pushed from another UIViewController instance, or alternatively it can be set as the root view controller of the application. Just instantiating it is not enough.

CodePudding user response:

You have to wait for user permission if it's not explicitly given before starting listening to the location updates, so you enable your listener only when this permission choice is delivered:

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface LocationC: UIViewController <CLLocationManagerDelegate>

@property (nonatomic, readonly) CLLocationManager *locationManager;

@end

@implementation LocationC

- (instancetype) init {
    if (self = [super init]) {
        _locationManager = [CLLocationManager new];
        _locationManager.delegate = self;
        _locationManager.distanceFilter = kCLDistanceFilterNone;
        _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        [self locationManagerDidChangeAuthorization:_locationManager];
    }
    return self;
}

#pragma mark CLLocationManagerDelegate

- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
    switch (manager.authorizationStatus) {
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        case kCLAuthorizationStatusAuthorizedAlways:
            [self startLocationListener];
            break;
        case kCLAuthorizationStatusNotDetermined:
            [manager requestWhenInUseAuthorization];
            break;
        default:
            [self stopLocationListener];
    }
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    NSLog(@"New locations: %@", locations);
}

#pragma mark Private

- (void)startLocationListener {
    [_locationManager startMonitoringSignificantLocationChanges];
    [_locationManager startUpdatingLocation];
}

- (void)stopLocationListener {
    [_locationManager stopMonitoringSignificantLocationChanges];
    [_locationManager stopUpdatingLocation];
}

@end

Also, be advised that you will need to provide the user with some message explaining why exactly you request location permissions by adding NSLocationWhenInUseUsageDescription key in your app's Info.plist

  • Related