Swift issue in Swift for Beginners Chapter 6 - swift

This line of code from "Swift for Beginners" won't work on the latest Swift Version. I'm guessing the repeat keyword can no longer be used as is in the code, so if I change it to repeato, the code loops 5 times as expected but only shows "()" in the console, without the actual String. How can this be fixed?
here is the simple code:
// extension with a closure as a parameter
extension Int {
func repeat(work: () -> ()) {
for _ in 0..<self {
work()
}
}
}
5.repeat({
println("repeat this string")
})

Changes in Swift 2:
repeat is now a keyword
println is now print
This should work:
extension Int {
func times(work: () -> Void) {
for _ in 0..<self {
work()
}
}
}
5.times {
print("repeat this string")
}

Related

facing issue while calling nested function in swift ios

func check(a: () -> ()){
func a(){
print("A Calling")
}
a()
}
Calling function
check {
print("Check Calling")
}
In the above code, i am not able to call a() function and it will directly be executing "check calling "
Result : "Check Calling"
When i am calling check function it should be execute a() function also and order should be
Result should be:
"A Calling"
"Check Calling"
The problem with the code in your question is that you do not call the nested function at all. It doesn't help that you've named it the same as the passed in function which is perhaps why you are having trouble isolating the issue.
This works
func check(completion: () -> Void) {
func localFunction() {
print("A Calling")
}
localFunction()
completion()
}
check {
print("Check Calling")
}
// Outputs:
//
// A Calling
// Check Calling

Trouble with non-escaping closures in Swift 3

I have an extension Array in the form of:
extension Array
{
private func someFunction(someClosure: (() -> Int)?)
{
// Do Something
}
func someOtherFunction(someOtherClosure: () -> Int)
{
someFunction(someClosure: someOtherClosure)
}
}
But I'm getting the error: Passing non-escaping parameter 'someOtherClosure' to function expecting an #escaping closure.
Both closures are indeed non-escaping (by default), and explicitly adding #noescape to someFunction yields a warning indicating that this is the default in Swift 3.1.
Any idea why I'm getting this error?
-- UPDATE --
Screenshot attached:
Optional closures are always escaping.
Why is that? That's because the optional (which is an enum) wraps the closure and internally saves it.
There is an excellent article about the quirks of #escaping here.
As already said, Optional closures are escaping. An addition though:
Swift 3.1 has a withoutActuallyEscaping helper function that can be useful here. It marks a closure escaping only for its use inside a passed closure, so that you don't have to expose the escaping attribute to the function signature.
Can be used like this:
extension Array {
private func someFunction(someClosure: (() -> Int)?) {
someClosure?()
}
func someOtherFunction(someOtherClosure: () -> Int) {
withoutActuallyEscaping(someOtherClosure) {
someFunction(someClosure: $0)
}
}
}
let x = [1, 2, 3]
x.someOtherFunction(someOtherClosure: { return 1 })
Hope this is helpful!
The problem is that optionals (in this case (()-> Int)?) are an Enum which capture their value. If that value is a function, it must be used with #escaping because it is indeed captured by the optional.
In your case it gets tricky because the closure captured by the optional automatically captures another closure. So someOtherClosure has to be marked #escaping as well.
You can test the following code in a playground to confirm this:
extension Array
{
private func someFunction(someClosure: () -> Int)
{
// Do Something
}
func someOtherFunction(someOtherClosure: () -> Int)
{
someFunction(someClosure: someOtherClosure)
}
}
let f: ()->Int = { return 42 }
[].someOtherFunction(someOtherClosure: f)

how to squelch "result not used" warnings

In Swift2.2, I have an extension to Optional that looks like:
extension Optional {
func ifNotNil<T>(_ closure:(Wrapped) -> T) -> T? {
switch self {
case .some (let wrapped):
return closure(wrapped)
case .none:
return nil
}
}
}
It allows for code like
anImageView.image = self.something.ifNotNil { self.getImageFor($0) }
But sometimes, I don't care about the result:
myBSON["key"].string.ifNotNil {
print($0}
}
In Swift2.2, it worked like a charm. But firing up the new XCode8 Beta and converting to Swift3, I'm getting warnings anywhere that I do the second type. It's almost as if there's an implicit #warn_unused_result. Is this just an early beta bug? Or something I can no longer do in Swift3? Or something I need to newly fix in Swift3?
You can discard the result using:
_ = myBSON["key"].string.ifNotNil {
print($0}
}
Or mark your method to not warn for unused results:
extension Optional {
#discardableResult func ifNotNil<T>(_ closure:(Wrapped) -> T) -> T? {
switch self {
case .some (let wrapped):
return closure(wrapped)
case .none:
return nil
}
}
}
Reference : SE-0047

swift repeat func: expected identifier in function declaration

I'm using a Swift learning book about extensions with a closure as a parameter.
In the book, it told me
extension Int {
func repeat(work: () -> ()) {
for _ in 0..<self {
work()
}
}
}
On the line
func repeat(work: () -> ()) {
Xcode tells me
Expected identifier in function declaration
and on the line:
for _ in 0..< self {
Xcode tells me
Braced block of statements is an unused closure
and
Expected ‘{’ to start the body of for-each loop
Can anyone can tell me why these errors occur and what should I do?
There are a number of problems with the posted code:
extensionInt should be extension Int, although I suspect this is a typo in you post
As #Zhao Yi pointed out, repeat is a Swift keyword, you need to rename your function (e.g. repeatWork)
The Swift Half-Open Range Operator requires either an empty space on both sides, or no space on both sides. Both these are valid:
0 ..< self
0..<self
Finally, you can call this function like this:
2.repeatWork({
print("Hello")
})
or this:
2.repeatWork {
print("Hola")
}
repeat is a keyword you can't use as a function name. Rename it to something else:
extension Int {
func repeat1(work: () -> ()) {
for _ in 0..<self {
work()
}
}
}

Swift error: cannot invoke 'init' with an argument of type '() -> () -> $T1'

I'm learning Apple's new programming language Swift. I was trying to add a new method printAll to Array instances, using Swift extensions, which when called will print all elements in the array
extention Array {
func printAll() {
for (i, value) in enumerate(self) {
println("\(i+1). \(value)")
}
}
}
// let someAppleProducts = ["iPhone", "iPad", "iWatch", "iMac"]
// someAppleProducts.printAll()
But I'm getting following error while running above script using a online compiler runswiftlang.com:
error: cannot invoke 'init' with an argument of type '() -> () -> $T1'
extention Array {
^~~~~~~~
Can someone explain why I'm getting this error?
However, adding times method to Int instances works fine
extension Int {
func times(task: () -> ()) {
for _ in 0..<self {
task()
}
}
}
3.times({
println("Hello!")
})
Prints:
Hello!
Hello!
Hello!
You've misspelled extension:
extention Array {
should be
extension Array {
The error message for this is misleading, I would expect it to be something like unrecognized token 'extention' or something helpful!