Permalink
Switch branches/tags
swift-DEVELOPMENT-SNAPSHOT-2018-11-15-a swift-DEVELOPMENT-SNAPSHOT-2018-11-14-a swift-DEVELOPMENT-SNAPSHOT-2018-11-13-a swift-DEVELOPMENT-SNAPSHOT-2018-11-01-a swift-DEVELOPMENT-SNAPSHOT-2018-10-24-a swift-DEVELOPMENT-SNAPSHOT-2018-10-23-a swift-DEVELOPMENT-SNAPSHOT-2018-10-22-a swift-DEVELOPMENT-SNAPSHOT-2018-10-21-a swift-DEVELOPMENT-SNAPSHOT-2018-10-20-a swift-DEVELOPMENT-SNAPSHOT-2018-10-19-a swift-DEVELOPMENT-SNAPSHOT-2018-10-03-a swift-DEVELOPMENT-SNAPSHOT-2018-10-02-a swift-DEVELOPMENT-SNAPSHOT-2018-10-01-a swift-DEVELOPMENT-SNAPSHOT-2018-09-28-a swift-DEVELOPMENT-SNAPSHOT-2018-09-27-a swift-DEVELOPMENT-SNAPSHOT-2018-09-22-a swift-DEVELOPMENT-SNAPSHOT-2018-09-21-a swift-DEVELOPMENT-SNAPSHOT-2018-09-20-a swift-DEVELOPMENT-SNAPSHOT-2018-09-19-a swift-DEVELOPMENT-SNAPSHOT-2018-09-18-a swift-DEVELOPMENT-SNAPSHOT-2018-09-14-a swift-DEVELOPMENT-SNAPSHOT-2018-09-13-a swift-DEVELOPMENT-SNAPSHOT-2018-09-10-a swift-DEVELOPMENT-SNAPSHOT-2018-09-08-a swift-DEVELOPMENT-SNAPSHOT-2018-09-07-a swift-DEVELOPMENT-SNAPSHOT-2018-09-04-a swift-DEVELOPMENT-SNAPSHOT-2018-08-25-a swift-DEVELOPMENT-SNAPSHOT-2018-08-24-a swift-DEVELOPMENT-SNAPSHOT-2018-08-23-a swift-DEVELOPMENT-SNAPSHOT-2018-08-22-a swift-DEVELOPMENT-SNAPSHOT-2018-08-21-a swift-DEVELOPMENT-SNAPSHOT-2018-08-20-a swift-DEVELOPMENT-SNAPSHOT-2018-08-18-a swift-DEVELOPMENT-SNAPSHOT-2018-08-16-a swift-DEVELOPMENT-SNAPSHOT-2018-08-15-a swift-DEVELOPMENT-SNAPSHOT-2018-08-14-a swift-DEVELOPMENT-SNAPSHOT-2018-08-10-a swift-DEVELOPMENT-SNAPSHOT-2018-08-09-a swift-DEVELOPMENT-SNAPSHOT-2018-08-06-a swift-DEVELOPMENT-SNAPSHOT-2018-08-02-a swift-DEVELOPMENT-SNAPSHOT-2018-08-01-a swift-DEVELOPMENT-SNAPSHOT-2018-07-31-a swift-DEVELOPMENT-SNAPSHOT-2018-07-30-a swift-DEVELOPMENT-SNAPSHOT-2018-07-28-a swift-DEVELOPMENT-SNAPSHOT-2018-07-27-a swift-DEVELOPMENT-SNAPSHOT-2018-07-24-a swift-DEVELOPMENT-SNAPSHOT-2018-07-23-a swift-DEVELOPMENT-SNAPSHOT-2018-07-22-a swift-DEVELOPMENT-SNAPSHOT-2018-07-21-a swift-DEVELOPMENT-SNAPSHOT-2018-07-20-a swift-DEVELOPMENT-SNAPSHOT-2018-07-19-a swift-DEVELOPMENT-SNAPSHOT-2018-07-18-a swift-DEVELOPMENT-SNAPSHOT-2018-07-17-a swift-DEVELOPMENT-SNAPSHOT-2018-07-16-a swift-DEVELOPMENT-SNAPSHOT-2018-07-14-a swift-DEVELOPMENT-SNAPSHOT-2018-07-13-a swift-DEVELOPMENT-SNAPSHOT-2018-07-12-a swift-DEVELOPMENT-SNAPSHOT-2018-07-11-a swift-DEVELOPMENT-SNAPSHOT-2018-07-09-a swift-DEVELOPMENT-SNAPSHOT-2018-07-07-a swift-DEVELOPMENT-SNAPSHOT-2018-07-06-a swift-DEVELOPMENT-SNAPSHOT-2018-07-05-a swift-DEVELOPMENT-SNAPSHOT-2018-07-04-a swift-DEVELOPMENT-SNAPSHOT-2018-07-03-a swift-DEVELOPMENT-SNAPSHOT-2018-07-02-a swift-DEVELOPMENT-SNAPSHOT-2018-07-01-a swift-DEVELOPMENT-SNAPSHOT-2018-06-30-a swift-DEVELOPMENT-SNAPSHOT-2018-06-29-a swift-DEVELOPMENT-SNAPSHOT-2018-06-27-a swift-DEVELOPMENT-SNAPSHOT-2018-06-26-a swift-DEVELOPMENT-SNAPSHOT-2018-06-25-a swift-DEVELOPMENT-SNAPSHOT-2018-06-24-a swift-DEVELOPMENT-SNAPSHOT-2018-06-23-a swift-DEVELOPMENT-SNAPSHOT-2018-06-22-a swift-DEVELOPMENT-SNAPSHOT-2018-06-21-a swift-DEVELOPMENT-SNAPSHOT-2018-06-20-a swift-DEVELOPMENT-SNAPSHOT-2018-06-19-a swift-DEVELOPMENT-SNAPSHOT-2018-06-18-a swift-DEVELOPMENT-SNAPSHOT-2018-06-17-a swift-DEVELOPMENT-SNAPSHOT-2018-06-16-a swift-DEVELOPMENT-SNAPSHOT-2018-06-15-a swift-DEVELOPMENT-SNAPSHOT-2018-06-14-a swift-DEVELOPMENT-SNAPSHOT-2018-06-08-a swift-DEVELOPMENT-SNAPSHOT-2018-06-07-a swift-DEVELOPMENT-SNAPSHOT-2018-06-06-a swift-DEVELOPMENT-SNAPSHOT-2018-06-05-a swift-DEVELOPMENT-SNAPSHOT-2018-06-04-a swift-DEVELOPMENT-SNAPSHOT-2018-06-03-a swift-DEVELOPMENT-SNAPSHOT-2018-06-02-a swift-DEVELOPMENT-SNAPSHOT-2018-06-01-a swift-DEVELOPMENT-SNAPSHOT-2018-05-31-a swift-DEVELOPMENT-SNAPSHOT-2018-05-30-a swift-DEVELOPMENT-SNAPSHOT-2018-05-29-a swift-DEVELOPMENT-SNAPSHOT-2018-05-28-a swift-DEVELOPMENT-SNAPSHOT-2018-05-27-a swift-DEVELOPMENT-SNAPSHOT-2018-05-26-a swift-DEVELOPMENT-SNAPSHOT-2018-05-25-a swift-DEVELOPMENT-SNAPSHOT-2018-05-24-a swift-DEVELOPMENT-SNAPSHOT-2018-05-23-a swift-DEVELOPMENT-SNAPSHOT-2018-05-22-a
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
195 lines (169 sloc) 8.44 KB
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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(macOS)
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.
public let playgroundSharedDataDirectory: URL = {
if let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
return URL(fileURLWithPath: documentsDirectory + "/Shared Playground Data/")
}
return URL(fileURLWithPath: ("~/Documents/Shared Playground Data/" as NSString).expandingTildeInPath)
}()
/// `PlaygroundPage` 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 PlaygroundPage {
/// Returns the `PlaygroundPage` instance representing the current page in the playground.
public static let current: PlaygroundPage = PlaygroundPage()
/// The initializer used to create PlaygroundPage.current.
private init() {}
/// 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 `PlaygroundPage.finishExecution()` to indicate to Xcode execution is done and the page should stop executing.
///
public var needsIndefiniteExecution: Bool = false {
didSet {
NotificationCenter.default.post(name: .playgroundPageNeedsIndefiniteExecutionDidChange, object: self, userInfo: ["PlaygroundPageNeedsIndefiniteExecution": needsIndefiniteExecution])
}
}
/// 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.
public func finishExecution() -> Never {
// Send a message to Xcode requesting that we be killed.
NotificationCenter.default.post(name: .playgroundPageIsReadyToFinishExecution, 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 `PlaygroundPage.needsIndefiniteExecution` to `true`.
/// Setting this property to nil will cause Xcode to dismiss the live view.
///
/// - note: This is nil by default.
public var liveView: PlaygroundLiveViewable? = nil {
didSet {
// Don't do anything if we just went from nil to nil.
guard !(liveView == nil && oldValue == nil) else { return }
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 = ["PlaygroundPageLiveViewController": viewController]
case .view(let view):
userInfo = ["PlaygroundPageLiveView": view]
}
}
else {
userInfo = [:]
}
NotificationCenter.default.post(name: .playgroundPageLiveViewDidChange, object: self, userInfo: userInfo)
}
}
}
/// An enum describing the supported representations for live views in playgrounds.
public enum PlaygroundLiveViewRepresentation {
#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(macOS)
/// 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 macOS, `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 PlaygroundLiveViewable {
/// A custom `PlaygroundLiveViewRepresentation` for this instance.
///
/// The value of this property can but does not need to be the same every time; PlaygroundLiveViewables may choose to create a new view or view controller every time.
///
/// - seealso: `PlaygroundLiveViewRepresentation`
var playgroundLiveViewRepresentation: PlaygroundLiveViewRepresentation { get }
}
#if os(iOS) || os(tvOS)
extension UIView: PlaygroundLiveViewable {
public var playgroundLiveViewRepresentation: PlaygroundLiveViewRepresentation {
get {
return .view(self)
}
}
}
extension UIViewController: PlaygroundLiveViewable {
public var playgroundLiveViewRepresentation: PlaygroundLiveViewRepresentation {
get {
return .viewController(self)
}
}
}
#elseif os(macOS)
extension NSView: PlaygroundLiveViewable {
public var playgroundLiveViewRepresentation: PlaygroundLiveViewRepresentation {
get {
return .view(self)
}
}
}
extension NSViewController: PlaygroundLiveViewable {
public var playgroundLiveViewRepresentation: PlaygroundLiveViewRepresentation {
get {
return .viewController(self)
}
}
}
#endif
/// A collection of Notification.Name values used internally by PlaygroundPage.
private extension Notification.Name {
/// Indicates that `PlaygroundPage.needsIndefiniteExecution` did change.
static let playgroundPageNeedsIndefiniteExecutionDidChange = Notification.Name(rawValue: "PlaygroundPageNeedsIndefiniteExecutionDidChangeNotification")
/// Indicates that `PlaygroundPage.finishExecution()` was called.
static let playgroundPageIsReadyToFinishExecution = Notification.Name(rawValue: "PlaygroundPageFinishExecutionNotification")
/// Indicates that `PlaygroundPage.liveView` did change.
static let playgroundPageLiveViewDidChange = Notification.Name(rawValue: "PlaygroundPageLiveViewDidChangeNotification")
}