2012-07-16 14 views
16

में मेरे पास एकाधिक दृश्य नियंत्रक हैं जिन्हें उपयोगकर्ता का स्थान प्राप्त करने की आवश्यकता है, इसलिए मैं एक अलग वर्ग बनाना चाहता हूं जो ViewControllers उपयोगकर्ता के नवीनतम स्थान को प्राप्त करने के लिए कॉल कर सकता है।आईओएस CLLocationManager एक अलग वर्ग

स्थान प्रबंधक: didUpdateToLocation: स्थान से शून्य रद्द हो जाता है। जैसे ही उपयोगकर्ता के अक्षांश और देशांतर की गणना की जाती है, मैं अक्षांश और देशांतर डेटा को अपने व्यू कंट्रोलर पर वापस कैसे पास करूं?

मैं अपने स्थान में गेटर्स और सेटर्स लिखने का प्रयास कर सकता हूं प्रबंधन कक्षा, लेकिन यदि मैं ऐसा करता हूं, तो मुझे कैसे पता चलेगा कि मेरे व्यू कंट्रोलर क्लास से अक्षांश गेटर और देशांतर गेटर विधियों को कब कॉल करना है? मैं स्थान प्रबंधन से अक्षांश और देशांतर मानों की प्रतीक्षा करने के लिए ViewController के मुख्य थ्रेड को कैसे पकड़ूं?

धन्यवाद!

+0

'locationManager: didUpdateToLocation: fromLocation' है एक प्रतिनिधि विधि। स्थान प्रबंधक इस ऑब्जेक्ट का उपयोग आपके ऑब्जेक्ट को सूचित करने के लिए करता है कि स्थान को नए मान के साथ अपडेट किया गया था - मूल्य के साथ कुछ करने के लिए इस विधि को लागू करने के लिए आप पर निर्भर है। – quellish

उत्तर

14

एक सिंगलटन क्लास बनाएं जिसमें latitude और longitude गुण, startLocating और endLocating हैं। कक्षा में, CLLocationManager उदाहरण बनाएं, और इसके प्रतिनिधि को सिंगलटन बनें। startLocating और endLocating में, CLLocationManager उदाहरण के उपयुक्त तरीकों को कॉल करें। प्रतिनिधि विधियों को latitude और longitude गुणों को अपडेट करें। अन्य ViewControllers में, इस सिंगलटन के latitude और longitude गुण पढ़ें।

पता करने के लिए जब एक और ViewController से उन गुणों को पढ़ने के इन गुणों पर एक पर्यवेक्षक स्थापित करने के लिए (देखें NSKeyValueObserving Protocol Reference

ऐसा करने से पहले, मौजूदा कोड के लिए इन्टरनेट देखो।

इस, अपलोड करने के बाद एक अनुमोदक लाइसेंस के साथ GitHub के लिए यह।

+0

धन्यवाद! मेरा अनुवर्ती प्रश्न है .. मुझे कैसे पता चलेगा कि मेरे व्यू कंट्रोलर को सिंगलटन के अक्षांश और देशांतर गुणों को कॉल करना चाहिए? दूसरे शब्दों में, मैं अपने सिंगलटन – user1467188

+0

में वैध अक्षरों के लंबे मूल्यों की प्रतीक्षा करने के लिए अपने व्यू कंट्रोलर के मुख्य थ्रेड को कैसे लॉक कर सकता हूं यह दूसरे अनुच्छेद में है (जब आप मेरी प्रारंभिक पोस्ट पढ़ रहे हों तो इसे जोड़ा हो सकता है) – user1071136

+0

आप सिंगलटन गुणों को एक्सेस करते हैं पर्यवेक्षक अधिसूचना विधि बदलते हैं – nilloc

23

रूप 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 का उपयोग करें। सटीक स्थानों को प्राप्त करने के लिए जीपीएस को गर्म करने में कुछ सेकंड लग सकते हैं।

+6

अपने @ सिंक्रनाइज़ किए गए ब्लॉक को 'dispatch_once' पर अपडेट करना चाहता है। – user

+0

@ रिकय एयरलाइन मोड के मामले में यह रिटर्न परिणाम देगा? –

+0

यदि आप यह उत्तर देखते हैं: (http://stackoverflow.com/questions/7376294/how-is-it-that-cllocationmanager-gets-a-location-when-airplane-mode-is-on) आप पाएंगे इस मामले में 'CLLocationManager' सबसे हाल ही में अधिग्रहित स्थान लौटाता है, लेकिन नई स्थान जानकारी नहीं। –

3

यहां मैंने जो किया है वह स्थान मैनेजर सिंगलटन को तेजी से कार्यान्वित करते समय किया। यह उपयोगकर्ता 1071136 की रणनीति के साथ-साथ 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

इस कोड को चलाने वाले डिवाइस का उपयोग करते समय ओवन mitts पहनें। – quellish

+0

मैं वर्तमान में आपकी कक्षा का उपयोग करने की कोशिश कर रहा हूं, लेकिन ऐप कभी प्राधिकरण के लिए नहीं पूछता है और न ही मुझे कोई स्थान मिलता है। कक्षा का उपयोग करने के लिए मुझे क्या करने की ज़रूरत है? – Thomas

+0

info.plst को कभी न भूलें: http://stackoverflow.com/questions/24050633/implement-cllocationmanagerdelegate-methods-in-swift/24056771#24056771 – Thomas

4

ऊपर जवाब के आधार पर, यहाँ मैं क्या किया है और आप 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)") 
    } 

} 
0

एक सिंगलटन कक्षा में उपयोगकर्ता स्थान प्राप्त करने के लिए सीखने की प्रक्रिया में, मैंने इस कोड को https://github.com/irfanlone/CLLocationManager-Singleton-Swift डाउनलोड किया। Xcode8.3.3 स्विफ्ट 3 पर चलाने के लिए इसके साथ फिसलने के बाद, मुझे डीबग कंसोल में कोई आउटपुट नहीं मिल सकता है। वास्तव में मैं प्रदर्शित करने के लिए इस स्थान autherization dlalog भी नहीं प्राप्त कर सकता। मुझे संदेह है कि सिंगलटन से डेटा व्यू कंट्रोलर को पास नहीं किया गया है, लेकिन मैं समाधान ठीक नहीं कर सकता, क्या आप देख सकते हैं कि क्या गलत है? धन्यवाद।

स्विफ्ट 3 के लिए सही कोड है: // सिंगलटन: आयात MapKit

प्रोटोकॉल LocationUpdateProtocol { समारोह locationDidUpdateToLocation (_ स्थान: CLLocation) }

जाने kLocationDidChangeNotification = "LocationDidChangeNotification"

वर्ग उपयोगकर्ता स्थान प्रबंधक: एनएसओब्जेक्ट, 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]) 
    } 
} 

}

// ViewController आयात UIKit आयात CoreLocation

वर्ग 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

आपको अपने प्रश्न को उत्तर के रूप में पोस्ट करने के बजाय स्वयं से एक प्रश्न पूछने पर विचार करना चाहिए। – stephenmuss

+0

कुछ भी नहीं के लिए धन्यवाद। मैं एक समान शीर्षक के साथ एक नया सवाल शुरू करता हूँ। आप इसे डुप्लिकेट के रूप में ब्रांड करेंगे! – Rich

संबंधित मुद्दे