ios - Stop publishing when there are no subscribers and auto start when there are subscribers -
how implement racsignal
stop publishing when there no subscribers , auto start when there subscribers?
here scenario:
let have currentlocationsignal
in appdelegate
. locationviewcontroller
subscribe currentlocationsignal
when view loads , unsubscribe (dispose) when view unloads. since takes few seconds current location, subscribe currentlocationsignal
when app opens (and auto unsubscribe after few seconds), time arrive locationviewcontroller
accurate location. there can more 1 subscribers signal. when first subscriber listens, needs start calling startupdatinglocation
, when there no subscribers needs phone call stopupdatinglocation
.
good question! normally, you'd utilize racmulticastconnection utilize cases this, but, because want signal able reactivate later, connection isn't suitable on own.
the simplest reply mimic how connection works, specific behaviors want. basically, we'll maintain track of how many subscribers there @ given time, , start/stop updating location based on number.
let's start adding locationsubject
property. subject needs racreplaysubject, because want new subscribers sent location immediately. implementing updates subject easy enough:
- (void)locationmanager:(cllocationmanager *)manager didupdatelocations:(nsarray *)locations { [self.locationsubject sendnext:locations.lastobject]; }
then, want implement signal tracks , increments/decrements subscriber count. works using numberoflocationsubscribers
integer property:
- (racsignal *)currentlocationsignal { homecoming [racsignal createsignal:^(id<racsubscriber> subscriber) { @synchronized (self) { if (self.numberoflocationsubscribers == 0) { [self.locationmanager startupdatinglocation]; } ++self.numberoflocationsubscribers; } [self.locationsubject subscribe:subscriber]; homecoming [racdisposable disposablewithblock:^{ @synchronized (self) { --self.numberoflocationsubscribers; if (self.numberoflocationsubscribers == 0) { [self.locationmanager stopupdatinglocation]; } } }]; }]; }
in above code, +createsignal:
block invoked every time new subscriber added returned signal. when happens:
locationsubject
, values latter automatically fed former. then, @ future time, when subscription disposed of, decrement count , stop location updates if appropriate. now, that's left subscribing currentlocationsignal
on startup, , automatically unsubscribing after few seconds:
- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions { // utilize capacity of 1 because ever care latest // location. self.locationsubject = [racreplaysubject replaysubjectwithcapacity:1]; [[self.currentlocationsignal takeuntil:[racsignal interval:3]] subscribecompleted:^{ // don't need here, need // subscription maintain location updating going // time specified. }]; homecoming yes; }
this subscribes self.currentlocationsignal
immediately, , automatically disposes of subscription when +interval:
signal sends first value.
interestingly, -[racmulticastconnection autoconnect]
used behave -currentlocationsignal
above, that behavior changed because makes side effects wildly unpredictable. utilize case should safe, there other times (like when making network request or running shell command) when automatic reconnection horrible.
ios objective-c cocoa-touch reactive-programming reactive-cocoa
No comments:
Post a Comment