关于C#:未在ios中从app delegate调用的方法

method not called from app delegate in ios

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

应用程序代理是,

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

用"-"将其更改为实例方法不起作用。是否应将"位置"设置为实例?应该将委托创建为实例,还是有更好的方法从其他地方访问它?


didUpdateLocations中,定义并设置局部变量location,而不是文件顶部定义的全局变量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;
}


马丁的回答是一种有效的快速和肮脏的方法,以与您的方法一致的方式解决这个问题——将位置存储在AppDelegate中。

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

你可以这样做:

数据模型

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

然后,你需要在任何你需要的地方使用#import"DataModel.h"。您可以将您的didUpdateLocations:更改为:

1
2
3
4
5
6
7
- (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结构-代码可读性更强

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


您可以使用[UIApplication sharedApplication].delegate从应用程序中的任何点访问AppDelegate,这样就可以:

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

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

为了避免每次在AppDelegates中实现静态方法时强制转换和访问[UIApplication sharedApplication].delegate

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

因此,您可以使用以下任何方法:

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