Archive for June, 2016

Dear Erica: How do I create a visible, non-mutable array?

Marc writes, that he wants an array that’s modifiable internally but visible to the outside world. “But don’t they get a pointer to an array object and they can append to it? I just ended up making a getter that make a copy of a private var myArray = [Object]“.

Say you have the following class code in a module. It’s a simple class that has an array and a public  function that adds twos to the array on each call. Call it ten times, you end up with an array containing ten twos. It’s not a very interesting class but it does showcase an interesting Swift behavior.

public class MyClass: DefaultReflectable {
    public var array: [Int] = []
    public func modifyArray() { array += [2] }
    public init() {}
}

If you run the following code from outside the module, you get the   following results. Consumers have unrestricted read-write access to that array.

let instance = MyClass() // MyClass(array: [])
instance.modifyArray() // MyClass(array: [2])
instance.array = [3] // MyClass(array: [3])
instance.array.append(4) // [3, 4]

You need a simple edit, which adjusts access to the array setter, as shown here.

public internal(set) var array: [Int] = []

This creates two access levels, public, except in the case of set, in which case the access control is internal.

Making this one change enables you to change this behavior and disallow the last two lines in the preceding example, the final two lines that applied array edits. With an internal access level for the setter consumers won’t be able to directly change the array except through your provided API. The final two lines of code no longer compile, raising the errors you’d expect from a let constant instead of a variable:

let instance = MyClass() // MyClass(array: [])
instance.modifyArray() // MyClass(array: [2])
instance.array = [3] // error, Cannot assign to property, 'array' setter is inaccessible
instance.array.append(4) // error, cannot use mutating member on immutable value

Like my posts? Consider buying a book.

Holocene and heard: What’s up in Swift Evolution

Accepted

SE-0089: Renaming String.init<T>(_: T) is accepted. Team writes:

The second review of SE-0089: “Renaming String.init<T>(_: T)” ran from June 4…7. The proposal is *accepted* for Swift 3.

The feedback from the community on this second round was light, which indicates that the extensive iteration on earlier rounds brought this to a good place. The core team discussed other possibilities for the parameter label (e.g. from: instead of describing:) but ended up agreeing that a more explicit “describing:” label is the best fit for this API.

SE-0106: Add a macOS Alias for the OSX Platform Configuration Test is accepted. Team writes:

The core team is proactively accepting SE-0106 “Add a macOS Alias for the OSX Platform Configuration Test” without a formal review, under the rationale that the proposal is “obvious” and probably should have been treated as a bug fix. Adding aliases for other uses of “OS X” in the language to use macOS are also proactively accepted.

SE-0095: Replace protocol<P1,P2> syntax with P1 & P2 syntax is accepted. “The current protocol<> construct, which defines an existential type consisting of zero or more protocols, should be replaced by an infix & type operator joining bare protocol type names.” Team writes:

This syntax has been extensively discussed by the community, and is a cornerstone of the “generalized existentials” work for future Swift releases.  The community was overall positive on the feature with a few subjective concerns about “&” being tightly associated with bitwise logical operations.  The core team believes this will not be contextually confusing since it appears in a type position, between two names that are obviously nominal types (e.g. they are capitalized).

I filed SR-1938 to track implementation of this work, this is a somewhat advanced starter project which would be a great place for someone to dive into the parsing logic in Swift.

SE-0104: Protocol-oriented integers is accepted with revisions. “This proposal cleans up Swifts integer APIs and makes them more useful for generic programming. The way the Arithmetic protocol is defined, it does not generalize to floating point numbers and also slows down compilation by requiring every concrete type to provide an implementation of arithmetic operators as free functions, thus polluting the overload set. Converting from one integer type to another is performed using the concept of the ‘maximum width integer’ (see MaxInt), which is an artificial limitation. Another annoying problem is the inability to use integers of different types in comparison and bit-shift operations.” Team writes:

The feedback from the community was very positive and contributed a number of improvements to the design of the proposal.  The core team has accepted the proposal, subject to the following changes:

  • The “Integer” protocol should be renamed to “BinaryInteger” to be more accurate and avoid confusion between “Int” and “Integer”.
  • The “FloatingPoint” protocol should conform to the “Arithmetic” protocol.
  • Rename the “absoluteValue” property to “magnitude”, and sink it down to the “Arithmetic” protocol.
  • Eliminate the “AbsoluteValuable” protocol, since “abs” can now be defined in terms of “Arithmetic”.
  • Rename the “signBitIndex” property to “minimumSignedRepresentationBitWidth”.
  • Add a “popcount” property requirement to the “FixedWidthInteger” protocol.
  • Change the “countLeadingZeros()” member of concrete types to be a “leadingZeros” property on “FixedWidthInteger”.
  • Rename “func nthWord(n: Int) -> UInt” to “func word(at: Int) -> UInt”.
  • Rename the “and”, “or”, and “xor” members of “FixedWidthInteger” to “bitwiseAnd”, “bitwiseOr” and “bitwiseXor”.
  • Change “doubleWidthMultiply” to be a static member, and add a “doubleWidthDivide” member as its dual.  The latter will return both quotient and remainder of type “Self”. Both are to be added to the “FixedWidthInteger” protocol.

SE-0102: Remove @noreturn attribute and introduce an empty NoReturn type is accepted. “We should remove the rarely-used @noreturn function type attribute and instead express functions that don’t return in terms of a standard uninhabited type.” Team writes,

The feedback on the proposal was generally very positive from the community.  The only significant concern was from people who felt that merging the concept of “does not return” into the result type of the function conflates two concepts.  The core team feels that unifying these concepts overall reduces the surface area of the language by eliminating an obscure (but important) type system concept outright.

The other significant discussion was about the actual name for the “NoReturn” type.  The core team enjoyed the community idea of naming it “?” or ”?” but decided that the name lacked clarity.  Ultimately the core team agreed with the loud voice of the community that “Never” is the right name for this type.

SE-0103: Make non-escaping closures the default is accepted with a minor revision. “This proposal switches the default to be non-escaping and requires an @escaping annotation if a closure argument can escape the function body. Since the escaping case can be statically detected, this annotation can be added via an error with a fixit. Other annotations that have consequences for escape semantics (e.g., @autoclosure(escaping)) will be altered to make use of the new @escaping annotation.” Team writes:

Instead of a “asUnsafeEscapingClosure(_:)” function that removes the @escaping attribute, the core team prefers a function with this signature (roughly) like:

func withoutActuallyEscaping<ClosureType, ResultType>(_ closure: ClosureType, do: (fn : @escaping ClosureType) -> ResultType) -> ResultType { … }

This allows one to safely add the @escaping attribute in situations where a closure is known not to actually escape.

The key to this approach is that the “withoutActuallyEscaping” function can verify that the closure has not actually escaped when it completes, providing a safe model for locally adding the @escaping attribute when needed. The core team believes that the actual implementation of withoutActuallyEscaping will require some magic, but that it should be implementable.

Returned for Revision

SE-0077: Improved operator declarations is returned for revisions. The team writes:

On June 22, 2016, the core team decided to return the first version of this proposal for revision. The core design proposed is a clear win over the Swift 2 design, but feels that revisions are necessary for usability and consistency with the rest of the language:

  • The proposed associativity(left) and precedence(<) syntax for precedence group attributes doesn’t have a precedent elsewhere in Swift. Furthermore, it isn’t clear which relationship < and > correspond to in the precedencesyntax. The core team feels that it’s more in the character of Swift to use colon-separated “key-value” syntax, with associativitystrongerThan, and weakerThan keyword labels:
      precedencegroup Foo {
        associativity: left
        strongerThan: Bar
        weakerThan: Bas
      }
  • If “stronger” and “weaker” relationships are both allowed, that would enable different code to express precedence relationships in different, potentially confusing ways. To promote consistency and clarity, the core team recommends the following restriction: Relationships between precedence groups defined within the same module must be expressedexclusively in terms of strongerThanweakerThan can only be used to extend the precedence graph relative to another module’s groups, subject to the transitivity constraints already described in the proposal. This enforces a consistent style internally within modules defining operators.
  • The proposal states that precedence groups live in a separate namespace from other declarations; however, this is unprecedented in Swift, and leads to significant implementation challenges. The core team recommends that precedence groups exist in the same namespace as all Swift declarations. It would be an error to reference a precedence group in value contexts.
  • Placing precedence groups in the standard namespace makes the question of naming conventions for precedencegroup declarations important. The core team feels that this is an important issue for the proposal to address. As a starting point, we recommend CamelCase with a -Precedence suffix, e.g. AdditivePrecedence. This is unfortunately redundant in the context of a precedencegroup declaration; however, precedencegroups should be rare in practice, and it adds clarity at the point of use in operator declarations in addition to avoiding naming collisions. The standard library team also requests time to review the proposed names of the standard precedence groups
  • This proposal quietly drops the assignment modifier that exists on operators today. This modifier had one important function–an operator marked assignment gets folded into an optional chain, allowing foo?.bar += 2 to work as foo?(.bar += 2) instead of (foo?.bar) += 2. In practice, all Swift operators currently marked assignment are at the Assignment precedence level, so the core team recommends making this optional chaining interaction a special feature of the Assignment precedence group.
  • This proposal also accidentally includes declarations of &&= and ||= operators, which do not exist in Swift today and should not be added as part of this proposal.

SE-0091: Improving operator requirements in protocols is returned for revision. “When a type conforms to a protocol that declares an operator as a requirement, that operator must be implemented as a global function defined outside of the conforming type. This can lead both to user confusion and to poor type checker performance since the global namespace is overcrowded with a large number of operator overloads. This proposal mitigates both of those issues by proposing that operators in protocols be declared statically (to change and clarify where the conforming type implements it) and use generic global trampoline operators (to reduce the global overload set that the type checker must search).” Team writes:

The review of “SE-0091: Improving operator requirements in protocols” ran from May 17…23.  While many people were positive about improving lookup of operators, several concerns about introduction of boilerplate were raised.  Tony and Doug have discussed it further and plan to revise and resubmit the proposal for another round of review.

 

SE-0101: Rename sizeof and related functions to comply with API Guidelines is returned for revision. “Upon accepting SE-0096, the core team renamed the proposed stdlib function from dynamicType() to type(of:) to better comply with Swift’s API guidelines. This proposal renames sizeofsizeofValuestrideofstrideofValuealign, and alignOf to emulate SE-0096’s example.” This one has a major alternative redesign being crafted. Team writes:

The thread discussing it has already turned towards new ways to express these ideas, so when that thread runs its course we’ll restart review of the revised proposal.

Rejected

SE-0105: Removing Where Clauses from For-In Loops is rejected. “This proposal removes where clauses from for-in loops, where they are better expressed (and read) as guard conditions.” Expect a rejection on this very unpopular proposal but the team may adopt some of the alternatives considered for better language consistency. Team writes:

The vast majority of the community of the community prefers to keep this language feature, and the core team agrees.  Even though ‘where’ is a small bit of syntactic sugar, it improves the expressivity (therefore readability and maintainability) of important loops.

In Review

  • May 9…16 SE-0086: Drop NS Prefix in Swift Foundation “As part of Swift 3 API Naming and the introduction of Swift Core Libraries, we are dropping the NS prefix from key Foundation types in Swift.”
  • June 28 … July 4 SE-0107: UnsafeRawPointer API “Swift enforces type safe access to memory and follows strict aliasing rules. However, code that uses unsafe APIs or imported types can circumvent the language’s natural type safety.” This extensive redesign addresses many issues under the microscope.
  • June 28 … July 4 SE-0109: Remove the Boolean protocol “For legacy and historical reasons Swift has supported a protocol named Boolean for abstracting over different concrete Boolean types. This causes problems primarily because it is pointless and very confusing to newcomers to Swift: is quite different than Bool, but shows up right next to it in documentation and code completion. Once you know that it is something you don’t want, you constantly ignore it. Boolean values are simple enough that we don’t need a protocol to abstract over multiple concrete implementations.”
  • SE-0077 v2: Improved operator declarations in 2nd review to 7/4. (1st version) “Replace syntax of operator declaration, and replace numerical precedence with partial ordering of operators” However many reviews it takes, this is a good one to get right.
  • SE-0111: Remove type system significance of function argument labels in review to 7/4. “Swift’s type system should not allow function argument labels to be expressed as part of a function type. Removing this feature simplifies the type system. It also changes the way argument labels are treated to be consistent with how default arguments are treated; that is, tied to a declaration and not part of the type system”
  • SE-0110: Distinguish between single-tuple and multiple-argument function types in review to 7/4. “Swift’s type system should properly distinguish between functions that take one tuple argument, and functions that take multiple arguments. The current behavior violates the principle of least surprise and weakens type safety, and should be changed.”
  • SE-0108: Remove associated type inference in review to 7/4. “The main advantage of removing associated type witness inference is that it decreases the complexity of the type checker. Doing so removes the only aspect of Swift that depends upon global type inference. Simplifying the type checker makes it easier to improve the performance and correctness of the type checker code. Given that both are widely acknowledged issues with current versions of Swift, any opportunity for improvement should be carefully considered.”
  • SE-0112: Improved NSError Bridging in review to 7/4. “Swift’s error handling model interoperates directly with Cocoa’s NSError conventions. For example, an Objective-C method with an NSError** parameter will be imported as a throwing method. This proposal introduces new protocols and a different way of bridging Objective-C error code types into Swift, along with some conveniences for working with Cocoa errors.”
  • SE-0114: Updating Buffer “Value” Names to “Header” Names in review to 7/7. “This proposal updates parameters and generic type parameters from value names to header names for ManagedBuffer, ManagedProtoBuffer, and ManagedBufferPointer. All user-facing Swift APIs must go through Swift Evolution. While this is a trivial API change with an existing implementation, this formal proposal provides a paper trail as is normal and usual for this process.”
  • SE-0115: Rename Literal Syntax Protocols in review to 7/7. “This proposal renames the *LiteralConvertible protocols to ExpressibleAs*Literal.”

Scheduled

Nothing right now

Not Yet Scheduled

Make it Swifter Challenge

Today’s challenge is courtesy of the Swift Users email list, posted by Adriano Ferreira. His starting point is here, where he was really looking to simplify chained calls. But making things Swifter isn’t always just about making chaining look better.

func selectionSort(_ array: [Int]) -> [Int] {

    guard array.count > 1, let minElement = array.min() else {
        return array
    }

    let indexOfMinElement = array.index(of: minElement)!

    // All of this just to filter out the first smallest element and return the rest
    // Also tried ‘suffix(from:)' here, but couldn’t make it work properly
    let rest = array.enumerated()
                    .filter({ index, _ in index != indexOfMinElement })
                    .map({ _, element in element })

    return [minElement] + selectionSort(rest)
}

What can make this Swifter?

First, practicality. Even though any array of 0 or 1 elements is already sorted, I don’t think adding code to test for those conditions is practical. I think it’s better just to streamline and let the code run, even if the case of one element isn’t perfectly ideal.

Second, flow. I don’t like the idea of first finding the minimum and then finding its index. Enumeration allows these operations to be run in tandem.

Third, style. Enumeration should really return (index: Index, value: Element) tuples. It doesn’t. So I took this opportunity to extend Array to create the kind of tuples I’d rather work with. Because of that, my solution is more complex than it really needs to be (for a sorting function no one ever actually uses) because I’d rather use code that handles $0.value and $1.index than $0.1 and $1.0.

My redesigned code is here. Share yours!

That Integer Literal Thing

Last night I put up a tweet asking developers to participate in a one-question survey. Enough people asked me what this was about that I promised a quick post.

The Swift standard library include a number of conversion protocols that Matthew Johnson and I thought were badly named. The standard library includes about 80-odd protocols, and about 15% of them have to do with conversion.

So we submitted a renaming proposal that was rejected. The standard library team preferred to use a new Syntax namespace. Our proposal had focused on naming guidance. Their response was specific to implementation, under the philosophy umbrella that Swift Evolution proposals need to address real world design not set theoretical guidance. We could not find a middle ground but the discussion has continued post-WWDC as the problems remain without a solution. Matthew has been working on a new proposal.

When a type conforms to the IntegerLiteralConvertible protocol, it   “allows an integer literal to be interpreted as an expression having the conforming type”. To allow this behavior to happen, the conforming type implements an initializer that accepts Int and returns the type.

/// Conforming types can be initialized with integer literals.
public protocol IntegerLiteralConvertible {

    associatedtype IntegerLiteralType

    /// Create an instance initialized to `value`.
    public init(integerLiteral value: Self.IntegerLiteralType)
}

I think this would be better expressed something like this:

/// Conformance allows integer literals to be interpreted
/// as an expression having the conforming type. 
///
/// ```
/// let instance: T = *integer literal*
/// ```
/// 
/// for example:
/// 
/// ```
/// let myDouble: Double = 2 // The literal 2 is automatically cast
/// let anotherDouble: Double = myDouble * 5 // The literal 5 is automatically cast
/// ```
///
public protocol NAME_TO_BE_DETERMINED {

    ///  For constrained integer literal types, which otherwise default to `Int`.
    associatedtype IntegerLiteralType

    /// Create an instance initialized to `value`.
    ///  Required to enable in-line syntax substitutions
    public init(integerLiteral value: Self.IntegerLiteralType)
}

The question of the protocol name is a tricky one. Discussion members  suggested Syntax.IntegerLiteral and Syntax.IntegerLiteralExpressible, both of which I find lacking. I don’t think they convey the intended meaning.

Last night I asked Swift developers what they thought Syntax.IntegerLiteralExpressible meant and here are the results. By a margin of about 9:1 they felt it meant “The conforming type can express itself as an integer literal.” There’s a tab at the top of the linked page that enables you to switch between “Question Summaries” and “Individual Responses”, so you can see how the explanations pair with survey responses.

Update: Dave Abrahams responds: 

[T]he only correct-ish option you gave people is slightly awkward and inaccurate—I’d have said “Instances of the conforming type can be expressed as integer literals,” but that matches the 90% meaning almost exactly; certainly much better than the 10%.

As far as I can tell, your poll supports my suggestion.

While conversion protocols exist almost exclusively for the consumption of types declared in the standard library, they (like their current brethren) will be seen, read about, and their effects used by regular Swift developers. In that light, I think there’s value in pursuing good naming. Hopefully Swift ends up with something better than Syntax.AllowsIntegerLiteralToBeInterpretedAsExpressionOfConformingType.

Dear Playgrounds Santa: Playgrounds

Dear Playgrounds Santa,

It’s awesome using #colorLiteral in Swift Playgrounds. The editor automagically picks up the literal and offers a context-sensitive picker. So might I have a new #numberLiteral to match? One that allows integer or floating point values, with max: and min:, so that the number tweaker cannot produce values outside my specifications?

#numberLiteral(0.2)
#numberLiteral(0.2, min:0.0, max:1.0)
#numberLiteral(8, min:1, max: 10)

It would sure make staging examples less error-prone, especially when working with frameworks like Core Image.

Speaking of being good this year, can I please have a standard  “Cover.png” resource file to display in the Playgrounds library? When found, it would replace the empty gray swift icon that makes one playground look so like another. Just because they’re not playground books doesn’t mean standalone playgrounds can’t be fun,  interesting, or exciting.

I’d also really like to have a new markup keyword. Can you add #-autorun, so my LiveView updates on edits (or at least when the editor has paused, say, for half a second?)

Finally (along with my pony), can I view and edit Sources when working with playgrounds (and not playground books) somehow?

Thanks!

p.s. I’ve left you milk, cookies, and Radar 27035484 next to the tree.

Bouncing AirDrop contents to my desktop

I never use my Downloads folder. It’s a fusion drive, so it’s precious, fast, and expensive. I don’t need a thousand downloaded copies of Xcode and firmware updates littering its limited space. Instead, I point all my browsers and other apps to download to my secondary data disk.

Screen Shot 2016-06-27 at 12.57.18 PM

And before you ask, I use numerical and alphabetic prefixes so everything shows up in the right place and the right order for quick reference and single-letter typing access. Whatever data I can offload from my main drive, I do offload:

Screen Shot 2016-06-27 at 12.59.42 PM

However, when it comes to airdropping, it’s generally true that whatever I’m sending back and forth is of immediate interest. In such case, I don’t want it heading into my Downloads folder. I want it on my desktop as soon as it lands. As  I’m updating my Playgrounds Book right now, I’m doing a lot more airdropping than I normally would.

I’m not a big user of smart folders and Automator actions. I have a smallish bunch that I occasionally use. Still, they have their place and today was a perfect occasion to bring a new one into the mix.

I just had had it with the Downloads folder and decided to build a bouncer that would automatically throw any item added to ~/Downloads up to the desktop. I thought I’d share how to do this.

Step 1. Create a new Folder Action

Screen Shot 2016-06-27 at 1.03.48 PM

Step 2. Choose the Downloads folder.

Screen Shot 2016-06-27 at 1.05.50 PM

Step 3. Drag “Move Finder Items” onto “Drag actions or files here to build your workflow”

Screen Shot 2016-06-27 at 1.06.37 PM

Screen Shot 2016-06-27 at 1.06.48 PM

This creates the following action, with Desktop selected by default. (If it’s not, choose Desktop for the destination.)

Screen Shot 2016-06-27 at 1.07.24 PM

Step 4. Then save:

Screen Shot 2016-06-27 at 1.09.12 PM

Your new automator action is stored in ~/Library/Workflows/Applications/Folder\ Actions:

Screen Shot 2016-06-27 at 1.11.43 PM

Step 5. Test. Drop a file into Downloads and confirm that it moves to the desktop. You should now be ready to airdrop to your desktop.

Note: I’m sure there’s a better way to do this, but I actually wrote an app that quickly opens AirDrop windows on the Mac side of things. I found an appropriate AppleScript online, compiled it to an app, and use Spotlight to launch it. Very handy when I’m more focused on iOS than OS X at the moment.

Book Review: Post this Book

cover86411-medium

Sometimes there is such a thing as too many memes and kitten gifs. David Sinden and Nikalas Catlow breathe fresh air into social media feeds with #Post This Book  (Sourcebooks, $9.99, complete with built-in hashtag). This sweet inspirational book is suitable for tweens, teens, and even college students. It offers 150+ pages of ideas for tweeting, tumbling, facebooking, vine filming, and instagramming.

It’s not a book you read. Each page offers one or two ideas along with quick descriptions. You turn pages, you get inspired, you go out and express yourself using those ideas. Everything is simple, but well tweaked to connect with an audience and inspire a conversation.

Screen Shot 2016-06-26 at 7.56.15 PM

With kids and social media, there’s always tension between privacy and free expression, appropriateness and creativity. I’m pleased to say that in the time I spent flicking through pages in this book and showing examples to my kids, that I didn’t find anything objectionable or problematic.

The ideas in this book allow kids involve themselves in public fora (using anonymous nicks and handles, of course, because, you know, reality). At the same time they’re exploring their imaginations, they’re not crossing inappropriate lines that are so prevalent on Tumblr and beyond.

Screen Shot 2016-06-26 at 8.17.05 PM

This book’s projects offer positive ways to test the waters of social media. Whether brainstorming how to “zombify something unlikely”, videoing time lapsed “tidying up”, or creating “a tabletop obstacle course”, all the projects I read through were inspirational and fun.

#Post This Book goes on sale on July 1st from Sourcebooks. It’s a perfect “gift” book — for just 10 bucks, you can probably buy a small tin of colored pencils or markers to pair with it without breaking the bank.

I was given early access to the manuscript for this review courtesy of NetGalley and Sourcebooks.

Playgrounds 7: In which I *finally* get the keyboard

Swift Playgrounds offers a smart, programmer-centric keyboard. Symbols, numbers, and common programming punctuation are included on the main keyboard.

Screen Shot 2016-06-24 at 11.35.29 AM

To access an alternate key, tap and then either drag down for single item keys, like qwerty’s numbers, or down-and-left / down-and-right for two-item keys, like fghj’s brackets and parentheses. Release your finger with the gray replacement key shown. Playgrounds uses smart insertion, so you may sometimes add a single bracket or you may add a bracket pair, depending on context.

Try these steps to add a line that says “let x: [Int] = []”:

  1. Tap the “let” bubble in the top keyboard accessory view. A template appears that says “let name = value”, with name highlighted.
  2. Tap x. This replaces “name”.
  3. Pull down on the “k” key until it turns into a colon and release. Playgrounds adds a colon and a space.
  4. Pull down-and-right on “h” until it turns into “]”. Release. Playgrounds adds a square-bracket pair (“[]”) and places the cursor in the middle.
  5. Tap Int on the accessory view.
  6. Tap the value placeholder in code.
  7. Repeat step 4 (Pull down-and-right on “h” until it turns into “]”. Release.) to add an empty array literal.

In addition to this sweet, super-convenient programming style, you can also connect a Bluetooth keyboard (or use your computer with a program like Houda’s Type2Phone), dictate (handy for populating comments), or switch to a standard iPhone numeric keyboard by tapping either of the “.?123” keys. You can even use Swift-supported emojis:

Screen Shot 2016-06-24 at 11.42.05 AM

After declaring the dog-cow variable, it appears in contextual completion lists like any other symbol:

Screen Shot 2016-06-24 at 11.46.52 AM

Izzy notes: The 12″ iPad doesn’t use it because the larger keyboard has an extra row of numbers/symbols. You can tap + hold or swipe up on the numbers to get the symbols without having to use shift.

Playgrounds 6: Focusing Interaction

Screen Shot 2016-06-24 at 9.37.20 AM

In this screenshot, I’ve circled a bit of directed interaction. There’s a highlight around “0.5” and a pop-up editor that allows the user to change the value. This new feature is made possible by Swift Playground markup.

Like all Swift playgrounds, this page uses live code, some of which you see and other parts of which are hidden, either by placement in Sources or by using playground markup. The code is marked up to disable edits except in this one place. Here’s what the key part of the underlying code looks like:

filter.setValue(/*#-editable-code*/1.0/*#-end-editable-code*/, forKey: "inputAmount")
imageView.image = UIImage(ciImage: filter.outputImage!)

Yes, those are in-line comments adding markup in the  setValue call. It’s kind of ugly and it relies on the old-style C /* */ comment delimiters that allow the markup to be inserted in-place.

From a coding viewpoint, it’s ugly as sin. From a user experience viewpoint, it ensures that users can explore exactly one setting to better understand the Core Image vibrancy filter.

This is no way, at least at this time, to use markup to limit values to legal parameters. For example, Core Image may not like negative numbers or numbers above 1.0. You could work around that by using a separate variable and adding clamping code, e.g.

var inputAmount = make this editable
inputAmount = clamp(inputAmount, 0.0, 1.0)
filter.setValue(inputAmount, forKey: "inputAmount")

But if you do that, you’re drawing attention away from the CI code you’re demonstrating and focusing it on user interaction instead. No one’s going to use this pattern in real code, while they may very well use the pattern in the screenshot. (Which, if you think about it is the real point of this.)

I’ve gone ahead and filed a radar (26996963) about the issue, asking for enhanced markup that allows input qualities for editable playground sections.

I probably should file another one asking for “Auto Run” markup, so these kind of examples will re-execute on each edit, just like they do on OS X.