如何将 CoreLocation 值从一个 VIewController 传递到 iOS 中的 AppDelegate?

Posted

技术标签:

【中文标题】如何将 CoreLocation 值从一个 VIewController 传递到 iOS 中的 AppDelegate?【英文标题】:how to pass CoreLocation values from one VIewController to AppDelegate in iOS? 【发布时间】:2013-11-20 13:13:54 【问题描述】:

我能够在一个 ViewController 中获取纬度和经度值。现在我想将这些值传递给我可以使用它们的 AppDelegate。我不想在 AppDelegate 中使用核心位置。所以这种方法不是使用。我怎样才能实现他的?

这是我的 Appdelegate 代码 -

-(void)updatePresence

 NSString *string = self.userLocationVC.locationInfo;// lat and long values as string.
 NSLog(@"value of string in appDelegate - %@", string);  // This shows null.

'userLocationVC' 是我的 ViewController,我在其中计算位置值,'locationInfo' 是该控制器的 NSString 属性,我在其中存储获得的值。

 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
  
   NSLog(@"didUpdateToLocation: %@", newLocation);
   CLLocation *currentLocation = newLocation;

  if (currentLocation != nil)
  
    longitude = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
    latitude = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
    self.locationInfo = [NSString stringWithFormat:@"latitude - %@ , longitude - %@",latitude,longitude];
    NSLog(@"current location is - %@", locationInfo);
    AppDelegate *myappDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    [myappDelegate updatePresence];

【问题讨论】:

为什么不使用“[myappDelegate updatePresence:self.locationInfo];”? 如果我这样做,我会收到一条错误消息 - 'AppDelegate' 没有可见的@interface 声明选择器'updatePresence'。 为什么不想声明呢? 我被告知要以这种方式实现 :-( 【参考方案1】:

使用通知,您从视图控制器发送通知,并由您的应用委托观察。将位置字符串与通知一起传递。

这样做的好处是,如果您稍后决定将位置数据移动到另一个模型类,那么您只需要在那里添加一个观察者,然后在应用委托中停止观察。

如果您想要这样做的原因是在应用程序委托中使用后台/前台委托方法,那么请考虑在您的视图控制器中使用这些等效的通知。

【讨论】:

【参考方案2】:

有很多方法可以做到这一点,但最简单的解决方案是向您的 Application Delegate 添加一个实例变量,然后在您的位置 ViewController 中为您的 Application Delegate 获取 reference 并追溯设置 ivar。

但是我认为以这种方式使用应用程序委托是一种不好的做法。

在实现推送通知时,我只向应用委托添加了一次实例变量,即存储设备 ID。

【讨论】:

【参考方案3】:

创建一个 LocationManager 单例类来检索您的位置并在需要时调用它

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

static NSString * const LocationManagerDidGetFirstAccurateLocationNotification = @"LocationManagerDidGetFirstAccurateLocationNotification";

@interface LocationManager : CLLocationManager <CLLocationManagerDelegate>

@property (readonly, nonatomic) CLPlacemark * currentPlacemark;
@property (readonly, nonatomic) CLLocation  * currentLocation;
@property (readonly, nonatomic) NSNumber    * latitude;
@property (readonly, nonatomic) NSNumber    * longitude;

+ (LocationManager *)sharedManager;
- (void)start;

- (double)currentDistanceFromLatitude:(NSNumber *)latitude
                            longitude:(NSNumber *)longitude;

@end




//
//  LocationManager.m
//  Post
//
//  Created by Nicolas Manzini on 26.01.13.
//  Copyright (c) 2013 MySo. All rights reserved.
//

#import "LocationManager.h"

@interface LocationManager ()

@property (assign, nonatomic, getter = isWaitingFirstLocation) BOOL waitingFirstLocation;
@property (strong, nonatomic) NSTimer * timer;
@property (assign, nonatomic, getter = isStarted) BOOL started;

- (void)restartLocationUpdates:(NSTimer *)timer;
- (void)addObservers;
- (void)addTimer;
- (void)updatePlacemarkFromLocation:(CLLocation *)location;

@end

@implementation LocationManager

@dynamic latitude;
@dynamic longitude;

+ (LocationManager *)sharedManager

    static dispatch_once_t pred;
    static LocationManager * sharedManager = nil;
    dispatch_once(&pred, ^
        sharedManager = [[self alloc] init];
    );
    return sharedManager;


- (void)start

    if (self.isStarted) return;

    _currentLocation          = nil;
    self.desiredAccuracy      = kCLLocationAccuracyBest;
    self.distanceFilter       = kCLDistanceFilterNone;
    self.delegate             = self;
    self.started              = YES;
    self.waitingFirstLocation = YES;

    [self startUpdatingLocation];
    [self addObservers];
    [self addTimer];


- (void)addObservers

    NSNotificationCenter * center = [NSNotificationCenter defaultCenter];

    [center addObserverForName:UIApplicationDidEnterBackgroundNotification
                        object:nil
                         queue:[NSOperationQueue mainQueue]
                    usingBlock:^(NSNotification *note)
    
        [self stopUpdatingLocation];
        [self.timer invalidate];
         self.timer = nil;

        _currentPlacemark = nil;
        _currentLocation  = nil;
    ];

    [center addObserverForName:UIApplicationWillEnterForegroundNotification
                        object:nil
                         queue:[NSOperationQueue mainQueue]
                    usingBlock:^(NSNotification *note)
    
        self.waitingFirstLocation = YES;
        [self startUpdatingLocation];
        [self addTimer];
    ];


- (void)addTimer

    self.timer =
    [NSTimer scheduledTimerWithTimeInterval:300
                                     target:self
                                   selector:@selector(restartLocationUpdates:)
                                   userInfo:nil
                                    repeats:YES];


#pragma mark - delegate

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

    CLLocation * location = [locations lastObject];
    _currentLocation      = location;

    if (location.horizontalAccuracy < 30.0)
    
        [self stopUpdatingLocation];
        [self updatePlacemarkFromLocation:location];
    
    else if (location.horizontalAccuracy < 100.0 && self.isWaitingFirstLocation)
    
        self.waitingFirstLocation = NO;
        [[NSNotificationCenter defaultCenter] postNotificationName:LocationManagerDidGetFirstAccurateLocationNotification
                                                            object:nil];
        [self updatePlacemarkFromLocation:location];

    


#pragma mark - timer

- (void)restartLocationUpdates:(NSTimer *)timer

    [self startUpdatingLocation];


#pragma mark - NSNumber Coordinates

- (NSNumber *)latitude

    return [NSNumber numberWithDouble:self.currentLocation.coordinate.latitude];


- (NSNumber *)longitude

    return [NSNumber numberWithDouble:self.currentLocation.coordinate.longitude];


#pragma mark - Distance From location

- (double)currentDistanceFromLatitude:(NSNumber *)latitude
                            longitude:(NSNumber *)longitude

    CLLocation * distantLocation =
    [[CLLocation alloc] initWithLatitude:[latitude doubleValue]
                               longitude:[longitude doubleValue]];
    double meters =
    [self.currentLocation distanceFromLocation:distantLocation];

    return meters;


#pragma mark - Placemark Lookup

- (void)updatePlacemarkFromLocation:(CLLocation *)location

    [[[CLGeocoder alloc] init] reverseGeocodeLocation:location
                                    completionHandler:^(NSArray *placemark, NSError *error)
     
         if (error)
         
             NSLog(@"could not get current geolocation infos %@",error);
         
         _currentPlacemark = [placemark firstObject];
     ];


#pragma mark - dealloc

- (void)dealloc

    [[NSNotificationCenter defaultCenter] removeObserver:self];

@end

【讨论】:

这是我的课,你可以复制过去

以上是关于如何将 CoreLocation 值从一个 VIewController 传递到 iOS 中的 AppDelegate?的主要内容,如果未能解决你的问题,请参考以下文章

如何将值从一个活动传递到上一个活动

如何将值从一个片段的回收器视图项传递到另一个片段

如何将值从服务传输到活动?

如何将 NsDictionary 值从 tableview 传递到下一个视图

如何将值从 javascript 函数传递到 django 视图

如何将值从 tableview 传递到 collectionview