过去几天我一直在敲打着脑袋,开始慢慢地消耗我。我正在尝试制作CLLocationManager Singleton,因为我需要一个位置用于我的应用程序的其他两个组件。但是,当我设置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];
}
}
编辑:这是我关注Singleton的指南: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
另一个编辑:好的,我想我完全不明白将观察者等等放在我的应用程序中的位置。我现在拥有它,以便我的viewcontroller是订阅者,现在我越来越接近我想要的行为。如果有人对MVC和MVC / iOS开发的软件设计有很好的指导,请分享。也欢迎预订建议。
答案 0 :(得分:0)
无法分辨导致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。
如果不符合您的预期,请详细说明您的崩溃
答案 1 :(得分:0)
我建议不要创建一个单例,只需在app delegate上创建一个实例,然后在appdelegate上保存用户坐标,这样你就可以随时获得用户精确的位置,也许你需要调整它的准确性,这样它就不会这样做。 t排水电池和appdelegate已经是一个单一的:))
如果你想做单打 与KVO的崩溃是因为这一行:
[[LocationFetch sharedInstance] addObserver:self forKeyPath:@"currentLocation" options:NSKeyValueObservingOptionNew context:nil];
当您添加观察者时,您必须自己将其删除,请在单例文件中尝试:
- (void)dealloc {
[[LocationFetch sharedInstance] removeObserver:self forKeyPath:@"currentLocation"];
}
我不是百分百肯定从一个单独的类中删除观察者。代码看起来很奇怪,但我认为它会起作用