2012-07-16 30 views
16

Tôi có nhiều bộ điều khiển xem cần lấy vị trí của người dùng, vì vậy tôi muốn tạo một lớp riêng biệt mà ViewControllers có thể gọi để nhận vị trí mới nhất của người dùng.iOS CLLocationQuản lý trong một lớp riêng biệt

locationManager: didUpdateToLocation: fromLocation return void. Làm cách nào để chuyển dữ liệu vĩ độ và kinh độ trở lại ViewControllers của tôi ngay khi vĩ độ và kinh độ của người dùng được tính?

Tôi có thể thử viết getters và setters ở vị trí của tôiQuản lý lớp, nhưng nếu tôi làm điều đó, làm cách nào để biết khi nào nên gọi hàm getter và kinh độ vĩ độ từ lớp ViewController của tôi? Làm thế nào để giữ thread chính của ViewController để chờ các giá trị vĩ độ và kinh độ từ lớp locationManaging?

Cảm ơn!

+0

'locationManager: didUpdateToLocation: fromLocation' là một phương thức đại biểu. Trình quản lý vị trí sử dụng phương pháp này để thông báo cho đối tượng của bạn rằng vị trí đã được cập nhật với một giá trị mới - tùy thuộc vào bạn để thực hiện phương pháp này để làm điều gì đó với giá trị. – quellish

Trả lời

14

Tạo một lớp đơn có các thuộc tính latitudelongitude, startLocatingendLocating. Trong lớp, tạo một cá thể CLLocationManager và đặt đại biểu của nó thành singleton. Trong startLocatingendLocating, hãy gọi các phương thức thích hợp của phiên bản CLLocationManager. Làm cho các phương thức ủy nhiệm cập nhật các thuộc tính latitudelongitude. Trong số khác ViewControllers, hãy đọc đơn vị số latitudelongitude của singleton này.

Để biết khi nào để đọc những thuộc tính từ ViewController khác, thiết lập một quan sát viên trên các đặc tính này (xem NSKeyValueObserving Protocol Reference

Trước khi làm điều này, hãy nhìn lên Internets cho mã hiện.

Sau khi làm điều này, upload nó để GitHub với một giấy phép dễ dãi.

+0

cảm ơn! câu hỏi tiếp theo của tôi là .. làm thế nào để tôi biết khi nào ViewController của tôi nên gọi các thuộc tính vĩ độ và kinh độ của singleton? Nói cách khác, làm thế nào để khóa chủ đề chính của ViewController để chờ các giá trị dài hợp lệ trong singleton – user1467188

+0

Đó là trong đoạn thứ hai (có thể đã thêm nó trong khi bạn đang đọc bài viết đầu tiên của tôi) – user1071136

+0

bạn truy cập các thuộc tính đơn bên trong quan sát viên thay đổi phương pháp thông báo – nilloc

23

Như user1071136 nói, một người quản lý vị trí singleton có lẽ là những gì bạn muốn. Tạo một lớp, một lớp con của NSObject, chỉ với một thuộc tính, một CLLocationManager.

LocationManagerSingleton.h:

#import <MapKit/MapKit.h> 

@interface LocationManagerSingleton : NSObject <CLLocationManagerDelegate> 

@property (nonatomic, strong) CLLocationManager* locationManager; 

+ (LocationManagerSingleton*)sharedSingleton; 

@end 

LocationManagerSingleton.m:

#import "LocationManagerSingleton.h" 

@implementation LocationManagerSingleton 

@synthesize locationManager; 

- (id)init { 
    self = [super init]; 

    if(self) { 
     self.locationManager = [CLLocationManager new]; 
     [self.locationManager setDelegate:self]; 
     [self.locationManager setDistanceFilter:kCLDistanceFilterNone]; 
     [self.locationManager setHeadingFilter:kCLHeadingFilterNone]; 
     [self.locationManager startUpdatingLocation]; 
     //do any more customization to your location manager 
    } 

    return self; 
}  

+ (LocationManagerSingleton*)sharedSingleton { 
    static LocationManagerSingleton* sharedSingleton; 
    if(!sharedSingleton) { 
     static dispatch_once_t onceToken; 
     dispatch_once(&onceToken, ^{ 
      sharedSingleton = [LocationManagerSingleton new]; 
     } 
    } 

    return sharedSingleton; 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 
    //handle your location updates here 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { 
    //handle your heading updates here- I would suggest only handling the nth update, because they 
    //come in fast and furious and it takes a lot of processing power to handle all of them 
} 

@end 

Để có được vị trí vừa nhận được hầu hết, chỉ cần sử dụng [LocationManagerSingleton sharedSingleton].locationManager.location. Có thể mất vài giây để khởi động GPS để có được vị trí chính xác.

+6

Có thể muốn cập nhật khối @synchronized của bạn thành 'dispatch_once'. – user

+0

@Rickay sẽ trả về kết quả này trong trường hợp Chế độ trên máy bay? –

+0

Nếu bạn kiểm tra câu trả lời này: (http://stackoverflow.com/questions/7376294/how-is-it-that-cllocationmanager-gets-a-location-when-airplane-mode-is-on) bạn sẽ thấy rằng trong trường hợp này 'CLLocationManager' trả về vị trí được mua gần đây nhất, nhưng không trả về thông tin vị trí mới. –

3

Dưới đây là những gì tôi đã làm khi thực hiện một vị trí manger singleton nhanh chóng. Nó dựa trên chiến lược của user1071136, cũng như this swift pattern.

// 
// UserLocationManager.swift 
// 
// Use: call SharedUserLocation.currentLocation2d from any class 


import MapKit 

class UserLocation: NSObject, CLLocationManagerDelegate { 

    var locationManager = CLLocationManager() 

    // You can access the lat and long by calling: 
    // currentLocation2d.latitude, etc 

    var currentLocation2d:CLLocationCoordinate2D? 


    class var manager: UserLocation { 
     return SharedUserLocation 
    } 

    init() { 
     super.init() 
     if self.locationManager.respondsToSelector(Selector("requestAlwaysAuthorization")) { 
      self.locationManager.requestWhenInUseAuthorization() 
     } 
     self.locationManager.delegate = self 
     self.locationManager.desiredAccuracy = kCLLocationAccuracyBest 
     self.locationManager.distanceFilter = 50 
     self.locationManager.startUpdatingLocation() 
    } 

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) { 
     self.currentLocation2d = manager.location.coordinate 

    } 
} 

let SharedUserLocation = UserLocation() 
+5

Mang găng tay bằng lò khi sử dụng thiết bị chạy mã này. – quellish

+0

Tôi hiện đang cố gắng sử dụng lớp học của bạn, nhưng ứng dụng không bao giờ yêu cầu ủy quyền cũng như tôi không nhận được vị trí. Tôi cần làm gì để sử dụng lớp học? – Thomas

+0

không bao giờ quên thông tin.plst: http://stackoverflow.com/questions/24050633/implement-cllocationmanagerdelegate-methods-in-swift/24056771#24056771 – Thomas

4

Dựa trên các câu trả lời ở trên, đây là những gì tôi đã làm và bạn có thể tìm thấy những ví dụ hoàn chỉnh trên github https://github.com/irfanlone/CLLocationManager-Singleton-Swift

Chỉ cần import file này trong dự án của bạn, sau đó bạn có thể chọn để thực hiện các LocationUpdateProtocol hoặc nghe thông báo để cập nhật vị trí

import MapKit 

protocol LocationUpdateProtocol { 
    func locationDidUpdateToLocation(location : CLLocation) 
} 

/// Notification on update of location. UserInfo contains CLLocation for key "location" 
let kLocationDidChangeNotification = "LocationDidChangeNotification" 

class UserLocationManager: NSObject, CLLocationManagerDelegate { 

    static let SharedManager = UserLocationManager() 

    private var locationManager = CLLocationManager() 

    var currentLocation : CLLocation? 

    var delegate : LocationUpdateProtocol! 

    private override init() { 
     super.init() 
     self.locationManager.delegate = self 
     self.locationManager.desiredAccuracy = kCLLocationAccuracyBest 
     self.locationManager.distanceFilter = kCLLocationAccuracyHundredMeters 
     locationManager.requestAlwaysAuthorization() 
     self.locationManager.startUpdatingLocation() 
    } 

    // MARK: - CLLocationManagerDelegate 

    func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) { 
     currentLocation = newLocation 
     let userInfo : NSDictionary = ["location" : currentLocation!] 

     dispatch_async(dispatch_get_main_queue()) {() -> Void in 
      self.delegate.locationDidUpdateToLocation(self.currentLocation!) 
      NSNotificationCenter.defaultCenter().postNotificationName(kLocationDidChangeNotification, object: self, userInfo: userInfo as [NSObject : AnyObject]) 
     } 
    } 

} 

Cách sử dụng:

class ViewController: UIViewController, LocationUpdateProtocol { 

    var currentLocation : CLLocation! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     NSNotificationCenter.defaultCenter().addObserver(self, selector: "locationUpdateNotification:", name: kLocationDidChangeNotification, object: nil) 

     let LocationMgr = UserLocationManager.SharedManager 
     LocationMgr.delegate = self 

    } 

    // MARK: - Notifications 

    func locationUpdateNotification(notification: NSNotification) { 
     let userinfo = notification.userInfo 
     self.currentLocation = userinfo!["location"] as! CLLocation 
     print("Latitude : \(self.currentLocation.coordinate.latitude)") 
     print("Longitude : \(self.currentLocation.coordinate.longitude)") 

    } 

    // MARK: - LocationUpdateProtocol 

    func locationDidUpdateToLocation(location: CLLocation) { 
     currentLocation = location 
     print("Latitude : \(self.currentLocation.coordinate.latitude)") 
     print("Longitude : \(self.currentLocation.coordinate.longitude)") 
    } 

} 
0

Trong quá trình tìm hiểu để có được vị trí của người dùng trong một lớp đơn, tôi đã tải xuống mã này https://github.com/irfanlone/CLLocationManager-Singleton-Swift. Sau khi foddleing với nó để làm cho chạy trên Xcode8.3.3 Swift 3, tôi không thể nhận được bất kỳ đầu ra trong giao diện điều khiển gỡ lỗi. Trong thực tế, tôi thậm chí không thể có được vị trí này tự động hóa dlalog để hiển thị. Tôi nghi ngờ các dữ liệu từ singleton không được thông qua để xem bộ điều khiển, nhưng tôi không thể phạt các giải pháp, bạn có thể xem những gì là sai? Cảm ơn.

Mã chỉnh cho Swift 3 là: // Các singleton: nhập khẩu MapKit

giao thức LocationUpdateProtocol { func locationDidUpdateToLocation (_ vị trí: CLLocation) }

hãy kLocationDidChangeNotification = "LocationDidChangeNotification"

lớp UserLocationManager: NSObject, CLLocationManagerDelegate {

static let SharedManager = UserLocationManager() 

fileprivate var locationManager = CLLocationManager() 

var currentLocation : CLLocation? 

var delegate : LocationUpdateProtocol! 

fileprivate override init() { 
    super.init() 
    self.locationManager.delegate = self 
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest 
    self.locationManager.distanceFilter = kCLLocationAccuracyHundredMeters 
    locationManager.requestAlwaysAuthorization() 
    self.locationManager.startUpdatingLocation() 
} 

// MARK: - CLLocationManagerDelegate 
func locationManager(manager: CLLocationManager,didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) { 
    currentLocation = newLocation 
    let userInfo : NSDictionary = ["location" : currentLocation!] 


    DispatchQueue.main.async() {() -> Void in 
     self.delegate.locationDidUpdateToLocation(self.currentLocation!) 
     NotificationCenter.default.post(name: Notification.Name(kLocationDidChangeNotification), object: self, userInfo: userInfo as [NSObject : AnyObject]) 
    } 
} 

}

// Các ViewController nhập khẩu UIKit nhập khẩu CoreLocation

lớp ViewController: UIViewController, LocationUpdateProtocol {

var currentLocation : CLLocation! 

override func viewDidLoad() { 
    super.viewDidLoad() 

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.locationUpdateNotification(_:)), name: NSNotification.Name(rawValue: kLocationDidChangeNotification), object: nil) 

    let LocationMgr = UserLocationManager.SharedManager 
    LocationMgr.delegate = self 

} 

// MARK: - Notifications 

func locationUpdateNotification(_ notification: Notification) { 
    let userinfo = notification.userInfo 
    self.currentLocation = userinfo!["location"] as! CLLocation 
    print("Latitude : \(self.currentLocation.coordinate.latitude)") 
    print("Longitude : \(self.currentLocation.coordinate.longitude)") 

} 

// MARK: - LocationUpdateProtocol 

func locationDidUpdateToLocation(_ location: CLLocation) { 
    currentLocation = location 
    print("Latitude : \(self.currentLocation.coordinate.latitude)") 
    print("Longitude : \(self.currentLocation.coordinate.longitude)") 
} 

}

+0

Bạn nên xem xét tự đặt câu hỏi thay vì đăng câu hỏi của mình làm câu trả lời. – stephenmuss

+0

Cảm ơn bạn vì không có gì. Tôi e Tôi bắt đầu một câu hỏi mới với một tiêu đề tương tự. bạn sẽ thương hiệu nó như là nhân đôi! – Rich

Các vấn đề liên quan