Why does Swift playground shows wrong number of executions?
It's showing how many times a function / expression is being called on that line:
since the calling expression (summer()) is on the same line, it counts as an extra operation. Hence, 6 prints + 6 returns + 1 summer() = 13 times something happened on that line.
I'm sure I'm not using the correct terminology, but this is what's going on.
Swift playground shows wrong number of executions for statement (forEach on array)
This is quite a confusing situation.
Let's consider the second forEach
first:
array.forEach { _ in print("hello") } // (2 times)
Different parts of that line are executed at different times, and Swift counts each of those times as a separate execution. The first time is when it calls array.forEach
, and the second time is inside that call to forEach
when it executes the call to print
in the body of the anonymous function. If we put newlines in, we can see that Swift only executes each line once and reports its “value”:
array.forEach { _ in // [1]
print("hello") // ()
}
We can also try putting the anonymous function in a variable:
let p: (Int) -> () = { _ in print("hello") } // (2 times)
array.forEach(p) // [1]
Above, Swift executes part of the let p
line once to create the anonymous function and store it in p
, and another part of the line later to call print
inside the body of the function.
Swift reports that the value of the print
line is ()
because forEach
s argument must be a function that returns ()
(the empty tuple, aka Void
). Since print
already returns ()
, Swift just lets that be the value of the line.
Before we go back to consider your first forEach
example, let's consider one other example:
print("hello"); print("goodbye") // (2 times)
Swift says this line executes two times because each individual statement on the line counts as a separate execution.
So now let's consider your first example:
array.forEach { $0.value } // (3 times)
Let's try it with newlines:
array.forEach { // [1]
$0.value // (2 times)
}
OK, so the forEach
call itself counts as one execution, as expected. But Swift claims it is executing the body of the anonymous function twice. Why?
Recall that forEach
's argument must be a function that returns ()
. But the type of $0.value
is not ()
; it is the internal type Builtin.Int64
. So Swift inserts another statement at the end of the line, to return ()
. Effectively, Swift acts like you wrote this:
array.forEach { // [1]
$0.value; () // (2 times)
}
And we can prove that by explicitly adding another line to the function:
array.forEach { // [1]
$0.value // <<<opaque type>>>
()
}
Now Swift thinks each line is executed once, as expected.
Playground shows strange count of execution
It's not telling you how many times the block was executed, but rather how many outputs were called on that line. Since the block returns false
and the function allSatisfy
returns false
, that's 2 outputs in 1 line. You'll notice that no matter the size of the array you get the same value, and if you expand the code, i.e.
intArray.allSatisfy {
$0 < 0
}
you don't see 2 times.
Playgrounds doesn't seem to give a counter for executions of closures/functions passed as parameters, rather only for regular for-loops instead.
Playground wrong output
The reason you are seeing only ["34"]
after the types[3..<5] = ["34"]
line is because the assignment operator =
returns the value that has been assigned.
The other lines show the whole array because the +=
operator returns the result of the assignment.
Playground execution aborted - EXC_BAD_INSTRUCTION
When you say:
NSString(string: String)
You are trying to create an NSString
instance using a String
variable named String
. But String
, is a type, not a variable. So your previous line works because you are passing it a variable:
let newTypeString = NSString(string: str)
But the one where you don't pass an actual variable, but instead pass in a type, fails. Does that make sense?
Update:
It appears that I misunderstood the code as it was originally formatted. The only code the OP was trying to run was:
var str = "Hello, playground"
let newTypeString = NSString(string: str)
According to the provided information, Playgrounds would crash on the second line even though the code was correct. I suggested that the OP try relaunching Xcode to see if that would resolve the issue since Xcode can sometimes be a bit temperamental :) Apparently, that solved the issue.
Swift Playground error: Execution was interrupted, reason: signal SIGABRT
The problem is that you are adding the constraint to stackView
rather than containerView
.
The documentation for addConstraint
states
The constraint to be added to the view. The constraint may only reference the view itself or its subviews.
containerView
is the super view of stackView
, not a sub view.
If you change your code to add the constraint to the containerView
it will run
containerView.addConstraint(.init(item: stackView, attribute: .top, relatedBy: .equal, toItem: containerView, attribute: .top, multiplier: 1, constant: 0))
containerView.addConstraint(.init(item: stackView, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .leading, multiplier: 1, constant: 0))
You will probably want to add a trailing and a bottom constraint so that the stack view fills the whole container view. You will, of course, also need to add an arrangedSubview
so that there is actually some content in the stack view.
It is generally simpler to add constraints by referencing layout guides rather than this older, more verbose, approach:
import UIKit
import PlaygroundSupport
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
containerView.backgroundColor = UIColor.white
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
let label = UILabel()
label.text = "Hello world"
label.textColor = .black
stackView.addArrangedSubview(label)
PlaygroundPage.current.liveView = containerView
xcode 8.3.3 Playground does not show the error next to line number
Please try this menu(although it's already shown):
Related Topics
How Constant Is the Firebase Anonymous Id
Difference Between String Interpolation and String Initializer in Swift
How to Create a String from Utf8 in Swift
Mutable Binding in Swiftui Live Preview
Spacer Not Working with Form Inside a VStack
How to Track More Than 4 Images at a Time with Arkit
Is Swift a Dynamic or Static Language
Get Current Time as String Swift 3.0
How to Get the Height of a Uilabel in Swift
In Swiftui, Where Are the Control Events, I.E. Scrollviewdidscroll to Detect the Bottom of List Data
Swift 2 Protocol Extension Not Calling Overridden Method Correctly
Swift 4.2 Setter Getter, All Paths Through This Function Will Call Itself
Can an Enum Contain Another Enum Values in Swift
Declaration Is Only Valid at File Scope (Extension)