iOS定位庫-INTULocationRequest

對象關(guān)系

對象關(guān)系.png

對象各自的功能

模塊和功能.png

業(yè)務(wù)流程

業(yè)務(wù)流程

源碼分析:

INTULocationRequestDefines.h

//這個(gè)文件主要定義庫使用的常量否过,宏和枚舉類型
  
//static 定義作用域曲秉, 在引入頭文件后可用
//命名規(guī)則: 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
  
//枚舉命名規(guī)則: 庫前綴 + 枚舉名稱
//app定位服務(wù)狀態(tài)
typedef NS_ENUM(NSInteger, INTULocationServicesState) {
  
//枚舉項(xiàng)命名規(guī)則:庫前綴 + 枚舉名稱 + 項(xiàng)名稱
    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,
 
};
 
 
//每次定位請求完成之后,回調(diào)參數(shù)登下,用于描述定位請求的狀態(tài),是成功還是失敗或者超時(shí)等
typedef NS_ENUM(NSInteger, INTULocationStatus) {
 
    INTULocationStatusSuccess = 0,
 
    INTULocationStatusTimedOut,
 
    INTULocationStatusServicesNotDetermined,
 
    INTULocationStatusServicesDenied,
 
    INTULocationStatusServicesRestricted,
 
    INTULocationStatusServicesDisabled,
 
    INTULocationStatusError
 
};
 
 
//定位結(jié)果回調(diào)
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能運(yùn)行的最高系統(tǒng)版本
#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];
 
        }
 
    }
 
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載叮喳,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末缰贝,一起剝皮案震驚了整個(gè)濱河市馍悟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌剩晴,老刑警劉巖锣咒,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赞弥,居然都是意外死亡毅整,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門绽左,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悼嫉,“玉大人,你說我怎么就攤上這事拼窥∠访铮” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵鲁纠,是天一觀的道長总棵。 經(jīng)常有香客問我,道長改含,這世上最難降的妖魔是什么情龄? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上骤视,老公的妹妹穿的比我還像新娘鞍爱。我一直安慰自己,他們只是感情好尚胞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布硬霍。 她就那樣靜靜地躺著,像睡著了一般笼裳。 火紅的嫁衣襯著肌膚如雪唯卖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天躬柬,我揣著相機(jī)與錄音拜轨,去河邊找鬼。 笑死允青,一個(gè)胖子當(dāng)著我的面吹牛橄碾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播颠锉,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼法牲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了琼掠?” 一聲冷哼從身側(cè)響起拒垃,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瓷蛙,沒想到半個(gè)月后悼瓮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡艰猬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年横堡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冠桃。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡命贴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出食听,到底是詐尸還是另有隱情套么,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布碳蛋,位于F島的核電站胚泌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肃弟。R本人自食惡果不足惜玷室,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一零蓉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧穷缤,春花似錦敌蜂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至身坐,卻和暖如春秸脱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背部蛇。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工摊唇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涯鲁。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓巷查,卻偏偏與公主長得像,于是被迫代替她去往敵國和親抹腿。 傳聞我的和親對象是個(gè)殘疾皇子岛请,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 記得畢業(yè)時(shí)崇败,我的同學(xué)海燕在畢業(yè)紀(jì)念冊上對我寫到: “你心細(xì)的時(shí)候比女孩子還心細(xì),你粗獷的時(shí)候比男孩子還粗獷房蝉。我曾“...
    林梢雁的家閱讀 914評論 11 24
  • 距離2018年沒幾天了,2017過得著實(shí)有些快微渠。這一年并沒有給自己定計(jì)劃搭幻,上半年過得忙碌且有規(guī)律,下半年過得忙碌又...
    織之閱讀 234評論 0 0