CoreLocation 定位
前言:
本章会使用OC和Swift分别进行实现,需要了解Swift的小伙伴可以翻一下之前的博文
LBS和SoloMo(索罗门)
- LBS:基于位置的服务,根据定位展示周边美食、景点等信息(全称:Location Bassed Service)
- SoloMo:将位置社交、本地、移动化(全称:Soclal Local Moblle)
- 社交化:在APP内加入一些社交元素,进行位置分享等
- 本地化:基于LBS周边的搜索等服务
- 移动化:基于3G\4G网络在移动APP上的服务
CoreLocation介绍
- 定位已经可以说是现在APP的主流,没有定位功能的APP都不好意思和大家见面,作为APP的重要组成部分,其实使用也非常简单,本章就苹果的CoreLocation框架进行简单分析和使用
- CoreLocation主要功能
- 地理定位:获取用户所以在区域,得到相应的经纬度或者海拔等一些地理信息
- 地理编码:根据详细的地址转换为经纬度信息
- 反地理编码:根据经纬度信息转换成具体地址
- 区域监听:指定一个区域,当用户进入或者离开这个区域,我们都可以监听到对应信息
- 一般MapKit和一起使用,因为Mapkit就是基于CoreLocation进行开发的,所以MapKit能进行定位也能展示地图,以后会就MapKit进行详解
distanceFilter(距离过滤)和 desiredAccuracy(定位精确度)属性
distanceFilter(距离过滤):最新位置距上次位置之间距离大于这个值,就会告诉通过代理告诉外界
- 默认距离KCLDistanceFilterNone (值为-1,因为小于0,所以会一直打印)
- 单位:米
desiredAccuracy(定位精确度):定位精确度越高,定位时间就越长,也就越耗电
- kCLLocationAccuracyBestForNavigation // 最适合导航
- kCLLocationAccuracyBest // 最好的
- kCLLocationAccuracyNearestTenMeters; // 附近10米
- kCLLocationAccuracyHundredMeters; // 附近100米
- kCLLocationAccuracyKilometer; // 附近1000米
- kCLLocationAccuracyThreeKilometers; // 附近3000米
iOS8之前定位
- 在XCode5之前我们需要用到的框架修需要手动导入(这边使用的是XCode7.3,有冲突的请进行相应调整)
- CoreLocation框架的主头文件#import <CoreLocation/CoreLocation.h>
- 定位前需要先获取CLLocationManager对象
- 从iOS6开始,想要获取用户的隐私(通讯录、日历、相机、定位、相册等),系统会自动弹框请求授权
- 在iOS8.0之前,为了提高用户点击允许授权的机率,通常会在info.plist中配置对应的key(Privacy - Location Usage Description)用来说明定位目的
OC:
// 为了全局只使用一个位置管理者,我们先对CLLocationManager进行懒加载
- (CLLocationManager *)locationM {
if (_locationM == nil) {
// 创建位置管理者
_locationM = [[CLLocationManager alloc] init];
// 设置代理
_locationM.delegate = self;
}
return _locationM;
}
// 在按钮点击事件中开启定位服务
// start:开启服务 stop:关闭服务
// 一旦调用这个方法,就会不断的调用用户信息(因为distanceFilter属性的默认值为-1)
// 基本定位(基于Wifi/GPS)
[self.locationM startUpdatingLocation];
// 这个方法是用来监听重大位置改变(因为基站与基站之间相距大所以这个方法会通过基站进行定位,前提是有电话模块的支持)
// [self.locationM startMonitoringSignificantLocationChanges];
// 先遵守CLLocationManagerDelegate协议,实现下面代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
NSLog(@"已定位到");
// 定位是非常频繁的,所以获取到用户信息后,最好马上关闭停止定位,以达到省电效果,在适当的时候再重新打开定位
[manager stopUpdatingLocation];
self.locationM = nil;
}
Swift:
// MARK:- 懒加载
private lazy var locationM : CLLocationManager = {
// 创建位置管理者
let locationM = CLLocationManager()
// 设置代理
locationM.delegate = self
return locationM
}()
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// 使用位置管理者获取用户位置信息
// 根据苹果的习惯,一般方法命中带ing(现在进行时),说明一旦执行这个方法,系统就会不断的调用这个方法
// 默认情况下只会在前台进行定位,如果在后台也想要获取用户的位置,需要开启后台模式 location updates
locationM.startUpdatingLocation()
}
// MARK:- CLLocationManagerDelegate
extension ViewController : CLLocationManagerDelegate {
// manager : 位置管理者
// locations : 位置数组
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("已定位到")
// 关闭定位
manager.stopUpdatingLocation()
}
startMonitoringSignificantLocationChanges(重大位置改变监听)
- 当位置发生较大变化后会调用这个服务(基于基站定位,所以必须要有电话模块)
- 优势:当APP被完全关闭后,也可以接收到位置通知,并且让APP进入后台处理,耗电量小
- 劣势:定位精度相对于标准定位服务较低,更新的频率根据当前位置附近的基站密度决定
后台继续定位
如果想要在后台继续进行定位,需要打开后台的定位模式
拓展:
- 标准的定位服务(基于GPS/Wifi/基站的定位服务)
- 程序被完全关闭后就无法再获取位置信息
- 显著位置变化定位服务(基于基站的定位服务,设备必须有电话模块支持)
- 当APP被完全关闭后,也可以接收到位置通知,并且让APP进入后台处理
- 定位精度相对于标准定位服务较低,耗电量小,更新的频率根据当前位置附近的基站密度决定
iOS8之后定位
从iOS8开始,苹果进一步加强了对用户隐私的保护,当APP想范围用户隐私信息的时候,系统不再自动弹出对话框让用户授权,为了能让系统自动弹出用户授权界面,需要进行下面设置
- 解决方案:调用iOS8的API,主动请求用户授权
// 注意:根据官方文档的解释,在使用下面2个方法的时候,如果不在info.plist中配置NSLocationWhenInUseUsageDescription这个key,那么方法都不会生效
// 请求前台定位授权
- (void)requestWhenInUseAuthorization // 注意:根据官方文档的解释,在使用下面2个方法的时候,如果不在info.plist中配置`NSLocationAlwaysUsageDescription`这个key,那么方法都不会生效
// 请求前后台定位授权
- (void)requestAlwaysAuthorization
OC:
- (CLLocationManager *)manager
{
if (_manager == nil) {
_manager = [[CLLocationManager alloc] init];
_manager.delegate = self;
// 需要注意的是,必须在info.plist文件中配置’NSLocationWhenInUseUsageDescription‘这个key,否则下面方法无效(官方注释有提到)
// 请求前台授权
[_manager requestWhenInUseAuthorization];
// 请求前后台授权
// [_manager requestAlwaysAuthorization];
}
return _manager;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.manager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(@"定位到了");
[self.manager stopUpdatingLocation];
}
swift:
class ViewController: UIViewController {
lazy var locationMgr : CLLocationManager = {
let locationMgr = CLLocationManager()
locationMgr.delegate = self
// 记得设置相应的授权请求Key
// 请求前台定位授权
locationMgr.requestWhenInUseAuthorization()
// 请求前后台定位授权
locationMgr.requestAlwaysAuthorization()
return locationMgr
}()
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// 开启定位
locationMgr.startUpdatingLocation()
}
}
//MARK: - CLLocationManager代理
extension ViewController : CLLocationManagerDelegate {
// 当定位到位置后调用
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("定位到了")
manager.stopUpdatingLocation()
}
}
定位适配
- 一般我们适配版本都会判断当前设备的版本,然后再进行相应的适配操作,这边就介绍另一种比较简单的适配方式
- 通过respondsToSelector:方法来判断方法是否可响应,可以的话再执行
OC:
if ([_manager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
// 需要注意的是,必须在info.plist文件中配置’NSLocationWhenInUseUsageDescription‘这个key,否则下面方法无效(官方注释有提到)
// 请求前台授权
[_manager requestWhenInUseAuthorization];
}
if ([_manager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
// 请求前后台授权(无论是否开启后台模式都可以获取位置信息,并且不会出现蓝条提示)
[_manager requestAlwaysAuthorization];
}
swift:
// 记得设置相应的授权请求Key
// 根据当前系统版本适配
// 当前版本是8.0及以上
if #available(iOS 8.0, *) {
// 请求前台定位授权
locationMgr.requestWhenInUseAuthorization()
}
if #available(iOS 8.0, *) {
// 请求前后台定位授权
locationMgr.requestAlwaysAuthorization()
}
- iOS9定位变化
- 前台定位于iOS8无变化
- 后台定位
- 方法一:在前台定位授权基础上,勾选后台模式location updates之后,需要额外设置属性allowsBackgroundLocationUpdates = YES
- 方法二:直接请求前后台定位授权,设置属性allowsBackgroundLocationUpdates = YES,开启后台模式
- 后台定位
- 前台定位于iOS8无变化
定位服务未开启或者被用户真正拒绝情况下的情况处理
- iOS8之前,需要将开启授权的截图展示给用户,让用户根据截图去开启授权
- iOS8之后,会自动弹出设置窗口,让用户选择是否需要开启授权
- iOS开始我们可以根据URL直接跳转到相应的设置界面
OC:
// 当授权状态发生改变时调用
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
NSLog(@"用户未选择");
break;
// 暂时没用,应该是苹果预留接口
case kCLAuthorizationStatusRestricted:
NSLog(@"受限制");
break;
// 真正被拒绝、定位服务关闭等影响定位服务的行为都会进入被拒绝状态
case kCLAuthorizationStatusDenied:
if ([CLLocationManager locationServicesEnabled]) { // 定位服务开启
NSLog(@"真正被用户拒绝");
// 跳转到设置界面
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if ([[UIApplication sharedApplication] canOpenURL:url]) { // url地址可以打开
[[UIApplication sharedApplication] openURL:url];
}
} else {
NSLog(@"服务未开启");
}
break;
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(@"前后台定位授权");
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"前台定位授权");
break;
default:
break;
}
}
swift:
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .NotDetermined:
print("用户未选择")
case .Restricted:
print("受限制")
case.Denied:
print("被拒绝")
if CLLocationManager .locationServicesEnabled() { // 定位服务开启
print("用户真正拒绝")
// 跳转到设置界面
if #available(iOS 8.0, *) {
let url = NSURL(string: UIApplicationOpenSettingsURLString)
if UIApplication.sharedApplication().canOpenURL(url!) {
UIApplication.sharedApplication().openURL(url!)
}
}
} else {
print("服务未开启")
}
case .AuthorizedAlways:
print("前后台定位授权")
case .AuthorizedWhenInUse:
print("前台定位授权")
}
}
获取位置信息
// 获取当前位置信息
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
// locations内的元素是按时间顺序排列,所以要获取最新的位置信息直接取locations数组内的最后一个元素即可(苹果官方文档注释)
NSLog(@"%@", [locations lastObject]);
}
结果:维度、经度、海拔(负值表示当前海拔无效)速度(负)航向(从0~359.9) 位置时间
根据获取的位置信息计算用户行走方向,行走距离,偏移角度
- coordinate:经纬度信息
- altitude:海拔
- horizontalAccuracy:水平方向精度,值为负数时,表示无效
- verticalAccuracy:判断海拔是否为负数,负数无效
- course:航向(0~359.9)
- floor:楼层(使用的楼层需要注册,否则无法使用)
- distanceFromLocation:计算2点之间的物理直线距离
OC:
// 获取当前位置信息
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
/*
* coordinate:经纬度信息
* altitude:海拔
* horizontalAccuracy:水平方向精确度,值如果小于0,代表位置数据无效
* verticalAccuracy:判断海拔是否为负数,负数无效
* floor:楼层,使用的楼层需要注册,否则无法使用
* course:航向(0~359.9)(这里的0表示的是正北不是磁北)
* distanceFromLocation:计算2各店之间物理直线距离
*/ // 获取当前位置信息
CLLocation *locationC = locations.lastObject; // 判断水平数据是否有效
if (locationC.horizontalAccuracy < 0) { // 负数表示无效
return;
}
// 计算行走方向(北偏东,东偏南,南偏西,西偏北)
NSArray *courseAry = @[@"北偏东", @"东偏南", @"南偏西", @"西偏北"];
// 将当前航向值/90度会得到对应的值(0,1,2,3)
NSInteger i = locationC.course / 90;
// 取出对应航向
NSString *courseStr = courseAry[i]; // 计算偏移角度
NSInteger angle = (int)locationC.course % 90;
// 判断是否为正方向
// 对角度取余,为0表示正
if (angle == 0) { // 截取字符串第一个字
courseStr = [courseStr substringToIndex:1];
// 拼接字符串
courseStr = [@"正" stringByAppendingString:courseStr];
} // 计算移动多少米
CGFloat distance = [locationC distanceFromLocation:self.lastLocation]; // 记录上次距离
self.lastLocation = locationC; NSLog(@"向 %@ 方向走了 %lf 米偏移角度 %ld 度", courseStr, distance, angle);
}swift:
// 当定位到位置后调用
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // 获取用户当前最新位置
let locationC = locations.last // 判断水平数据是否有效
if locationC?.horizontalAccuracy < 0 { // 负数表示无效
return
} // 计算行走方向(北偏东,东偏南,南偏西,西偏北)
let courseAry = ["北偏东", "东偏南", "南偏西", "西偏北"]
// 将当前航向值/90度会得到相应的值(0,1,2,3)
let i = Int((locationC?.course)! / 90)
// 取出对应航向
var courseStr = courseAry[i] // 计算偏移角度
let angle = Int((locationC?.course)! % 90)
// 判断是否为正方向
// 对角度取余,为0就表示正
if Int(angle) == 0 {
// 截取字符串第一个字
courseStr = (courseStr as NSString).substringToIndex(1)
} // 确定移动距离
let lastLoc = lastLocation ?? locationC
let distance = locationC?.distanceFromLocation(lastLoc!)
lastLocation = locationC // 拼接字符串
print("向\(courseStr)方向走了\(distance!)米偏移角度\(angle)")
}
区域监听
- 区域监听就是根据需求指定一块区域,当用户持设备进入或离开指定区域,我们都可以监听到
- iOS8开始,想要做区域监听,必须请求位置授权(因为区域监听原理就是获取用户位置,然后判断位置是否在设定的区域内,涉及到用户隐私)
OC:
- (CLLocationManager *)manager
{
if (!_manager) {
_manager = [[CLLocationManager alloc] init];
_manager.delegate = self;
// 请求用户授权区域监听
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
[_manager requestAlwaysAuthorization];
}
}
return _manager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 判断区域监听是否可用
if ([CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
return;
}
// 创建一个区域
// 确定圆心
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(21.23, 123.345);
// 确定半径
CLLocationDistance distance = 1000.0;
// 因为监听区域有最大值,所以要判断下是否超过监听的最大值
if (distance > self.manager.maximumRegionMonitoringDistance) {
distance = self.manager.maximumRegionMonitoringDistance;
}
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center radius:distance identifier:@"123"];
// 开始监听区域
[self.manager startMonitoringForRegion:region];
}
// 进入区域时
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(@"进入区域%@",region.identifier);
}
// 离开区域时
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(@"离开区域%@",region.identifier);
}
// 但外界调用请求某个指定区域的状态时
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
if (state == CLRegionStateUnknown)
{
NSLog(@"未识别");
}
if (state == CLRegionStateInside) {
NSLog(@"在区域内");
}
if (state == CLRegionStateOutside) {
NSLog(@"在区域外");
}
}
swift:
lazy var locationMgr : CLLocationManager = {
let locationMgr = CLLocationManager()
locationMgr.delegate = self
// 记得设置相应的授权请求Key
// 当前版本是8.0及以上
if #available(iOS 8.0, *) {
// 请求前后台定位授权
locationMgr.requestAlwaysAuthorization()
}
return locationMgr
}()
override func viewDidLoad() {
super.viewDidLoad()
// 创建一个区域
// 确定圆心
let center = CLLocationCoordinate2DMake(21.23, 123.345)
// 确定半径
var distance : CLLocationDistance = 1000
// 因为监听区域有最大值,索引先判断是否超过了监听区域的最大值
if distance > locationMgr.maximumRegionMonitoringDistance {
distance = locationMgr.maximumRegionMonitoringDistance
}
let region = CLCircularRegion(center: center, radius: distance, identifier: "123")
// 判断取余监听是否可用
if CLLocationManager.isMonitoringAvailableForClass(region.classForCoder) {
// 开始监听区域
locationMgr.startMonitoringForRegion(region)
}
}
// 进入区域
func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) {
print("进入监听区域")
}
// 离开区域
func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion) {
print("离开监听区域")
}
// 区域状态改变
func locationManager(manager: CLLocationManager, didDetermineState state: CLRegionState, forRegion region: CLRegion) {
if state == .Unknown {
print("未识别")
}
if state == .Inside {
print("在区域内")
}
if state == .Outside {
print("在区域外")
}
}
- 注意:
- 必须请求用户定位授权
- 使用前先判断区域监听是否可用
- 判断区域半径是否大于最大监听区域,如果大于最大监听区域范围,则无法监听成功
地理编码和反地理编码
- 地理编码:指根据地质关键字,将其转换成对应的经纬度等信息
- 反地理编码:指根据经纬度信息,将其转换成对应的省市区等信息
- CLPlacemark(地表对象)
- location:CLLocation类型,位置对象的信息,包含经纬度,海拔等
- region:CLRegion类型,地表对象对应区域
- addressDictionary:NSDictionary类型,存放省市,街道等信息
- name:NSString类型,地址全称
- thoroughfare:NSString类型,街道名称
- locality:NSString类型,城市名称
- administrativeArea:NSString类型,省名称
- country:NSString类型,国家名称
- 注意
- 必须联网
- 有时候反地理编码时会找不到对应信息,需要尝试更换经纬度
OC:
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
// 地理编码
[geocoder geocodeAddressString:@"福建省厦门市" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
CLPlacemark *placeM = [placemarks lastObject];
NSLog(@"维度:%@ -- 经度:%@", @(placeM.location.coordinate.latitude).stringValue, @(placeM.location.coordinate.longitude).stringValue);
}];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
// 反地理编码
CLLocationDegrees latitude = 24.490474;
CLLocationDegrees longitude = 118.11022;
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
NSLog(@"地址:%@", [placemarks firstObject].name);
}];
swift:
let geocoder = CLGeocoder()
// 地理编码
geocoder.geocodeAddressString("福建省厦门市") { (placemarks, error) in
let placeM = placemarks?.last
print("维度\(placeM?.location?.coordinate.latitude) -- 经度\(placeM?.location?.coordinate.longitude)")
}
// 反地理编码
let latitude : CLLocationDegrees = 24.490474
let longitude : CLLocationDegrees = 118.11022
let location = CLLocation(latitude: latitude, longitude: longitude)
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
print("地址:\(placemarks?.first?.name)")
}
}
先到这,最近太忙,过两天找个时间根据定位做个小项目再分享出来
小项目地址
CoreLocation 定位的更多相关文章
- iOS - CoreLocation 定位
前言 NS_CLASS_AVAILABLE(10_6, 2_0) @interface CLLocationManager : NSObject 1.CoreLocation 定位 配置 1.在 iO ...
- iOS开发拓展篇—CoreLocation定位服务
iOS开发拓展篇—CoreLocation定位服务 一.简单说明 1.CLLocationManager CLLocationManager的常用操作和属性 开始用户定位- (void)startUp ...
- iOS8中使用CoreLocation定位[转]
本文转自:http://blog.devzeng.com/blog/ios8-corelocation-framework.html iOS8以前使用CoreLocation定位 1.首先定义一个全局 ...
- iOS-----使用CoreLocation定位
使用CoreLocation定位 CoreLocation框架 (CoreLocation.framework)可用于定位设备当前经纬度, 通过该框架, 应用程序可通过附近的蜂窝基站\WIFI信号 或 ...
- CoreLocation定位技术
CoreLocation框架可用于定位设备当前经纬度,通过该框架,应用程序可通过附近的蜂窝基站,WIFI信号或者GPS等信息计算用户位置. iOS定位支持的3种模式. (1)GPS ...
- iOS iOS9.0 的CoreLocation定位
一.简介 iOS9.0如果当前处于前台授权状态,默认是不可以后台获取用户位置. 如果在前台授权下,让其能获取到后台定位,该怎么办 可以设置以下属性为YES,就可以继续获取后台位置,但是会出现蓝条 使用 ...
- 使用系统的CoreLocation定位
//// ViewController.m// LBS//// Created by tonnyhuang on 15/8/28.// Copyright (c) 2015年 tonnyhua ...
- ios8 - CoreLocation定位服务的变化
在iOS8开发中,发现一个CoreLocation的使用问题,执行操作之后,不会调用到定位之后的delegate方法中. 根据文档,需要在使用CoreLocation前调用方法: [locationm ...
- 关于CoreLocation定位服务的简单使用
在我们发微博,发表空间内容,以及在朋友圈发表动态的时候,会发现有一个位置信息的控件.iOS中是如何定位我们的位置信息的呢?基于此写一个小Demo,供大家参考使用. 在iOS中,用于定位时需要我们导入以 ...
随机推荐
- python注释
初学python 习得注释方法 如下: #我是注释 print("hello") ''' 我是 多行 注释! ''' 其实就是#号和三个单引号(也可以双引号)啦 看下面:这注释其实 ...
- log4net的配置详解
log4net是一款优秀的第三方日志框架,可以很容易的加载到开发项目中(引用log4net的dll,再配置些基本参数即可),帮助程序员把日志信息输出到各种不同的目标,常见的有文本.数据库.window ...
- easyui combobox 值怎样获取
$('#com').combobox('getValue')获取当前选中的值$('#com').combobox('getText')获取当前选中的文字
- Kosaraju算法---强联通分量
1.基础知识 所需结构:原图.反向图(若在原图中存在vi到vj有向边,在反向图中就变为vj到vi的有向边).标记数组(标记是否遍历过).一个栈(或记录顶点离开时间的数组). 算法描叙: :对 ...
- 聊一下C#开发者如何过渡到JAVA 开发者
由于工作需要,最近也开始倒腾Java了.NET的话,从2012年测试版开始玩的,那个时候VB6比较熟悉,还天真的以为VB.NET以后会很火, 事实证明,也只是一厢情愿,有C#了,要VB.NET干什么? ...
- CodeSmith连接Oracle
Win7上仅安装了Oracle32位客户端,此时CodeSmith无法连接Oracle数据库. 解决方法一:如果同一台电脑安装了Oracle64位数据库,这样CodeSmith可以连接数据库. 解决方 ...
- 不可或缺 Windows Native (11) - C++: hello c++, C++ 与 C语言的区别小介
[源码下载] 不可或缺 Windows Native (11) - C++: hello c++, C++ 与 C语言的区别小介 作者:webabcd 介绍不可或缺 Windows Native 之 ...
- csharp:workflow and bpm(Business Process Management)
http://ccflow.codeplex.com/ http://winwf.codeplex.com/ http://nginn.codeplex.com/ https://github.com ...
- 新平台,新版本,ComponentOne 持续发力
我们很高兴宣布2016年 V1 版本发布了,可免费下载试用. 今年ComponentOne 将聚焦WinForm.WPF.MVC.UWP平台和核心控件Flex家族. 本次发布主要包括UWP平台:Win ...
- springmvc(3)拦截器HandlerInterceptor源码的简单解析
其实拦截器就是我们的AOP编程.拦截器在我们的实际项目中实用性比较大的,比如:日志记录,权限过滤,身份验证,性能监控等等.下面就简单的来研究一下拦截器: public interface Handle ...