ฉันจะรับตำแหน่งปัจจุบันจากผู้ใช้ใน iOS ได้อย่างไร


คำตอบ:


336

คำตอบของ RedBlueThing ทำงานได้ค่อนข้างดีสำหรับฉัน นี่คือตัวอย่างโค้ดของวิธีที่ฉันทำ

หัวข้อ

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface yourController : UIViewController <CLLocationManagerDelegate> {
    CLLocationManager *locationManager;
}

@end

MainFile

ในวิธีการเริ่มต้น

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];

ฟังก์ชั่นการโทรกลับ

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSLog(@"OldLocation %f %f", oldLocation.coordinate.latitude, oldLocation.coordinate.longitude);
    NSLog(@"NewLocation %f %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
}

iOS 6

ใน iOS 6 ฟังก์ชั่นของผู้แทนถูกคัดค้าน ผู้รับมอบสิทธิ์ใหม่คือ

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations

ดังนั้นเพื่อให้ได้ตำแหน่งการใช้งานใหม่

[locations lastObject]

iOS 8

ใน iOS 8 ควรขออนุญาตอย่างชัดเจนก่อนเริ่มอัปเดตตำแหน่ง

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    [self.locationManager requestWhenInUseAuthorization];

[locationManager startUpdatingLocation];

คุณต้องเพิ่มสตริงสำหรับNSLocationAlwaysUsageDescriptionหรือNSLocationWhenInUseUsageDescriptionปุ่มใน Info.plist ของแอป มิฉะนั้นการโทรถึงstartUpdatingLocationจะถูกละเว้นและผู้รับมอบสิทธิ์ของคุณจะไม่ได้รับการโทรกลับใด ๆ

และในตอนท้ายเมื่อคุณเสร็จสิ้นการอ่านสถานที่โทรหยุดการปรับปรุงสถานที่ในสถานที่ที่เหมาะสม

[locationManager stopUpdatingLocation];

4
+1 ขอบคุณสำหรับการโพสต์โค้ดขนาดเล็กเพื่อชมคำตอบที่ได้รับการยอมรับ
AngeloS

12
ระวังด้วยตัวอย่างนี้ค่าคุณสมบัติเหล่านี้นำไปสู่การใช้พลังงานแบตเตอรี่ที่สูงขึ้น
DanSkeel

36
สำคัญ: คุณต้อง "stopUpdatingLocations" มิฉะนั้นวิธีการมอบหมายจะถูกเรียกทุกครั้งที่ผู้ใช้เปลี่ยนตำแหน่ง ดังนั้นปัญหาแบตเตอรี่ดังกล่าวข้างต้นและหากมีวิธีการอื่นที่ถูกกระตุ้นในวิธีการมอบหมายนี้ก็จะถูกเรียกต่อไป พวกแฮปปี้เข้ารหัส !! ไชโย !!
Apple_iOS0304

5
คุณเป็นผู้ใช้ประเภทที่ทำให้ StackOverflow ยอดเยี่ยม ตัวอย่างรหัสเป็นแบบอย่างและฉันหวังว่าผู้คนจะรวมพวกเขาไว้ด้วยคำตอบของพวกเขา
Danny

26
สำหรับ iOS 8.0+ คุณต้องใส่รหัสต่อไปนี้ลงใน Info.plist สำหรับโครงการของคุณ: NSLocationAlwaysUsageDescriptionหากคุณใช้งานอยู่[self.locationManager requestAlwaysAuthorization]หรือNSLocationWhenInUseUsageDescriptionกำลังใช้งาน[self.locationManager requestWhenInUseAuthorization]อยู่ นอกจากนี้เพื่อสนับสนุน iOS 6.0+ ถึง iOS 7.0+ รวมถึงคีย์NSLocationUsageDescriptionหรือ 'ความเป็นส่วนตัว - คำอธิบายการใช้ตำแหน่ง' ข้อมูลเพิ่มเติมเกี่ยวกับลิงค์: developer.apple.com/library/ios/documentation/General/Reference/
......

79

ใน iOS 6 นั้น

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

เลิกใช้แล้ว

ใช้รหัสต่อไปนี้แทน

- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations {
    CLLocation *location = [locations lastObject];
    NSLog(@"lat%f - lon%f", location.coordinate.latitude, location.coordinate.longitude);
}

สำหรับ iOS 6 ~ 8 วิธีการข้างต้นยังจำเป็น แต่คุณต้องจัดการการอนุญาต

_locationManager = [CLLocationManager new];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 &&
    [CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse
    //[CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways
   ) {
     // Will open an confirm dialog to get user's approval 
    [_locationManager requestWhenInUseAuthorization]; 
    //[_locationManager requestAlwaysAuthorization];
} else {
    [_locationManager startUpdatingLocation]; //Will update location immediately 
}

นี่คือวิธีการมอบสิทธิ์ซึ่งจัดการการอนุญาตของผู้ใช้

#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
    case kCLAuthorizationStatusNotDetermined: {
        NSLog(@"User still thinking..");
    } break;
    case kCLAuthorizationStatusDenied: {
        NSLog(@"User hates you");
    } break;
    case kCLAuthorizationStatusAuthorizedWhenInUse:
    case kCLAuthorizationStatusAuthorizedAlways: {
        [_locationManager startUpdatingLocation]; //Will update location immediately
    } break;
    default:
        break;
    }
}

10
สิ่งนี้ไม่ควรเป็น[locations lastObject]หรือ
Ian Dundas

1
ฉันลองทำตามขั้นตอนเดียวกันกับที่กล่าวไว้ข้างต้น แต่ฉันได้รับ "ผู้ใช้ยังคิดอยู่" พิมพ์ในคอนโซล ดังนั้นหมายความว่าแอพไม่ได้รับอนุญาตให้ใช้ตำแหน่ง ถ้าใช่ฉันจะอนุญาตให้แอปใช้ตำแหน่งได้อย่างไร กรุณาช่วย.
kirans_6891

61

คุณใช้กรอบงาน CoreLocationเพื่อเข้าถึงข้อมูลตำแหน่งเกี่ยวกับผู้ใช้ของคุณ คุณจะต้องสร้างอินสแตนซ์ของวัตถุCLLocationManagerและเรียกใช้ข้อความแบบอะซิงโครนัสstartUpdatingLocation คุณจะได้รับการโทรกลับด้วยตำแหน่งของผู้ใช้ผ่านCLLocationManagerDelegateที่คุณให้


31

ลองขั้นตอนง่าย ๆ นี้ ....

หมายเหตุ:โปรดตรวจสอบละติจูดและตำแหน่งของอุปกรณ์หากคุณใช้เครื่องมือจำลอง โดยค่าเริ่มต้นไม่มีใครเท่านั้น

ขั้นตอนที่ 1:นำเข้าCoreLocationกรอบงานในไฟล์. h

#import <CoreLocation/CoreLocation.h>

ขั้นตอนที่ 2:เพิ่มผู้รับมอบสิทธิ์ CLLocationManagerDelegate

@interface yourViewController : UIViewController<CLLocationManagerDelegate>
{
    CLLocationManager *locationManager;
    CLLocation *currentLocation;
}

ขั้นตอนที่ 3:เพิ่มรหัสนี้ในไฟล์คลาส

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self CurrentLocationIdentifier]; // call this method
}

ขั้นตอนที่ 4:วิธีการตรวจจับตำแหน่งปัจจุบัน

//------------ Current Location Address-----
-(void)CurrentLocationIdentifier
{
    //---- For getting current gps location
    locationManager = [CLLocationManager new];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [locationManager startUpdatingLocation];
    //------
}

ขั้นตอนที่ 5: รับตำแหน่งโดยใช้วิธีนี้

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    currentLocation = [locations objectAtIndex:0];
    [locationManager stopUpdatingLocation];
    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if (!(error))
         {
             CLPlacemark *placemark = [placemarks objectAtIndex:0];
             NSLog(@"\nCurrent Location Detected\n");
             NSLog(@"placemark %@",placemark);
             NSString *locatedAt = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "];
             NSString *Address = [[NSString alloc]initWithString:locatedAt];
             NSString *Area = [[NSString alloc]initWithString:placemark.locality];
             NSString *Country = [[NSString alloc]initWithString:placemark.country];
             NSString *CountryArea = [NSString stringWithFormat:@"%@, %@", Area,Country];
             NSLog(@"%@",CountryArea);
         }
         else
         {
             NSLog(@"Geocode failed with error %@", error);
             NSLog(@"\nCurrent Location Not Detected\n");
             //return;
             CountryArea = NULL;
         }
         /*---- For more results 
         placemark.region);
         placemark.country);
         placemark.locality); 
         placemark.name);
         placemark.ocean);
         placemark.postalCode);
         placemark.subLocality);
         placemark.location);
          ------*/
     }];
}

14

ใน Swift (สำหรับ iOS 8+)

Info.plist

สิ่งแรกก่อน คุณต้องเพิ่มสตริงคำอธิบายในไฟล์ info.plist สำหรับคีย์NSLocationWhenInUseUsageDescriptionหรือNSLocationAlwaysUsageDescriptionขึ้นอยู่กับประเภทของบริการที่คุณร้องขอ

รหัส

import Foundation
import CoreLocation

class LocationManager: NSObject, CLLocationManagerDelegate {
    
    let manager: CLLocationManager
    var locationManagerClosures: [((userLocation: CLLocation) -> ())] = []
    
    override init() {
        self.manager = CLLocationManager()
        super.init()
        self.manager.delegate = self
    }
    
    //This is the main method for getting the users location and will pass back the usersLocation when it is available
    func getlocationForUser(userLocationClosure: ((userLocation: CLLocation) -> ())) {
        
        self.locationManagerClosures.append(userLocationClosure)
        
        //First need to check if the apple device has location services availabel. (i.e. Some iTouch's don't have this enabled)
        if CLLocationManager.locationServicesEnabled() {
            //Then check whether the user has granted you permission to get his location
            if CLLocationManager.authorizationStatus() == .NotDetermined {
                //Request permission
                //Note: you can also ask for .requestWhenInUseAuthorization
                manager.requestWhenInUseAuthorization()
            } else if CLLocationManager.authorizationStatus() == .Restricted || CLLocationManager.authorizationStatus() == .Denied {
                //... Sorry for you. You can huff and puff but you are not getting any location
            } else if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
                // This will trigger the locationManager:didUpdateLocation delegate method to get called when the next available location of the user is available
                manager.startUpdatingLocation()
            }
        }
        
    }
    
    //MARK: CLLocationManager Delegate methods
    
    @objc func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        if status == .AuthorizedAlways || status == .AuthorizedWhenInUse {
            manager.startUpdatingLocation()
        }
    }
    
    func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
        //Because multiple methods might have called getlocationForUser: method there might me multiple methods that need the users location.
        //These userLocation closures will have been stored in the locationManagerClosures array so now that we have the users location we can pass the users location into all of them and then reset the array.
        let tempClosures = self.locationManagerClosures
        for closure in tempClosures {
            closure(userLocation: newLocation)
        }
        self.locationManagerClosures = []
    }
}

การใช้

self.locationManager = LocationManager()
self.locationManager.getlocationForUser { (userLocation: CLLocation) -> () in
            print(userLocation)
        }

8
ฉันเชื่อว่ามีสวิตช์ () อย่างรวดเร็วสำหรับกรณีเช่นนี้: ^)
Anton Tropashko

self.locationManager = LocationManager()ใช้บรรทัดนี้ในเมธอด viewDidLoad เพื่อให้ ARC ไม่ลบอินสแตนซ์และป๊อปอัปสำหรับตำแหน่งหายไปเร็วเกินไป
Kunal Gupta

12

เอกสาร Xcode มีความมั่งคั่งของความรู้และตัวอย่างแอพพลิเค - ตรวจสอบให้ความรู้สถานที่ตั้ง Programming คู่มือ

LocateMeโครงการตัวอย่างแสดงให้เห็นถึงผลกระทบของการปรับเปลี่ยนที่CLLocationManagerการตั้งค่าความถูกต้องที่แตกต่างกันของ


2

Info.plist iOS 11.x Swift 4.0 ต้องการคุณสมบัติทั้งสองนี้

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We're watching you</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Watch Out</string>

และรหัสนี้ ... ทำให้แน่ใจว่าเป็น CLLocationManagerDelegate ของคุณแน่นอน

let locationManager = CLLocationManager()

// MARK location Manager delegate code + more

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    switch status {
    case .notDetermined:
        print("User still thinking")
    case .denied:
        print("User hates you")
    case .authorizedWhenInUse:
            locationManager.stopUpdatingLocation()
    case .authorizedAlways:
            locationManager.startUpdatingLocation()
    case .restricted:
        print("User dislikes you")
    }

และแน่นอนรหัสนี้ด้วยซึ่งคุณสามารถใส่ใน viewDidLoad ()

locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestLocation()

และสองสิ่งนี้สำหรับคำขอตำแหน่งที่จะให้คุณไปหรือช่วยให้คุณไม่ต้องลุกจากที่นั่ง :)

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print(error)
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    print(locations)
}

1

คุณสามารถใช้บริการนี้ฉันเขียนเพื่อจัดการทุกอย่างให้คุณ

บริการนี้จะขอสิทธิ์และจัดการกับ CLLocationManager เพื่อให้คุณไม่ต้อง

ใช้แบบนี้:

LocationService.getCurrentLocationOnSuccess({ (latitude, longitude) -> () in
    //Do something with Latitude and Longitude

    }, onFailure: { (error) -> () in

      //See what went wrong
      print(error)
})

0

สำหรับ Swift 5 ต่อไปนี้เป็นคลาสสั้น ๆ เพื่อรับตำแหน่ง:

class MyLocationManager: NSObject, CLLocationManagerDelegate {
    let manager: CLLocationManager

    override init() {
        manager = CLLocationManager()
        super.init()
        manager.delegate = self
        manager.distanceFilter = kCLDistanceFilterNone
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // do something with locations
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.