method not called from app delegate in ios
我想从应用程序的其他地方调用一个方法来获取在应用程序委托中获得的用户位置。从另一个视图控制器调用
应用程序代理是,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @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; } |
用"-"将其更改为实例方法不起作用。是否应将"位置"设置为实例?应该将委托创建为实例,还是有更好的方法从其他地方访问它?
在
1 | CLLocation *location = [locations lastObject]; |
到
1 | location = [locations lastObject]; |
可以解决问题。但更好的解决方案是在AppDelegate类中使用属性。您可以在类扩展中定义它:
1 2 3 | @interface AppDelegate () @property(strong, nonatomic) CLLocation *location; @end |
然后在实例方法中访问它,比如
1 2 3 4 5 6 | - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ [locations lastObject]; [manager stopUpdatingLocation]; self.location = [locations lastObject]; } |
在类方法中
1 2 3 4 5 6 | +(CLLocation *)getCurrentLocation{ // Get the instance: AppDelegate *app = [[UIApplication sharedApplication] delegate]; return app.location; } |
更新:如果AppDelegate声明为符合某个协议(在公共接口或类扩展中),例如:
1 2 3 | @interface AppDelegate () <CLLocationManagerDelegate> @property(strong, nonatomic) CLLocation *location; @end |
然后上面的代码会创建一个警告
1 | initializing 'AppDelegate *__strong' with an expression of incompatible type 'id<UIApplicationDelegate>' |
并且需要明确的强制转换:
1 2 3 4 5 6 | +(CLLocation *)getCurrentLocation{ // Get the instance: AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; return app.location; } |
马丁的回答是一种有效的快速和肮脏的方法,以与您的方法一致的方式解决这个问题——将位置存储在
如果您想更进一步,您可能会考虑实现一个特殊的对象来保存数据——数据模型。将数据存储在应用程序委托中被认为是一种糟糕的做法——这不是它的用途(尽管它在示例或小型应用程序中工作得很好)。
你可以这样做:
数据模型
1 2 3 4 5 6 7 8 9 | #import <Foundation/Foundation.h> @interface DataModel : NSObject @property (strong) CLLocation *location; + (DataModel *)sharedModel; @end |
数据模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #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 |
然后,你需要在任何你需要的地方使用
1 2 3 4 5 6 7 | - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { [locations lastObject]; [manager stopUpdatingLocation]; [DataModel sharedInstance].location = [locations lastObject]; } |
从代码中的任何地方,您都可以通过
编辑:
对于一个非常简单的应用程序来说,这种方法可能看起来是多余的。但一旦你的应用程序增长,使用它肯定会有回报。
这种类型的类/对象/单例可以保存应用程序所需的所有数据(固定的和临时的)。所以所有的数据源都可以很好地利用它。简而言之:它使您能够轻松地遵循模型视图控制器指南。
当然,您可以使用另一个类/对象/单例来保存临时数据——这取决于数据结构的复杂性。
您不必专门初始化这种对象。它在您第一次引用时被初始化。这就是为什么
这个单一的
例如,苹果对
我倾向于把
赞成的意见:-可在整个应用程序中访问的数据-代码可重用性MVC结构-代码可读性更强
欺骗:-我真的找不到。除了
您可以使用
1 | CLLocation *location = [(YourAppDelegateClassName*)[UIApplication sharedApplication].delegate getCurrentLocation]; |
方法
为了避免每次在AppDelegates中实现静态方法时强制转换和访问
1 2 3 | + (YourAppDelegateClassName*)sharedDelegate { return (YourAppDelegateClassName*)[UIApplication sharedApplication].delegate; } |
因此,您可以使用以下任何方法:
1 | CLLocation *location = [[YourAppDelegateClassName sharedDelegate] getCurrentLocation]; |