> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/ios/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/ios/master/todo/custom-types/playgroundconsole.md).

# PlaygroundConsole

讓 print() 可以在 Swift Playgrounds 中方便使用。

{% tabs %}
{% tab title="🐶  PlaygroundConsole" %}

```swift
import Combine
import PlaygroundSupport

// 🐶 PlaygroundConsole
public class PlaygroundConsole : 
    TextOutputStream, 
    CustomStringConvertible, 
    CustomPlaygroundDisplayConvertible 
{
    // console text
    private var text = ""
    
    // 🅿️ TextOutputStream
    public func write(_ string: String) { text += string }
    // 🅿️ CustomPlaygroundDisplayConvertible
    public var playgroundDescription: Any { text }
    // 🅿️ CustomStringConvertible
    public var description : String { text }
    
    // 1. static let (can't change this static instance)
    public static let `default` = PlaygroundConsole()
    
    // 2. public init (can create new instance)
    public init() {}
    
    // 3. other public services
    public func clear() { text = "" }
}

// 🌀 PlaygroundPage.console
extension PlaygroundPage {
    public static let console = PlaygroundConsole.default
}

/// shadows `Swift.print()`, prints to `PlaygroundConsole.shared`.
/// (based on [StackOverflow](https://stackoverflow.com/a/47223166))
public func print(
    _    items: Any..., 
    separator : String = " ", 
    terminator: String = "\n"
) {
    let output = items.map { "\($0)" }.joined(separator: separator)
    PlaygroundConsole.default.write(output + terminator)
}
```

{% endtab %}

{% tab title="Singleton 版本" %}

```swift
/*
 Viewing console output in iPad Swift Playgrounds
 https://damian.fyi/2020/07/01/ipad_swift_playgrounds_console/
 */

import Combine
import PlaygroundSupport

// 🐶 PlaygroundConsole
public class PlaygroundConsole : 
    TextOutputStream, 
    CustomStringConvertible, 
    CustomPlaygroundDisplayConvertible 
{
    // console text
    private var text = ""
    
    // 🅿️ TextOutputStream
    public func write(_ string: String) { text += string }
    // 🅿️ CustomPlaygroundDisplayConvertible
    public var playgroundDescription: Any { text }
    // 🅿️ CustomStringConvertible
    public var description : String { text }
    
    ///////////////// Singleton Pattern ///////////////////////
    
    // 1. static let (so no one can change this static instance)
    public static let shared = PlaygroundConsole()
    
    // 2. private init (so no one can create new instance)
    private init() {}
    
    // 3. other public services
    public func clear() { text = "" }
}

// 🌀 PlaygroundPage.console
extension PlaygroundPage {
    public static let console = PlaygroundConsole.shared
}

/// shadows `Swift.print()`, prints to `PlaygroundConsole.shared`.
/// (based on [StackOverflow](https://stackoverflow.com/a/47223166))
public func print(
    _    items: Any..., 
    separator : String = ", ", 
    terminator: String = "\n"
) {
    let output = items.map { "\($0)" }.joined(separator: separator)
    PlaygroundConsole.shared.write(output + terminator)
}
```

{% endtab %}

{% tab title="💈 範例" %}

```swift
import Combine
import PlaygroundSupport

// PlaygroundConsole.shared
let console = PlaygroundPage.console

// String conforms to `TextOutputStream`
var con = ""

[1,2,3]
    // ⭐️ Publishers.Sequence<[Int], Never>
    .publisher                                      
    
    // Combine.PassthroughSubject.print(_:to:) 
    // DOESN'T accept an inout parameter
    // .print(to: &con)  // ❌ '&' used with non-inout argument
    // .print(to:  con)  // ❌ pass by copy: 所以跟原來的 `con` 無關
    // ⭐️ Publishers.Print<...>
    .print(to: console)  // ✅ pass by reference    
    
    // ⭐️ Publishers.FlatMap<...>
    .flatMap { Array(repeating: $0, count: $0).publisher }
    
    // `Swift.print(_:separator:terminator:to:)` accepts in-out `to` argument
    // ⭐️ AnyCancellable
    .sink { print("got: \($0)", to: &con) }

con
// got: 1
// got: 2
// got: 2
// got: 3
// got: 3
// got: 3

console
// receive subscription: ([1,2,3])
// request unlimited
// receive value: (1)
// receive value: (2)
// receive value: (3)
// receive finished
```

{% endtab %}

{% tab title="📘 參考" %}

* [ ] [Viewing console output in iPad Swift Playgrounds](https://damian.fyi/2020/07/01/ipad_swift_playgrounds_console/) - Damian Mehers
* [ ] [Extending functionality of print() function](https://stackoverflow.com/questions/39026752/swift-extending-functionality-of-print-function) - StackOverflow
  {% endtab %}

{% tab title="👥 相關" %}

* [Swift Playgrounds](/ios/swift-playgrounds.md)
  {% endtab %}

{% tab title="🌷 應用" %}

* [📦 URLSession.DataTaskPublisher](/ios/swift/scope/framework/built-in-frameworks/combine/publishers/urlsession.datataskpublisher.md)
  {% endtab %}
  {% endtabs %}
