# Memory leak issue while asynchronously iterating over async sequence

**URL:** <https://forums.swift.org/t/memory-leak-issue-while-asynchronously-iterating-over-async-sequence/64584>\
**Category:** Using Swift\
**Tags:** combine, retain-cycle, asyncpublisher, swift-ui\
**Created:** [April 24, 2023, 9:00am UTC](https://forums.swift.org/t/memory-leak-issue-while-asynchronously-iterating-over-async-sequence/64584 "2023-04-24T09:00:15Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![vigdora](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vigdora/32/34512_2.png) [@vigdora](https://forums.swift.org/u/vigdora)\
**Post date:** [April 24, 2023, 9:00am UTC](https://forums.swift.org/t/memory-leak-issue-while-asynchronously-iterating-over-async-sequence/64584/1 "2023-04-24T09:00:15Z")

</div>

I am having memory leak issue while iterating over async sequence like so:

```plaintext
import Foundation
import Combine

class MyServiceClass {
    
    let timerSequence = Timer.publish(every: 1, on: .main, in: .default).autoconnect().values
    
    init() {
        Task { [weak self] in
            await self?.setUpStreamIteration()
        }
    }
    
    func setUpStreamIteration() async {
        for await time in timerSequence {
            print(time)
        }
    }
}

var service: MyServiceClass? = MyServiceClass()
service = nil

```

the task continues to run and print the time even after the screen\class is "dismissed".  
Output:

```bash
2023-03-26 00:14:11 +0000
2023-03-26 00:14:12 +0000
2023-03-26 00:14:13 +0000
2023-03-26 00:14:14 +0000
2023-03-26 00:14:15 +0000
2023-03-26 00:14:16 +0000
2023-03-26 00:14:17 +0000
2023-03-26 00:14:18 +0000
2023-03-26 00:14:19 +0000
...

```

but when using .sink mechanism instead - I don't experience and memory leak.  
the working example is:

```swift
import Foundation
import Combine

class MyServiceClass {
    
    let timerSequence = Timer.publish(every: 1, on: .main, in: .default).autoconnect()

    
    init() {
        Task { [weak self] in
            await self?.setUpStreamIteration()
        }
    }
    
    func setUpStreamIteration() async {
         await timerSequence
                        .sink { [weak self] time in
                            print(time)
                        }
                        .store(in: &cancellations)
    }
}

var service: MyServiceClass? = MyServiceClass()
service = nil

```

can any one try to explain why using .sink managed to prevent the memory leak?  
is it ok to use .sink always as oppose of iterating over async sequence?  
can we compare the two approaches - to decide which one is better and why?  
thanks!

---

<div class="post-metadata">

**Author:** ![Kyle-Ye](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kyle-ye/32/19686_2.png) [@Kyle-Ye](https://forums.swift.org/u/Kyle-Ye)\
**Post date:** [April 24, 2023, 10:37am UTC](https://forums.swift.org/t/memory-leak-issue-while-asynchronously-iterating-over-async-sequence/64584/2 "2023-04-24T10:37:03Z")

</div>

Since setUpStreamIteration will never finish, you just keep a strong ref of self.

You can check the following post for more detail

[#02 – Not understanding that `Task` automatically captures `self`](https://www.swiftwithvincent.com/blog/three-mistakes-to-avoid-with-async-await-in-swift)

Suggested code 👇

```swift
class MyServiceClass {
    
    let timerSequence = Timer.publish(every: 1, on: .main, in: .default).autoconnect().values
    
    init() {
        Task { [weak self] in
            guard let timerSequence = self?.timerSequence else { return }
            for await time in timerSequence {
                guard let self else { return }
                print(time)
            }
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![vigdora](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vigdora/32/34512_2.png) [@vigdora](https://forums.swift.org/u/vigdora)\
**Post date:** [April 24, 2023, 11:23am UTC](https://forums.swift.org/t/memory-leak-issue-while-asynchronously-iterating-over-async-sequence/64584/3 "2023-04-24T11:23:52Z")

</div>

thanks @Kyle-Ye , but in the post you referred me to has no explanation on using .sink over setUpStreamIteration. why wouldn't I be using .sink always?

---

<div class="post-metadata">

**Author:** ![Kyle-Ye](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kyle-ye/32/19686_2.png) [@Kyle-Ye](https://forums.swift.org/u/Kyle-Ye)\
**Post date:** [April 24, 2023, 11:27am UTC](https://forums.swift.org/t/memory-leak-issue-while-asynchronously-iterating-over-async-sequence/64584/4 "2023-04-24T11:27:34Z")

</div>

`sink` is an API of Combine framework (Only available on Apple platforms)  
`AsyncSequence` and `Task` are Swift standard library API (Available on all platform Swift supports)

---

<div class="post-metadata">

**Author:** ![shp7724](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/shp7724/32/29761_2.png) [@shp7724](https://forums.swift.org/u/shp7724)\
**Post date:** [June 9, 2023, 1:01pm UTC](https://forums.swift.org/t/memory-leak-issue-while-asynchronously-iterating-over-async-sequence/64584/5 "2023-06-09T13:01:28Z")

</div>

The code you suggested unwraps `await self?.setUpStreamIteration()` to avoid `self` reference. But what if the function `setUpStreamIteration` is quite long and complex to be unwrapped into a single `Task` closure? Would there be any better, scalable solution?
