web-dev-qa-db-ja.com

別のクラスのiOSCLLocationManager

ユーザーの場所を取得する必要がある複数のViewControllerがあるため、ViewControllerがユーザーの最新の場所を取得するために呼び出すことができる別のクラスを作成したいと思いました。

locationManager:didUpdateToLocation:fromLocationはvoidを返します。ユーザーの緯度と経度が計算されたらすぐに、緯度と経度のデータをViewControllerに戻すにはどうすればよいですか?

LocationManagingクラスでゲッターとセッターを書いてみることができますが、そうすると、ViewControllerクラスから緯度ゲッターメソッドと経度ゲッターメソッドをいつ呼び出すかをどのように知ることができますか? ViewControllerのメインスレッドを保持して、locationManagingクラスからの緯度と経度の値を待機するにはどうすればよいですか?

ありがとう!

16
user1467188

latitudeおよびlongitudeプロパティ、startLocatingおよびendLocatingを持つシングルトンクラスを作成します。クラスで、CLLocationManagerインスタンスを作成し、そのデリゲートをシングルトンに設定します。 startLocatingおよびendLocatingで、CLLocationManagerインスタンスの適切なメソッドを呼び出します。デリゲートメソッドにlatitudeプロパティとlongitudeプロパティを更新させます。他のViewControllersで、このシングルトンのlatitudeおよびlongitudeプロパティを読んでください。

これらのプロパティを別のViewControllerから読み取るタイミングを知るには、これらのプロパティにオブザーバーを設定します( NSKeyValueObservingプロトコルリファレンス を参照)。

これを行う前に、インターネットで既存のコードを検索してください。

これを行った後、パーミッシブライセンスを使用してGitHubにアップロードします。

16
user1071136

User1071136が言ったように、シングルトンロケーションマネージャーはおそらくあなたが望むものです。 NSObjectのサブクラスであるクラスを作成します。プロパティは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

最近受信した場所を取得するには、[LocationManagerSingleton sharedSingleton].locationManager.locationを使用するだけです。正確な位置を取得するためにGPSをウォームアップするのに数秒かかる場合があります。

23
eric.mitchell

上記の回答に基づいて、これが私がしたことであり、githubで完全な例を見つけることができます https://github.com/irfanlone/CLLocationManager-Singleton-Swift

このファイルをプロジェクトにインポートするだけで、LocationUpdateProtocolを実装するか、場所の更新の通知を聞くかを選択できます。

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])
        }
    }

}

使用法:

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)")
    }

}
7
Irfanlone

Swiftでロケーションマネージャーシングルトンを実装したときに私がしたことは次のとおりです。これは、user1071136の戦略と、 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()
3
rgoldfinger

シングルトンクラスでユーザーの場所を取得する方法を学習する過程で、このコードをダウンロードしました https://github.com/irfanlone/CLLocationManager-Singleton-Swift 。 Xcode8.3.3 Swift 3で実行するためにそれをいじった後、デバッグコンソールで出力を取得できません。実際、このロケーション認証dlalogを表示することさえできません。IシングルトンからのデータがViewControllerに渡されていないのではないかと思われますが、解決策を見つけることができません。何が問題なのかわかりますか?ありがとうございます。

Swift 3の修正されたコードは次のとおりです。

//The singleton:
import MapKit

protocol LocationUpdateProtocol {
func locationDidUpdateToLocation(_ location : CLLocation)
}

let kLocationDidChangeNotification = "LocationDidChangeNotification"

class 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])
    }
}

}



  // The ViewController
    import UIKit
    import CoreLocation

 class 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
Rich