foursquare/FSQLocationBroker

addRegionMonitoringSubscriber

Closed this issue · 14 comments

I need to register a monitor subscriber when the app starts in order to get notified when the user enters a specific geofence. The problem is that I don't have( and don't want imediate) access to subscriber's regions(the regions are not hardcoded). In that case, when I call "addRegionMonitoringSubscriber", the library will think that all my geofences are unmonitored and will remove them. Am I missing something?

Ah, this looks like it might be a regression in our code, I am sorry. It is supposed to re-pair geofences with subscribers on app startup based on subscriberIdentifier, but it looks like it is too aggressively clearing out monitored regions. I will work on a fix, sorry about this.

No problem @bdorfman . Thanks for looking into this. Do you have an et? I could try to fix it if not.

I have a fix already written up. Just want to run it by some coworkers and do a bit more testing before pushing. Hopefully have something up here for you tomorrow.

On Jun 30, 2015, at 10:33 PM, bogdantmm92 notifications@github.com wrote:

No problem @bdorfman . Thanks for looking into this. Do you have an et? I could try to fix it if not.


Reply to this email directly or view it on GitHub.

Great news, Thanks!

I have pushed a substantial rewrite of how the broker deals with region subscribers. It should now properly reconnect your subscribers to any regions they were monitoring on a previous app launch. A thorough list of changes and fixes is in the commit description.

Please update to latest master and let me know if this solves your problem. If so I will bump the version number and push out a new release.

It works, thanks!
The only "problem" is that

@property (nonatomic, readonly) NSSet *monitoredRegions;

is immutable, so it's not very optimum to create a new set when adding a new region from

- (void)addMonitoredRegion:(CLRegion *)region;  

Especially when the app is in background and you listen to 10-20 geofences. What do you think?
I'm not very used to objc, so again I may miss something.

Glad the issue is fixed for you!

Generally immutable collections are preferable to mutable ones for thread safety reasons. If you are mutating the set while the broker is trying to read out from it on another thread, that will cause a crash. self.monitoredRegions = [self.monitoredRegions setByAddingObject:newRegion] shouldn't have any noticeable difference in performance.

Note that, since the protocol specifies a readonly property, you can theoretically provide any subclass of NSSet (such as NSMutableSet) as the actual property on your class and it should fulfill the conformance requirement. However I don't recommend this for the reasons given above.

Closing this issue for now, but if you have any other questions feel free to reach out to me. Always happy to help.

Could you please publish a new release? I want to be able to get it from cocoapods.

Yes, I'll do that today.

Version bumped and new podspec has been pushed to cocoapods trunk.

I need to do the following things:

  • change the position of a region with the same id
  • force update the regions for a specific subscriber

@bdorfman I think that the only way to remove a region from a RegionMonitoringSubscriber is by removing the RegionMonitoringSubscriber itself.

If you just set a new NSSet to your monitoredRegions property that has the region you want to remove, removed it should update CLLocationManager for you if your property is KVO compliant. Otherwise you need to manually call refreshRegionMonitoringSubscribers after you make a change.

Regions are uniqued based on identifier, because CLLocationManager does not guarantee it will return you the same region objects you provided when you ask for them, only that the identifiers will be the same. If you change the bounds of the region you should change the identifier as well.

From what I've seen, refreshRegionMonitoringSubscribers won't remove unmonitored regions. The region would be removed only if I call refreshRegionMonitoringSubscribersRemovingSubscriberWithIdentifer: identifier shouldRemoveAllUnmonitoredRegions: false (or true), but this method is private .

I need to modify the same region because I'm tracking user's location using geofences(it's more battery efficient). When exit events gets triggered, I fetch the new location & move the region's center in that location.

I am not sure exactly what you are doing, but it works fine for me. If I set my regions to be, for example, regions with identifiers "SubscriberID+Test1" and "SubscriberID+Test2", and then later set them again to be just "SubscriberID+Test1", the region identified as "SubscriberID+Test2" gets removed properly for me.

CLLocationManager has no mechanism to change currently monitored regions. You have to remove the old one and then add a new one.