0

我想从应用程序的其他地方调用一个方法来获取在应用程序委托中获得的用户位置。CLLocation *getCurLoc = [AppDelegate getCurrentLocation];从另一个视图控制器调用时,不会返回任何内容。

应用程序代表是,

@synthesize locationManager;

CLLocation *location;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

    locationManager = [[CLLocationManager alloc]init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy=kCLLocationAccuracyKilometer;
    [locationManager startUpdatingLocation];

    return YES;
}

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

    [locations lastObject];
    [manager stopUpdatingLocation];

    CLLocation *location =  [locations lastObject];
}

+(CLLocation *)getCurrentLocation{
    return location;
}

将其更改为带有“-”的实例方法不起作用。是否应该将“位置”作为实例?应该将委托变成一个实例,还是有更好的方法从其他地方访问它?

4

3 回答 3

2

didUpdateLocations中,您定义并设置了一个局部变量location,而不是在文件顶部定义的全局变量。location换行

CLLocation *location =  [locations lastObject];

location =  [locations lastObject];

会解决这个问题。但更好的解决方案是使用 AppDelegate 类中的属性。您可以在类扩展中定义它:

@interface AppDelegate ()
@property(strong, nonatomic) CLLocation *location;
@end

然后你在实例方法中访问它,比如

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

    [locations lastObject];
    [manager stopUpdatingLocation];
    self.location =  [locations lastObject];
}

并在类方法

+(CLLocation *)getCurrentLocation{
    // Get the instance:
    AppDelegate *app = [[UIApplication sharedApplication] delegate];

    return app.location;
}

更新:如果 AppDelegate 被声明为符合某些协议(在公共接口或类扩展中),例如:

@interface AppDelegate () <CLLocationManagerDelegate>
@property(strong, nonatomic) CLLocation *location;
@end

然后上面的代码会创建一个警告

initializing 'AppDelegate *__strong' with an expression of incompatible type 'id<UIApplicationDelegate>'

并且需要明确的演员表:

+(CLLocation *)getCurrentLocation{
    // Get the instance:
    AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    return app.location;
}
于 2013-11-02T19:56:10.580 回答
1

马丁的回答是以与您的方法一致的方式解决此问题的一种有效的快速而肮脏的方法 - 将位置存储在appDelegate.

如果您想更进一步,您可能需要考虑实现一个保存数据的特殊对象——数据模型。在应用程序委托中存储数据被认为是一种不好的做法 - 这不是它的用途(尽管它在示例或小型应用程序中工作得非常好)。

你可以这样做:

数据模型.h

#import <Foundation/Foundation.h>

@interface DataModel : NSObject

@property (strong) CLLocation *location;

+ (DataModel *)sharedModel;

@end

数据模型.m

#import "DataModel.h"

@class CLLocation;

@implementation DataModel

- (id) init
{
    self = [super init];
    if (self)
    {
        _location = nil;
    }
    return self;
}

+ (DataModel *)sharedModel
{
    static DataModel *_sharedModel = nil;
    static dispatch_once_t onceSecurePredicate;
    dispatch_once(&onceSecurePredicate,^
                  {
                      _sharedModel = [[self alloc] init];
                  });

    return _sharedModel;
}

@end

然后,您需要到#import "DataModel.h"任何需要它的地方。您将更didUpdateLocations:改为:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    [locations lastObject];
    [manager stopUpdatingLocation];

    [DataModel sharedInstance].location = [locations lastObject];
}

从代码中的任何地方,您都可以简单地通过[DataModel sharedInstance].location.

编辑:

对于一个非常简单的应用程序,这种方法可能看起来有点矫枉过正。但是,一旦您的应用程序发展壮大,使用它肯定会有所回报。

这种类/对象/单例用于保存您的应用程序需要的所有数据(固定的和临时的)。所以所有的数据源都可以很好地利用它。简而言之:它使您能够轻松地遵循模型-视图-控制器指南。

您当然可以使用另一个类/对象/单例来保存临时数据——这取决于您的数据结构的复杂性。

您不必专门初始化这种对象。它在您第一次引用它时被初始化。这就是为什么dispatch_once存在。它确保存在此共享对象的一个​​且只有一个实例:https ://stackoverflow.com/a/9119089/653513

并且这一个实例[DataModel sharedInstance]将保留在那里,直到您的应用程序终止。

例如,Apple 使用类似的方法[NSUserDefaults standardDefaults], [UIApplication sharedApplicaton]

我倾向于将其#import "DataModel.h"放入我的项目Prefix.pch中,因此我不必每次使用它时都导入它(它在所有应用程序中都使用)。

优点: - 数据可在整个应用程序中访问 - 代码可重用性 - MVC 结构 - 代码更具可读性

缺点: - 我真的找不到。除了dispatch_once(&onceSecurePredicate,^...可能会在前几秒钟混淆一个。

于 2013-11-02T19:57:09.517 回答
0

您可以AppDelegate从应用程序中的任何位置访问 ,[UIApplication sharedApplication].delegate这样您就可以执行以下操作:

CLLocation *location = [(YourAppDelegateClassName*)[UIApplication sharedApplication].delegate getCurrentLocation];

该方法getCurrentLocation必须是实例方法 ( -(CLLocation *)getCurrentLocation)。您还需要导入#import "YourAppDelegateClassName.h"需要使用该方法的那些文件。

为了避免[UIApplication sharedApplication].delegate每次我更喜欢在我的 AppDelegates 中实现静态方法时进行强制转换和访问:

+ (YourAppDelegateClassName*)sharedDelegate {
    return (YourAppDelegateClassName*)[UIApplication sharedApplication].delegate;
}

所以你可以使用这样的任何方法:

CLLocation *location = [[YourAppDelegateClassName sharedDelegate] getCurrentLocation];
于 2013-11-02T19:54:31.063 回答