---
title: Understanding the RxSwift Share Operator | ArcTouch
description: Learn about sharing subscriptions in RxSwift, which helps developers use replay and share operators with RxSwift’s playground examples.
url: "https://arctouch.com/blog/rxswift-share-operator"
date_modified: "2025-04-10T19:21:45.240Z"
---
# Understanding the RxSwift share operator

Learn about sharing subscriptions in RxSwift, which helps developers use replay and share operators with RxSwift’s playground examples.

5 min. read - June 10, 2019

By ArcTouch Team

[](mailto:?subject=Interesting%20blog%20post&body=I%20thought%20you%20might%20like%20this%20blog%20post%20from%20ArcTouch%3A%20https%3A%2F%2Farctouch.com%2Fblog%2Frxswift-share-operator)

![RxSwift Connectable Observable Sequences](/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fefnbmai9c55m%2FKtsPHFSipBHc6VA2QpSJk%2Fa375ee895b63f0c868f51a7e91893f91%2Frxswift-blog-hero&w=3840&q=75)

_\[_ **_Editor’s note_**_: This is the second post in a two-part series about sharing subscriptions in_ [_RxSwift_](/tag/rxswift)_, designed to help developers learn how to use replay and share operators with RxSwift’s playground examples\]_

In Part 1 of this series, we explored [RxSwift’s Connectable Observable sequences](/blog/rxswift-connectable-observable-sequences) by detailing `publish`, `replay` and `refCount` operators. We also briefly discussed the `share` operator, and now we’ll go into a more extensive explanation by performing the same kind of analysis we did in [Part 1](/blog/rxswift-connectable-observable-sequences). If you haven’t already, I’d recommend reading read Part 1 so you get to know the auxiliary functions and how the code examples are structured.

This series is written for developers with a basic understanding of Swift 5.0 and RxSwift 5.0.

## The share operator

We use the `share` operator when we need the chain of operators not to re-execute upon every subscription. Thus, everything before `share` is executed only once, as depicted in **Listing 1** and **Output 1**:

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

12

13

14

15

16

```
let observable = Observable<Int>.create { observer -> Disposable in
  print("Creating observable")
  DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 1, execute: {
    observer.onNext(2)
  }
  return Disposables.create()
}

let doubleObservable = observable.map { value -> Int in
  print("Multiplying by 2")
  return value * 2
}
let doubleSharedObservable = doubleObservable.share()

doubleSharedObservable.printNext("Subscription A")
doubleSharedObservable.printNext("Subscription B")
```

**Listing 1**: Example of share operator.

1

2

3

4

```
Creating observable
Multiplying by 2
Subscription A -> 4
Subscription B -> 4
```

**Output 1:** Logs of Listing 1.

In the example, `observable` is created by emitting **2** after one second. The value is then mapped to **4** in the `doubleObservable` and the mapping becomes shared in `doubleSharedObservable`. `A` and `B` are subscribed to the shared observable, so the creation closure will execute only once, upon the first subscription. The mapping function will also execute once for each emitted value, no matter the number of subscribers. That behavior can be verified in **Output 1**, where both subscriptions print the emitted value **4**, but `Creating observable` and `Multiplying by 2` don’t print twice.

Notice this is pretty much the same behavior of `publish`. And if you’re curious, take a look at the source code of those operators to see that their implementations are very similar. Both are based on the `multicast` operator. This operator basically broadcasts emitted values through a subject, which is an entity that is at the same time an observable and an observer. You can find additional information about this topic in this [RxSwift Medium post](https://medium.com/fantageek/rxswift-subjects-part1-publishsubjects-103ff6b06932).

In (very) simple terms, `share` passes a `ReplaySubject` to `multicast`. Internally, the subject is subscribed to the source observable (the underlying subscription) and its emitted values are handed to the subject, which in turn passes the values to the actual subscribers. Since this is not really the focus of this post, I suggest that you dig into RxSwift’s source code if you want to know more about the details of `share`.

In the example above we used `share` with its default parameters, but its full signature is `share(replay:scope:)`, which also gives us similar functionality to `replay` and `refCount` operators. We’ll examine how that works below.

## Replaying elements in shared subscriptions

The replaying functionality of `share` differs from `replay` only in the resulting sequence’s type, which is a regular observable rather than the connectable observable returned by `replay`.

1

2

3

4

5

```
_ = printSecondBoundary()
let intSequence = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance).share(replay: 2)

_ = intSequence.printNext("Subscription A")
delay(3) { _ = intSequence.printNext("Subscription B") }
```

**Listing 2**: Example of share’s replay functionality.

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

12

13

14

15

```
Subscription A -> 0
----- t1 -----

Subscription A -> 1
----- t2 -----

Subscription B -> 0
Subscription B -> 1
Subscription A -> 2
Subscription B -> 2
----- t3 -----

Subscription A -> 3
Subscription B -> 3
----- t4 -----
```

**Output 2**: Results of Listing 2’s execution.

In **Listing 2**, we have `A` subscribing at `t0` (before any delay) and printing the incrementing emitted values at `t1` and `t2`. Since we’re using a buffer of size **2**, when `B` subscribes just before `t3`, the last two emitted values — **0** and **1** — are passed to it. Notice that these values don’t mean that `intSequence` was recreated. Otherwise, the values would be emitted one second apart from each other. Thus, `share` emits buffered elements (if any) as soon as a subscription occurs. It’s also worth mentioning that `replay` parameter has a default value of **0** — which explains **Listing 1**’s behavior.

## Controlling replay buffer with scopes

In the previous examples, we didn’t care much about the `scope` parameter. However, we used its default value of `.whileConnected`, which is one of the cases of the `SubjectLifetimeScope` enum. The other possibility is `.forever`.The `scope` parameter dictates how `share` handles the lifetime of the cache it uses for replaying elements. In reality, this is related to how `share` constructs the underlying subject it passes to `multicast`. However, since we’re interested in describing behavior rather than implementation details, I will keep the term “cache” for simplicity. Now let’s look at **Listing 3** and **Output 3**:

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

```
_ = printSecondBoundary()
let intSequence = Observable<Int>
  .interval(.seconds(1), scheduler: MainScheduler.instance)
  .share(replay: 2, scope: .whileConnected)

var subscriptionA = intSequence.printNext("Subscription A")
var subscriptionB: Disposable?
delay(3) { subscriptionB = intSequence.printNext("Subscription B") }
delay(4) { subscriptionA.dispose() }
delay(5) { subscriptionB?.dispose() }
delay(6) { _ = intSequence.printNext("Subscription C") }
```

**Listing 3**: Using .whileConnected scope.

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

12

13

14

15

16

17

18

19

20

21

```
Subscription A -> 0
----- t1 -----

Subscription A -> 1
----- t2 -----

Subscription B -> 0
Subscription B -> 1
Subscription A -> 2
Subscription B -> 2
----- t3 -----

Subscription B -> 3
----- t4 -----

----- t5 -----

----- t6 -----

Subscription C -> 0
----- t7 -----
```

**Output 3**: Output of Listing 3.

**Listing 3** is actually an extension of Listing 2, where I disposed of the first two subscriptions and performed another one, `C`, later on. This is a situation when the differences between scopes become evident, as does the `refCount`‘s aspect of share.Pay careful attention to **Output 3** and you will notice that `C` prints values from **0** and one second after its subscription. That’s share’s `refCount`\-like behavior causing `intSequence` to be recreated (`share` actually uses `refCount` internally). Thus, `intSequence` is created when `A` subscribes at `t0` and recreated when `C` subscribes at `t6`, since all previous subscriptions had been disposed of at this point.Also, did you notice that unlike `B`, no elements were replayed for `C`? Because we’re using `.whileConnected` scope, when all subscriptions are disposed of, `share`‘s internal cache gets cleared. The same doesn’t happen with `.forever`, where the cached elements are kept no matter the number of subscribers. This is what we get by simply changing the scope in **Listing 3**:

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

```
Subscription A -> 0
----- t1 -----

Subscription A -> 1
----- t2 -----

Subscription B -> 0
Subscription B -> 1
Subscription A -> 2
Subscription B -> 2
----- t3 -----

Subscription B -> 3
----- t4 -----

----- t5 -----

Subscription C -> 2
Subscription C -> 3
----- t6 -----

Subscription C -> 0
----- t7 -----
```

**Output 4**: Results of using .forever scope.

As expected, the divergence lies in `t6`. The last emitted values — **2** and **3** — are replayed upon **C**‘s subscription, even though the sequence was recreated and restarted counting from “0.”Thus, the key difference between scopes becomes clear when the number of subscribers drops from **1** to **0**. In `.forever` scope, `share` will keep the replay cache. In `.whileConnected`, it won’t.In the vast majority of the cases, you’ll be using `.whileConnected` — it’s the default parameter. But if you really need to use `.forever`, be careful. Especially if you’re working with large objects, ask yourself if it’s really a good idea to keep these objects indefinitely cached in memory.

## Legacy sharing options

If you’re familiar with RxSwift 3.x, you’ve probably seen `shareReplay(_:)` and `shareReplayLatestWhileConnected()`. Both are deprecated since RxSwift 4.x and now you should only be using the `share(replay:scope:)` we analyzed in this series. If you try to use one of those, Xcode will fire a very descriptive warning telling you how to replace them, but here’s a quick summary:

* `shareReplay(bufferSize)` now behaves like `share(replay: bufferSize, scope: .whileConnected)`. However, in RxSwift 3.x, `shareReplay(_:)` acted like using `.forever` scope. Thus, if you’re refactoring legacy code, think carefully about which scope to use.
* `shareReplayLatestWhileConnected()` is the same as using `share(replay: 1, scope: .whileConnected)`.

## Bonus: RxCocoa’s shared sequences

While RxSwift encloses the reactive extensions for the Swift programming language, RxCocoa encompasses abstractions specifically for the Cocoa environment (iOS, tvOS, macOS and watchOS).[Traits](https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Traits.md) are examples of these abstractions. They are essentially syntactic-sugared observables modified in a way that’s useful for specific scenarios. And when discussing shared sequences, two important traits quickly come to mind: `Driver` and `Signal`.Both are type aliases of `SharedSequence` with specific sharing strategy. `Driver` behaves like `share(replay: 1)` and `Signal` like `share()`. `Driver` will replay elements, while `Signal` won’t.Except for the sharing capability, `Driver` and `Signal` are pretty much the same. They both dispatch events to the main thread and they don’t error out. Thus, you can use them to bind events to UI components in an easy and safe way. **Listing 4** depicts an example of `Driver`:

 1

 2

 3

 4

 5

 6

 7

 8

 9

10

11

12

13

14

15

16

17

18

19

```
let dataObservable = Observable<String>.create { observer -> Disposable in
  print("Feching data...")
  DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 2, execute: {
    observer.onNext("Some data from the internet")
  })
  return Disposables.create()
}

let dataDriver = dataObservable.asDriver(onErrorJustReturn: "")

let bag = DisposeBag()

dataDriver
  .drive(textField.rx.text)
  .disposed(by: bag)

dataDriver
  .drive(otherTextField.rx.text)
  .disposed(by: bag)
```

**Listing 4:** Example of Driver.

In the example, I am creating a `Driver` from a regular observable that simulates fetching data from the Internet. Since it’s a shared sequence, the data is fetched only once and the result is bound to the text fields. And even though the data is sent from a background thread, `Driver` enforces that they are delivered on the main thread. Finally, it doesn’t let any errors reach the components, in this case, by sending an empty string instead. Traits are so cool!

## What’s next? Keep playing on RxSwift playgrounds

In this series, we discussed many operators related to sharing subscriptions in RxSwift. We also learned what connectable observable sequences are and how to buffer elements. And even though we left out operators such as multicast, we developed a great understanding about the most commonly used operators. Hopefully, you are now able to use them in the most everyday scenarios.Keep in mind that this is based on RxSwift’s playground examples, where you can find other cool stuff that’s not limited to sharing subscriptions and connectable operators. I recommend playing around with those examples.

Thank you for reading this — and [find me on Twitter](https://twitter.com/alanpaivaa) to let me know what you think!

## Article Author:

[AT | ArcTouch Team | ArcTouch Employees](/blog/author/arctouch-team)

## Tags:

[Agile Development](/tag/agile-development) [Best Practices](/tag/best-practices) [Developer Tips](/tag/developer-tips) [iOS](/tag/ios) [RxSwift](/tag/rxswift) [Swift](/tag/swift)

## Subscribe for more insights

Get our newsletter in your inbox.

## Related posts

[12 web accessibility best practices: A starter list | ArcTouch shares 12 best practices that provide a great starting point for building accessible web experiences. | 5 min. read - April 16, 2024](/blog/web-accessibility-best-practices) [Injecting AI into software development — an ArcTouch blog series | The ArcTouch design and development team shares how to use AI to build lovable apps and websites — better and faster. | 5 min. read - April 9, 2024](/blog/ai-software-development)

## Contact us.

### Let's build something lovable. Together.

We help companies of all sizes build lovable apps, websites, and connected experiences.
