Debugging with total

RxSwift includes another utility operator that counts all Observable allocations, called total. This is not enabled by default. To enable it, the trace resources flag needs to be added to the RxSwift target. The most reliable way to do this with CocoaPods is to set this flag to the debug configuration in the pod file's post install hook. Check the pod file of the starter project for this section, and you will note the install hook, as follows:

post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['CONFIGURATION_BUILD_DIR'] = '$
PODS_CONFIGURATION_BUILD_DIR'
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['-D',
'TRACE_RESOURCES']
end
end
end
end

Returning to the playground, we will begin by printing out the total property as shown:

print(RxSwift.Resources.total)

Note that total is a type method on resources and in this case, the total is zero. Now we will create a dispose bag instance and print the total again using the previous print statement, and you will see in the console logs that the total is 2 this time. You might ask: Why is it 2 this time?

The answer to that question is in the implementation details. We can just accept this by creating a disposeBag that increments the total by 2, but let's delve more deeper to answer the question. command and click on DisposeBag() to go to its definition. You will see that DisposeBag inherits from DisposeBase. command and click on DisposeBase and you will see that it increments the total in its init. However, back in the DisposeBag definition, you will note that DisposeBag has a private var_lock that is an instance of SpinLock(). Let's command and click into SpinLock() and see that it is an alias for RecursiveLock. Also, command and clicking into RecursiveLock shows that even RecursiveLock increments the total.

Back to the playground; Resources.total only tracks Rx allocations. For example, consider that we create an instance of NSObject before the dispose bag, as follows:

exampleOf(description: "total") {
print(RxSwift.Resources.total)

let object = NSObject()
let disposeBag = DisposeBag()
print(RxSwift.Resources.total)

}

The total is still 2, but now we will create an Observable sequence of string and print the total again, as shown:

print(RxSwift.Resources.total)

let stringSequence = Observable.just("I am a string")
print(RxSwift.Resources.total)

Then, you will see that the total is now 3, as shown in the following screenshot:

Then, we will subscribe to the Observable and print total in the handler, as follows:

stringSequence
.subscribe(onNext: { _ in
print(RxSwift.Resources.total)
})
.disposed(by: disposeBag)

Also, you will note that the total will now be 4, as illustrated:

Let's print total again after the subscription too and note in the console logs that the total is still 4, because the subscription is still allocated. So we will set the disposeBag to a new instance of DisposeBag() before the print statement that will call for disposal of all its contents. We will also need to make disposeBag a variable so that it can be changed, as follows:

let object = NSObject()
var disposeBag = DisposeBag()
print(RxSwift.Resources.total)

let stringSequence = Observable.just("I am a string")
print(RxSwift.Resources.total)

stringSequence
.subscribe(onNext: { _ in
print(RxSwift.Resources.total)
})
.disposed(by: disposeBag)

disposeBag = DisposeBag()
print(RxSwift.Resources.total)

You will then note that the total has now decremented by 1 for the subscription that was disposed.

We will print the total once more after the example block, as follows:

exampleOf(description: "total") {
print(RxSwift.Resources.total)

let object = NSObject()
var disposeBag = DisposeBag()
print(RxSwift.Resources.total)

let stringSequence = Observable.just("I am a string")
print(RxSwift.Resources.total)

stringSequence
.subscribe(onNext: { _ in
print(RxSwift.Resources.total)
})
.disposed(by: disposeBag)

disposeBag = DisposeBag()
> print(RxSwift.Resources.total)
}
print(RxSwift.Resources.total)

Now, you will see that it has returned to zero, as shown:

Using total, and the debug operator that we covered in the last section, will help you resolve any issues you encounter in your RxSwift world.