【问题标题】:Setting Property Causes EXC_BAD_ACCESS crash (CLLocationManager Singleton)设置属性导致 EXC_BAD_ACCESS 崩溃(CLLocationManager Singleton)
【发布时间】:2016-06-24 22:41:52
【问题描述】:

在过去的几天里,我一直在努力解决这个问题,它开始慢慢耗尽我的精力。我正在尝试制作 CLLocationManager 单例,因为我需要为我的应用程序的其他两个组件提供位置。但是,当我设置 currentLocation 属性时,我不断收到 EXC_BAD_ACCESS。当我通过它时,我在 main.m 上得到一个 SIGABRT 哦,最重要的是,什么时候通过,连同 SIGABRT 我被告知我的 KVO 消息已收到但未处理,我不知道这意味着。

感谢任何帮助以及有关 KVO 的资源和/或在使用 KVO 之前我应该​​了解的基础知识

LocationFetch.h

@interface LocationFetch : NSObject <CLLocationManagerDelegate>

+(LocationFetch *) sharedInstance;

@property (nonatomic,strong) CLLocationManager *locationManager;
@property (nonatomic, strong) CLLocation *currentLocation;

-(void)startingUpdatingLocation;
-(void)stopUpdatingLocation;

@end

LocationFetch.m

#import "LocationFetch.h"

@implementation LocationFetch

@synthesize locationManager, currentLocation;

+(LocationFetch *) sharedInstance
{
    static LocationFetch *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc]init];
        });
    return instance;
}
- (id)init
{
    self = [super init];
    if(self)
    {

        self.locationManager = [[CLLocationManager alloc]init];
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        self.locationManager.distanceFilter = 100;
        self.locationManager.delegate = self;
        //Request Authorization
        if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
        {
            [self.locationManager requestWhenInUseAuthorization];
        }
    }
    return self;
}
- (void)startingUpdatingLocation
{
    [self.locationManager startUpdatingLocation];
    NSLog(@"Starting Location Updates");
}
-(void)stopUpdatingLocation
{
    [self.locationManager stopUpdatingLocation];
     NSLog(@"Stopping Location Updates");
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"Location updates failed with %@", error);
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    CLLocation *location = [locations lastObject];
    NSLog(@"LocationFetch sharedInstance: Latitude %+.6f, Longitude %+.6f\n",
          location.coordinate.latitude,
          location.coordinate.longitude);
    self.currentLocation = location;
}



@end

WeatherFetch.m 的一部分(这是注册观察者的地方)

-(id)init
{
    self = [super init];
    if(self)
    {
        [[LocationFetch sharedInstance] addObserver:self forKeyPath:@"currentLocation" options:NSKeyValueObservingOptionNew context:nil];
    }
    return self;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object  

change:(NSDictionary *)change context:(void *)context
{
    if([keyPath isEqualToString:@"currentLocation"]) {
        [self setWeatherLocation];
        [self sendWeatherRequest];
        NSLog(@"Observer has received message");
        [self removeObserver:self forKeyPath:@"currentLocation" context:nil];
    }
}

编辑:这是我为单身人士关注的指南:http://derpturkey.com/cllocationmanager-singleton/

另一个编辑:好的,我通过删除 CLLocationManager 和 CLLocation 的强和非原子属性属性克服了 EXC_BAD_ACCESS 错误,但现在 SIGABRT 现在是一个更关键的问题,这里是异常的调试输出。从好的方面来说,现在 KVO 似乎已收到通知,只是不明白“消息已收到但未处理”的错误

2016-06-24 21:25:51.111 TrafficAlarmClock[1504:18554] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '(
    "<CALayer: 0x7f95a043eb00>"
): An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: currentLocation
Observed object: <LocationFetch: 0x7f95a040c5a0>
Change: {
    kind = 1;
    new = "<+40.75921100,-73.98463800> +/- 5.00m (speed -1.00 mps / course -1.00) @ 6/24/16, 9:25:50 PM Eastern Daylight Time";
}
Context: 0x1050f7c08'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000105f97d85 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x0000000105682deb objc_exception_throw + 48
    2   CoreFoundation                      0x0000000105f97cbd +[NSException raise:format:] + 205
    3   Foundation                          0x00000001052e71ae -[NSObject(NSKeyValueObserving) observeValueForKeyPath:ofObject:change:context:] + 168
    4   Foundation                          0x0000000105213cad NSKeyValueNotifyObserver + 347
    5   Foundation                          0x0000000105212f39 NSKeyValueDidChange + 466
    6   Foundation                          0x00000001052e7fff -[NSObject(NSKeyValueObservingPrivate) _changeValueForKeys:count:maybeOldValuesDict:usingBlock:] + 912
    7   Foundation                          0x0000000105210804 -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:key:key:usingBlock:] + 60
    8   Foundation                          0x000000010526ea9b _NSSetObjectValueAndNotify + 261
    9   TrafficAlarmClock                   0x00000001050f2143 -[LocationFetch locationManager:didUpdateLocations:] + 227
    10  CoreLocation                        0x0000000105192418 CLClientGetCapabilities + 20974
    11  CoreLocation                        0x000000010518e823 CLClientGetCapabilities + 5625
    12  CoreLocation                        0x00000001051892dd CLClientInvalidate + 923
    13  CoreFoundation                      0x0000000105ebd2ec __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    14  CoreFoundation                      0x0000000105eb2f75 __CFRunLoopDoBlocks + 341
    15  CoreFoundation                      0x0000000105eb2d28 __CFRunLoopRun + 2472
    16  CoreFoundation                      0x0000000105eb20f8 CFRunLoopRunSpecific + 488
    17  GraphicsServices                    0x0000000108660ad2 GSEventRunModal + 161
    18  UIKit                               0x000000010634ef09 UIApplicationMain + 171
    19  TrafficAlarmClock                   0x00000001050f1b6f main + 111
    20  libdyld.dylib                       0x0000000108fd192d start + 1
    21  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

另一个编辑:好的,我想我完全不明白在我的应用程序中放置诸如观察者之类的东西的位置。我现在有了它,所以我的视图控制器是订阅者,现在我越来越接近我想要的行为。如果有人对 MVC 和 MVC/iOS 开发的软件设计有很好的指导,请分享。也欢迎推荐书籍。

【问题讨论】:

  • KVO 确实是个好主意。我建议你让你的单身人士发布一个 NSNotification 并让你的 WeatherFetch 订阅它。然后它可以从单例中检索值
  • 另外,您已经好几年不需要@synthesize 语句了
  • 看了几十个资源,是不是非常相似?
  • KVO 和 NSNotification?有点类似。 KVO 为您提供有关更改内容和方式的更多信息,而 NSNotification 是任意消息;它可以被发送,因为属性改变,用户登录,一天中的时间,无论你想要什么。更重要的是 NSNotification 不那么复杂,也不那么脆弱。
  • 除了 Apple 文档,还有什么指南吗?我主要选择 KVO,因为我跟随的指南使用了 KVO,并且承诺是自动的

标签: ios objective-c swift singleton key-value-observing


【解决方案1】:

由于缺乏精确性,无法说出导致 KVO 错误的原因,但只能说出我们在类似案例中所做的事情

这就是我们分配 LocationHelper 实例的方式:

- (id)init { self = [super init];

if (!self) {
    return self;
}

// Check if the service is available
if ([CLLocationManager locationServicesEnabled])
{
    // Init the location manager
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    self.locationManager.pausesLocationUpdatesAutomatically = YES;
    self.locationManager.desiredAccuracy = LOCATION_ACCURACY_IN_METER;
}

return self;}

然后我不明白你为什么不使用:

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

然后使用 manager.location 从这里调用 setWeatherLocation 或 sendWeatherRequest。

如果不是您所期望的,请提供有关您的崩溃的更多详细信息

【讨论】:

【解决方案2】:

我建议不要创建单例,而是在应用委托上创建一个实例并将用户坐标保存在应用委托上,这样您就可以随时获得用户的精确位置,也许您需要调整它的准确性,以免它耗尽battery 和 appdelegate 已经是一个单例了 :)

如果你想使用单项 KVO 的崩溃是因为这行:

[[LocationFetch sharedInstance] addObserver:self forKeyPath:@"currentLocation" options:NSKeyValueObservingOptionNew context:nil];

当你添加一个观察者时,你必须自己删除它,在单例文件中试试这个:

- (void)dealloc {
 [[LocationFetch sharedInstance] removeObserver:self forKeyPath:@"currentLocation"];
}

我不是 100% 确定要从单例类中删除观察者。代码对我来说看起来很奇怪,但我认为它会起作用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 2011-09-29
    相关资源
    最近更新 更多