iOS定位库-INTULocationRequest

对象关系

对象关系.png

对象各自的功能

模块和功能.png

业务流程

业务流程

源码分析:

INTULocationRequestDefines.h

//这个文件主要定义库使用的常量,宏和枚举类型
  
//static 定义作用域, 在引入头文件后可用
//命名规则: k + 库的前缀 + 名称  解决duplicate symbols
//定位精确度纬度:距离
static const CLLocationAccuracy kINTUHorizontalAccuracyThresholdCity =
5000.0;  // in meters
 
static const CLLocationAccuracy kINTUHorizontalAccuracyThresholdNeighborhood = 
1000.0;  // in meters
 
static const CLLocationAccuracy kINTUHorizontalAccuracyThresholdBlock =
         100.0;  // in meters
 
static const CLLocationAccuracy kINTUHorizontalAccuracyThresholdHouse =
          15.0;  // in meters
 
static const CLLocationAccuracy kINTUHorizontalAccuracyThresholdRoom =
            5.0;  // in meters
 
 
//定位精确度纬度:定位频率
static const NSTimeInterval kINTUUpdateTimeStaleThresholdCity = 
600.0;  // in seconds
 
static const NSTimeInterval kINTUUpdateTimeStaleThresholdNeighborhood = 
300.0;  // in seconds
 
static const NSTimeInterval kINTUUpdateTimeStaleThresholdBlock = 
60.0;  // in seconds
 
static const NSTimeInterval kINTUUpdateTimeStaleThresholdHouse = 
15.0;  // in seconds
 
static const NSTimeInterval kINTUUpdateTimeStaleThresholdRoom = 
5.0;  // in seconds
  
//枚举命名规则: 库前缀 + 枚举名称
//app定位服务状态
typedef NS_ENUM(NSInteger, INTULocationServicesState) {
  
//枚举项命名规则:库前缀 + 枚举名称 + 项名称
    INTULocationServicesStateAvailable,
 
    INTULocationServicesStateNotDetermined,
 
    INTULocationServicesStateDenied,
//受限的,不太清楚什么意思
    INTULocationServicesStateRestricted,
 
    INTULocationServicesStateDisabled
 
};
//每一次定位请求的唯一Id ,可以通过它操作某次定位请求,比如停止请求操作
//主要是可以使用INTULocationRequestID来描述它的意义,可读性比NSInteger高很多,
//比如方法返回就可以写成INTULocationRequestID而不是NSInteger
typedef NSInteger INTULocationRequestID;
 
 
//定位精确度枚举类型
typedef NS_ENUM(NSInteger, INTULocationAccuracy) {
 
    INTULocationAccuracyNone = 0,
 
    INTULocationAccuracyCity,
 
    INTULocationAccuracyNeighborhood,
 
    INTULocationAccuracyBlock,
 
    INTULocationAccuracyHouse,
 
    INTULocationAccuracyRoom,
 
};
 
 
//每次定位请求完成之后,回调参数,用于描述定位请求的状态,是成功还是失败或者超时等
typedef NS_ENUM(NSInteger, INTULocationStatus) {
 
    INTULocationStatusSuccess = 0,
 
    INTULocationStatusTimedOut,
 
    INTULocationStatusServicesNotDetermined,
 
    INTULocationStatusServicesDenied,
 
    INTULocationStatusServicesRestricted,
 
    INTULocationStatusServicesDisabled,
 
    INTULocationStatusError
 
};
 
 
//定位结果回调
typedef void(^INTULocationRequestBlock)(CLLocation *currentLocation, 
    INTULocationAccuracy achievedAccuracy, INTULocationStatus status);

INTULocationManager.m

@interface INTULocationManager () <CLLocationManagerDelegate, INTULocationRequestDelegate>
 
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, strong) CLLocation *currentLocation;
@property (nonatomic, assign) BOOL isMonitoringSignificantLocationChanges;
@property (nonatomic, assign) BOOL isUpdatingLocation;
@property (nonatomic, assign) BOOL updateFailed;
@property (nonatomic, strong) __INTU_GENERICS(NSArray, INTULocationRequest *) *
locationRequests;
 
@end
 
 
@implementation INTULocationManager
 
static id _sharedInstance;
 
 
+ (INTULocationServicesState)locationServicesState
 
{
 
    if ([CLLocationManager locationServicesEnabled] == NO) {
 
        return INTULocationServicesStateDisabled;
 
    }
 
    else if ([CLLocationManager authorizationStatus] == 
        kCLAuthorizationStatusNotDetermined) {
 
        return INTULocationServicesStateNotDetermined;
 
    }
 
    else if ([CLLocationManager authorizationStatus] == 
        kCLAuthorizationStatusDenied) {
 
        return INTULocationServicesStateDenied;
 
    }
 
    else if ([CLLocationManager authorizationStatus] == 
        kCLAuthorizationStatusRestricted) {
 
        return INTULocationServicesStateRestricted;
    }
 
    return INTULocationServicesStateAvailable;
 
}
 
 
 
+ (instancetype)sharedInstance
 
{
 
    static dispatch_once_t _onceToken;
 
    dispatch_once(&_onceToken, ^{
 
        _sharedInstance = [[self alloc] init];
 
    });
 
    return _sharedInstance;
 
}
 
- (instancetype)init
{
    NSAssert(_sharedInstance == nil, @"Only one instance of 
    INTULocationManager should be created. Use +[INTULocationManager 
    sharedInstance] instead.");
 
    self = [super init];
 
    if (self) {
 
        _locationManager = [[CLLocationManager alloc] init];
 
        _locationManager.delegate = self;
         
 
#ifdef __IPHONE_8_4
 
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_4
 
        /* iOS 9 requires setting allowsBackgroundLocationUpdates to YES in 
        order to receive background location updates.
 
         We only set it to YES if the location background mode is enabled for 
         this app, as the documentation suggests it is a
 
         fatal programmer error otherwise. */
 
        NSArray *backgroundModes = [[NSBundle mainBundle] 
        objectForInfoDictionaryKey:@"UIBackgroundModes"];
 
        if ([backgroundModes containsObject:@"location"]) {
 
            if ([_locationManager respondsToSelector:@selector(
                setAllowsBackgroundLocationUpdates:)]) {
 
                [_locationManager setAllowsBackgroundLocationUpdates:YES];
 
            }
 
        }
 
#endif /* __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_4 */
 
#endif /* __IPHONE_8_4 */
 
 
 
 
        _locationRequests = @[];
 
    }
 
    return self;
}
 
 
- (INTULocationRequestID)requestLocationWithDesiredAccuracy:(
    INTULocationAccuracy)desiredAccuracy
 
                                                    timeout:(NSTimeInterval)
                                                    timeout
 
                                                      block:(
                                                        INTULocationRequestBloc
                                                        k)block
 
{
 
    return [self requestLocationWithDesiredAccuracy:desiredAccuracy
 
                                            timeout:timeout
 
                               delayUntilAuthorized:NO
 
                                              block:block];
 
}
 
- (INTULocationRequestID)requestLocationWithDesiredAccuracy:(
    INTULocationAccuracy)desiredAccuracy
 
                                                    timeout:(NSTimeInterval)
                                                    timeout
 
                                       delayUntilAuthorized:(BOOL)
                                       delayUntilAuthorized
 
                                                      block:(INTULocationRequestBlock)
                                                      block
 
{
 
    if (desiredAccuracy == INTULocationAccuracyNone) {
 
        NSAssert(desiredAccuracy != INTULocationAccuracyNone, @"
        INTULocationAccuracyNone is not a valid desired accuracy.");
 
        desiredAccuracy = INTULocationAccuracyCity; // default to the lowest valid desired accuracy
 
    }
 
     
 
    INTULocationRequest *locationRequest = [[INTULocationRequest alloc] 
    initWithType:INTULocationRequestTypeSingle];
 
    locationRequest.delegate = self;
 
    locationRequest.desiredAccuracy = desiredAccuracy;
 
    locationRequest.timeout = timeout;
 
    locationRequest.block = block;
 
     
 
    BOOL deferTimeout = delayUntilAuthorized && ([CLLocationManager 
        authorizationStatus] == kCLAuthorizationStatusNotDetermined);
 
    if (!deferTimeout) {
 
        [locationRequest startTimeoutTimerIfNeeded];
 
    }
 
     
 
    [self addLocationRequest:locationRequest];
 
     
 
    return locationRequest.requestID;
 
}
 
- (INTULocationRequestID)subscribeToLocationUpdatesWithBlock:(
    INTULocationRequestBlock)block
 
{
 
    return [self subscribeToLocationUpdatesWithDesiredAccuracy:
    INTULocationAccuracyRoom
 
                                                         block:block];
 
}
 
- (INTULocationRequestID)subscribeToLocationUpdatesWithDesiredAccuracy:(
    INTULocationAccuracy)desiredAccuracy
 
                                                                 block:(INTULoc
                                                                    ationReques
                                                                    tBlock)
                                                                    block
 
{
 
    INTULocationRequest *locationRequest = [[INTULocationRequest alloc] 
    initWithType:INTULocationRequestTypeSubscription];
 
    locationRequest.desiredAccuracy = desiredAccuracy;
 
    locationRequest.block = block;
 
     
 
    [self addLocationRequest:locationRequest];
 
     
 
    return locationRequest.requestID;
 
}
 
- (INTULocationRequestID)subscribeToSignificantLocationChangesWithBlock:(
    INTULocationRequestBlock)block
 
{
 
    INTULocationRequest *locationRequest = [[INTULocationRequest alloc] 
    initWithType:INTULocationRequestTypeSignificantChanges];
 
    locationRequest.block = block;
 
     
 
    [self addLocationRequest:locationRequest];
 
     
 
    return locationRequest.requestID;
 
}
 
- (void)forceCompleteLocationRequest:(INTULocationRequestID)requestID
 
{
 
    for (INTULocationRequest *locationRequest in self.locationRequests) {
 
        if (locationRequest.requestID == requestID) {
 
            if (locationRequest.isRecurring) {
 
                [self cancelLocationRequest:requestID];
 
            } else {
 
                [locationRequest forceTimeout];
 
                [self completeLocationRequest:locationRequest];
 
            }
 
            break;
 
        }
 
    }
 
}
 
 
 
- (void)cancelLocationRequest:(INTULocationRequestID)requestID
 
{
    for (INTULocationRequest *locationRequest in self.locationRequests) {
 
        if (locationRequest.requestID == requestID) {
 
            [locationRequest cancel];
 
            INTULMLog(@"Location Request canceled with ID: %ld", (long)
            locationRequest.requestID);
 
            [self removeLocationRequest:locationRequest];
 
            break;
 
        }
 
    }
 
}
 
- (void)addLocationRequest:(INTULocationRequest *)locationRequest
 
{
 
    INTULocationServicesState locationServicesState = [INTULocationManager
     locationServicesState];
 
    if (locationServicesState == INTULocationServicesStateDisabled ||
 
        locationServicesState == INTULocationServicesStateDenied ||
 
        locationServicesState == INTULocationServicesStateRestricted) {
 
        // No need to add this location request, because location services are 
        //turned off device-wide, or the user has denied this app permissions 
        //to use them
 
        [self completeLocationRequest:locationRequest];
 
        return;
 
    }
 
    switch (locationRequest.type) {
 
        case INTULocationRequestTypeSingle:
 
        case INTULocationRequestTypeSubscription:
 
        {
 
            INTULocationAccuracy maximumDesiredAccuracy = 
            INTULocationAccuracyNone;
 
            for (INTULocationRequest *locationRequest in [self 
                activeLocationRequestsExcludingType:
                INTULocationRequestTypeSignificantChanges]) {
 
                if (locationRequest.desiredAccuracy > maximumDesiredAccuracy) {
 
                    maximumDesiredAccuracy = locationRequest.desiredAccuracy;
 
                }
 
            }
 
            maximumDesiredAccuracy = MAX(locationRequest.desiredAccuracy, 
                maximumDesiredAccuracy);
 
            [self updateWithMaximumDesiredAccuracy:maximumDesiredAccuracy];
            
            [self startUpdatingLocationIfNeeded];
        }
 
            break;
 
        case INTULocationRequestTypeSignificantChanges:
 
            [self startMonitoringSignificantLocationChangesIfNeeded];
 
            break;
 
    }
 
    __INTU_GENERICS(NSMutableArray, INTULocationRequest *) *
    newLocationRequests = [NSMutableArray arrayWithArray:self.locationRequests]
    ;
 
    [newLocationRequests addObject:locationRequest];
 
    self.locationRequests = newLocationRequests;
 
    INTULMLog(@"Location Request added with ID: %ld", (long)locationRequest.
    requestID);
 
}
 
- (void)removeLocationRequest:(INTULocationRequest *)locationRequest
 
{
 
    __INTU_GENERICS(NSMutableArray, INTULocationRequest *) *
    newLocationRequests = [NSMutableArray arrayWithArray:self.locationRequests]
    ;
 
    [newLocationRequests removeObject:locationRequest];
 
    self.locationRequests = newLocationRequests;
 
    switch (locationRequest.type) {
 
        case INTULocationRequestTypeSingle:
 
        case INTULocationRequestTypeSubscription:
 
        {
 
            INTULocationAccuracy maximumDesiredAccuracy = INTULocationAccuracyNone;
 
            for (INTULocationRequest *locationRequest in [self 
                activeLocationRequestsExcludingType:
                INTULocationRequestTypeSignificantChanges]) {
 
                if (locationRequest.desiredAccuracy > maximumDesiredAccuracy) {
 
                    maximumDesiredAccuracy = locationRequest.desiredAccuracy;
 
                }
 
            }
 
            [self updateWithMaximumDesiredAccuracy:maximumDesiredAccuracy];
 
            [self stopUpdatingLocationIfPossible];
        }
 
            break;
 
        case INTULocationRequestTypeSignificantChanges:
 
            [self stopMonitoringSignificantLocationChangesIfPossible];
 
            break;
 
    }
 
}
 
 
- (CLLocation *)currentLocation
{   
    if (_currentLocation) {
 
        if (_currentLocation.coordinate.latitude == 0.0 && _currentLocation.
            coordinate.longitude == 0.0) {
            _currentLocation = nil;
        }
    }
 
    return _currentLocation;
 
}
 
- (void)requestAuthorizationIfNeeded
 
{
 
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1
 
    // As of iOS 8, apps must explicitly request location services 
    //permissions. INTULocationManager supports both levels, "Always" and 
    //"When In Use".
 
    // INTULocationManager determines which level of permissions to request 
    //based on which description key is present in your app's Info.plist
 
    // If you provide values for both description keys, the more permissive 
    //"Always" level is requested.
 
    if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1 &&
     [CLLocationManager authorizationStatus] == 
     kCLAuthorizationStatusNotDetermined) {
 
        BOOL hasAlwaysKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:
        @"NSLocationAlwaysUsageDescription"] != nil;
 
        BOOL hasWhenInUseKey = [[NSBundle mainBundle] 
        objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != 
        nil;
 
        if (hasAlwaysKey) {
 
            [self.locationManager requestAlwaysAuthorization];
 
        } else if (hasWhenInUseKey) {
 
            [self.locationManager requestWhenInUseAuthorization];
 
        } else {
 
            // At least one of the keys NSLocationAlwaysUsageDescription or 
            //NSLocationWhenInUseUsageDescription MUST be present in the 
            //Info.plist file to use location services on iOS 8+.
 
            NSAssert(hasAlwaysKey || hasWhenInUseKey, @"To use location 
            services in iOS 8+, your Info.plist must provide a value for 
            either NSLocationWhenInUseUsageDescription or 
            NSLocationAlwaysUsageDescription.");
 
        }
 
    }
 
#endif /* __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1 */
 
}
 
- (void)updateWithMaximumDesiredAccuracy:(INTULocationAccuracy)
maximumDesiredAccuracy
 
{
 
    switch (maximumDesiredAccuracy) {
 
        case INTULocationAccuracyNone:
 
            break;
 
        case INTULocationAccuracyCity:
 
            if (self.locationManager.desiredAccuracy != 
                kCLLocationAccuracyThreeKilometers) {
 
                self.locationManager.desiredAccuracy = 
                kCLLocationAccuracyThreeKilometers;
 
                INTULMLog(@"Changing location services accuracy level to: low (
                    minimum).");
 
            }
 
            break;
 
        case INTULocationAccuracyNeighborhood:
 
            if (self.locationManager.desiredAccuracy != 
                kCLLocationAccuracyKilometer) {
 
                self.locationManager.desiredAccuracy = 
                kCLLocationAccuracyKilometer;
 
                INTULMLog(@"Changing location services accuracy level to: 
                medium low.");
 
            }
 
            break;
 
        case INTULocationAccuracyBlock:
 
            if (self.locationManager.desiredAccuracy != 
                kCLLocationAccuracyHundredMeters) {
 
                self.locationManager.desiredAccuracy = 
                kCLLocationAccuracyHundredMeters;
 
                INTULMLog(@"Changing location services accuracy level to: 
                medium.");
 
            }
 
            break;
 
        case INTULocationAccuracyHouse:
 
            if (self.locationManager.desiredAccuracy != 
                kCLLocationAccuracyNearestTenMeters) {
 
                self.locationManager.desiredAccuracy = 
                kCLLocationAccuracyNearestTenMeters;
 
                INTULMLog(@"Changing location services accuracy level to: 
                medium high.");
 
            }
 
            break;
 
        case INTULocationAccuracyRoom:
 
            if (self.locationManager.desiredAccuracy != kCLLocationAccuracyBest) {
 
                self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
 
                INTULMLog(@"Changing location services accuracy level to: high 
                (maximum).");
 
            }
 
            break;
 
        default:
 
            NSAssert(nil, @"Invalid maximum desired accuracy!");
 
            break;
 
    }
 
}
 
 
- (void)startMonitoringSignificantLocationChangesIfNeeded
 
{
 
    [self requestAuthorizationIfNeeded];
 
     
 
    NSArray *locationRequests = [self activeLocationRequestsWithType:
    INTULocationRequestTypeSignificantChanges];
 
    if (locationRequests.count == 0) {
 
        [self.locationManager startMonitoringSignificantLocationChanges];
 
        if (self.isMonitoringSignificantLocationChanges == NO) {
 
            INTULMLog(@"Significant location change monitoring has started.")
 
        }
 
        self.isMonitoringSignificantLocationChanges = YES;
 
    }
 
}
 
- (void)startUpdatingLocationIfNeeded
 
{
 
    [self requestAuthorizationIfNeeded];
 
     
 
    NSArray *locationRequests = [self activeLocationRequestsExcludingType:
    INTULocationRequestTypeSignificantChanges];
 
    if (locationRequests.count == 0) {
 
        [self.locationManager startUpdatingLocation];
 
        if (self.isUpdatingLocation == NO) {
 
            INTULMLog(@"Location services updates have started.");
 
        }
 
        self.isUpdatingLocation = YES;
 
    }
 
}
 
 
 
 
- (void)stopMonitoringSignificantLocationChangesIfPossible
 
{
 
    NSArray *locationRequests = [self activeLocationRequestsWithType:
    INTULocationRequestTypeSignificantChanges];
 
    if (locationRequests.count == 0) {
 
        [self.locationManager stopMonitoringSignificantLocationChanges];
 
        if (self.isMonitoringSignificantLocationChanges) {
 
            INTULMLog(@"Significant location change monitoring has stopped.");
 
        }
 
        self.isMonitoringSignificantLocationChanges = NO;
 
    }
 
}
 
 
- (void)stopUpdatingLocationIfPossible
 
{
 
    NSArray *locationRequests = [self activeLocationRequestsExcludingType:
    INTULocationRequestTypeSignificantChanges];
 
    if (locationRequests.count == 0) {
 
        [self.locationManager stopUpdatingLocation];
 
        if (self.isUpdatingLocation) {
 
            INTULMLog(@"Location services updates have stopped.");
 
        }
 
        self.isUpdatingLocation = NO;
 
    }
 
}
 
 
- (void)processLocationRequests
 
{
 
    CLLocation *mostRecentLocation = self.currentLocation;
 
     
 
    for (INTULocationRequest *locationRequest in self.locationRequests) {
 
        if (locationRequest.hasTimedOut) {
 
            // Non-recurring request has timed out, complete it
 
            [self completeLocationRequest:locationRequest];
 
            continue;
 
        }
 
         
 
        if (mostRecentLocation != nil) {
 
            if (locationRequest.isRecurring) {
 
                // This is a subscription request, which lives indefinitely (
                    //unless manually canceled) and receives every location 
                    //update we get
 
                [self processRecurringRequest:locationRequest];
 
                continue;
 
            } else {
 
                // This is a regular one-time location request
 
                NSTimeInterval currentLocationTimeSinceUpdate = fabs([
                    mostRecentLocation.timestamp timeIntervalSinceNow]);
 
                CLLocationAccuracy currentLocationHorizontalAccuracy = 
                mostRecentLocation.horizontalAccuracy;
 
                NSTimeInterval staleThreshold = [locationRequest 
                updateTimeStaleThreshold];
 
                CLLocationAccuracy horizontalAccuracyThreshold = [
                locationRequest horizontalAccuracyThreshold];
 
                if (currentLocationTimeSinceUpdate <= staleThreshold &&
 
                    currentLocationHorizontalAccuracy <= 
                    horizontalAccuracyThreshold) {
 
                    // The request's desired accuracy has been reached, 
                    //complete it
 
                    [self completeLocationRequest:locationRequest];
 
                    continue;
 
                }
 
            }
 
        }
 
    }
 
}
 
 
- (void)completeAllLocationRequests
 
{
 
    __INTU_GENERICS(NSArray, INTULocationRequest *) *locationRequests = [self.
    locationRequests copy];
 
    for (INTULocationRequest *locationRequest in locationRequests) {
 
        [self completeLocationRequest:locationRequest];
 
    }
 
    INTULMLog(@"Finished completing all location requests.");
 
}
 
- (void)completeLocationRequest:(INTULocationRequest *)locationRequest
 
{
 
    if (locationRequest == nil) {
 
        return;
 
    }
 
     
 
    [locationRequest complete];
 
    [self removeLocationRequest:locationRequest];
 
     
 
    INTULocationStatus status = [self statusForLocationRequest:locationRequest]
    ;
 
    CLLocation *currentLocation = self.currentLocation;
 
    INTULocationAccuracy achievedAccuracy = [self achievedAccuracyForLocation:
    currentLocation];
 
    dispatch_async(dispatch_get_main_queue(), ^{
 
        if (locationRequest.block) {
 
            locationRequest.block(currentLocation, achievedAccuracy, status);
 
        }
 
    });
 
    INTULMLog(@"Location Request completed with ID: %ld, currentLocation: %@, 
    achievedAccuracy: %lu, status: %lu", (long)locationRequest.requestID, 
    currentLocation, (unsigned long) achievedAccuracy, (unsigned long)status);
}
 
- (void)processRecurringRequest:(INTULocationRequest *)locationRequest
 
{
 
    NSAssert(locationRequest.isRecurring, @"This method should only be called 
    for recurring location requests.");
 
     
 
    INTULocationStatus status = [self statusForLocationRequest:locationRequest];
 
    CLLocation *currentLocation = self.currentLocation;
 
    INTULocationAccuracy achievedAccuracy = [self achievedAccuracyForLocation:
    currentLocation];
 
 
    if (locationRequest.block) {
 
        locationRequest.block(currentLocation, achievedAccuracy, status);
 
    }
 
}
 
 
- (NSArray *)activeLocationRequestsWithType:(INTULocationRequestType)
locationRequestType
 
{
 
    return [self.locationRequests filteredArrayUsingPredicate:[NSPredicate 
    predicateWithBlock:^BOOL(INTULocationRequest *evaluatedObject, NSDictionary
     *bindings) {
 
        return evaluatedObject.type == locationRequestType;
 
    }]];
 
}
 
 
- (NSArray *)activeLocationRequestsExcludingType:(INTULocationRequestType)
locationRequestType
 
{
 
    return [self.locationRequests filteredArrayUsingPredicate:[NSPredicate 
    predicateWithBlock:^BOOL(INTULocationRequest *evaluatedObject, NSDictionary
     *bindings) {
 
        return evaluatedObject.type != locationRequestType;
 
    }]];
 
}
 
 
- (INTULocationStatus)statusForLocationRequest:(INTULocationRequest *)
locationRequest
 
{
 
    INTULocationServicesState locationServicesState = [INTULocationManager 
    locationServicesState];
 
     
 
    if (locationServicesState == INTULocationServicesStateDisabled) {
 
        return INTULocationStatusServicesDisabled;
 
    }
 
    else if (locationServicesState == INTULocationServicesStateNotDetermined) {
 
        return INTULocationStatusServicesNotDetermined;
 
    }
 
    else if (locationServicesState == INTULocationServicesStateDenied) {
 
        return INTULocationStatusServicesDenied;
 
    }
 
    else if (locationServicesState == INTULocationServicesStateRestricted) {
 
        return INTULocationStatusServicesRestricted;
 
    }
 
    else if (self.updateFailed) {
 
        return INTULocationStatusError;
 
    }
 
    else if (locationRequest.hasTimedOut) {
 
        return INTULocationStatusTimedOut;
 
    }
 
     
 
    return INTULocationStatusSuccess;
 
}
 
 
- (INTULocationAccuracy)achievedAccuracyForLocation:(CLLocation *)location
 
{
 
    if (!location) {
 
        return INTULocationAccuracyNone;
 
    }
 
     
 
    NSTimeInterval timeSinceUpdate = fabs([location.timestamp 
        timeIntervalSinceNow]);
 
    CLLocationAccuracy horizontalAccuracy = location.horizontalAccuracy;
 
     
 
    if (horizontalAccuracy <= kINTUHorizontalAccuracyThresholdRoom &&
 
        timeSinceUpdate <= kINTUUpdateTimeStaleThresholdRoom) {
 
        return INTULocationAccuracyRoom;
 
    }
 
    else if (horizontalAccuracy <= kINTUHorizontalAccuracyThresholdHouse &&
 
             timeSinceUpdate <= kINTUUpdateTimeStaleThresholdHouse) {
 
        return INTULocationAccuracyHouse;
 
    }
 
    else if (horizontalAccuracy <= kINTUHorizontalAccuracyThresholdBlock &&
 
             timeSinceUpdate <= kINTUUpdateTimeStaleThresholdBlock) {
 
        return INTULocationAccuracyBlock;
 
    }
 
    else if (horizontalAccuracy <= kINTUHorizontalAccuracyThresholdNeighborhood
     &&
 
             timeSinceUpdate <= kINTUUpdateTimeStaleThresholdNeighborhood) {
 
        return INTULocationAccuracyNeighborhood;
 
    }
 
    else if (horizontalAccuracy <= kINTUHorizontalAccuracyThresholdCity &&
 
             timeSinceUpdate <= kINTUUpdateTimeStaleThresholdCity) {
 
        return INTULocationAccuracyCity;
 
    }
 
    else {
 
        return INTULocationAccuracyNone;
 
    }
 
}
 
 
 
 
#pragma mark INTULocationRequestDelegate method
 
- (void)locationRequestDidTimeout:(INTULocationRequest *)locationRequest
 
{
 
    for (INTULocationRequest *activeLocationRequest in self.locationRequests) {
 
        if (activeLocationRequest.requestID == locationRequest.requestID) {
 
            [self completeLocationRequest:locationRequest];
 
            break;
 
        }
 
    }
 
}
 
 
 
 
#pragma mark CLLocationManagerDelegate methods
 
 
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(
    NSArray *)locations
 
{
    self.updateFailed = NO;
 
     
 
    CLLocation *mostRecentLocation = [locations lastObject];
 
    self.currentLocation = mostRecentLocation;
 
    [self processLocationRequests];
 
}
 
 
 
 
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError 
    *)error
 
{
 
    INTULMLog(@"Location services error: %@", [error localizedDescription]);
 
    self.updateFailed = YES;
 
 
 
 
    for (INTULocationRequest *locationRequest in self.locationRequests) {
 
        if (locationRequest.isRecurring) {
 
  
 
            [self processRecurringRequest:locationRequest];
 
        } else {
 
   
 
            [self completeLocationRequest:locationRequest];
 
        }
 
    }
 
}
 
 
 
 
- (void)locationManager:(CLLocationManager *)manager 
didChangeAuthorizationStatus:(CLAuthorizationStatus)status
 
{
 
    if (status == kCLAuthorizationStatusDenied || status == 
        kCLAuthorizationStatusRestricted) {
 
        [self completeAllLocationRequests];
 
    }
 
 
//__IPHONE_OS_VERSION_MAX_ALLOWED app能运行的最高系统版本
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1
 
    else if (status == kCLAuthorizationStatusAuthorizedAlways || status == 
        kCLAuthorizationStatusAuthorizedWhenInUse) {
 
#else
 
    else if (status == kCLAuthorizationStatusAuthorized) {
 
#endif /* __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1 */
 
 
        for (INTULocationRequest *locationRequest in self.locationRequests) {
 
            [locationRequest startTimeoutTimerIfNeeded];
 
        }
 
    }
 
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 记得毕业时,我的同学海燕在毕业纪念册上对我写到: “你心细的时候比女孩子还心细,你粗犷的时候比男孩子还粗犷。我曾“...
    林梢雁的家阅读 899评论 11 24
  • 距离2018年没几天了,2017过得着实有些快。这一年并没有给自己定计划,上半年过得忙碌且有规律,下半年过得忙碌又...
    织之阅读 230评论 0 0