File: XCPlaygroundPage.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (188 lines) | stat: -rw-r--r-- 9,246 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#if os(iOS) || os(tvOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif

/// The URL for the directory where data which is shared between all playgrounds may be stored.
///
/// This directory is at the path `~/Documents/Shared Playground Data/`.
/// This directory must already exist to be usable by playgrounds; Xcode will *not* create it for you.
@available(*,deprecated,message:"Use 'PlaygroundSharedDataDirectoryURL' from the 'PlaygroundSupport' module instead")
public let XCPlaygroundSharedDataDirectoryURL: NSURL = {
    if let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
        return NSURL(fileURLWithPath: documentsDirectory + "/Shared Playground Data/")
    }
    return NSURL(fileURLWithPath: ("~/Documents/Shared Playground Data/" as NSString).expandingTildeInPath)
}()

/// `XCPlaygroundPage` provides a collection of methods and properties which represent the state of a playground page and
/// which allow the code in a playground page to interact with Xcode.
///
/// This includes things like capturing values into the page's timeline, controlling the page's execution lifecycle, and
/// setting up a live view for the page.
public final class XCPlaygroundPage {
    /// Returns the `XCPlaygroundPage` instance representing the current page in the playground.
    public static let currentPage: XCPlaygroundPage = XCPlaygroundPage()

    /// The initializer used to create XCPlaygroundPage.currentPage.
    private init() {}

    /// Captures the given `value` and passes it to Xcode, where it is displayed in a timeline item along with other values captured with the given `identifier`.
    ///
    /// - note: This function has been deprecated. 
    @available(*,deprecated) public func captureValue<T>(value: T, withIdentifier identifier: String) {
        NotificationCenter.default.post(name: "XCPCaptureValue" as NSString as NSNotification.Name, object: self, userInfo: [ "value" : value, "identifier": identifier as AnyObject])
    }

    /// Indicates whether the playground page needs to execute indefinitely.
    /// The default value of this property is `false`, but playground pages with live views will automatically set this to `true`.
    ///
    /// If set to `true`, this tells Xcode that the playground page should continue to run once it reaches the end of top-level code.
    /// If set to `false`, Xcode will kill the playground page when it has finished executing top-level code.
    ///
    /// Setting this after the playground page has reached the end of top-level code has no effect.
    /// Instead, use `XCPlaygroundPage.finishExecution()` to indicate to Xcode execution is done and the page should stop executing.
    ///
    /// - note: This is the replacement for the `XCPExecutionShouldContinueIndefinitely` and `XCPSetExecutionShouldContinueIndefinitely` APIs.
    @available(*,deprecated,message:"Use 'PlaygroundPage.current.needsIndefiniteExecution' from the 'PlaygroundSupport' module instead")
    public var needsIndefiniteExecution: Bool = false {
        didSet {
            NotificationCenter.default.post(name: "XCPlaygroundPageNeedsIndefiniteExecutionDidChangeNotification" as NSString as NSNotification.Name, object: self, userInfo: [ "XCPlaygroundPageNeedsIndefiniteExecution" : needsIndefiniteExecution as AnyObject])
        }
    }

    /// Instructs Xcode that the playground page has finished execution.
    ///
    /// This method does not return, as Xcode will kill the process hosting playground execution when this method is called.
    @available(*,deprecated,message:"Use 'PlaygroundPage.current.finishExecution()' from the 'PlaygroundSupport' module instead")
    public func finishExecution() -> Never {
        // Send a message to Xcode requesting that we be killed.
        NotificationCenter.default.post(name: "XCPlaygroundPageFinishExecutionNotification" as NSString as NSNotification.Name, object: self, userInfo: nil)
    
        // Sleep for a while to let Xcode kill us.
        for _ in 1...10 {
            sleep(60)
        }

        // If Xcode doesn't kill us before we stop sleeping, just exit on our own.
        exit(0)
    }

    /// The live view currently being displayed by Xcode on behalf of the playground page, or nil if there is no live view.
    ///
    /// Setting this property to a non-nil value will cause the live view to become visible, and implies setting `XCPlaygroundPage.needsIndefiniteExecution` to `true`.
    /// Setting this property to nil will cause Xcode to dismiss the live view.
    ///
    /// - note: This is nil by default.
    @available(*,deprecated,message:"Use 'PlaygroundPage.current.liveView' from the 'PlaygroundSupport' module instead")
    public var liveView: XCPlaygroundLiveViewable? = nil {
        didSet {
            if liveView != nil {
                // Setting a live view enables implies a need for indefinite execution.
                needsIndefiniteExecution = true
            }
            
            let userInfo: [AnyHashable: Any]
            
            if let liveView = liveView {
                switch liveView.playgroundLiveViewRepresentation() {
                case .ViewController(let viewController):
                    userInfo = ["XCPlaygroundPageLiveViewController" : viewController]
                case .View(let view):
                    userInfo = ["XCPlaygroundPageLiveView" : view]
                }
            }
            else {
                if oldValue == nil {
                    // Don't send a notification if we just went from nil to nil.
                    return
                }
                
                userInfo = [:]
            }

            NotificationCenter.default.post(name: "XCPlaygroundPageLiveViewDidChangeNotification" as NSString as NSNotification.Name, object: self, userInfo: userInfo)
        }
    }
}

/// An enum describing the supported representations for live views in playgrounds.
public enum XCPlaygroundLiveViewRepresentation {
#if os(iOS) || os(tvOS)
    /// A view which will be displayed as the live view.
    ///
    /// - note: This view must be the root of a view hierarchy (i.e. it must not have a superview), and it must *not* be owned by a view controller.
    case View(UIView)

    /// A view controller whose view will be displayed as the live view.
    ///
    /// - note: This view controller must be the root of a view controller hierarchy (i.e. it has no parent view controller), and its view must *not* have a superview.
    case ViewController(UIViewController)

#elseif os(OSX)
    /// A view which will be displayed as the live view.
    ///
    /// - note: This view must be the root of a view hierarchy (i.e. it must not have a superview), and it must *not* be owned by a view controller.
    case View(NSView)

    /// A view controller whose view will be displayed as the live view.
    ///
    /// - note: This view controller must be the root of a view controller hierarchy (i.e. it has no parent view controller), and its view must *not* have a superview.
    case ViewController(NSViewController)

#endif
}

/// A protocol for types which can be displayed as the live view for a playground page.
///
/// On iOS and tvOS, `UIView` and `UIViewController` conform to this protocol.
/// Likewise, on OS X, `NSView` and `NSViewController` conform to this protocol.
///
/// Implement this protocol if your custom type should be usable as the "live view" for a playground page.
public protocol XCPlaygroundLiveViewable {
    /// Returns the `XCPlaygroundLiveViewRepresentation` for the receiver.
    ///
    /// The value returned from this method can but does not need to be the same every time; XCPlaygroundLiveViewables may choose to create a new view or view controller every time.
    ///
    /// - seealso: `XCPlaygroundLiveViewRepresentation`
    func playgroundLiveViewRepresentation() -> XCPlaygroundLiveViewRepresentation
}

#if os(iOS) || os(tvOS)
extension UIView: XCPlaygroundLiveViewable {
    public func playgroundLiveViewRepresentation() -> XCPlaygroundLiveViewRepresentation {
        return .View(self)
    }
}

extension UIViewController: XCPlaygroundLiveViewable {
    public func playgroundLiveViewRepresentation() -> XCPlaygroundLiveViewRepresentation {
        return .ViewController(self)
    }
}
#elseif os(OSX)
extension NSView: XCPlaygroundLiveViewable {
    public func playgroundLiveViewRepresentation() -> XCPlaygroundLiveViewRepresentation {
        return .View(self)
    }
}

extension NSViewController: XCPlaygroundLiveViewable {
    public func playgroundLiveViewRepresentation() -> XCPlaygroundLiveViewRepresentation {
        return .ViewController(self)
    }
}
#endif