我想从应用程序的其他地方调用一个方法来获取在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;
}
将其更改为带有“ - ”的实例方法不起作用。应该将“位置”变成一个实例吗?代表是应该成为一个实例,还是有更好的方法从其他地方访问它?
答案 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]
的单个实例将一直存在,直到您的应用终止。
[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];