在ios中没有从app委托调用的方法

时间:2013-11-02 19:45:15

标签: ios objective-c delegates cllocationmanager

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

App Delegate是,

@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;
}

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

3 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:1)

Martin's answer是以与您的方法一致的方式解决此问题的有效快速和肮脏方式 - 将位置存储在appDelegate中。

如果您想更进一步,可能需要考虑实现一个保存数据的特殊对象 - 数据模型。将数据存储在应用程序委托中被认为是一种不好的做法 - 它不是它的用途(尽管它在样本或小应用程序中完美地运行)。

你可以这样做:

<强> DataModel.h

#import <Foundation/Foundation.h>

@interface DataModel : NSObject

@property (strong) CLLocation *location;

+ (DataModel *)sharedModel;

@end

<强> DataModel.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结构 - 代码更具可读性

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

答案 2 :(得分:0)

您可以使用AppDelegate从应用中的任意位置访问[UIApplication sharedApplication].delegate,这样您就可以:

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

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

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

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

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

CLLocation *location = [[YourAppDelegateClassName sharedDelegate] getCurrentLocation];