CoreLocation 定位

来源:http://www.cnblogs.com/miaomiaoshen/archive/2016/05/28/5536751.html
-Advertisement-
Play Games

前言: 本章會使用OC和Swift分別進行實現,需要瞭解Swift的小伙伴可以翻一下之前的博文 LBS和SoloMo(索羅門) LBS:基於位置的服務,根據定位展示周邊美食、景點等信息(全稱:Location Bassed Service) SoloMo:將位置社交、本地、移動化(全稱:Soclal ...


前言:
本章會使用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進入後臺處理,耗電量小
    • 劣勢:定位精度相對於標准定位服務較低,更新的頻率根據當前位置附近的基站密度決定

後臺繼續定位

如果想要在後臺繼續進行定位,需要打開後臺的定位模式

開啟後臺定位模式.gif

拓展:

  • 標準的定位服務(基於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之後,會自動彈出設置視窗,讓用戶選擇是否需要開啟授權
    • 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)")
        }
        
    }

先到這,最近太忙,過兩天找個時間根據定位做個小項目再分享出來


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、 前言 最近剛換了一家公司,由於之前的公司代碼並沒有用到項目框架,需要我整理下NHibernate與Entity Framework之間的區別及適用性。並寫出相關的示例代碼 面試的時候吹的牛,得把他填上啊。 剛剛整完相應的EF code first的示例代碼,需要連接oracle,那個資料庫遷移 ...
  • 偶然在博客園中瞭解到這種技術,順便學習了幾天。 以下是搜索到一些比較好的博文供參考: MEF核心筆記 《MEF程式設計指南》博文彙總 先上效果圖 一、新建解決方案 開始新建一個解決方案Mef,再添加一個winform項目為:MefDemo 如圖: 打開Form1視窗,拉入MenuStrip菜單控制項, ...
  • <!--[if !supportLists]-->1、<!--[endif]-->下載與引用 <!--[if !supportLists]-->a) <!--[endif]-->首先需要下載一個oracle clinent 12c 發行版(我這邊下載的是發行版)併進行安裝,下載內容如下圖 B) 創建 ...
  • 升級文檔: "Migrating from DNX to .NET Core" "Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0 RC2" "Migrating your Entity Framework Code from RC1 to RC2" ...
  • View視圖界面 請求的控制器方法 部分視圖方法 這樣的做法讓多個界面可以共用,例如: 1、點擊分類展示相關產品數據 2、點擊品牌展示相關產品數據 3、搜索產品,展示數據 4、············ 第一步:先確認好前端界面,以及數據使用的部分 第二步:將包含從資料庫查詢的數據html代碼和相關展 ...
  • 昨晚至今早,在新的項目中,實現一個小功能,就是當有訪問者瀏覽網頁在留言簿留言時,系統把留言內容發送至某一個郵箱或是抄送指定的郵箱中。 使用以前能正常發送郵件的代碼,但在新項目中,測試時,就是出現標題的錯誤:Mailbox unavailable. The server response was: 5 ...
  • 一、關於構造函數和析構函數 1、python中有構造函數和析構函數,和其他語言是一樣的。如果子類需要用到父類的構造函數,則需要在子類的構造函數中顯式的調用,且如果子類有自己的構造函數,必然不會自動調用父類的構造函數;但是對於沒有構造函數的子類來說,則會自動繼承父類的構造函數,且子類總會預設繼承多個父 ...
  • 本文內容全部出自《Python基礎教程》第二版,在此分享自己的學習之路。 lxx___歡迎轉載:http://www.cnblogs.com/Marlowes/p/5520948.htmllxx___ Created on Marlowes 本章將會介紹如何創建Python程式的圖形用戶界面(GUI ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...