Ios 编写CLLocationManagerDelegate的最佳方法,它将不经常获取位置 背景
我对ReactiveCocoa框架及其潜力感到非常兴奋,因此我决定咬紧牙关,用它编写我的第一个应用程序。 在我的应用程序中,我已经编写了各种服务和委托,但我现在需要“激活”它们,以便我能够继续处理实际的GUI方面的事情 也就是说,为了更好地理解这一点,我正在编写一段简单的代码来尝试一些概念。 在本例中,为CLLocationManagerDelegate编写包装器 在实际应用程序中,用例如下所示:Ios 编写CLLocationManagerDelegate的最佳方法,它将不经常获取位置 背景,ios,objective-c,reactive-cocoa,Ios,Objective C,Reactive Cocoa,我对ReactiveCocoa框架及其潜力感到非常兴奋,因此我决定咬紧牙关,用它编写我的第一个应用程序。 在我的应用程序中,我已经编写了各种服务和委托,但我现在需要“激活”它们,以便我能够继续处理实际的GUI方面的事情 也就是说,为了更好地理解这一点,我正在编写一段简单的代码来尝试一些概念。 在本例中,为CLLocationManagerDelegate编写包装器 在实际应用程序中,用例如下所示: 1) 当应用程序加载(viewDidLoad)后,2)尝试获取 设备的位置由 2.1)如果未启用
- 1) 当应用程序加载(viewDidLoad)后,2)尝试获取 设备的位置由
- 2.1)如果未启用位置服务,则
- 2.1.1)检查授权状态,如果允许
开始监控重要位置变化
- 2.1.2)否则返回错误
- 2.2)其他(位置服务已启用)
- 2.2.1)如果地点经理上一个地点是“最近的”(6小时或更短),则返回
- 2.2.2)其他开始监控重要位置变化
- 3) 返回位置时(直接返回或通过
),然后我们也停止监视重要位置更改locationManager:(CLLocationManager*)管理器 didUpdateLocations:(NSArray*)位置
- 4) 如果调用LocationManagerDelegate的代码收到并出错,则向代理请求一个固定的“默认”值
- 5) 然后,下一段代码使用该位置(获取或默认)启动并对第三方服务进行一系列调用(对Web服务的调用等)
RACSignal *fetchLocationSignal = [lmDelegate latestLocationSignal];
RACSignal *locationSignal = [fetchLocationSignal catch:^RACSignal *(NSError *error) {
NSLog(@"Unable to fetch location, going to grab default instead: %@", error);
CLLocation *defaultLocation = [lmDelegate defaultLocation];
NSLog(@"defaultLocation = [%@]", defaultLocation);
// TODO OK, so now what. I just want to handle the error and
// pass back this default location as if nothing went wrong???
return [RACSignal empty];
}];
NSLog(@"Created signal, about to bind on self.locationLabel text");
RAC(self.locationLabel, text) = [[locationSignal filter:^BOOL(CLLocation *newLocation) {
NSLog(@"Doing filter first, newLocation = [%@]", newLocation);
return newLocation != nil;
}] map:^(CLLocation *newLocation) {
NSLog(@"Going to return the coordinates in map function");
return [NSString stringWithFormat:@"%d, %d", newLocation.coordinate.longitude, newLocation.coordinate.latitude];
}];
问题
- 1) 我如何处理错误?我可以使用
,这样我就有机会向学员询问默认位置。但是,我被困在如何将默认位置作为信号传回?或者我只是更改我的catch
方法以返回defaultLocation
而不是RACSignal
CLLocation
- 2) 当我返回位置时,是否应按
或sendNext
执行?目前它被编码为sendCompleted
,但它看起来像是将被编码为sendNext
李>sendCompleted
- 3) 实际上,答案是否取决于我如何创建委托。每次加载视图时,此测试应用程序都会创建一个新的委托。这是我应该做的事情吗?我应该让代表成为一个单独的人。如果是单身,那么sendNext似乎是正确的选择。但是如果这样做,是否意味着我将委托中的
中的代码移到init方法中latestLocationSignal
+[RACSignal return::
创建一个只发送默认位置的信号:
RACSignal *locationSignal = [fetchLocationSignal catch:^RACSignal *(NSError *error) {
NSLog(@"Unable to fetch location, going to grab default instead: %@", error);
CLLocation *defaultLocation = [lmDelegate defaultLocation];
NSLog(@"defaultLocation = [%@]", defaultLocation);
return [RACSignal return:defaultLocation];
}];
当我返回位置时,应该按sendNext或sendCompleted执行吗?目前它被编码为sendNext,但它似乎是在sendNext完成时完成的
为了实际发送数据,您需要使用-sendNext:
。如果这是信号发送的唯一内容,那么在这之后它也应该-sendCompleted
。但是,如果随着准确度的提高或位置的改变,它将继续发送位置,那么它还不应该完成
一般来说,信号可以发送任意数量的next
s(0*),但只能完成或错误。一旦发送完成或错误,信号就完成了。它不会发送更多的值
实际上,答案是否取决于我如何创建委托。每次加载视图时,此测试应用程序都会创建一个新的委托。这是我应该做的事情吗?我应该让代表成为一个单独的人。如果是单身,那么sendNext似乎是正确的选择。但是如果这样做,是否意味着我将委托中latestLocationSignal中的代码移到init方法中
我不确定我是否有足够的背景来回答这个问题,除了说单身永远不是答案;)每次加载视图时创建一个新代理对我来说似乎是合理的
很难回答像这样广泛的问题,因为我对你的设计的了解不如你。希望这些答案能有所帮助。如果您需要更多的说明,具体的示例非常有用。在ReactiveCocoa 3.0和swift中似乎非常简单:
import ReactiveCocoa
import LlamaKit
class SignalCollector: NSObject, CLLocationManagerDelegate {
let (signal,sink) = Signal<CLLocation, NoError>.pipe()
let locationManager = CLLocationManager()
func start(){
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
for item in locations {
if let location = item as? CLLocation {
sink.put(Event.Next(Box(location))
}
}
}
}
请注意,由于目前是alpha之前的版本,语法可能会发生变化。将上述答案更新为ReactiveCocoa 4和Swift 2.1:
import Foundation
import ReactiveCocoa
class SignalCollector: NSObject, CLLocationManagerDelegate {
let (signal,sink) = Signal<CLLocation, NoError>.pipe()
let locationManager = CLLocationManager()
func start(){
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for item in locations {
guard let location = item as CLLocation! else { return }
sink.sendNext(location)
}
}
谢谢你<代码>+[RACSignal return::方法似乎不错。我尝试的另一种方法是在委托中定义defaultLocation方法以返回信号。你的方法似乎更简单,也达到了同样的效果。而且,是的,请欣赏这是一个广泛的问题,因此更难“回答”。但这给了我一些思考和尝试的机会。我不会把这个问题标记为完整的,以防其他人有什么补充。(我不确定Github上的代码是否有助于我尝试通过委托实现什么。)
import Foundation
import ReactiveCocoa
class SignalCollector: NSObject, CLLocationManagerDelegate {
let (signal,sink) = Signal<CLLocation, NoError>.pipe()
let locationManager = CLLocationManager()
func start(){
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for item in locations {
guard let location = item as CLLocation! else { return }
sink.sendNext(location)
}
}
var locationSignals : [CLLocation] = []
signal.observeNext({ newLocation in
locationSignals.append(newLocation)
})