7
\$\begingroup\$

I have a localization manager class which can change app language on the fly. It's using ReactiveCocoa and my main concern is that I'm not using some of RAC parts correctly.

First (in - (void)configureSignals):

+ (instancetype)sharedInstance
{
 static i2KRLMLocalizationManagerObject *sharedInstance = nil;
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
 sharedInstance = [[[self class] alloc] init];
 [sharedInstance initialConfiguration];
 });
 return sharedInstance;
}
- (void)initialConfiguration
{
 [self configureSignals];
 [self configureAppLocalizations];
}
- (void)configureSignals
{
 RACReplaySubject *subject = [RACReplaySubject replaySubjectWithCapacity:1];
 self.localeConnection = [subject multicast:subject];
 [self.localeConnection autoconnect];
 RACReplaySubject *languagesSubject = [RACReplaySubject replaySubjectWithCapacity:1];
 self.languageNamesConnection = [languagesSubject multicast:languagesSubject];
 [self.languageNamesConnection autoconnect];
 RACReplaySubject *languageIndexSubject = [RACReplaySubject replaySubjectWithCapacity:1];
 self.languageIndexConnection = [languageIndexSubject multicast:languageIndexSubject];
 [self.languageIndexConnection autoconnect];
}

It feels for me that multicast should be used differently(and is used wrong currently, although it works), although I'm not sure how to use it correctly.

Those signals are used to propagate NSLocale, array of supported languages and current language index in that array. I use multicast so that if there is more then 1 subscriber, signal will be shared and current values will be just replayed. I'm not sure that signal multicasting itself is idiomatic/correct way. Also I'm not completely sure if connection is needed at all or I can just go with ReplaySubject.

Second (like here):

- (void)changeToLocale:(NSLocale *)locale
{
 [self reloadBundleWithLocaleID:[locale localeIdentifier]];
 [(RACSubject *)[self localeSignal] sendNext:locale];
}

Cast has to be made now because in interface it's declared as - (RACSignal *)localeSignal; and is actually

- (RACSignal *)localeSignal
{
 return self.localeConnection.signal;
} 

which is defined as RACSignal in ReactiveCocoa as well, but since it's definitely RACSubject(RACReplaySubject is subclass of RACSubject and since sendNext is available on RACSubject and not on RACSignal I need to cast to avoid compiler complaints).

I use that getter instead of self.languageNamesConnection.signal because if I ever change this to something I wouldn't have to go all over and remove traces of that. But the cast looks just wrong.

I don't like this cast at all, although not sure how to improve this(since I'm sending values through multicasted signal; and probably get rid of this sending altogether if possible).

Also general suggestions on improving would be very helpful(I think there should be more FRP way to do this).

Full repo with example is here, class is here.

nhgrif
25.4k3 gold badges64 silver badges129 bronze badges
asked Mar 3, 2015 at 6:09
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

Excerpts from answers to my question on RAC repo:

For the first question -

Subjects are naturally multicasted, so you could replace the multicast connection property with @property RACReplaySubject *localeSubject and subscribe directly to that in place of localeSignal.

So there's no need to use connection here.

For the second part - it's enough to have RACSignal in interface and RAC(Replay)Subject in the implementation.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
answered Mar 10, 2015 at 8:25
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.