博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS定位库-INTULocationRequest
阅读量:5797 次
发布时间:2019-06-18

本文共 27357 字,大约阅读时间需要 91 分钟。

对象关系

对象各自的功能

业务流程

源码分析:

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而不是NSIntegertypedef 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 () 
@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]; } } }复制代码

转载地址:http://ansfx.baihongyu.com/

你可能感兴趣的文章
Android实例-录音与回放(播放MP3)(XE8+小米2)
查看>>
构建自己的PHP框架--抽象Controller的基类
查看>>
CSS——(2)与标准流盒模型
查看>>
MYSQL 基本SQL语句
查看>>
Codeforces 451E Devu and Flowers(容斥原理)
查看>>
P2P行业专业术语(最全)
查看>>
C#中的Marshal
查看>>
网站发的文章有收录 但是没有排名怎么处理
查看>>
linux命令:ls
查看>>
Using RequireJS in AngularJS Applications
查看>>
hdu 2444(二分图最大匹配)
查看>>
shell编程笔记六:实现ll命令
查看>>
【SAP HANA】关于SAP HANA中带层次结构的计算视图Cacultation View创建、激活状况下在系统中生成对象的研究...
查看>>
[nodejs] nodejs开发个人博客(五)分配数据
查看>>
《Linux内核修炼之道》 之 高效学习Linux内核
查看>>
Java数据持久层框架 MyBatis之API学习九(SQL语句构建器详解)
查看>>
30分钟Git命令“从入门到放弃”
查看>>
nginx : TCP代理和负载均衡的stream模块
查看>>
MYSQL数据库间同步数据
查看>>
DevOps 前世今生 | mPaaS 线上直播 CodeHub #1 回顾
查看>>